воскресенье, 25 ноября 2012 г.

Qt Quick - несколько форм (окон в одном приложении)

В данном посте я расскажу о том, как добавить несколько форм в одно приложение. Речь пойдёт не о QWidget, а формах внутри одного окна. Для показательного примера мы создадим одно окно регистрации, и в случае ввода верного логина и пароля покажем скрытый текст.

Как обычно в случае qml создаём "приложение Qt Quick". Далее создадим окно регистрации и назовём его Register.qml. Очень важно называть файл с большой буквы, тогда QML будет воспринимать его как класс.
Весь код класса описан ниже:

// import QtQuick 1.0 // to target S60 5th Edition or Maemo 5
import QtQuick 1.1
Rectangle {
    id: loginPg
    signal loginAccepted // сигнал об успешном логине и пароле
    width: 100
    height: 62
    Rectangle
    {
        id: rec1 // id, по которому мы сможем ссылаться на этот прямоугольник
        border.width: 1 // задаем рамку в 1 пиксель
        border.color: "black" // и черного цвета
        y: parent.height * 0.2 // координата по y (задаётся по высоте от основного окна, т.е. 0.2 окна или 20%)
        height: parent.height * 0.1 // высота (задаётся по высоте основного окна, т.е. 0.1 окна или 10%)
        anchors.left: parent.left // прижимаем левую часть рамки к левой стороне окна
        anchors.right: parent.right // а правую сторону к правой
        anchors.leftMargin: parent.width * 0.1 // делаем отступ слева в 0.1 (10%) от ширины окна
        anchors.rightMargin: parent.width * 0.1 // и такой же отступ справа
        TextInput
        {
            id: text1 // тут мы создаём наше окно ввода скажем логина
            anchors.fill: parent // растягиваем его во всю рамку
            anchors.margins: 3 // делаем отступ от рамки по всем сторонам в 3 пикселя
            font.pixelSize: parent.height * 0.7 // и задаём что шрифт будет всегда в 70% от высоты рамки
        }
    }
    Text
    {
        // это текстовое поле - заголовок с текстом логин, единственная его особенность в самом низу
        height: parent.height * 0.1
        anchors.left: parent.left // прижимаем левую часть рамки к левой стороне окна
        anchors.right: parent.right // а правую сторону к правой
        anchors.leftMargin: parent.width * 0.1 // делаем отступ слева в 0.1 (10%) от ширины окна
        anchors.rightMargin: parent.width * 0.1 // и такой же отступ справа
        font.pixelSize: parent.height * 0.05
        text: 'Login'
        anchors.bottom: rec1.top // здесь мы низ текстового поля привязываем к верху прямоугольника
    }
    // то же самое делаем и для второго поля ввода
    Rectangle
    {
        id: rec2
        y: parent.height * 0.5
        height: parent.height * 0.1
        anchors.leftMargin: parent.width * 0.1
        anchors.rightMargin: parent.width * 0.1
        anchors.left: parent.left
        anchors.right: parent.right
        //width: parent.width
        //x: 0
        border.width: 1
        border.color: "black"
        TextInput
        {
            id: text2
            anchors.fill: parent
            anchors.margins: 3
            font.pixelSize: parent.height * 0.7
        }
    }
    Text
    {
        // это текстовое поле - заголовок с текстом логин, единственная его особенность в самом низу
        height: parent.height * 0.1
        anchors.left: parent.left // прижимаем левую часть рамки к левой стороне окна
        anchors.right: parent.right // а правую сторону к правой
        anchors.leftMargin: parent.width * 0.1 // делаем отступ слева в 0.1 (10%) от ширины окна
        anchors.rightMargin: parent.width * 0.1 // и такой же отступ справа
        font.pixelSize: parent.height * 0.05
        text: 'Password'
        anchors.bottom: rec2.top // здесь мы низ текстового поля привязываем к верху прямоугольника
    }
    Button
    {
        // здесьс мы создаём кнопочку и делаем её обработку
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        height: parent.height * 0.1
        anchors.margins: parent.width * 0.1
        onClicked:
        {
            console.log("clicked") // вывод отладочной информации
            if (text1.text == "login" && text2.text == "password")
            {
                console.log("login accepted") // вывод отладочной информации
                loginPg.loginAccepted()  // собственно вызываем сигнал что login и password верные
            }
        }
    }
}

Надеюсь из комментариев всё понятно. Чувствую на днях придётся создать репозиторий для хранения всех примеров. Кнопку я уже описывал ранее, но т.к. большинству наверняка лень искать, выложу и её:


// import QtQuick 1.0 // to target S60 5th Edition or Maemo 5
import QtQuick 1.1
Rectangle {
    id: button
    signal clicked // этот сигнал вызывается ниже при нажании в MouseArea
    width: 100
    height: 62
    border.width: 1
    border.color: "black"
    radius: 5
    color: mArea.pressed ? "#AAAAAA" : "#EEEEEE"
    MouseArea
    {
        id: mArea
        anchors.fill: parent
        onClicked: button.clicked() // собственно тут мы и вызываем сигнал clicked
    }
    Text
    {
        anchors.fill: parent
        text: "Knopka"
        horizontalAlignment: Text.AlignHCenter
        verticalAlignment: Text.AlignVCenter
    }
}


Следующим этапом добавим нашу форму в главное окно. Для этого в main.qml надо убрать Text и MouseArea, а добавить наше окно Register:


// import QtQuick 1.0 // to target S60 5th Edition or Maemo 5
import QtQuick 1.1
Rectangle {
    width: 360
    height: 360
    Register { // добавляем наше окно 
        anchors.fill: parent // растягиваем его на всё окно
    }
}


После запуска приложения вы увидите окно, показанное на рисунке ниже:


Следующим этапом необходимо добавить недостающий нам текст. При этом надо учесть, что изначально он не должен отображаться. Отобразим мы его только тогда, когда окно Register вызовет сигнал loginAccepted(). После всех необходимых изменений код в main.qml примет следующий вид:


// import QtQuick 1.0 // to target S60 5th Edition or Maemo 5
import QtQuick 1.1
Rectangle {
    width: 360
    height: 360
    Register { // добавляем наше окно
        id: loginWindow
        anchors.fill: parent // растягиваем его на всё окно
        onLoginAccepted:
        {
            loginWindow.visible = false // прячем окно логина
            secrText.visible = true // и показываем окно с текстом
        }
    }
    Text
    {
        id: secrText // id, по которому мы обращаемся к тексту
        visible: false // изначально наш текст не виден
        anchors.fill: parent
        verticalAlignment: Text.AlignVCenter
        horizontalAlignment: Text.AlignHCenter
        text: "Секретный текст" // выводим текст
    }
}


После ввода login и password вы получите следующее окно:

P. S. вместо Text можете создать второе окно по образцу для Register (а если хотите и ещё одно Register :)  ) и точно так же управлять им через свойство visible.

5 комментариев:

  1. а еще через состояния можно делать. Так то для организации больших программ в которых интерфейс меняется это дико неудобно и main.qml в результате выглядит объемно. Мечтаю о способе когда можно подгружать необходимsq qml файл в нужный момент.

    ОтветитьУдалить
  2. Loader в QML для подгрузки *.qml файлов

    ОтветитьУдалить
  3. а как такое сделать в обычном qt просто с qml не знаком

    ОтветитьУдалить
  4. Этот комментарий был удален автором.

    ОтветитьУдалить
  5. Этот комментарий был удален автором.

    ОтветитьУдалить