0

I found the calendar implemented using QML. I want to embed it in my program. I have the main window of the program ui-form. Clicking on "line Edith" should open a calendar implemented with QML? How to do it? And how do I transfer the date from the calendar to "Line Edit"? enter image description here This is the code for popupCalendar.qml:

import QtQuick 2.0
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.2

Item {
    property var tempDate: new Date();

    Dialog {
         id: dialogCalendar
         // Задаём размеры диалогового окна
         width: 250
         height: 300

         // Создаем контент диалогового окна
         contentItem: Rectangle {
             id: dialogRect
             color: "#f7f7f7"

             // Первым идёт кастомный календарь
             Calendar {
                 id: calendar
                 // Размещаем его в верхней части диалога и растягиваем по ширине
                 anchors.top: parent.top
                 anchors.left: parent.left
                 anchors.right: parent.right
                 anchors.bottom: row.top

                 // Стилизуем Календарь
                 style: CalendarStyle {

                     // Стилизуем navigationBar
                     navigationBar: Rectangle {
                         /* Он будет состоять из прямоугольника,
                          * в котором будет располагаться две кнопки и label
                          * */
                         height: 48
                         color: "#f7f7f7"

                         /* Горизонтальный разделитель,
                          * который отделяет navigationBar от поля с  числами
                          * */
                         Rectangle {
                             color: "#d7d7d7"
                             height: 1
                             width: parent.width
                             anchors.bottom: parent.bottom
                         }

                         // Кнопка промотки месяцев назад
                         Button {
                             id: previousMonth
                             width: parent.height - 8
                             height: width
                             anchors.verticalCenter: parent.verticalCenter
                             anchors.left: parent.left
                             anchors.leftMargin: 8

                             /* По клику по кнопке вызываем функцию
                              * календаря, которая отматывает месяц назад
                              * */
                             onClicked: control.showPreviousMonth()

                             // Стилизуем кнопку
                             style: ButtonStyle {
                                 background: Rectangle {
                                     // Окрашиваем фон кнопки
                                     color: "#f7f7f7"
                                     /* И помещаем изображение, у которго будет
                                      * два источника файлов в зависимости от того
                                      * нажата кнопка или нет
                                      */
                                     Image {
                                         source: control.pressed ? "left_arrow_disable.png" : "left_arrow.png"
                                         width: parent.height - 8
                                         height: width
                                     }
                                 }
                             }
                         }

                         // Помещаем стилизованный label
                         Label {
                             id: dateText
                             /* Забираем данные из title календаря,
                              * который в данном случае не будет виден
                              * и будет заменён данным label
                              */
                             text: styleData.title
                             color:  "#34aadc"
                             elide: Text.ElideRight
                             horizontalAlignment: Text.AlignHCenter
                             font.pixelSize: 16
                             anchors.verticalCenter: parent.verticalCenter
                             anchors.left: previousMonth.right
                             anchors.leftMargin: 2
                             anchors.right: nextMonth.left
                             anchors.rightMargin: 2
                         }

                         // Кнопка промотки месяцев вперёд
                         Button {
                             id: nextMonth
                             width: parent.height - 8
                             height: width
                             anchors.verticalCenter: parent.verticalCenter
                             anchors.right: parent.right

                             /* По клику по кнопке вызываем функцию
                              * календаря, которая отматывает месяц назад
                              * */
                             onClicked: control.showNextMonth()

                              // Стилизуем кнопку
                             style: ButtonStyle {
                                 // Окрашиваем фон кнопки
                                 background: Rectangle {
                                     color: "#f7f7f7"
                                     /* И помещаем изображение, у которго будет
                                      * два источника файлов в зависимости от того
                                      * нажата кнопка или нет
                                      */
                                     Image {
                                         source: control.pressed ? "right_arrow_disable.png" : "right_arrow.png"
                                         width: parent.height - 8
                                         height: width
                                     }
                                 }
                             }
                         }
                     }


                     // Стилизуем отображением квадратиков с числами месяца
                     dayDelegate: Rectangle {
                         anchors.fill: parent
                         anchors.margins: styleData.selected ? -1 : 0
                         // Определяем цвет в зависимости от того, выбрана дата или нет
                         color: styleData.date !== undefined && styleData.selected ? selectedDateColor : "transparent"

                         // Задаём предопределённые переменные с цветами, доступные только для чтения
                         readonly property color sameMonthDateTextColor: "#444"
                         readonly property color selectedDateColor: "#34aadc"
                         readonly property color selectedDateTextColor: "white"
                         readonly property color differentMonthDateTextColor: "#bbb"
                         readonly property color invalidDateColor: "#dddddd"

                         // Помещаем Label для отображения числа
                         Label {
                             id: dayDelegateText
                             text: styleData.date.getDate() // Устанавливаем число в текущий квадрат
                             anchors.centerIn: parent
                             horizontalAlignment: Text.AlignRight
                             font.pixelSize: 10

                             // Установка цвета
                             color: {
                                 var theColor = invalidDateColor; // Устанавливаем невалидный цвет текста
                                 if (styleData.valid) {
                                     /* Определяем цвет текста в зависимости от того
                                      * относится ли дата к выбранному месяцу или нет
                                      * */
                                     theColor = styleData.visibleMonth ? sameMonthDateTextColor : differentMonthDateTextColor;
                                     if (styleData.selected)
                                         // Перекрашиваем цвет текста, если выбрана данная дата в календаре
                                         theColor = selectedDateTextColor;
                                 }
                                 theColor;
                             }
                         }
                     }
                 }
             }

             // Делаем панель с кнопками
             Row {
                 id: row
                 height: 48
                 anchors.left: parent.left
                 anchors.right: parent.right
                 anchors.bottom: parent.bottom

                 // Кнопка для закрытия диалога
                 Button {
                     id: dialogButtonCalCancel
                     anchors.top: parent.top
                     anchors.bottom: parent.bottom
                     width: parent.width / 2 - 1

                     style: ButtonStyle {
                         background: Rectangle {
                             color: control.pressed ? "#d7d7d7" : "#f7f7f7"
                             border.width: 0
                         }

                         label: Text {
                             text: qsTr("Cancel")
                             font.pixelSize: 14
                             color: "#34aadc"
                             verticalAlignment: Text.AlignVCenter
                             horizontalAlignment: Text.AlignHCenter
                         }
                     }
                     // По нажатию на кнопку - просто закрываем диалог
                     onClicked: dialogCalendar.close()
                 }

                 // Вертикальный разделитель между кнопками
                 Rectangle {
                     id: dividerVertical
                     width: 2
                     anchors.top: parent.top
                     anchors.bottom: parent.bottom
                     color: "#d7d7d7"
                 }

                 // Кнопка подтверждения выбранной даты
                 Button {
                     id: dialogButtonCalOk
                     anchors.top: parent.top
                     anchors.bottom: parent.bottom
                     width: parent.width / 2 - 1

                     style: ButtonStyle {
                         background: Rectangle {
                             color: control.pressed ? "#d7d7d7" : "#f7f7f7"
                             border.width: 0
                         }

                         label: Text {
                             text: qsTr("Ok")
                             font.pixelSize: 14
                             color: "#34aadc"
                             verticalAlignment: Text.AlignVCenter
                             horizontalAlignment: Text.AlignHCenter
                         }
                     }

                     /* По клику по кнопке сохраняем выбранную дату во временную переменную
                      * и помещаем эту дату на кнопку в главном окне,
                      * после чего закрываем диалог
                      */
                     onClicked: {
                         tempDate = calendar.selectedDate
                         button.text = Qt.formatDate(tempDate, "dd.MM.yyyy");
                         dialogCalendar.close();
                     }
                 }
             }
         }

         /* Данная функция необходима для того, чтобы
          * установить дату с кнопки в календарь,
          * иначе календарь откроется с текущей датой
          */
         function show(x){
             calendar.selectedDate = x
             dialogCalendar.open()
         }
     }
}
1
  • I don't know of a straightforward signal to detect clicks inside QLineEdit, but you can use returnpressed signal when press Enter key inside focused QLineEdit widget. Commented Mar 19, 2018 at 18:28

