質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Qt

QtはGUIプログラムの開発で広く使われているクロスプラットフォーム開発のフレームワークです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

1348閲覧

Qt5の自作ウィジェットにStyleSheetのための独自属性を設けたい。背景色はこの自作ウィジェットを利用する人に決めさせてあげたい

jiro.kaihatsu

総合スコア16

Qt

QtはGUIプログラムの開発で広く使われているクロスプラットフォーム開発のフレームワークです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/11/23 00:40

Qt5で3つの状態により背景色を変えて見せるQLabel派生の自作ウィジェットを作成しました。

ざっと次のようになります。

c++

1#include <QLabel> 2 3class StatusIndicator : public QLabel 4{ 5Q_OBJECT 6public: 7 enum class Status { 8 Unknown, // 不明 9 Normal, // 正常 10 Error // 異常 11 }; 12 13public: 14 explicit StatusIndicator(const Status &initStatus = Status::Unknown, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); 15 16 Status status(); 17 void setStatus(const Status &status); // 状態が変わったら背景色も変えたい。色はクライアントに任意にしたい 18 19private: 20 Status _status{Status::Unknown}; 21 22private: 23 24 QString generateText(const Status &status); 25}; 26

現時点、3つの状態に対応するbackgroud-colorはハードコーディングで決め打ちです。これだといまいちなので改良しようと考えています。

改良として、このクラスを利用する側(クライアントと呼びます)に任意として、状態に対応する背景色をそれぞれ設定できるようにしたいのですが、その方法がわかりません。

(1) 自作ウィジェットにQt5スタイルシートで認識できる独自属性を設けることはできるのでしょうか?できるとして、どうすれば良いのでしょうか?

(2) 独自属性の値(先述のクラスであればNormal/Error)に基づきbackground-colorを変更する方法はないものでしょうか。

イメージとしては、次のように背景色の変更ができるようにしたいです。

c++

1auto label = StatusIndicator(StatusIndicator::Status::Normal, this); 2// StatusIndicatorのstatus属性がNormalの時は背景をLime色にしたい 3label->setStyleSheet("StatusIndicator::_status:Normal {background-color: Lime;"}); 4// StatusIndicatorのstatus属性がErrorの時は背景をOrangeRed色にしたい 5label->setStyleSheet("StatusIndicator::_status:Error {background-color: OrangeRed;"}); 6/* 7 * (補足)このコードでは色を変更することができません 8 */

念の為コードを掲載しておきます。

c++

1#include <QtGlobal> 2 3#include "GStatusIndicator.h" 4 5 6GStatusIndicator::GStatusIndicator(const Status &initStatus, QWidget *parent, Qt::WindowFlags f) 7 :QLabel(generateText(initStatus), parent, f) 8{ 9 setFrameShape(QFrame::Panel); 10 setFrameShadow(QFrame::Sunken); 11} 12 13GStatusIndicator::Status GStatusIndicator::status() 14{ 15 return _status; 16} 17 18/* 19 * 背景色が固定で変更できないのはいまいち 20 */ 21void GStatusIndicator::setStatus(const Status &status) 22{ 23 if (status != _status) 24 { 25 _status = status; 26 setText(generateText(_status)); // 正常 or 異常 or 不明 27 28 switch (_status) 29 { 30 case Status::Normal: 31 { 32 setStyleSheet("background-color: lime;"); 33 break; 34 } 35 36 case Status::Error: 37 { 38 setStyleSheet("background-color: OrangeRed;"); 39 break; 40 } 41 42 default: 43 { 44 setStyleSheet("background-color: lightgrey;"); 45 break; 46 } 47 } 48 } 49} 50 51QString GStatusIndicator::generateText(const Status &status) 52{ 53 switch (status) 54 { 55 case Status::Unknown: 56 return {"不明"}; 57 58 case Status::Normal: 59 return {"正常"}; 60 61 case Status::Error: 62 return {"異常"}; 63 64 default: 65 Q_ASSERT_X(false, __func__, QString("Invalid status=%1").arg(static_cast<int>(status)).toStdString().c_str()); 66 break; 67 } 68}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

