How to make a non-modal Dialog window be always on top?

你。 提交于 2021-01-27 03:57:22

问题


I am using an instance of a Dialog {} in my application to display a small controller window that the user can interact with to affect the functions in the main window (sort of a remote control). I can make this Dialog modal (modality: Qt.WindowModal or modality: Qt.ApplicationModal) or I can make it non-modal with modality: Qt.NonModal.

My problem is that I need to make it non-modal but be always on top of the main window. If I use Qt.NonModal I can still click on the main form but then my Dialog goes behind it. The Dialog class does not seem to have a flags: property, so I can't just set it to Qt.WindowsStaysOnTopHint.

Is there any way to set the flags of a Dialog like this purely from the QML side? Or is it possible to write a simple utility method in c++ that I could call from my Dialog's Component.onCompleted: and pass in the dialog to set its windows flags there?

Update: to illustrate what I'm talking about, here is my dialog on top of my main window:

Here is my dialog underneath my main window:

I want my dialog to not go underneath my main window like this, but I still want to be able to click on and interact with my main window. In other words, I want my dialog to be non-modal, but always-on-top.


回答1:


Try to use Window instead of Dialog this way you will have access to the flags property.

You can set flags to Qt.WindowStaysOnTopHint to have your window always on top of other ones. You can find the list of flags here. (Don't forget to replace the :: by . in QML)

Main.qml :

import QtQuick 2.5
import QtQuick.Controls 2.0
import QtQuick.Dialogs 1.2

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")


    Button {
        id: btn
        width: 100 ; height : 40
        text: "click me"
    }

    Text {
        anchors.top : btn.bottom
        text: "Button currently pressed"
        visible: btn.pressed
    }

    DialogOnTop {

    }
}

DialogOnTop.qml :

import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.4

Window {
    id: myWindow

    width: 200
    height: 200

    flags:  Qt.Window | Qt.WindowSystemMenuHint
            | Qt.WindowTitleHint | Qt.WindowMinimizeButtonHint
            | Qt.WindowMaximizeButtonHint | Qt.WindowStaysOnTopHint


    visible: true
    modality: Qt.NonModal // no need for this as it is the default value


    Rectangle {
        color: "lightskyblue"
        anchors.fill: parent
        Text {
            text: "Hello !"
            color: "navy"
            anchors.centerIn: parent
        }
    }
}

Result :




回答2:


Okay, so you simply want to create a Dialog (or a Component which looks like a Dialog) and just want to interact with the Main window and the Dialog window.

Please try the following:

main.qml

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0

ApplicationWindow {
    id: rootWindow
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    color: "green"

    Rectangle {
        id: behind
        anchors.fill: parent
        color: Qt.rgba(0, 0, 0,  0.7)
        visible: false
    }

    MouseArea {
        enabled: behind.visible
        anchors.fill: parent

        onClicked: {
            console.log("Root Window")
        }
    }

    Button {

        text: "Open Dialog"

        onClicked: {
            behind.visible = true;
            var comp = Qt.createComponent("qrc:/MyDialog.qml");
            // var comp = Qt.createComponent("qrc:/DialogQt.qml");
            var obj1 = comp.createObject(rootWindow, {});
            obj1.z = 2;
        }
    }
}

MyDialog.qml

import QtQuick 2.7

Rectangle {
    id: modalWindow
    width: 200
    height: 200
    color: "red"

    anchors.centerIn: parent

    MouseArea {
        anchors.fill: parent
        onClicked: {
            console.log("Modal Window")
        }
    }
}

Clicking on 'Open Dialog' button will create and open the 'modal' Dialog at top of your Main window component.

Of course you have to adjust "MyDialog.qml" file to fit your design requirements on your own.

However, using this as a 'real' Dialog does also work (for me) like G.M has already pointed out in the comments section:

DialogQt.qml

Dialog {
    visible: true
    title: "Blue sky dialog"

    modality : Qt.ApplicationModal

    contentItem: Rectangle {
        color: "lightskyblue"
        anchors.fill: parent
        Text {
            text: "Hello blue sky!"
            color: "navy"
            anchors.centerIn: parent
        }
    }

}



回答3:


Usually you want to use the Dialog not just to create a new window, but for its implemented functionality and interface...

The reason that the Dialog does not inherit Window or ApplicationWindow is obvious: There is no window, as long as it is not open(). But once it is open, there is a ApplicationWindow (from QtQuick.Controls 1.4)

Now, in the documentation we find this nice attatched property: ApplicationWindow which is available to every Item, and conveniently it allows us to access the window. Then we just need to find a way, to set the right flags, as soon as the ApplicationWindow becomes available - e.g. when we get the signal visibleChanged.
As the Dialog is no Item either, we need to use its contentItem to access this attached property.

When we put all of this together the result might look like this:

NonModalDialogThatStaysOnTop.qml // I suck at naming

import QtQuick 2.3
import QtQuick.Controls 1.4 // You need this, to have access to the `ApplicationWindow`-attatched property
import QtQuick.Dialogs 1.2

Dialog {
    onVisibleChanged: {
        if (visible) contentItem.ApplicationWindow.window.flags |= Qt.WindowStaysOnTopHint
    }
    modality: "NonModal"
}

Now you have your favorite Dialog that stays on top but is not modal.



来源:https://stackoverflow.com/questions/44951046/how-to-make-a-non-modal-dialog-window-be-always-on-top

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!