QtQuick2 - custom MessageBox

1k views Asked by At

Does anyone know how to implement custom MessageBox for mobile devices? I've tried to use Window type, but with no luck (it just shows but somewhere out of screen). I appreciate if someone can show me why usage of Window doesn't work. I used also this example. But on mobile devices it doesn't work.

Here is my current code, using Window. As said, it doesn't work since it does show out of screen range.

import QtQuick 2.4
import QtQuick.Window 2.1

Item{

    function showMessage(text, title)
    {
        messageBox.text = text;
        messageBox.title = title;
        messageBox.visible = true;
    }

    Window {
        id: messageBox
        modality: Qt.ApplicationModal
        title: ""
        visible: false
        property alias text: messageBoxLabel.text
        color: parent.color
        minimumHeight: 100
        minimumWidth: 300
        Label {
            anchors.margins: 10
            anchors.top: parent.top
            anchors.left: parent.left
            anchors.right: parent.right
            anchors.bottom: messageBoxButton.top
            horizontalAlignment: Text.AlignHCenter
            wrapMode: Text.WordWrap
            id: messageBoxLabel
            text: ""
        }

        Button {
            anchors.margins: 10
            id: messageBoxButton
            anchors.bottom: parent.bottom
            anchors.horizontalCenter: parent.horizontalCenter
            text: "Ok"
            onClicked: messageBox.visible = false
        }
    }
}

Can someone show me why it's working wrong?

2

There are 2 answers

0
AdrianEddy On BEST ANSWER

MessageBox.qml

import QtQuick 2.2
import QtQuick.Controls 1.2

Rectangle {
    id: mainWrapper
    color: "#80000000"
    x: 0;
    y: 0;
    width: parent.width;
    height: parent.height;
    opacity: 0;
    Behavior on opacity { NumberAnimation { duration: 500; easing.type: Easing.OutExpo } }
    visible: opacity > 0

    property string text;

    MouseArea {
        anchors.fill: parent;
        preventStealing: true
    }

    signal finished(bool ok);

    function init() {
        opacity = 1;
        msgB.scale = 1.0;
    }

    Rectangle {
        id: msgB
        color: "#323232"
        gradient: Gradient {
            GradientStop { position: 0; color: "#323232" }
            GradientStop { position: 1; color: "#252525" }
        }
        //radius: 7

        width: parent.width * 0.4;
        height: cont.height + 20 * 2;
        anchors.centerIn: parent;
        scale: 0.6
        Behavior on scale { NumberAnimation { duration: 500; easing.type: Easing.OutExpo } }
        Behavior on height { NumberAnimation { duration: 500; easing.type: Easing.OutExpo } }

        Column {
            id: cont
            width: parent.width;
            y: 20;
            spacing: 20;
            Text {
                color: "#ffffff"
                horizontalAlignment: Text.AlignHCenter
                anchors.horizontalCenter: parent.horizontalCenter
                font {
                    bold: false;
                    pixelSize: 21;
                }
                wrapMode: Text.WordWrap;
                text: mainWrapper.text;
            }
            Button {
                anchors.margins: 10
                anchors.bottom: parent.bottom
                anchors.horizontalCenter: parent.horizontalCenter
                text: "OK"
                onClicked: {
                    mainWrapper.opacity = 0;
                    msgB.scale = 0.6;
                    mainWrapper.finished(true);
                }
            }
        }
    }
}

Somewhere in main.qml file (window is the id of main.qml element):

function message(msg, finished) {
    var alert = Qt.createComponent("MessageBox.qml").createObject(window, { text: msg });
    alert.onFinished.connect(function(ok) {
        if (ok) {
            if (finished)
                finished();
        }
        alert.destroy(500);
    });
    alert.init();
    return alert;
}

Use it like this:

Button {
    ...
    onClicked: {
        message("Hello world", function() { console.log("OK clicked"); });
    }
}
0
user3417815 On

Thanks all for answers and comments, summarizing above I created element without Window type, but with contentItem property. It's very raw element, but usable like Dialog as suggested by BaCaRoZzo or Window as in Mechan example.

Here is source:

main.qml

import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Window 2.2

ApplicationWindow {
    title: qsTr("Hello World")
    width: Screen.width
    height: Screen.height
    visible: true
    id: win
    color: brPalette.charcoal
    BreezeQuickMessageBox{
        id: mbox
        palette: brPalette
        contentItem: Rectangle{
            color: "lightblue"
            anchors.fill: parent
            BreezeQuickButton{
                id: btn
                anchors {
                    verticalCenter: parent.verticalCenter
                    horizontalCenter: parent.horizontalCenter
                }
                palette: brPalette
                gradiented: false
                onClicked: {
                    mbox.hide()
                }
            }
        }
    }
/*
Another bunch of code
*/
    BreezeQuickPalette{
        id: brPalette
        theme: "dark"
    }
}

BreezeQuickMessageBox.qml

import QtQuick 2.4

Item {
    id: root
    property BreezeQuickPalette palette: BreezeQuickPalette
    property bool __buttonGradiented: false
    property string title: "Message Box"
    property Item contentItem
    anchors.fill: parent
    Behavior on opacity {
        NumberAnimation{
            duration: 250
        }
    }
    opacity: 0
    visible: opacity > 0
    z: parent.z + 100
    BreezeQuickPalette{
        id: __palette
        theme: palette.theme
    }
    Rectangle {
        id: window
        width: parent.width
        height: parent.height*0.4
        anchors {
            verticalCenter: parent.verticalCenter
        }
        z: parent.z + 1
        color: palette.charcoal
        Item {
            id: content
            width: parent.width
            anchors {
                top: titleText.bottom
                bottom: line.top
                horizontalCenter: parent.horizontalCenter
                topMargin: 8
                bottomMargin: 8
            }
            children: contentItem
        }
        Rectangle{
            id: line
            width: parent.width
            anchors{
                bottom: buttonArea.top
                horizontalCenter: parent.horizontalCenter
            }
            height: 1
            color: palette.focusColor
        }
        Text{
            id: titleText
            font.pointSize: buttonOk.font.pointSize
            color: palette.normalText
            text: title
            anchors {
                top: parent.top
                horizontalCenter: parent.horizontalCenter
                topMargin: 16
            }
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignHCenter
        }
        Rectangle{
            id: buttonArea
            width: parent.width
            anchors{
                horizontalCenter: parent.horizontalCenter
                bottom: window.bottom
            }
            height: buttonOk.height*1.2
            color: "transparent"
        }
        BreezeQuickButton {
            id: buttonOk
            caption: "Ok"
            width: 128
            palette: __palette
            gradiented: __buttonGradiented
            anchors{
                horizontalCenter: parent.horizontalCenter
                verticalCenter: buttonArea.verticalCenter
            }
            onClicked: {
                root.hide()
            }
        }
    }
    Rectangle{
        id: shadow
        anchors.fill: parent
        z: parent.z
        color: palette.shadeBlack
        opacity: 0.4
        MouseArea{
            id: rootArea
            anchors.fill: parent
            hoverEnabled: true
        }
        gradient: Gradient {
            GradientStop { position: 0.0; color: palette.black }
            GradientStop { position: 0.1; color: palette.shadeBlack }
            GradientStop { position: 0.3; color: palette.grey }
            GradientStop { position: 0.7; color: palette.grey }
            GradientStop { position: 0.9; color: palette.shadeBlack }
            GradientStop { position: 1.0; color: palette.black }
        }
    }

    function show (title, message) {
        root.opacity = 1
    }
    function hide () {
        root.opacity = 0
    }
}

And actual look for Android:

Application mainwindow

MessageBox in action