Evgenii Legotckoi
24 грудня 2015 р. 21:27

QML - Урок 021. Перемикання між вікнами в QML

В одній із статей довелося відповісти на запитання читача, як реалізувати перемикання між вікнами в Qt , так, щоб при перемиканні неактивне вікно ховалося. Після натискання спеціальної кнопки відкриваємо друге вікно, а перше закриваємо. І перемикаємося назад аналогічним чином.

А тепер задали те саме питання, але вже стосовно QML. Отже, подивимося, як це продати на QML.

Структура проекта

  • question4.pro - профайл проекту, що створюється за замовчуванням і не змінюється;
  • main.cpp - основний файл вихідних кодів, що створюється за замовчуванням і не змінюється;
  • main.qml - основний файл qml з головним вікном програми;
  • AnotherWindow.qml - тип другорядних вікон проекту.

AnotherWindow.qml

Пояснення коду почну з другорядного вікна програми, оскільки передача інформації про натискання кнопки для відкриття основного вікна реалізується за допомогою сигналу. І зручніше буде описати цей момент на початку, перш ніж приступити до основного коду програми.


Синтаксис сигналу виглядає так:

  1. signal closeThisWindow

Тобто оголошується сам signal і далі йде його назва. Обробник цього сигналу буде визначатися в коді наступним чином:

  1. onCloseThisWindow: {
  2. // Какой-то код
  3. }

А викликається сигнал як функція, що і показано нижче наступному програмному коді другорядного вікна програми.

  1. import QtQuick 2.5
  2. import QtQuick.Controls 1.4
  3. import QtQuick.Window 2.2
  4.  
  5. Window {
  6. id: anotherWindow
  7. signal signalExit // Задаём сигнал
  8. width:480
  9. height:320
  10.  
  11. // Кнопка для открытия главного окна приложения
  12. Button {
  13. text: qsTr("Главное окно")
  14. width: 180
  15. height: 50
  16. anchors.centerIn: parent
  17. onClicked: {
  18. anotherWindow.signalExit() // Вызываем сигнал
  19. }
  20. }
  21. }

main.qml

А в даному файлі реалізована решта логіки програми. У головному вікні є дві кнопки. В обробнику кожної кнопки відкривається відповідне другорядне вікно та ховається основне вікно. Тоді як в обробнику натискання кнопки кожного другорядного вікна відбувається закриття цього вікна та відкриття основного вікна програми.

  1. import QtQuick 2.5
  2. import QtQuick.Controls 1.4
  3. import QtQuick.Layouts 1.1
  4.  
  5. ApplicationWindow {
  6. id: mainWindow
  7. visible: true
  8. width: 640
  9. height: 480
  10. title: qsTr("Переключение между окнами в QML")
  11.  
  12. Rectangle {
  13. anchors.fill: parent
  14. color: "white"
  15.  
  16. GridLayout {
  17. id: grid
  18. anchors.fill: parent
  19.  
  20. rows: 2
  21. columns: 1
  22.  
  23. Rectangle {
  24. Layout.fillHeight: true
  25. Layout.fillWidth: true
  26. Layout.column: 1
  27. Layout.row: 1
  28.  
  29. // Кнопка для открытия первого второстепенного окна приложения
  30. Button {
  31. text: qsTr("Первое окно")
  32. anchors.centerIn: parent
  33. width: 300
  34. height: 50
  35.  
  36. onClicked: {
  37. firstWindow.show() // Открываем первое окно
  38. mainWindow.hide() // Скрываем основное окно
  39. }
  40. }
  41. }
  42.  
  43. Rectangle {
  44. Layout.fillHeight: true
  45. Layout.fillWidth: true
  46. Layout.column: 1
  47. Layout.row: 2
  48.  
  49. // Кнопка для открытия второго второстепенного окна приложения
  50. Button {
  51. text: qsTr("Второе окно")
  52. anchors.centerIn: parent
  53. width: 300
  54. height: 50
  55.  
  56. onClicked: {
  57. secondWindow.show() // Открываем второе окно
  58. mainWindow.hide() // Скрываем основное окно
  59. }
  60. }
  61. }
  62. }
  63. }
  64.  
  65. AnotherWindow {
  66. id: firstWindow
  67. title: qsTr("Первое окно")
  68.  
  69. // Обработчик сигнала на открытие основного окна
  70. onSignalExit: {
  71. firstWindow.close() // Закрываем первое окно
  72. mainWindow.show() // Показываем основное окно
  73. }
  74. }
  75.  
  76. AnotherWindow {
  77. id: secondWindow
  78. title: qsTr("Второе окно")
  79.  
  80. // Обработчик сигнала на открытие основного окна
  81. onSignalExit: {
  82. secondWindow.close() // Закрываем второе окно
  83. mainWindow.show() // Показываем основное окно
  84. }
  85. }
  86. }

