「QMLの基礎 - ウインドウ」の版間の差分

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動
154行目: 154行目:
<br>
<br>
==== 動的生成方式 ====
==== 動的生成方式 ====
動的生成方式は、<code>Qt.createComponent</code>メソッドおよび<code>Component.createObject</code>メソッドを使用して、動的にコンポーネントおよびオブジェクトを生成する方法である。
動的生成方式は、<code>Qt.createComponent</code>メソッドおよび<code>Component.createObject</code>メソッドを使用して、動的にコンポーネントおよびオブジェクトを生成する方法である。<br>
<br>
<br>
動的生成方式の特徴を以下に示す。<br>
動的生成方式の特徴を以下に示す。<br>
175行目: 175行目:
  </syntaxhighlight>
  </syntaxhighlight>
<br>
<br>
以下の例では、メインウインドウのボタンを押下する時、各プロパティに初期値を渡して別のウインドウを開いている。<br>
  <syntaxhighlight lang="qml">
  <syntaxhighlight lang="qml">
  // SecondWindow.qml
  // SecondWindow.qml
183行目: 184行目:
   
   
  ApplicationWindow {
  ApplicationWindow {
     id: secondWindow
     id:     secondWindow
     width: 400
     width:   400
     height: 300
     height: 300
     visible: true
     visible: true
   
   
225行目: 226行目:
   
   
  ApplicationWindow {
  ApplicationWindow {
     id: mainWindow
     id:     mainWindow
     width: 640
     width:   640
     height: 480
     height: 480
     visible: true
     visible: true
     title: qsTr("Main Window")
     title:   qsTr("Main Window")
   
   
     Button {
     Button {
242行目: 243行目:
           });
           });
           window.show();
           window.show();
      }
    }
}
</syntaxhighlight>
<br>
===== シグナル / シグナルハンドラの定義 =====
動的生成方式において、コンポーネントを生成して、そのコンポーネントにシグナルを定義して、シグナルハンドラで受信することもできる。<br>
<br>
以下の例では、サブウインドウでwindowClosedシグナルを定義して、メインウインドウで動的に生成したサブウインドウのシグナルを接続・受信している。<br>
<br>
ボタンを押下する時、サブウインドウが開く。<br>
サブウインドウのボタンを押下する時、サブウインドウを閉じてシグナルがメインウインドウに送信される。<br>
<br>
<syntaxhighlight lang="qml">
// DynamicWindow.qml
import QtQuick
import QtQuick.Window
import QtQuick.Controls
Window {
    id:      dynamicWindow
    width:  400
    height:  300
    visible: true
    title: windowTitle
    property string windowTitle: "Dynamic Window"
    signal windowClosed(string message)
    Column {
      anchors.centerIn: parent
      spacing: 20
      Button {
          text: "Close Window"
          onClicked: {
            dynamicWindow.windowClosed("Window is closing")
            dynamicWindow.close()
          }
      }
    }
}
</syntaxhighlight>
<br>
<syntaxhighlight lang="qml">
// MainWindow.qml
import QtQuick
import QtQuick.Window
import QtQuick.Controls
Window {
    id:      mainWindow
    width:  640
    height:  480
    visible: true
    title:  qsTr("Main Window")
    Column {
      anchors.centerIn: parent
      spacing: 20
      Button {
          text: "Create Dynamic Window"
          onClicked: {
            var component = Qt.createComponent("DynamicWindow.qml");
            if (component.status === Component.Ready) {
                var dynamicWindow = component.createObject(mainWindow, {"windowTitle": "New Dynamic Window"});
                // シグナルの接続
                dynamicWindow.windowClosed.connect(function(message) {
                  console.log("Received signal:", message);
                  statusText.text = "Last signal: " + message;
                });
            }
          }
      }
      Text {
          id:  statusText
          text: "No signal received yet"
      }
    }
}
</syntaxhighlight>
<br>
===== メソッドの定義 / 戻り値の受け取り =====
動的生成方式において、コンポーネントを生成して、そのコンポーネントに定義したメソッドの戻り値を受け取ることもできる。<br>
<br>
以下の例では、サブウインドウでgetWindowInfoメソッドを定義して、メインウインドウで動的に生成したサブウインドウのメソッドを実行して、戻り値を取得している。<br>
<br>
ボタンを押下する時、サブウインドウが開く。<br>
サブウインドウのボタンを押下する時、サブウインドウを閉じてシグナルがメインウインドウに送信される。<br>
<br>
<syntaxhighlight lang="qml">
// DynamicWindow.qml
import QtQuick
import QtQuick.Window
import QtQuick.Controls
Window {
    id:      dynamicWindow
    width:  400
    height:  300
    visible: true
    title:  windowTitle
    property string windowTitle: "Dynamic Window"
    function getWindowInfo() {
      return {
          title: windowTitle,
          width: width,
          height: height
      }
    }
    Column {
      anchors.centerIn: parent
      spacing: 20
      Button {
          text: "Change Title"
          onClicked: {
            windowTitle = "Updated Title"
          }
      }
    }
}
</syntaxhighlight>
<br>
<syntaxhighlight lang="qml">
// MainWindow.qml
import QtQuick
import QtQuick.Window
import QtQuick.Controls
Window {
    id:      mainWindow
    width:  640
    height:  480
    visible: true
    title:  qsTr("Main Window")
    Column {
      anchors.centerIn: parent
      spacing: 20
      Button {
          text: "Create Dynamic Window"
          onClicked: {
            var component = Qt.createComponent("DynamicWindow.qml");
            if (component.status === Component.Ready) {
                var dynamicWindow = component.createObject(mainWindow, {"windowTitle": "New Dynamic Window"});
                // メソッドの実行および戻り値の取得
                var windowInfo = dynamicWindow.getWindowInfo();
                console.log("Window Info:", JSON.stringify(windowInfo));
                infoText.text  = "Window Info: " + JSON.stringify(windowInfo);
            }
          }
      }
      Text {
          id: infoText
          text: "No window info yet"
       }
       }
     }
     }