statusをプロパティとして定義すればセレクタで指定できました。
enumのままだと数値でしか指定できないみたいなので、文字列としてプロパティにしています。

cpp

1class StatusIndicator : public QLabel 2{ 3 Q_OBJECT 4 // こっちだと数値で指定 5 //Q_PROPERTY(Status status READ status WRITE setStatus) 6 Q_PROPERTY(QString status MEMBER _statusText) 7 8public: 9 enum class Status { 10 Unknown, // 不明 11 Normal, // 正常 12 Error // 異常 13 }; 14 Q_ENUM(Status); 15 16public: 17 explicit StatusIndicator(QWidget* parent= nullptr) : QLabel(parent) {} 18 19 Status status() const { return _status; } 20 void setStatus(const Status &status) { 21 _status = status; 22 if (_status == Status::Unknown) { _statusText = "Unknown"; } 23 else if (_status == Status::Normal) { _statusText = "Normal"; } 24 else if (_status == Status::Error) { _statusText = "Error"; } 25 setText(_statusText); 26 } 27 28private: 29 Status _status{Status::Unknown}; 30 QString _statusText; 31};

cpp

1MainWindow::MainWindow(QWidget *parent) 2 : QMainWindow(parent) 3 , ui(new Ui::MainWindow) 4{ 5 ui->setupUi(this); 6 7 auto indicator1 = new StatusIndicator(ui->centralwidget); 8 auto indicator2 = new StatusIndicator(ui->centralwidget); 9 auto indicator3 = new StatusIndicator(ui->centralwidget); 10 11// 数値の場合 12// auto ss = R"( 13//StatusIndicator[status="0"] { background-color: Pink; } 14//StatusIndicator[status="1"] { background-color: Lime; } 15//StatusIndicator[status="2"] { background-color: OrangeRed; } 16//)"; 17 18 auto ss = R"( 19StatusIndicator[status="Unknown"] { background-color: Pink; } 20StatusIndicator[status="Normal"] { background-color: Lime; } 21StatusIndicator[status="Error"] { background-color: OrangeRed; } 22)"; 23 24 indicator1->setStyleSheet(ss); 25 indicator2->setStyleSheet(ss); 26 indicator3->setStyleSheet(ss); 27 28 auto button = new QPushButton("Change"); 29 connect(button, &QPushButton::clicked, this, [=] { 30 indicator1->setStatus(StatusIndicator::Status::Error); 31 indicator2->setStatus(StatusIndicator::Status::Unknown); 32 indicator3->setStatus(StatusIndicator::Status::Normal); 33 }); 34 35 auto layout = new QVBoxLayout(ui->centralwidget); 36 layout->addWidget(indicator1); 37 layout->addWidget(indicator2); 38 layout->addWidget(indicator3); 39 layout->addWidget(button); 40 layout->addStretch(1); 41 42 indicator1->setStatus(StatusIndicator::Status::Unknown); 43 indicator2->setStatus(StatusIndicator::Status::Normal); 44 indicator3->setStatus(StatusIndicator::Status::Error); 45}

投稿2021/11/27 09:05

mah

総合スコア591

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jiro.kaihatsu

2021/11/27 23:34

アドバイスありがとうございました。 お陰様でQColor型のプロパティを持つことを止めて、文字列型(または整数)で持つとイメージ通りのStatusIndicatorにすることができました。 (追伸) 私の手元では1行追加しました。 void StatusIndicator::setStatus(const Status &status) { _status = status; if (_status == Status::Unknown) { _statusText = "Unknown"; } else if (_status == Status::Normal) { _statusText = "Normal"; } else if (_status == Status::Error) { _statusText = "Error"; } setText(_statusText); style()->polish(this);  // 追加 }
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問