1 Answer 1

2

The problem is divided into 2 parts:

1. Detection of the click in QLineEdit.

to detect the mouse click you must use eventFilter:

   ui->lineEdit->installEventFilter(this);

....

bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    if(watched == ui->lineEdit){
        if(event->type() == QEvent::MouseButtonPress){
             // clicked 
             showCalendar();
        }
    }
    return QMainWindow::eventFilter(watched, event);
}

2. Show the Dialog and get the selected date:

The first task is to remove the Item {}, and only keep the Dialog, and adding the selectedDate property that will be the selected date.

popularCalendar.qml

import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.2

Dialog {
    id: dialogCalendar
    property date selectedDate: new Date()
    // Задаём размеры диалогового окна
    width: 250
    height: 300

    // Создаем контент диалогового окна
    contentItem: Rectangle {
        id: dialogRect
        color: "#f7f7f7"

        // Первым идёт кастомный календарь
        Calendar {
            id: calendar
            // Размещаем его в верхней части диалога и растягиваем по ширине
            anchors.top: parent.top
            anchors.left: parent.left
            anchors.right: parent.right
            anchors.bottom: row.top

            // Стилизуем Календарь
            style: CalendarStyle {

                // Стилизуем navigationBar
                navigationBar: Rectangle {
                    /* Он будет состоять из прямоугольника,
                         * в котором будет располагаться две кнопки и label
                         * */
                    height: 48
                    color: "#f7f7f7"

                    /* Горизонтальный разделитель,
                         * который отделяет navigationBar от поля с  числами
                         * */
                    Rectangle {
                        color: "#d7d7d7"
                        height: 1
                        width: parent.width
                        anchors.bottom: parent.bottom
                    }

                    // Кнопка промотки месяцев назад
                    Button {
                        id: previousMonth
                        width: parent.height - 8
                        height: width
                        anchors.verticalCenter: parent.verticalCenter
                        anchors.left: parent.left
                        anchors.leftMargin: 8

                        /* По клику по кнопке вызываем функцию
                             * календаря, которая отматывает месяц назад
                             * */
                        onClicked: control.showPreviousMonth()

                        // Стилизуем кнопку
                        style: ButtonStyle {
                            background: Rectangle {
                                // Окрашиваем фон кнопки
                                color: "#f7f7f7"
                                /* И помещаем изображение, у которго будет
                                     * два источника файлов в зависимости от того
                                     * нажата кнопка или нет
                                     */
                                Image {
                                    source: control.pressed ? "left_arrow_disable.png" : "left_arrow.png"
                                    width: parent.height - 8
                                    height: width
                                }
                            }
                        }
                    }

                    // Помещаем стилизованный label
                    Label {
                        id: dateText
                        /* Забираем данные из title календаря,
                             * который в данном случае не будет виден
                             * и будет заменён данным label
                             */
                        text: styleData.title
                        color:  "#34aadc"
                        elide: Text.ElideRight
                        horizontalAlignment: Text.AlignHCenter
                        font.pixelSize: 16
                        anchors.verticalCenter: parent.verticalCenter
                        anchors.left: previousMonth.right
                        anchors.leftMargin: 2
                        anchors.right: nextMonth.left
                        anchors.rightMargin: 2
                    }

                    // Кнопка промотки месяцев вперёд
                    Button {
                        id: nextMonth
                        width: parent.height - 8
                        height: width
                        anchors.verticalCenter: parent.verticalCenter
                        anchors.right: parent.right

                        /* По клику по кнопке вызываем функцию
                             * календаря, которая отматывает месяц назад
                             * */
                        onClicked: control.showNextMonth()

                        // Стилизуем кнопку
                        style: ButtonStyle {
                            // Окрашиваем фон кнопки
                            background: Rectangle {
                                color: "#f7f7f7"
                                /* И помещаем изображение, у которго будет
                                     * два источника файлов в зависимости от того
                                     * нажата кнопка или нет
                                     */
                                Image {
                                    source: control.pressed ? "right_arrow_disable.png" : "right_arrow.png"
                                    width: parent.height - 8
                                    height: width
                                }
                            }
                        }
                    }
                }


                // Стилизуем отображением квадратиков с числами месяца
                dayDelegate: Rectangle {
                    anchors.fill: parent
                    anchors.margins: styleData.selected ? -1 : 0
                    // Определяем цвет в зависимости от того, выбрана дата или нет
                    color: styleData.date !== undefined && styleData.selected ? selectedDateColor : "transparent"

                    // Задаём предопределённые переменные с цветами, доступные только для чтения
                    readonly property color sameMonthDateTextColor: "#444"
                    readonly property color selectedDateColor: "#34aadc"
                    readonly property color selectedDateTextColor: "white"
                    readonly property color differentMonthDateTextColor: "#bbb"
                    readonly property color invalidDateColor: "#dddddd"

                    // Помещаем Label для отображения числа
                    Label {
                        id: dayDelegateText
                        text: styleData.date.getDate() // Устанавливаем число в текущий квадрат
                        anchors.centerIn: parent
                        horizontalAlignment: Text.AlignRight
                        font.pixelSize: 10

                        // Установка цвета
                        color: {
                            var theColor = invalidDateColor; // Устанавливаем невалидный цвет текста
                            if (styleData.valid) {
                                /* Определяем цвет текста в зависимости от того
                                     * относится ли дата к выбранному месяцу или нет
                                     * */
                                theColor = styleData.visibleMonth ? sameMonthDateTextColor : differentMonthDateTextColor;
                                if (styleData.selected)
                                    // Перекрашиваем цвет текста, если выбрана данная дата в календаре
                                    theColor = selectedDateTextColor;
                            }
                            theColor;
                        }
                    }
                }
            }
        }

        // Делаем панель с кнопками
        Row {
            id: row
            height: 48
            anchors.left: parent.left
            anchors.right: parent.right
            anchors.bottom: parent.bottom

            // Кнопка для закрытия диалога
            Button {
                id: dialogButtonCalCancel
                anchors.top: parent.top
                anchors.bottom: parent.bottom
                width: parent.width / 2 - 1

                style: ButtonStyle {
                    background: Rectangle {
                        color: control.pressed ? "#d7d7d7" : "#f7f7f7"
                        border.width: 0
                    }

                    label: Text {
                        text: qsTr("Cancel")
                        font.pixelSize: 14
                        color: "#34aadc"
                        verticalAlignment: Text.AlignVCenter
                        horizontalAlignment: Text.AlignHCenter
                    }
                }
                // По нажатию на кнопку - просто закрываем диалог
                onClicked: dialogCalendar.close()
            }

            // Вертикальный разделитель между кнопками
            Rectangle {
                id: dividerVertical
                width: 2
                anchors.top: parent.top
                anchors.bottom: parent.bottom
                color: "#d7d7d7"
            }

            // Кнопка подтверждения выбранной даты
            Button {
                id: dialogButtonCalOk
                anchors.top: parent.top
                anchors.bottom: parent.bottom
                width: parent.width / 2 - 1

                style: ButtonStyle {
                    background: Rectangle {
                        color: control.pressed ? "#d7d7d7" : "#f7f7f7"
                        border.width: 0
                    }

                    label: Text {
                        text: qsTr("Ok")
                        font.pixelSize: 14
                        color: "#34aadc"
                        verticalAlignment: Text.AlignVCenter
                        horizontalAlignment: Text.AlignHCenter
                    }
                }

                /* По клику по кнопке сохраняем выбранную дату во временную переменную
                     * и помещаем эту дату на кнопку в главном окне,
                     * после чего закрываем диалог
                     */
                onClicked: {
                    dialogCalendar.selectedDate = calendar.selectedDate
                    dialogCalendar.close()
                }
            }
        }
    }

    /* Данная функция необходима для того, чтобы
         * установить дату с кнопки в календарь,
         * иначе календарь откроется с текущей датой
         */
    function show(x){
        calendar.selectedDate = x
        dialogCalendar.open()
    }
}