2024年9月29日 (日) 12:44時点における版

概要



ウインドウのオープン / クローズ

静的宣言方式

静的宣言方式は、QMLファイル内で直接ウインドウやコンポーネントを宣言する方法である。
これは、直接的な実装を行う場合に適している。

静的宣言方式の特徴を以下に示す。

  • コードが簡潔で可読性が良い。
  • デザイン時にレイアウトが理解しやすい。
  • アプリケーション起動時の初期化が速い。
  • 宣言されたオブジェクトは常に存在するため、常にメモリを消費する。


以下の例では、静的宣言方式を使用して、ウインドウ間の表示・非表示をスイッチングしている。

  • メインウインドウ
    2つのボタンがあり、各ボタンを押下する時、メインウインドウが非表示になりサブウインドウが開く。
    各サブウィンドウのボタンを押下する時、サブウインドウを閉じて、メインウインドウが再度表示される。


まず、QMLにおけるシグナルの構文を以下に示す。

シグナル(signal <シグナル名>)を宣言して、シグナルの定義を記述する。
シグナルの定義名は、プレフィックスに"on"という文字を付加して、シグナル名の先頭文字を大文字にする必要がある。

 signal closeThisWindow
 
 onCloseThisWindow: {
    // ...略
 }


 // AnotherWindow.qml
 
 import QtQuick
 import QtQuick.Controls
 import QtQuick.Window
 
 Window {
    id: anotherWindow
    width:  480
    height: 320
 
    // シグナルは、サブウインドウの関数として呼び出す
    signal signalExit  // シグナルの宣言
 
    // Button to open the main application window
    Button {
       text: qsTr("メインウインドウに戻る")
       width: 180
       height: 50
       anchors.centerIn: parent
 
       onClicked: {
          anotherWindow.signalExit()  // シグナルを発行する
       }
    }
 }


 // main.qmlファイル
 
 import QtQuick
 import QtQuick.Controls
 import QtQuick.Layouts
 
 ApplicationWindow {
    id: mainWindow
    width:  640
    height: 480
    title: qsTr("Switching between windows in QML")
    visible: true
 
    Rectangle {
       anchors.fill: parent
       color: "white"
 
       GridLayout {
          id: grid
          anchors.fill: parent
 
          rows: 2
          columns: 1
 
          Rectangle {
             Layout.fillHeight: true
             Layout.fillWidth: true
             Layout.column: 1
             Layout.row: 1
 
             // Button to open the first secondary application window
             Button {
                text: qsTr("サブウインドウ 1 を開く")
                anchors.centerIn: parent
                width: 300
                height: 50
 
                onClicked: {
                   firstWindow.show()  // Open the first window
                   mainWindow.hide()   // Hide the main window
                }
             }
          }
 
          Rectangle {
             Layout.fillHeight: true
             Layout.fillWidth: true
             Layout.column: 1
             Layout.row: 2
 
             // Button to open the second secondary application window
             Button {
                text: qsTr("サブウインドウ 2 を開く")
                anchors.centerIn: parent
                width: 300
                height: 50
 
                onClicked: {
                   secondWindow.show() // Open a second window
                   mainWindow.hide()   // Hide the main window
                }
             }
          }
       }
    }
 
    AnotherWindow {
       id: firstWindow
       title: qsTr("サブウインドウ 1")
 
       // The signal handler for the opening of the main window
       onSignalExit: {
          firstWindow.close()     // Close the first window
          mainWindow.show()       // Shows the main window
       }
    }
 
    AnotherWindow {
       id: secondWindow
       title: qsTr("サブウインドウ 2")
 
       // The signal handler for the opening of the main window
       onSignalExit: {
          secondWindow.close()    // We close the second window
          mainWindow.show()       // Shows the main window
       }
    }
 }


