Qt カスタム ウィジェットはどのようにして相互排他効果を実現しますか

最先端

相互排他を実現するためのカスタム ウィジェットとは何ですか?

Qt を使用してより美しいインターフェイスを持つ関数を作成する場合、複数のコントロールが相互に排他的であり、QRadiButton コントロールと同様ですが、純粋な QRadioButton コントロールではありません。相互に排他的なのは 1 つのウィンドウである場合もあれば、複数の場合もあります。ボタンなど

ここでは、相互排除の簡単な例を挙げました。単純ではありますが、さまざまな落とし穴が含まれています。必要に応じて、小さなメモを取ることができます。特に Qt 初心者にとっては、それでも非常に必要です。

エフェクト図を見ると3つのカスタムウィジェットが作成されており、そのうちの1つをクリックすると、他の2つの背景色と文字色が変わり選択状態になります。

次に、レンダリングで表示される機能を、ナレッジポイントや落とし穴レコードも含めて 1 つずつ説明します。

この記事の特典として、Qt 開発学習教材パッケージ、技術ビデオ (C++ 言語基礎、C++ デザイン パターン、Q​​t プログラミング入門、QT シグナルとスロット メカニズム、QT インターフェイス開発イメージ描画、QT ネットワーク、QT など) を無料で受け取ることができます。データベースプログラミング、QTプロジェクト実戦、QSS、OpenCV、Quickモジュール、面接での質問など) ↓↓↓↓下記参照↓↓料金受け取りは記事下部をクリック↓↓

機能実現

カスタム相互排他ウィジェットを実装する過程で以下のような知識や問題に遭遇しましたが、遭遇した機能や必要な機能がないか確認してみましょう。

知識ポイント

1: ウィジェットのアナログ ボタンの 4 つの状態機能 (通常、押された、フォーカスされている、無効になっている)

2: Widgetカスタムクラスの背景色設定と文字内容スタイル設定

3: 複数のウィジェットで相互排他効果を実現する方法

質問

1: カスタム ウィジェットの背景色が有効にならないのはなぜですか?

上記の知識と問題点を踏まえて、この簡単な関数について話していきましょう!

知識ポイント 1 を説明する

ウィジェットの 4 状態関数を使用してボタンをシミュレートするには、ウィジェット自体のメッセージ (マウス ダウン、マウス イン、およびマウス アウト) を使用する必要があります。

virtual void mousePressEvent(QMouseEvent *event); //鼠标按下响应消息
virtual void enterEvent(QEvent *event); //鼠标进入响应消息
virtual void leaveEvent(QEvent *event); //鼠标离开响应消息

なぜmouseMoveEventメッセージがないのか尋ねる人はいますか?

回答: Qt で MouseMoveEvent メッセージを直接使用してマウスをトリガーすることはできません。現在のウィンドウでマウス トラッキング イベントを有効にするには SetMouseTracking(true) を設定する必要があります。

使用状況に応じてこの機能を設定する必要があるかどうか。現在の小規模なデモでは画像変換のみが行われており、mouseMove で常にリソースを消費する必要はありません。

(余談: MFC フレームワークの Mousemove イベントは、特別な設定を行わずに直接使用できます)

マウスがウィジェットに入ると、leaveEvent メッセージがトリガーされない限り、マウスはウィジェット内で常にアクティブであるとしてマークできます。

マウスダウン応答メッセージ

void QCustomWidget::mousePressEvent(QMouseEvent *event)
{
	this->SetWidgetStyle(Style_Down);
	QWidget::mousePressEvent(event);
}

現在採用されている列挙型: マウス プレス応答。

マウスがウィジェットの応答メッセージを入力します

void QCustomWidget::enterEvent(QEvent *event)
{
	this->SetWidgetStyle(Style_Focus);
	QWidget::enterEvent(event);
}

現在採用されている列挙型: マウス フォーカス状態。mousemove メッセージの代わりに Enter メッセージを使用します。

