タスクメニュー拡張
Qt Widgets Designer 用のカスタムウィジェットプラグインを作成し、プラグインに関連付けられたカスタムタスクメニューエントリを提供します。
Task Menu Extension の例では、Qt Widgets Designer 用のカスタムウィジェットプラグインの作成方法と、QDesignerTaskMenuExtension クラスを使用してプラグインに関連付けられたカスタムタスクメニューエントリを提供する方法を示します。
Qt Widgets Designerで使用できるカスタムウィジェットを提供するには、自己完結型の実装を提供する必要があります。この例では、タスクメニュー拡張機能を表示するように設計されたカスタムウィジェットを使用します:TicTacToe ウィジェットです。
拡張機能とは、Qt Widgets Designerの動作を変更するオブジェクトです。QDesignerTaskMenuExtension は、この拡張機能を持つウィジェットが選択されたときに、カスタムタスクメニューエントリを提供できます。
Qt Widgets Designerには、4種類の拡張機能があります:
- QDesignerContainerExtension Qt Widgets Designer のマルチページ・コンテナ・プラグインにページを追加(および削除)できる拡張機能。
- QDesignerMemberSheetExtension Qt Widgets Designerのシグナルとスロットの編集モードを使用して接続を構成するときに表示されるウィジェットのメンバ関数を操作できる拡張機能。
- QDesignerPropertySheetExtension Qt Widgets Designer のプロパティエディタで表示されるウィジェットのプロパティを操作できる拡張機能を提供します。
- QDesignerTaskMenuExtension Qt Widgets Designerのタスクメニューにカスタムメニューエントリを追加できる拡張機能。
この例と同じパターンに従って、それぞれの拡張機能ベースクラスを置き換えるだけで、すべての拡張機能を使用できます。詳細については、Qt Widgets Designer C++ Classes を参照してください。
タスクメニュー・エクステンションの例は、5つのクラスで構成されています:
TicTacToe
は、ユーザーに三目並べゲームをプレイさせるカスタムウィジェットです。TicTacToePlugin
TicTacToe
クラスを Qt Widgets Designer に公開します。TicTacToeTaskMenuFactory
TicTacToeTaskMenu
オブジェクトを作成します。TicTacToeTaskMenu
タスクメニューの拡張、つまりプラグインに関連するタスクメニューのエントリを提供します。TicTacToeDialog
Qt Widgets DesignerにロードされたTic-Tac-Toeプラグインの状態を変更します。
カスタムウィジェットプラグインのプロジェクトファイルには、Qt Widgets Designer内で確実に動作するための追加情報が必要です。例えば、カスタムウィジェットプラグインはQt Widgets Designerで提供されるコンポーネントに依存しており、使用するプロジェクトファイルでこれを指定する必要があります。まず、プラグインのプロジェクトファイルを見てみましょう。
続いて、TicTacToePlugin
クラスを確認し、TicTacToeTaskMenuFactory
とTicTacToeTaskMenu
クラスを見ていきます。最後に、TicTacToe
ウィジェットのクラス定義を簡単に見る前に、TicTacToeDialog
クラスを確認します。
プロジェクト・ファイル
CMake
プロジェクトファイルには、Qt Widgets Designer ライブラリにリンクするプラグインをビルドすることを記述する必要があります:
find_package(Qt6 REQUIRED COMPONENTS Core Designer Gui Widgets) qt_add_plugin(taskmenuextension) target_link_libraries(taskmenuextension PUBLIC Qt::Core Qt::Designer Qt::Gui Qt::Widgets )
次の例では、ウィジェットのヘッダーファイルとソースファイルを追加する方法を示します:
target_sources(taskmenuextension PRIVATE tictactoe.cpp tictactoe.h tictactoedialog.cpp tictactoedialog.h tictactoeplugin.cpp tictactoeplugin.h tictactoetaskmenu.cpp tictactoetaskmenu.h )
Qt Widgets Designerがカスタムウィジェットを使用できるように、プラグイン・インターフェースの実装を提供します。この例では、タスクメニュー拡張と拡張ファクトリ、ダイアログの実装も提供します。
Qt Widgets Designerが検索できる場所にプラグインをインストールすることが重要です。プロジェクトのターゲットパスを指定し、インストールするアイテムのリストに追加することでこれを行います:
set(INSTALL_EXAMPLEDIR "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_PLUGINS}/designer") install(TARGETS taskmenuextension RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" )
タスクメニュー拡張はライブラリとして作成されます。タスクメニュー拡張機能はライブラリとして作成され、プロジェクトのインストール時に他の Qt Widgets Designer プラグインと一緒にインストールされます(ninja install
または同等のインストール手順を使用)。
プラグインの詳細については、How to Create Qt Pluginsドキュメントを参照してください。
qmake
次の例は、プラグインを Qt Widgets Designer ライブラリにリンクする方法を示しています:
TEMPLATE = lib CONFIG += plugin QT += widgets designer
次の例では、ウィジェットのヘッダーファイルとソースファイルを追加する方法を示します:
HEADERS += tictactoe.h \ tictactoedialog.h \ tictactoeplugin.h \ tictactoetaskmenu.h SOURCES += tictactoe.cpp \ tictactoedialog.cpp \ tictactoeplugin.cpp \ tictactoetaskmenu.cpp OTHER_FILES += tictactoe.json
次の例は、プラグインを Qt Widgets Designer のプラグインパスにインストールする方法を示しています:
target.path = $$[QT_INSTALL_PLUGINS]/designer INSTALLS += target
TicTacToePluginクラスの定義
TicTacToePlugin
クラスは、the
TicTacToe クラスを Qt Widgets Designer に公開します。その定義はCustom Widget Pluginの例のプラグインクラスと同じです。クラス定義のうち、この特定のカスタムウィジェットに固有の部分はクラス名だけです。
Qt がウィジェットをプラグインとして認識するように、Q_PLUGIN_METADATA()
マクロを追加して、ウィジェットに関する関連情報をエクスポートします:
#ifndef TICTACTOEPLUGIN_H #define TICTACTOEPLUGIN_H #include <QtUiPlugin/QDesignerCustomWidgetInterface> class QIcon; class QWidget; class TicTacToePlugin : public QObject, public QDesignerCustomWidgetInterface { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface") Q_INTERFACES(QDesignerCustomWidgetInterface) public: explicit TicTacToePlugin(QObject *parent = nullptr); QString name() const override; QString group() const override; QString toolTip() const override; QString whatsThis() const override; QString includeFile() const override; QIcon icon() const override; bool isContainer() const override; QWidget *createWidget(QWidget *parent) override; bool isInitialized() const override; void initialize(QDesignerFormEditorInterface *formEditor) override; QString domXml() const override; private: bool initialized = false; }; #endif
プラグインクラスは、クラス名やインクルードファイルなど、プラグインの基本情報を Qt Widgets Designer に提供します。さらに、TicTacToe
ウィジェットのインスタンスを作成する方法も知っています。TicTacToePluginは、プラグインがQt Widgets Designerにロードされた後に呼び出されるinitialize ()関数も定義します。この関数のQDesignerFormEditorInterface パラメータは、Qt Widgets Designer のすべての API へのゲートウェイをプラグインに提供します。
TicTacToePlugin
クラスは、QObject とQDesignerCustomWidgetInterface の両方を継承します。多重継承を使用する場合、Q_INTERFACES() マクロを使用して、すべてのインターフェイス(つまり、Q_OBJECT を継承しないクラス)をメタオブジェクトシステムに知らせることが重要です。これにより、Qt Widgets Designerは、qobject_cast()を使用して、QObject ポインタだけを使用して、サポートされているインターフェイスを問い合わせることができます。
TicTacToePluginクラスの実装
TicTacToePluginクラスの実装は、ほとんどの部分でCustom Widget Pluginサンプルのプラグインクラスと同等です:
TicTacToePlugin::TicTacToePlugin(QObject *parent) : QObject(parent) { } QString TicTacToePlugin::name() const { return u"TicTacToe"_s; } QString TicTacToePlugin::group() const { return u"Display Widgets [Examples]"_s; } QString TicTacToePlugin::toolTip() const { return u"Tic Tac Toe Example, demonstrating class QDesignerTaskMenuExtension (C++)"_s; } QString TicTacToePlugin::whatsThis() const { return {}; } QString TicTacToePlugin::includeFile() const { return u"tictactoe.h"_s; } QIcon TicTacToePlugin::icon() const { return {}; } bool TicTacToePlugin::isContainer() const { return false; } QWidget *TicTacToePlugin::createWidget(QWidget *parent) { auto *ticTacToe = new TicTacToe(parent); ticTacToe->setState(u"-X-XO----"_s); return ticTacToe; } bool TicTacToePlugin::isInitialized() const { return initialized; }
大きく異なる唯一の関数は、initialize()関数です:
void TicTacToePlugin::initialize(QDesignerFormEditorInterface *formEditor) {
initialize()
関数はQDesignerFormEditorInterface オブジェクトを引数にとります。QDesignerFormEditorInterface クラスは Qt Widgets Designer のコンポーネントへのアクセスを提供します。
Qt Widgets Designerでは、カスタムウィジェットプラグインとツールプラグインの2種類のプラグインを作成できます。QDesignerFormEditorInterface 、通常ツールプラグインを作成するために必要なQt Widgets Designerのすべてのコンポーネント(拡張機能マネージャ、オブジェクトインスペクタ、プロパティエディタ、ウィジェットボックス)にアクセスできます。カスタムウィジェットプラグインも同じコンポーネントにアクセスできます。
if (initialized) return; auto *manager = formEditor->extensionManager(); Q_ASSERT(manager != nullptr);
カスタムウィジェットプラグインに関連する拡張機能を作成する場合、QDesignerFormEditorInterface パラメータから取得した Qt Widgets Designer の現在の拡張機能マネージャにアクセスする必要があります。
Qt Widgets Designer のQDesignerFormEditorInterface には、Qt Designer のすべてのコンポーネントに関する情報が格納されています:アクションエディタ、オブジェクトインスペクタ、プロパティエディタ、ウィジェットボックス、拡張機能およびフォームウィンドウマネージャです。
QExtensionManager クラスは Qt Widgets Designer の拡張管理機能を提供します。Qt Widgets Designerの現在の拡張機能マネージャを使用すると、指定したオブジェクトの拡張機能を取得できます。また、与えられたオブジェクトの拡張機能を登録したり解除したりすることもできます。拡張機能はQt Widgets Designerの動作を変更するオブジェクトです。
拡張機能を登録する場合、実際に登録されるのは関連する拡張機能ファクトリです。Qt Widgets Designerでは、拡張機能ファクトリは必要に応じて名前の付いた拡張機能を検索し、作成するために使用されます。したがって、この例では、タスクメニューの拡張機能自体は、ユーザーによってタスクメニューが要求されるまで作成されません。
manager->registerExtensions(new TicTacToeTaskMenuFactory(manager), Q_TYPEID(QDesignerTaskMenuExtension)); initialized = true; } QString TicTacToePlugin::domXml() const { return uR"( <ui language="c++"> <widget class="TicTacToe" name="ticTacToe"/> <customwidgets> <customwidget> <class>TicTacToe</class> <propertyspecifications> <tooltip name="state">Tic Tac Toe state</tooltip> <stringpropertyspecification name="state" notr="true" type="singleline"/> </propertyspecifications> </customwidget> </customwidgets> </ui> )"_s; }
QDesignerFormEditorInterface パラメータから取得した Qt Widgets Designer の現在のextension manager を使用して登録するTicTacToeTaskMenuFactory
オブジェクトを作成します。最初の引数は新しく作成されたファクトリーで、2番目の引数は文字列である拡張識別子です。Q_TYPEID()
マクロは単に文字列をQLatin1String に変換します。
TicTacToeTaskMenuFactory
クラスはQExtensionFactory のサブクラスです。ユーザが指定されたタスクメニュー拡張機能を持つウィジェットの上でマウスの右ボタンをクリックしてタスクメニューを要求すると、Qt Widgets Designer の拡張機能マネージャは登録されたすべてのファクトリーを実行し、選択されたウィジェットのタスクメニュー拡張機能を作成できる最初のファクトリーを呼び出します。このファクトリーはTicTacToeTaskMenu
オブジェクト(拡張機能)を作成します。
デフォルト値は必要ないので、QDesignerCustomWidgetInterface::domXml() 関数 (Qt Widgets Designer で使用される標準 XML フォーマットのウィジェットのデフォルト設定を含む) の再実装は省略します。
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface")
最後に、Q_PLUGIN_METADATA()マクロを使用して、Qtのプラグイン処理クラスで使用するためにTicTacToePluginクラスをエクスポートします:このマクロは、Qt Widgets Designerがカスタムウィジェットにアクセスして構築できるようにします。このマクロがないと、Qt Widgets Designerはウィジェットを使用できません。
TicTacToeTaskMenuFactory クラスの定義
TicTacToeTaskMenuFactory
クラスは、Qt Widgets Designer の標準拡張ファクトリを提供するQExtensionFactory を継承します。
class TicTacToeTaskMenuFactory : public QExtensionFactory { Q_OBJECT public: explicit TicTacToeTaskMenuFactory(QExtensionManager *parent = nullptr); protected: QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const override; };
このサブクラスの目的は、QExtensionFactory::createExtension() 関数を再実装し、TicTacToe
タスクメニュー拡張機能を作成できるようにすることです。
TicTacToeTaskMenuFactory クラスの実装
クラスのコンストラクタは、QExtensionFactory ベースクラスのコンストラクタを呼び出すだけです:
TicTacToeTaskMenuFactory::TicTacToeTaskMenuFactory(QExtensionManager *parent) : QExtensionFactory(parent) { }
上述したように、Qt Widgets Designerで指定されたタスクメニュー拡張機能を持つウィジェットの上でマウスの右ボタンをクリックして、ユーザがタスクメニューを要求すると、ファクトリーが呼び出されます。
Qt Widgets Designerの動作は、要求された拡張機能がコンテナ、メンバーシート、プロパティシート、タスクメニューのいずれに関連付けられていても同じです:拡張機能マネージャは、登録されているすべての拡張機能ファクトリを実行し、要求された拡張機能を作成するまでcreateExtension()
を呼び出します。
QObject *TicTacToeTaskMenuFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const { if (iid != Q_TYPEID(QDesignerTaskMenuExtension)) return nullptr; if (auto *tic = qobject_cast<TicTacToe*>(object)) return new TicTacToeTaskMenu(tic, parent); return nullptr; }
したがって、TicTacToeTaskMenuFactory::createExtension()
で最初にすることは、要求された拡張機能がタスクメニュー拡張機能かどうかをチェックすることです。もしそうで、要求しているウィジェットがTicTacToe
ウィジェットなら、TicTacToeTaskMenu
オブジェクトを作成して返します。そうでない場合は、単に null ポインタを返し、Qt Widgets Designer の拡張機能マネージャが登録されたファクトリの検索を続行できるようにします。
TicTacToeTaskMenu クラスの定義
TicTacToeTaskMenu
クラスは、Qt Widgets Designer のタスクメニューにカスタムエントリ(QActions の形式)を追加できるQDesignerTaskMenuExtension を継承しています。
class TicTacToeTaskMenu : public QObject, public QDesignerTaskMenuExtension { Q_OBJECT Q_INTERFACES(QDesignerTaskMenuExtension) public: explicit TicTacToeTaskMenu(TicTacToe *tic, QObject *parent); QAction *preferredEditAction() const override; QList<QAction *> taskActions() const override; private slots: void editState(); private: QAction *editStateAction; TicTacToe *ticTacToe; };
preferredEditAction()
とtaskActions()
関数を再実装します。親ウィジェットと、タスクメニューが要求されるTicTacToe
ウィジェットの2 つの引数を取るコンストラクタを実装します。
さらに、editState()
のプライベートスロット、editStateAction
のカスタムスロット、TicTacToe
ウィジェットへのプライベートポインタを宣言します。
TicTacToeTaskMenuクラスの実装
TicTacToeTaskMenu::TicTacToeTaskMenu(TicTacToe *tic, QObject *parent) : QObject(parent) , editStateAction(new QAction(tr("Edit State..."), this)) , ticTacToe(tic) { connect(editStateAction, &QAction::triggered, this, &TicTacToeTaskMenu::editState); }
コンストラクタでは、まずパラメータとして送られたTicTacToe
ウィジェット、つまり変更したい状態のウィジェットへの参照を保存します。これは後でカスタムアクションを呼び出すときに必要になります。また、カスタムeditStateAction
を作成し、editState()
スロットに接続します。
void TicTacToeTaskMenu::editState() { TicTacToeDialog dialog(ticTacToe); dialog.exec(); }
editState()
スロットは、ユーザがTicTacToe
ウィジェットのタスクメニューでEdit State...オプションを選択するたびに呼び出されます。このスロットは、ウィジェットの現在の状態を表示するTicTacToeDialog
を作成し、ユーザがゲームをプレイすることで状態を編集できるようにします。
QAction *TicTacToeTaskMenu::preferredEditAction() const { return editStateAction; }
preferredEditAction()
関数を再実装して、TicTacToe
ウィジェットを選択してF2を押したときに呼び出されるアクションとして、独自のeditStateAction
を返します。
QList<QAction *> TicTacToeTaskMenu::taskActions() const { return QList<QAction *>{editStateAction}; }
taskActions()
関数を再実装して、カスタムアクションのリストを返し、TicTacToe
ウィジェットのタスクメニューのデフォルトメニューエントリの上に表示します。
TicTacToeDialogクラスの定義
TicTacToeDialog
クラスはQDialog を継承しています。このダイアログによって、ユーザーは現在選択されているTic-Tac-Toeプラグインの状態を修正できます。
class TicTacToeDialog : public QDialog { Q_OBJECT public: explicit TicTacToeDialog(TicTacToe *plugin = nullptr, QWidget *parent = nullptr); QSize sizeHint() const override; private slots: void resetState(); void saveState(); private: TicTacToe *editor; TicTacToe *ticTacToe; QDialogButtonBox *buttonBox; };
sizeHint()
関数を再実装します。また、resetState()
とsaveState()
の2つのプライベートスロットを宣言します。ダイアログのボタンとレイアウトに加えて、TicTacToe
の2つのポインタを宣言します。1つは、ユーザが対話できるウィジェットへのポインタ、もう1つは、ユーザが状態を編集したい元のカスタムウィジェットプラグインへのポインタです。
TicTacToeDialogクラスの実装
TicTacToeDialog::TicTacToeDialog(TicTacToe *tic, QWidget *parent) : QDialog(parent) , editor(new TicTacToe) , ticTacToe(tic) , buttonBox(new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Reset)) { editor->setState(ticTacToe->state()); connect(buttonBox->button(QDialogButtonBox::Reset), &QAbstractButton::clicked, this, &TicTacToeDialog::resetState); connect(buttonBox, &QDialogButtonBox::accepted, this, &TicTacToeDialog::saveState); connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); auto *mainLayout = new QVBoxLayout(this); mainLayout->addWidget(editor); mainLayout->addWidget(buttonBox); setWindowTitle(tr("Edit State")); }
コンストラクタでは、まずパラメータとして送られたTicTacToeウィジェットへの参照を保存します。次に、新しいTicTacToe
ウィジェットを作成し、その状態をパラメータ・ウィジェットの状態と同じに設定します。
最後に、ダイアログのボタンとレイアウトを作成します。
QSize TicTacToeDialog::sizeHint() const { return {250, 250}; }
sizeHint()
関数を再実装して、ダイアログが適切なサイズになるようにします。
void TicTacToeDialog::resetState() { editor->clearBoard(); }
resetState()
スロットは、ユーザーがリセットボタンを押すたびに呼び出されます。エディタウィジェット、つまりダイアログのコンストラクタで作成したTicTacToe
ウィジェットに対してclearBoard()
関数を呼び出すだけです。
void TicTacToeDialog::saveState() {
saveState()
スロットは、ユーザがOKボタンを押すたびに呼び出され、エディタ・ウィジェットの状態を変更したいウィジェットに転送します。状態の変更を Qt Widgets Designer に見えるようにするには、QDesignerFormWindowInterface クラスを使用して後者のウィジェットの state プロパティを設定する必要があります。
QDesignerFormWindowInterface は、関連するフォーム・ウィンドウに関する情報を提供し、そのプロパティを変更できるようにします。このインターフェイスは直接インスタンス化することを意図しておらず、Qt Widgets Designerのフォームウィンドウマネージャによって制御されるQt Widgets Designerの現在のフォームウィンドウへのアクセスを提供します。
特定のウィジェットを含むフォーム・ウィンドウを探す場合は、staticQDesignerFormWindowInterface::findFormWindow() 関数を使用できます:
if (auto *formWindow = QDesignerFormWindowInterface::findFormWindow(ticTacToe)) formWindow->cursor()->setProperty("state", editor->state());
変更したいウィジェットのフォーム・ウィンドウを取得した後、QDesignerFormWindowInterface::cursor() 関数を使用してフォーム・ウィンドウのカーソルを取得します。
QDesignerFormWindowCursorInterface クラスは、フォーム・ウィンドウのテキスト・カーソルへのインタフェースを提供します。カーソルを取得したら、最後にQDesignerFormWindowCursorInterface::setProperty ()関数を使ってstateプロパティを設定します。
accept(); }
最後に、イベント・オブジェクトのacceptフラグを設定するQEvent::accept ()関数を呼び出します。accept
パラメータを設定することは、イベント受信者がイベントを望んでいることを示す。不要なイベントは、親ウィジェットに伝搬される可能性があります。
TicTacToe クラスの定義
TicTacToe
クラスは、ユーザが三目並べゲームをプレイできるカスタムウィジェットです。
class TicTacToe : public QWidget { Q_OBJECT Q_PROPERTY(QString state READ state WRITE setState) public: explicit TicTacToe(QWidget *parent = nullptr); QSize minimumSizeHint() const override; QSize sizeHint() const override; void setState(const QString &newState); QString state() const; void clearBoard(); protected: void mousePressEvent(QMouseEvent *event) override; void paintEvent(QPaintEvent *event) override; private: static constexpr char16_t Empty = '-'; static constexpr char16_t Cross = 'X'; static constexpr char16_t Nought = 'O'; QRect cellRect(int position) const; int cellWidth() const { return width() / 3; } int cellHeight() const { return height() / 3; } QString myState; int turnNumber = 0; };
TicTacToe
クラス定義の主な内容は、state
プロパティの宣言と、state()
関数およびsetState()
関数です。
Qt Widgets Designerから見えるようにするために、TicTacToe
ウィジェットの状態をプロパティとして宣言する必要があります。TicTacToe
ウィジェットがQWidget とQObject から継承したプロパティと同じように、Qt Widgets Designerが管理できるようにします。
©2024 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。