動的生成方式

動的生成方式は、Qt.createComponentメソッドおよびComponent.createObjectメソッドを使用して、動的にコンポーネントおよびオブジェクトを生成する方法である。

動的生成方式の特徴を以下に示す。

  • 柔軟性が高い。
  • 実行時にコンポーネントを生成できる。
  • メモリ使用を最適化できる。(必要な時にのみオブジェクトを生成)
  • ソースコードが複雑になる可能性がある。


動的生成方法でコンポーネントに引数を渡す場合は、コンポーネントにプロパティを定義して、それらのプロパティに値を渡すことで行う。

 var component = Qt.createComponent("<QMLファイル名>");
 var window    = component.createObject(<親コンポーネントのID>,
                                        // 各プロパティの設定
                                        { "生成するコンポーネントのプロパティ名 1":     "値",
                                          "生成するコンポーネントのプロパティ名 2":     "値",
                                          "生成するコンポーネントのプロパティ名 3":     "値"
                                        }
                                       );


以下の例では、メインウインドウのボタンを押下する時、各プロパティに初期値を渡して別のウインドウを開いている。

 // SecondWindow.qml
 
 import QtQuick
 import QtQuick.Window
 import QtQuick.Controls
 
 ApplicationWindow {
    id:      secondWindow
    width:   400
    height:  300
    visible: true
 
    property string windowTitle:     "Default Title"
    property color  backgroundColor: "white"
    property string message:         "Default message"
 
    title: windowTitle
    color: backgroundColor
 
    Column {
       anchors.centerIn: parent
       spacing: 20
 
       Label {
          text: message
          font.pixelSize: 16
       }
 
       Button {
          text: "Debug Button"
          onClicked: {
             console.log("Debug button clicked in Second Window")
             console.log("Window Title:", windowTitle)
             console.log("Background Color:", backgroundColor)
             console.log("Message:", message)
          }
       }
    }
 }


 // MainWindow.qml
 
 import QtQuick
 import QtQuick.Window
 import QtQuick.Controls
 
 ApplicationWindow {
    id:      mainWindow
    width:   640
    height:  480
    visible: true
    title:   qsTr("Main Window")
 
    Button {
       anchors.centerIn: parent
       text: "Open Second Window"
       onClicked: {
          var component = Qt.createComponent("SecondWindow.qml");
          var window = component.createObject(mainWindow, {
             "windowTitle":     "Custom Title",
             "backgroundColor": "lightblue",
             "message":         "Hello from Main Window!"
          });
          window.show();
       }
    }
 }