and then load and create that component using QQmlComponent.

*.h

class MainWindow : public QMainWindow
{
    ...
private:
    void showCalendar();
    Q_SLOT void onSelectedDate();

    QObject *dialog = Q_NULLPTR;
    QQmlEngine *engine;
    QQmlComponent *component;
    ....
};

*.cpp

// constructor
engine = new QQmlEngine(this);
component = new QQmlComponent(engine, QUrl(QStringLiteral("qrc:/popupCalendar.qml")), this);

and then using a previous answer with the help of QMetaObject we connect the signal associated with the property selectedDate with a slot, in addition we call the show function implemented in the QML.

void MainWindow::showCalendar()
{
    if(dialog == Q_NULLPTR){
        dialog = component->create();
        int index = dialog->metaObject()->indexOfProperty("selectedDate");
        const QMetaProperty property = dialog->metaObject()->property(index);
        if (property.hasNotifySignal()){
            const QMetaMethod s = property.notifySignal();
            QString sig = QString("2%1").arg(QString(s.methodSignature()));
            connect(dialog, sig.toStdString().c_str() , this, SLOT(onSelectedDate()));
        }
    }
    QMetaObject::invokeMethod(dialog, "show", Q_ARG(QVariant, QVariant(QDate::currentDate())));
}

void MainWindow::onSelectedDate()
{
    ui->lineEdit->setText(dialog->property("selectedDate").toDate().toString());
    ui->lineEdit->adjustSize();
}

The complete code can be found at the following link.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.