タスクメニュー拡張

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.

Task Menu Extensionの例は、5つのクラスで構成されています:

  • TicTacToe は、ユーザーに三目並べゲームをプレイさせるカスタムウィジェットです。
  • TicTacToePlugin TicTacToe クラスを Designer に公開します。Qt Widgets
  • TicTacToeTaskMenuFactory TicTacToeTaskMenu オブジェクトを作成します。
  • TicTacToeTaskMenu タスクメニュー拡張、つまりプラグインに関連するタスクメニューエントリを提供します。
  • TicTacToeDialog Qt Widgets DesignerにロードされたTic-Tac-Toeプラグインの状態を変更できます。

カスタムウィジェットプラグインのプロジェクトファイルには、Qt Widgets Designer内で確実に動作するための追加情報が必要です。たとえば、カスタム ウィジェット プラグインはQt Widgets Designer で提供されるコンポーネントに依存するため、使用するプロジェクト ファイルで指定する必要があります。まず、プラグインのプロジェクト ファイルを確認します。

次に、TicTacToePlugin クラスを確認し、TicTacToeTaskMenuFactoryTicTacToeTaskMenu クラスを確認します。最後に、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 はinitialize() 関数も定義しており、プラグインがQt Widgets Designer にロードされた後に呼び出されます。この関数のQDesignerFormEditorInterface パラメータは、Qt Widgets Designer のすべての API へのゲートウェイをプラグインに提供します。

TicTacToePlugin クラスはQObjectQDesignerCustomWidgetInterface の両方を継承します。多重継承を使用する場合は、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 オブジェクトを作成します。第 1 引数は新しく作成されたファクトリで、第 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 クラスはQDesignerTaskMenuExtension を継承し、Qt Widgets Designer のタスク メニューにカスタム エントリ(QActions 形式)を追加できます。

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 ウィジェットです

さらに、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;
}

TicTacToe ウィジェットを選択してF2キーを押したときに呼び出されるアクションとして、カスタムeditStateAction を返すようにpreferredEditAction() 関数を再実装します。

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 このクラスは、関連するフォーム・ウィンドウの情報を提供し、そのプロパティを変更できるようにします。このインターフェイスは直接インスタンス化することを意図しておらず、 Designerのフォームウィンドウマネージャによって制御される Designerの現在のフォームウィンドウへのアクセスを提供します。Qt Widgets Qt Widgets

特定のウィジェットを含むフォームウィンドウを検索する場合は、静的関数QDesignerFormWindowInterface::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 ウィジェットの状態をプロパティとして宣言する必要があります。Qt Widgets Designerは、TicTacToe ウィジェットがQWidgetQObject から継承したプロパティと同じ方法で管理できます。

プロジェクト例 @ code.qt.io

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.