シグナル / シグナルハンドラの定義

動的生成方式において、コンポーネントを生成して、そのコンポーネントにシグナルを定義して、シグナルハンドラで受信することもできる。

以下の例では、サブウインドウでwindowClosedシグナルを定義して、メインウインドウで動的に生成したサブウインドウのシグナルを接続・受信している。

ボタンを押下する時、サブウインドウが開く。
サブウインドウのボタンを押下する時、サブウインドウを閉じてシグナルがメインウインドウに送信される。

 // DynamicWindow.qml
 
 import QtQuick
 import QtQuick.Window
 import QtQuick.Controls
 
 Window {
    id:      dynamicWindow
    width:   400
    height:  300
    visible: true
    title: windowTitle
 
    property string windowTitle: "Dynamic Window"
 
    signal windowClosed(string message)
 
    Column {
       anchors.centerIn: parent
       spacing: 20
 
       Button {
          text: "Close Window"
          onClicked: {
             dynamicWindow.windowClosed("Window is closing")
             dynamicWindow.close()
          }
       }
    }
 }


 // MainWindow.qml
 
 import QtQuick
 import QtQuick.Window
 import QtQuick.Controls
 
 Window {
    id:      mainWindow
    width:   640
    height:  480
    visible: true
    title:   qsTr("Main Window")
 
    Column {
       anchors.centerIn: parent
       spacing: 20
 
       Button {
          text: "Create Dynamic Window"
          onClicked: {
             var component = Qt.createComponent("DynamicWindow.qml");
             if (component.status === Component.Ready) {
                var dynamicWindow = component.createObject(mainWindow, {"windowTitle": "New Dynamic Window"});
 
                // シグナルの接続
                dynamicWindow.windowClosed.connect(function(message) {
                   console.log("Received signal:", message);
                   statusText.text = "Last signal: " + message;
                });
             }
          }
       }
 
       Text {
          id:   statusText
          text: "No signal received yet"
       }
    }
 }


メソッドの定義 / 戻り値の受け取り

動的生成方式において、コンポーネントを生成して、そのコンポーネントに定義したメソッドの戻り値を受け取ることもできる。

以下の例では、サブウインドウでgetWindowInfoメソッドを定義して、メインウインドウで動的に生成したサブウインドウのメソッドを実行して、戻り値を取得している。

ボタンを押下する時、サブウインドウが開く。
サブウインドウのボタンを押下する時、サブウインドウを閉じてシグナルがメインウインドウに送信される。

 // DynamicWindow.qml
 
 import QtQuick
 import QtQuick.Window
 import QtQuick.Controls
 
 Window {
    id:      dynamicWindow
    width:   400
    height:  300
    visible: true
    title:   windowTitle
 
    property string windowTitle: "Dynamic Window"
 
    function getWindowInfo() {
       return {
          title: windowTitle,
          width: width,
          height: height
       }
    }
 
    Column {
       anchors.centerIn: parent
       spacing: 20
 
       Button {
          text: "Change Title"
          onClicked: {
             windowTitle = "Updated Title"
          }
       }
    }
 }


 // MainWindow.qml
 
 import QtQuick
 import QtQuick.Window
 import QtQuick.Controls
 
 Window {
    id:      mainWindow
    width:   640
    height:  480
    visible: true
    title:   qsTr("Main Window")
 
    Column {
       anchors.centerIn: parent
       spacing: 20
 
       Button {
          text: "Create Dynamic Window"
          onClicked: {
             var component = Qt.createComponent("DynamicWindow.qml");
             if (component.status === Component.Ready) {
                var dynamicWindow = component.createObject(mainWindow, {"windowTitle": "New Dynamic Window"});
 
                // メソッドの実行および戻り値の取得
                var windowInfo = dynamicWindow.getWindowInfo();
                console.log("Window Info:", JSON.stringify(windowInfo));
                infoText.text  = "Window Info: " + JSON.stringify(windowInfo);
             }
          }
       }
 
       Text {
          id: infoText
          text: "No window info yet"
       }
    }
 }