ログに記録すると、トリガー機能はマウスが入ったときに 1 回だけ実行され、ウィジェット内でマウスが動き続けた場合にはトリガーされないことがわかります。これにより、メッセージ処理が大幅に軽減されます。

マウスがウィジェットの応答メッセージを残す

void QCustomWidget::leaveEvent(QEvent *event)
{
	this->SetWidgetStyle(Style_Normal);
	QWidget::leaveEvent(event);
}

現在採用されている列挙型: マウス放置状態。

最も単純な放置設定を示しましたが、考慮すべき点の 1 つは、現在のウィジェットが押された状態にあり、この時点でマウスが離れた場合、ウィジェットはどのように表示されるべきかということです。

それでも普通のスタイルを見せたいですか?

答えは間違いなくNOです!

マウスが離れていますが、選択状態は通常の状態から押された状態に変わります。プログラムでは、現在のウィジェットが選択されているかどうかを記録するためにブール値変数を使用する必要があります。選択されている場合は、マウスを離したときに選択状態に変更する必要があります。

変更は次のようになります。

if (m_bClickedState == true)
{
	this->SetWidgetStyle(Style_Down);
}
else
	this->SetWidgetStyle(Style_Normal);

知識ポイント 2 を説明する

プログラムでは、シミュレーションの状態は列挙型で表現されます。

タイプ

説明する

スタイル_ノーマル

何も操作していないマウスの初期状態

スタイルダウン

ウィジェット内でマウスが押された

スタイルフォーカス

ウィジェット内でマウスを移動したときの動作状態

スタイル_無効化

現在のウィジェットは進行中です

各ウィジェットには同じ内容が表示されます: 数値、テキスト

単なる表示機能であるため、すべての QLabel コントロールが使用されます

QLabel *m_labNumber; //数値クラス ポインタ

QLabel *m_LabContent; //コンテンツクラスポインタ

対応する実際の処理

void QCustomWidget::SetWidgetStyle(ENUM_WidgetStyle enumStyle)
{
	//TODO:设置widget风格
	QString qsStyle = "", gStyleNumberNormal = "", gStyleContentNormal = "";
	switch (enumStyle)
	{
	case Style_Normal: //常态显示
	{
		//设置:背景
		qsStyle = "QWidget{background-color:#FFD700}";
		//设置:编号风格
		gStyleNumberNormal = "QLabel{color:#666666; font-family:Microsoft YaHei UI; font-size:14px;} QLabel{background-color: transparent}";
		//设置:内容风格
		gStyleContentNormal = "QLabel{color:#666666; font-family:Microsoft YaHei UI; font-size:14px;} QLabel{background-color: transparent}";
	}
		break;
	case Style_Down: //按下
	{
		//设置:背景
		qsStyle = "QWidget{background-color:#FFB6C1}";
		//设置:编号风格
		gStyleNumberNormal = "QLabel{color:#0000FF; font-family:Microsoft YaHei UI; font-size:14px;} QLabel{background-color: transparent}";
		//设置:内容风格
		gStyleContentNormal = "QLabel{color:#00FFFF; font-family:Microsoft YaHei UI; font-size:14px;} QLabel{background-color: transparent}";
	}
		break;
	case Style_Focus: //聚焦
	{
		//设置:背景
		qsStyle = "QWidget{background-color:#FFF0F5}";
		//设置:编号风格
		gStyleNumberNormal = "QLabel{color:#98FB98; font-family:Microsoft YaHei UI; font-size:14px;} QLabel{background-color: transparent}";
		//设置:内容风格
		gStyleContentNormal = "QLabel{color:#98FB98; font-family:Microsoft YaHei UI; font-size:14px;} QLabel{background-color: transparent}";
	}
		break;
	case Style_Disable: //禁用
	{
		//设置:背景
		qsStyle = "QWidget{background-color:#DCDCDC}";
		//设置:编号风格
		gStyleNumberNormal = "QLabel{color:#696969; font-family:Microsoft YaHei UI; font-size:14px;} QLabel{background-color: transparent}";
		//设置:内容风格
		gStyleContentNormal = "QLabel{color:#696969; font-family:Microsoft YaHei UI; font-size:14px;} QLabel{background-color: transparent}";
	}
		break;
	default:
		break;
	}
	this->setStyleSheet(qsStyle);
	m_labNumber->setStyleSheet(gStyleNumberNormal);
	m_labContent->setStyleSheet(gStyleContentNormal);
}

