Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

qt

qml

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:

enter image description here

Here is my dialog underneath my main window:

enter image description here

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.

like image 695
MusiGenesis Avatar asked Jul 06 '17 13:07

MusiGenesis


People also ask

What is the difference between a modal and a dialog?

Dialog (dialogue): A conversation between two people. In a user interface, a dialog is a “conversation” between the system and the user. Mode: A special state of the system in which the same system has somewhat different user interfaces.

Is a dialog box a modal?

Dialog box — A top-level pop-up window with a title and a border that typically takes some form of input from the user. A dialog box can be modal or modeless. For more information about dialog boxes, see An Overview of Dialogs in the How to Make Dialogs page.


3 Answers

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 :

always on top window

like image 122
Blabdouze Avatar answered Sep 28 '22 01:09

Blabdouze


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.

like image 25
derM Avatar answered Sep 28 '22 03:09

derM


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
        }
    }

}
like image 26
sk2212 Avatar answered Sep 28 '22 01:09

sk2212