;;
はじめての Qt Creator - 部品化 - カスタムウィジェット
(掲載 2024年3月21日)
カスタムウィジェットのフォーム編集について一通りの基本的な事項を説明しました。今回と次回は、部品として使うために必要なことを説明します。
プロパティー定義
部品化のために必要な処理を実装します。まず、プロパティー定義です。ヘッダーに以降のコードを追加します。
設定されている色を返すゲッターです。
public slots:
void setColor(const QColor& newColor);
色を設定するセッターで、スロットとして宣言します。
Q_PROPERTY(QColor color READ color WRITE setColor)
宣言したゲッターとセッターを使って、色のプロパティーを定義します。このようにしておくと、
プラグイン化して、ウィジェットボックスに配置して扱えるようにしたときに、プロパティーエディターで色の値を設定できるようになります。
シグナルとスロット
Qt 側が実装コードを生成するので、シグナルは宣言するだけです。スロットを実装します。
.
色のプレビューを更新するヘルパー関数を用意します。
private:
void updatePreviewColor(const QColor& newColor);
void ColorPreview::updatePreviewColor(const QColor &newColor)
{
auto colorFramePalette = colorFrame->palette();
colorFramePalette.setColor(QPalette::Window, newColor);
colorFrame->setPalette(colorFramePalette);
}
コンストラクターでは、スライダーを動かしたときに、ヘルパー関数を呼び出して、シグナルを送信するようにします。
ColorPreview::ColorPreview(QWidget *parent)
: QWidget(parent)
{
setupUi(this);
colorFrame->setAutoFillBackground(true);
updatePreviewColor(color());
const auto sliderMoved = [this]() {
updatePreviewColor(color());
emit colorChanged(color());
};
connect(redSlider, &QSlider::valueChanged, sliderMoved);
connect(greenSlider, &QSlider::valueChanged, sliderMoved);
connect(blueSlider, &QSlider::valueChanged, sliderMoved);
connect(alphaSlider, &QSlider::valueChanged, sliderMoved);
}
ゲッターの実装です。色の構成要素はスライダーに保持されているので、色をメンバー変数で保持せずに、スライダーの値から色を求めています。
QColor ColorPreview::color() const
{
return QColor(redSlider->value(), greenSlider->value(), blueSlider->value(), alphaSlider->value());
}
スロットとしてのセッターの実装です。
void ColorPreview::setColor(const QColor &newColor)
{
if (newColor == color()) {
return;
}
redSlider->setValue(newColor.red());
greenSlider->setValue(newColor.green());
blueSlider->setValue(newColor.blue());
alphaSlider->setValue(newColor.alpha());
updatePreviewColor(newColor);
emit colorChanged(newColor);
}
部品化のためのレイアウト調整
今迄のフォーム編集では、フォームの最上ウィジェットのレイアウトにマージンがデフォルトで設定されています。このマージンがあると、部品として使うときに余分な空白がウィジェットの周りに常に取られてしまいます。最上位ウィジェットをプロパティーエディターで表示し、最下部にスクロールすると最上レイアウトのプロパティーが表示されます。layoutLeftMargin、layoutTopMargin、layoutRightMargin、layoutBottomMargin の各マージンを 0 に設定します。
ヘッダーの完全なコードは以降のようになります。
#ifndef COLORPREVIEW_H
#define COLORPREVIEW_H
#include "ui_colorpreview.h"
#include <QWidget>
class ColorPreview : public QWidget, private Ui::ColorPreview
{
Q_OBJECT
Q_PROPERTY(QColor color READ color WRITE setColor)
public:
ColorPreview(QWidget *parent = nullptr);
~ColorPreview();
QColor color() const;
signals:
void colorChanged(const QColor& newColor);
public slots:
void setColor(const QColor& newColor);
private:
void updatePreviewColor(const QColor& newColor);
};
#endif // COLORPREVIEW_H
実装部の完全なコードは以降のようになります。
#include "colorpreview.h"
ColorPreview::ColorPreview(QWidget *parent)
: QWidget(parent)
{
setupUi(this);
colorFrame->setAutoFillBackground(true);
updatePreviewColor(color());
const auto sliderMoved = [this]() {
updatePreviewColor(color());
emit colorChanged(color());
};
connect(redSlider, &QSlider::valueChanged, sliderMoved);
connect(greenSlider, &QSlider::valueChanged, sliderMoved);
connect(blueSlider, &QSlider::valueChanged, sliderMoved);
connect(alphaSlider, &QSlider::valueChanged, sliderMoved);
}
ColorPreview::~ColorPreview()
{
}
QColor ColorPreview::color() const
{
return QColor(redSlider->value(), greenSlider->value(), blueSlider->value(), alphaSlider->value());
}
void ColorPreview::setColor(const QColor &newColor)
{
if (newColor == color()) {
return;
}
redSlider->setValue(newColor.red());
greenSlider->setValue(newColor.green());
blueSlider->setValue(newColor.blue());
alphaSlider->setValue(newColor.alpha());
updatePreviewColor(newColor);
emit colorChanged(newColor);
}
void ColorPreview::updatePreviewColor(const QColor &newColor)
{
auto colorFramePalette = colorFrame->palette();
colorFramePalette.setColor(QPalette::Window, newColor);
colorFrame->setPalette(colorFramePalette);
}
動作確認のために、ColorPreview を 2 つ並べて、シグナルとスロットを接続し、実行すると以下のようになります。
次回は、リファクタリングの後にプラグイン化して、Qt Designer と Qt Creator のフォーム編集のウィジェットボックスに配置して、既存のウィジェット同じように扱えるようにします。