Возвращаемся к курсу по QML и сегодня продолжим рассмотрение основных типов и компонентов. Подошла очередь QML Dialog
, собственно, им и займемся. Все по привычной схеме - рассмотрим теоретически-обзорные моменты, по максимуму сопровождая их наглядными практическими примерами, так что переходим к делу. Использовать будем Dialog
из QtQuick.Controls 2.15
(не QtQuick.Dialogs 1.3
).
QML Dialog. Основные свойства и методы.
Итак, компонент Dialog
по сути представляет из себя окно, предлагающее пользователю осуществить те или иные действия, допустим, сохранить или загрузить информацию в файл/из файла. Схематично имеем следующее:
То есть диалоговое окно состоит из трех отдельных частей:
- header
- contentItem
- footer
И, поскольку я предпочитаю любые теоретические аспекты демонстрировать на конкретном примере, то так и поступим. Создаем пустое Qt Quick приложение и добавляем к нему два элемента:
- кнопку, по нажатию на которую будет происходить открытие диалогового окна
- и непосредственно этот самый
Dialog
В результате в main.qml получаем:
import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 Window { width: 320 height: 240 visible: true title: qsTr("QML Dialog Review") Dialog { id: testDialog title: "Test dialog title" standardButtons: Dialog.Ok | Dialog.Cancel implicitWidth: parent.width implicitHeight: parent.height } Button { id: openDialogButton anchors.centerIn: parent text: qsTr("Open Dialog") onClicked: { testDialog.open(); } } }
Здесь мы помимо физических параметров, а именно ширины и высоты, задали еще title
и standardButtons
. По дефолту (когда header, contentItem и footer не заданы явно) данные части диалогового окна представляют из себя следующее:
- в качестве header - заголовок, содержащий текст, введенный в
title
- contentItem остается пустым
- footer же состоит из DialogButtonBox, содержащим кнопки, указанные в
standardButtons
Запускаем приложение и нажимаем на кнопку:
Соответственно, наблюдаем ровно то, что и планировали:
И опять же во имя максимальной наглядности зададим в качестве частей Dialog
элементы Rectangle
разных цветов, дабы оценить их взаимное расположение:
import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 Window { width: 320 height: 240 visible: true title: qsTr("QML Dialog Review") Dialog { id: testDialog title: "Test dialog title" standardButtons: Dialog.Ok | Dialog.Cancel implicitWidth: parent.width implicitHeight: parent.height header: Rectangle { color: "red" height: 50 } contentItem: Rectangle { color: "green" } footer: Rectangle { color: "blue" height: 50 } } Button { id: openDialogButton anchors.centerIn: parent text: qsTr("Open Dialog") onClicked: { testDialog.open(); } } }
Результат закономерен:
Единственный нюанс - наличествует белое поле вокруг contentItem
, оно регулируется свойством padding
. Добавляем:
Dialog { id: testDialog title: "Test dialog title" standardButtons: Dialog.Ok | Dialog.Cancel implicitWidth: parent.width implicitHeight: parent.height padding: 0 // ...............
Таким образом, получили результат, полностью повторяющий схему Dialog
из начала статьи 👍
Полный список свойств доступен в официальной документации Qt, мы же кратко пробежимся по паре наиболее часто используемых, а именно:
modal
- определяет, является ли окно модальным, то есть блокирующим взаимодействие с остальным приложением до своего закрытия. Возможные значения: true/false.result
- хранит в себе результат работы окна, значения:Dialog.Accepted
/Dialog.Rejected
(1/0).
Этот самый результат зависит от того, каким образом было закрыто диалоговое окно. И тут копнем чуть глубже... В качестве кнопок Dialog
(которые мы задавали в standardButtons
) может быть использован довольно внушительный ряд различных вариантов. При этом у каждой кнопки, в свою очередь, есть определенная роль (DialogButtonBox.buttonRole
), назначенная ей. А уже каждой роли соответствует определенный сигнал. Так мы плавно и логично перешли к следующему подразделу.
QML Dialog. События и сигналы.
Так вот, вышеописанное я систематизировал следующим образом:
Button | Text | Role | Signal |
---|---|---|---|
Dialog.Ok | "OK" | AcceptRole | accepted() |
Dialog.Open | "Open" | AcceptRole | accepted() |
Dialog.Save | "Save" | AcceptRole | accepted() |
Dialog.Cancel | "Cancel" | RejectRole | rejected() |
Dialog.Close | "Close" | RejectRole | rejected() |
Dialog.Discard | "Discard" | DiscardRole | discarded() |
Dialog.Apply | "Apply" | ApplyRole | applied() |
Dialog.Reset | "Reset" | ResetRole | reset() |
Dialog.RestoreDefaults | "Restore Defaults" | ResetRole | reset() |
Dialog.Help | "Help" | HelpRole | helpRequested() |
Dialog.SaveAll | "Save All" | AcceptRole | accepted() |
Dialog.Yes | "Yes" | YesRole | accepted() |
Dialog.YesToAll | "Yes to All" | YesRole | accepted() |
Dialog.No | "No" | NoRole | rejected() |
Dialog.NoToAll | "No to All" | NoRole | rejected() |
Dialog.Abort | "Abort" | RejectRole | rejected() |
Dialog.Retry | "Retry" | AcceptRole | accepted() |
Dialog.Ignore | "Ignore" | AcceptRole | accepted() |
Вернемся к нашему самому первому диалогу с дефолтным набором параметров:
И добавим два обработчика:
onAccepted
onRejected
import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 Window { width: 320 height: 240 visible: true title: qsTr("QML Dialog Review") Dialog { id: testDialog title: "Test dialog title" standardButtons: Dialog.Ok | Dialog.Cancel implicitWidth: parent.width implicitHeight: parent.height onAccepted: { console.log("Ok button clicked " + testDialog.result); } onRejected: { console.log("Cancel button clicked " + testDialog.result); } } Button { id: openDialogButton anchors.centerIn: parent text: qsTr("Open Dialog") onClicked: { testDialog.open(); } } }
При нажатии на кнопки Ok и Cancel в консоли получаем:
- Кнопка Ok: "Ok button clicked 1".
- Кнопка Cancel: "Cancel button clicked 0".
Что соответствует значениям result
, равным Dialog.Accepted
в первом случае и Dialog.Rejected
- во втором.
Аналогичный механизм для добавления других кнопок и обработчиков сигналов, например:
import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 Window { width: 320 height: 240 visible: true title: qsTr("QML Dialog Review") Dialog { id: testDialog title: "Test dialog title" standardButtons: Dialog.Ok | Dialog.Apply | Dialog.Cancel implicitWidth: parent.width implicitHeight: parent.height onAccepted: { console.log("Ok button clicked " + testDialog.result); } onRejected: { console.log("Cancel button clicked " + testDialog.result); } onApplied: { console.log("Apply button clicked " + testDialog.result); } } Button { id: openDialogButton anchors.centerIn: parent text: qsTr("Open Dialog") onClicked: { testDialog.open(); } } }
В результате нажатия на Apply ("Применить") получаем в консоли: "Apply button clicked 1". При этом обратите внимание, что нажатие на Apply не приводит к закрытию диалога.
Плюс ко всему Dialog
имеет ряд методов, позволяющих "вручную" осуществить действия, аналогичные нажатию кнопок:
void accept()
- закрывает диалоговое окно и генерирует сигналaccepted()
.void done(int result)
- также закрывает диалог и устанавливает свойствоresult
диалога равным одноименному аргументу данной функции. При вызове с аргументомDialog.Accepted
(done(Dialog.Accepted)
) будет сгенерирован сигналaccepted()
, а если вызываемdone(Dialog.Rejected)
, то будет уже сигналrejected()
, что согласитесь, логично.void reject()
- аналогично закрываетDialog
и генерирует сигналrejected()
.
На этом в целом заканчиваем с рассмотрением нюансов работы с QML Dialog, перейдем к еще одному практическому примеру.
QML Dialog. Кастомизация, пример.
Итак, я сделал простенькое диалоговое окно, которое используется для закрытия приложения. При нажатии "Ok" как раз и произойдет закрытие, а при нажатии "Cancel" никаких действий не предпринимаем. В примере задействовано по максимуму различных свойств, чтобы при желании можно было легко адаптировать под свои конкретные нужды. Результат выглядит так:
И код:
import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 Window { width: 320 height: 240 visible: true title: qsTr("QML Dialog Review") Dialog { id: closeAppDialog title: "Close Application" implicitWidth: parent.width implicitHeight: parent.height padding: 0 header: Label { text: closeAppDialog.title horizontalAlignment: Text.AlignHCenter color: "#ffffff" font.bold: true padding: 10 background: Rectangle { color: "#707070" border.width: 1.0 border.color: "#000000" } } contentItem: Label { text: qsTr("Are you sure?") font.pointSize: 12 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter color: "#ffffff" font.bold: true padding: 10 background: Rectangle { color: "#353535" } } footer: DialogButtonBox { background: Rectangle { color: "#707070" border.width: 1.0 border.color: "#000000" } Button { DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole contentItem: Text { text: qsTr("Ok") color: "#ffffff" horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter font.pointSize: 10 } background: Rectangle { color: "#8fbc8f" radius: 10 border.width: 1.0 border.color: "#006400" } } Button { DialogButtonBox.buttonRole: DialogButtonBox.RejectRole contentItem: Text { text: qsTr("Cancel") color: "#ffffff" horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter font.pointSize: 10 } background: Rectangle { color: "#cd5c5c" radius: 10 border.width: 1.0 border.color: "#8b0000" } } } onAccepted: { Qt.quit(); } onRejected: { // Nothing to be done } } Button { id: closeAppButton anchors.centerIn: parent text: qsTr("Close") onClicked: { closeAppDialog.open(); } } }
На этом на сегодня и заканчиваем 🤝
Здравствуйте!
Это Дмитрий (Инстаграм: kupratsevich_dima), писал вам раньше про покупку сайта microtechnics.ru, но не получил ответа.
Возможно, что не устроила цена. Готов рассмотреть по рыночной оценке.
Мои контакты:
kupratsevich (Telegram)
kuprdimasites@gmail.com (Почта)
+79959176538 (Телефон/whatsapp)
Добрый день!
Благодарю за предложение, не интересует в целом.