種類に応じて対応する背景スタイルも異なります。コードを取り込んで実行して効果を確認できます。それは私が示した効果と一致していますか?

ははは!試してみると、次のようになっていることがわかります。

テキストしか表示できないのですが、背景はどうなるのでしょうか? あなたは何処に行きましたか?もう設定してないんですか?

多くの Qt 初心者はここでこのような問題に遭遇するため、さまざまな検索モードを開いてさまざまな方法を試し、場合によっては単に変更を加えてこの問題を無視します。

カスタムウィジェットを作成する際、一般的なメソッドは new インスタンスメソッドを使用しますが、new の処理では階層関係を管理し親子関係を明確にするため、新規ウィジェットの親ポインタとしてこれを渡します。作成されたウィンドウ。

this ポインターを渡し、カスタム ウィジェットで何も処理を行わないと、この時点でこれが発生します。

サブクラスは親ウィンドウのスタイルを継承します。

一般に、この状況が発生した場合、これに対処する方法は 2 つあります。1 つは現在のウィンドウのPaintEvent 関数を書き換える方法、もう 1 つは親ウィンドウに従わないようにスタイルを設定する方法です。

便宜上、ウィンドウによって描画される背景画像が複雑でない場合は 2 番目の方法が使用されます。

this->setAttribute(Qt::WA_StyledBackground);

現在のカスタム ウィジェット クラスのコンストラクターに上記のコードを設定すると、背景スタイルを設定しても表示されないという以前の問題は解決されます。

知識ポイント 3 を説明する

複数のウィジェット間で相互排他を実現するにはどうすればよいですか?

QRadioButton コントロールを使用したことがある人なら誰でも、このコントロールには相互排他を設定するための簡単な設定関数のみが必要であることがわかります。

カスタム ウィジェットにはそのような機能はなく、相互排他効果はコードで手動で設定することのみが可能で、対応する表示効果は選択状態と選択解除状態に応じて置き換えられます。

現在「コンテンツ 1」のカスタム ウィジェットが選択されているとします。このとき、現在のカスタム ウィジェットが押されたことを外部に通知するために、ウィジェット内のマウス プレス応答でメッセージをトリガーする必要があり、特別な処理が行われます。必要。

void QCustomWidget::mousePressEvent(QMouseEvent *event)
{
	this->SetWidgetStyle(Style_Down);
	emit Msg_SendClicked();
	QWidget::mousePressEvent(event);
}

カスタム ウィジェットを呼び出す親クラスの対応するスロット関数に応答して特別な処理を実行します。

この時点で、カスタム ウィジェットの相互排他効果を簡単に実現できます。

相互排他操作の実装は非常に簡単で、習得する最も重要なことは、ウィジェットの背景の設定方法です。

多くの場合、子ウィンドウと親ウィンドウの間にネストされたレベルが多すぎる場合、この種の問題が発生する可能性が最も高くなります。新しいウィジェット オブジェクトを作成するたびに、親ウィンドウのスタイルに従わないことが最善の方法となるからです。毎回窓。

この記事の特典として、Qt 開発学習教材パッケージ、技術ビデオ (C++ 言語基礎、C++ デザイン パターン、Q​​t プログラミング入門、QT シグナルとスロット メカニズム、QT インターフェイス開発イメージ描画、QT ネットワーク、QT など) を無料で受け取ることができます。データベースプログラミング、QTプロジェクト実戦、QSS、OpenCV、Quickモジュール、面接での質問など) ↓↓↓↓下記参照↓↓料金受け取りは記事下部をクリック↓↓

おすすめ

転載: blog.csdn.net/m0_60259116/article/details/130584962