Підсумок

В результаті буде реалізовано перемикання між вікнами програми вже на QML, і при цьому у Вас буде відкрито завжди лише одне вікно програми. Демонстрацію роботи програми Ви можете побачити у відеоуроці.

Відеоурок

Вам це подобається? Поділіться в соціальних мережах!

Alex
  • 24 листопада 2017 р. 02:17

Спасибо за урок. Очень понравился. Подскажите если знаете сейчас везде системы управления автомобилей (выбор песни, навигатор, климат контроль (BMW, MERCEDES, etc))  делают с помощью Qt + Qml, там так же примерно сделан переход между окнами ?

Evgenii Legotckoi
  • 24 листопада 2017 р. 15:13

Нет. Там приложения работает в однооконном режиме, скорее всего в качестве базы используются объекты типа Rectangle, которые кастомизированы до состояния диалоговых окон. Также могут использоваться всякие StackView, SwipeView, Loader и т.д.


Хотя... Если там стоит полноценная Ubuntu с приложением в полноэкранном режиме, то вполне возможно наличие диалогов и окон, как в этой статье. Я могу только предполагать, как это работает, но у меня такие мысли на этот счёт.
a
  • 12 січня 2018 р. 13:45

Добрый день! Подскажите пожалуйста. В учебных целях занимаюсь реализацией игры в шахматы, пока пишу игру для двух пользователей. Использую CPP + QML. Хочу сделать несколько окон. Главное окно с кнопками Игра и Просмотреть историю.

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    Logic logic;
    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("logic", &logic);
    engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));

    return app.exec();
}
В классе Logic у меня прописана логика фигур и обработка ходов. Отрисовка доски с фигурами реализована на QML. При нажатии кн. Игра хочу открывать окно с  QQmlApplicationEngine (так как реализовано у меня сейчас в однооконном режиме) и при закрытии окна с игрой возвращаться в главное окно. Вопрос в следующем: можно реализовать это с помощью QML или лучше создавать окна как описано https://evileg.com/post/112/ ?
Evgenii Legotckoi
  • 12 січня 2018 р. 14:03

Добрый день!
Это всё можно реализовать средствами QML, однако я немного недопонимаю вашего вопроса в следующем отношении.
Вы хотите сделать это сохранив одноконный режим? (Что в рамках игры вполне логично, поскольку в большинстве случаев они делаются однооконными), или хотите повторить то, что сделано в этой статье?
В этой статье также используется только один QQmlApplicationEngine даже для двух окон, если ещё раз посмотрите статью, то можете обратить внимание на то, что там вызов окон осуществляется из файла main.qml.
Если хотите однооконный режим, то Вам может помочь Loader

Alex
  • 12 січня 2018 р. 14:13
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    Logic logic;
    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("logic", &logic);
    engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));

    return app.exec();
}

Добрый день, этот код не ваш, я видел этот код так как тоже его делал. Это задание для прохождения на собеседование в одну из крупных украинских IT компаний. Для переключения между окнами используйте Loader QML Type . И на будущее если используете чужой код, изменяйте его, так как не честно использовать чужое, или хотя бы указывайте что код не мой. Будут вопросы пишите.
a
  • 12 січня 2018 р. 15:13

Все верно, я и не говорил что этот кусок кода лично мое произведение. Это тоже верно:

Это задание для прохождения на собеседование в одну из крупных украинских IT компаний.
Логику написал и уперся в окна. Я же не прошу написать за меня, хочу разобраться сам, спашиваю совета. Если кого обидел - прошу прощения. Спасибо огромное за совет.
Alex
  • 12 січня 2018 р. 15:16

Ничего сложного, делаете по тех заданию 3 файла qml, называете их как указанно в тех задании, потом из первого окна через Loader их переключаете, в окне 2 и 3 делаете сигналы которые при закрытии формы вызывают первое окно, подключаете потом к ним логику. Готово.

a
  • 16 січня 2018 р. 18:40

Спасибо всем. Все получилось. Прикручиваю логику.

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
  • Останні коментарі
  • Evgenii Legotckoi
    16 квітня 2025 р. 17:08
    Благодарю за отзыв. И вам желаю всяческих успехов!
  • IscanderChe
    12 квітня 2025 р. 17:12
    Добрый день. Спасибо Вам за этот проект и отдельно за ответы на форуме, которые мне очень помогли в некоммерческих пет-проектах. Профессиональным программистом я так и не стал, но узнал мно…
  • AK
    01 квітня 2025 р. 11:41
    Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
  • Evgenii Legotckoi
    09 березня 2025 р. 21:02
    К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
  • VP
    09 березня 2025 р. 16:14
    Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…