Qt for HarmonyOS/user development/mainwindow and subwindow guide
中文 中文
\== Guide to Main Window and Sub-Window Development with Qt on HarmonyOS ==
\=== 1. Main Window and Sub-Window Concepts ===
\==== 1.1 Main Windows and Sub-Windows in HarmonyOS ==== Main Window: Represents a "task" window. It has a Dock icon and a task icon (visible when switching tasks with Alt+Tab), generally has an independent lifecycle, and can be maximized, minimized, and windowed.
Sub-Window: An interactive interface for a sub-function of a task. It is an independent window that can be displayed outside the main window but has no Dock icon or task icon. It must belong to a main window. When the main window is closed, the sub-window is also closed. When the main window is minimized, the sub-window is hidden. When the main window is restored, the sub-window is also restored. In HarmonyOS, this typically corresponds to various pop-ups and dialogs.
\==== 1.2 Qt Widget or Window Creation ==== When creating a Widget or Window in Qt, there is no native concept similar to the main/sub relationship in HarmonyOS (though some widgets like `QDialog` have the concept of a "Transient Parent," which is close to the HarmonyOS main/sub-window model).
Example:\<syntaxhighlight lang="c++"\> // Independent window QWidget w; w.show();
// Window with a parent-child relationship (assuming w is associated with a native window) QWidget wp; wp.show(); QWidget w(\&wp);
// Dialog QDialog dlg; dlg.exec();
// Dialog with a parent window (Transient Parent) QWidget w; w.show(); QDialog dlg(\&w); dlg.exec(); \</syntaxhighlight\>
\=== 2. HarmonyOS Adaptation Rules ===
\==== 2.1 Core Rules ====
1. **Tagging Function**: Use the QOhosFunctions::tagWindowOrWidgetAsSubWindowOf(QObject \*windowOrWidgetToTag, QWindow \*mainWindow) function. This function tells Qt to create a HarmonyOS sub-window instead of a main window when creating the native window for the specified top-level window, and assigns its parent window. This interface must be called after the mainWindow has been created but before the subWindow is created.
2. **First Window Rule**: When the first QWindow (or a parentless QWidget) in a process is created, it is automatically bound to the first main window created by the system for the application.
3. **Subsequent Window Rule**: When a subsequent QWindow (or a parentless QWidget) is created, if it has not been tagged with AsSubWindowOf, it will create a new HarmonyOS main window.
4. **Transient Parent Handling**: For Qt objects that natively have a Transient Parent (e.g., passing a parent object to a QDialog constructor), if the developer provides a Transient Parent, the main window for this object will be the main window of its Transient Parent. If no parent is provided, its main window is determined by the same rules as a normal QWidget.
5. **Automatic Fallback Mechanism**: When a tagged parent window is invalid, the system will automatically find a suitable parent for certain types of windows (such as Qt::Popup, Qt::ToolTip, Qt::Dialog, Qt::Tool):
* It will first try to use the currently focused window. * Next, it will try to use the first available top-level window. * This ensures that the window can always find a suitable parent.
\==== 2.2 Development Recommendations ==== Developers need to understand the main/sub-window concept in HarmonyOS. When creating a new top-level Widget (one without a parent), they must consider if it should be a HarmonyOS sub-window. If so, they need to call the QOhosFunctions::tagWindowOrWidgetAsSubWindowOf() function and specify its parent window.
The process can be simplified in the following cases:
* 1. **Single-Instance Applications**: If the application has only a single instance (i.e., one main window), you need to call the AsSubWindowOf tag function when creating sub-windows. * 2. **Multi-Instance Applications**: If the application has multiple instances (i.e., multiple main windows in a single process), but all sub-windows are triggered by user interaction with the UI, you need to call the AsSubWindowOf tag when creating sub-windows. No special action is needed to create a new main window. * 3. **Transient Parent Windows**: If you are creating a QDialog or another QWidget that supports a Transient Parent and you pass the Transient Parent parameter, you do not need to call the AsSubWindowOf tag; the default behavior is sufficient.
\=== 3. API Description ===
\==== 3.1 Main Function ==== \<syntaxhighlight lang="c++"\> static void QOhosFunctions::tagWindowOrWidgetAsSubWindowOf(QObject \*windowOrWidgetToTag, QWindow \*mainWindow) \</syntaxhighlight\>This function provides a hint to the windowing system, instructing it not to instantiate the given QWindow or QWidget as a main window, but rather as a sub-window of the specified main window.
Parameters:
* windowOrWidgetToTag: The QObject (must be a QWindow or QWidget) to be tagged as a sub-window. * mainWindow: The specified parent main window.
\==== 3.2 Helper Functions ==== \<syntaxhighlight lang="cpp"\> // Tag a window as a main window static void QOhosFunctions::tagWindowOrWidgetAsMainWindow(QObject \*windowOrWidgetToTag, bool forceMainWindow = true);
// Get the parent window pointer that was tagged via tagWindowOrWidgetAsSubWindowOf. static QWindow \*QOhosFunctions::getWindowOrWidgetAsSubWindowOfTagValue(QObject \*targetWindowOrWidget); \</syntaxhighlight\>
\=== 4. Important Notes ===
\==== ⚠️ Warning: ====
1. Calling winId() or show() before calling the tagging function will cause the tag to be ineffective. 2. mainWindow must be a valid QWindow pointer. 3. If mainWindow points to a valid QWindow, but that QWindow is not a main window, the Qt framework will enable the automatic fallback mechanism to find a suitable main window as the owner. If a suitable main window cannot be found, a new main window will be created instead of a sub-window.
\=== 5. Code Examples ===
\==== 5.1 Basic Usage ==== \<syntaxhighlight lang="c++"\> \#include \<QtPlatformHeaders/QOhosFunctions\>
// Create a sub-window and specify that it belongs to the current main window m\_subwindow = new QWidget();
QOhosFunctions::tagWindowOrWidgetAsSubWindowOf(m\_subwindow, this-\>windowHandle());
m\_subwindow-\>resize(800, 600); m\_subwindow-\>show(); \</syntaxhighlight\>
\==== 5.2 Dialog Example ==== \<syntaxhighlight lang="c++"\> // Method 1: Using Transient Parent (Recommended) QDialog \*dialog = new QDialog(this); // 'this' is the main window widget dialog-\>exec(); // No extra tagging needed
// Method 2: Manual Tagging QDialog \*dialog = new QDialog(); QOhosFunctions::tagWindowOrWidgetAsSubWindowOf(dialog, this-\>windowHandle()); dialog-\>exec(); \</syntaxhighlight\>
\==== 5.3 Multi-Window Application Example ==== \<syntaxhighlight lang="c++"\> class MainWindow : public QMainWindow { public: void createSubWindow() { // Create a sub-window QWidget \*subWindow = new QWidget(); // Tag it as a sub-window of the current main window QOhosFunctions::tagWindowOrWidgetAsSubWindowOf(subWindow, this-\>windowHandle()); subWindow-\>setWindowTitle("Sub-Window"); subWindow-\>resize(400, 300); subWindow-\>show(); }
``` void createNewMainWindow() {
// Create a new main window (no special tagging needed) MainWindow *newMainWindow = new MainWindow(); newMainWindow->show();
} ```
}; \</syntaxhighlight\>
\=== 6. Best Practices ===
* Tag Promptly: Complete the window tagging before calling show() or winId(). * Categorize Reasonably: Clearly distinguish which windows should be main windows and which should be sub-windows. * Utilize Transient Parent: For temporary windows like dialogs, prioritize using Qt's native parent mechanism. * Test and Verify: Verify the window hierarchy and lifecycle behavior on a HarmonyOS device. * Error Handling: Consider the fallback behavior when the parent window is invalid.
\=== 7. FAQ === Q: Why is my sub-window being displayed as a main window?
A: Possible reasons:
* The tagging function was called after calling `show()`. * The passed `mainWindow` parameter was invalid. * You forgot to call the tagging function.
Q: Can a sub-window exist independently of its main window?
A: No. In HarmonyOS, a sub-window must be attached to a main window. When the main window is closed, the sub-window is automatically closed with it.
Q: How can I confirm if the parent-child relationship of a window is correct?
A: You can use the `QOhosFunctions::getWindowOrWidgetAsSubWindowOfTagValue()` function to query the tagged status of a window.