QMLでコンテキストメニューを作成する

ContextMenu on QML
ポップアップメニューを実装するにはQtQuick.Controlsの「Menu」コンポーネントを使用します。コンテキストメニュー、いわゆる右クリックメニューはMouseAreaで調べますが、タッチデバイスでは右クリックによる画面の長押しとして扱うことになるので、この場合はクリックに使用したデバイスがマウス以外であるかを調べる必要があります。

メニューを表示するには「popup()」を実行します。第1引数にxの値(real値)を指定した場合、第2引数はy値とみなされます。第1引数に表示対象のアイテムを指定すると、そのアイテムに対する相対位置(第2引数,第3引数)=(x,y)に表示されます。引数を省略することもできますが、UWPなどの環境によっては正しい位置に表示されないので、座標値は指定したほうがよいでしょう。

メニューの分割線は「MenuSeparator」を使用します。サブメニューを用意したいのであれば、Menuを入れ子にして、titleプロパティーにサブメニューの親として表示したいテキストを指定します。

メニューが選択されたかどうかは「triggered」シグナルで検知します。
menu.qml
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.4

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Context Menu")

    Label{
        id:lbl
        x:0; y:0
    }

    MouseArea {
        anchors.fill: parent
        acceptedButtons: Qt.LeftButton | Qt.RightButton

        // 右クリックでポップアップメニューを表示
        onClicked:{
            if (mouse.button === Qt.RightButton){
                // UWPなど一部の環境では、引数を省略すると正しい場所に表示されない
                menu.popup(mouse.x, mouse.y);
            }
        }
        // マウス以外のデバイスによる長押しでも同様に表示
        onPressAndHold: if (mouse.source === Qt.MouseEventNotSynthesized) menu.popup(mouse.x, mouse.y)

        Menu {
            id: menu

            MenuItem {
                text: "Menu1"
                onTriggered: {
                    lbl.text = "Menu1 clicked.";
                    m2.checked = !m2.checked;
                }
            }
            MenuItem {
                // チェック付きメニュー
                id: m2
                text: "Menu2"
                checkable: true
            }

            MenuSeparator {
            }

            // サブメニュー
            Menu {
                title: "SubMenu1"
                MenuItem { text: "Menu2-1" }
                MenuItem { text: "Menu2-2" }
            }
        }
    }
}
2018/11/05