cmolina
cmolina

Reputation: 1378

Is there any DatePicker control for Qt 5?

I'm writing my first QML/Javascript app for QtQuick 2.0. I need to place a DatePicker control, but I haven't found any control like that under QtQuick.Controls -and nowhere, in fact-.

I'm starting to believe there is no way to call a 'native' DatePicker in QML. Do I have to implement one or there is exist one?

Upvotes: 13

Views: 14584

Answers (4)

anderas
anderas

Reputation: 5854

Just in case anyone else stumbles upon this, there is a Calendar element in QtQuick.Controls by now. This should make the implementation of such a Datepicker a lot easier: Calendar QML Type.

Upvotes: 9

Yubo
Yubo

Reputation: 408

I wrote another date picker, relying purely on the JavaScript Date object as follows. It adheres to material design.

enter image description here

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.15
import QtQuick.Controls.Material.impl 2.15

Pane {
    id: control
    property int radius: 2

    background: Rectangle {
        color: control.Material.background
        radius: control.Material.elevation > 0 ? control.radius : 0

        layer.enabled: control.enabled && control.Material.elevation > 0
        layer.effect: ElevationEffect {
            elevation: control.Material.elevation
        }
    }
}

And then, here is it

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls.Material 2.15


Rectangle {
    id: root

    property int month: selectedDate.getMonth()
    property int year: selectedDate.getFullYear()
    property int day: selectedDate.getDate()
    property int weekday: selectedDate.getDay()
    property int daysInMonth: new Date(year, month + 1, 0).getDate()

    property date selectedDate: new Date()

    property int _start_weekday: new Date(year, month, 1).getDay()

    implicitWidth: layout.width
    implicitHeight: layout.height
    color: "transparent"

    ColumnLayout {
        id: layout

        Rectangle {
            id: title
            implicitHeight: 40
            Layout.fillWidth: true
            color: "transparent"

            Text {
                anchors.fill: parent
                anchors.leftMargin: 8

                text: selectedDate.toLocaleDateString(Qt.locale(), "ddd, MMM d")
                font.pixelSize: 40
            }
        }

        Rectangle {
            color: "transparent"
            implicitHeight: 28
            Layout.fillWidth: true
        }

        Rectangle {
            id: controls
            color: "transparent"
            implicitHeight: 24

            RowLayout {
                anchors.fill: parent
                anchors.leftMargin: 8
                spacing: 16
                Layout.alignment: Qt.AlignHCenter

                Text {
                    text: selectedDate.toLocaleDateString(Qt.locale(), "MMMM yyyy")
                    font.pixelSize: 16
                }

                RoundButton {
                    id: monthButton
                    contentItem: MIcon {
                        icon: "expand_more"
                        color: "black"
                        size: 16
                    }
                    Material.elevation: 0
                    onClicked: {
                        monthMenu.open()
                    }

                    Menu {
                        id: monthMenu
                        Repeater {
                            model: 12
                            MenuItem {
                                text: new Date(2020, index, 1).toLocaleDateString(Qt.locale(), "MMMM")
                                onTriggered: {
                                    set_month(index)
                                    monthMenu.close()
                                }
                            }
                        }
                    }
                }


                // 2 button to change month <>
                RowLayout {
                    Layout.alignment: Qt.AlignRight
                    spacing: 8

                    RoundButton {
                        Material.background: 'transparent'
                        contentItem: MIcon {
                            icon: 'navigate_before'
                            color: 'black'
                            size: 16
                        }
                        onClicked: {
                            set_month(month - 1)
                        }
                    }

                    RoundButton {
                        Material.background: 'transparent'
                        contentItem: MIcon {
                            icon: 'navigate_next'
                            color: 'black'
                            size: 16
                        }
                        onClicked: {
                            set_month(month + 1)
                        }
                    }
                }
            }
        }

        Rectangle {
            color: "transparent"
            implicitHeight: 16
            Layout.fillWidth: true
        }

        Rectangle {
            color: Material.accent
            implicitHeight: 1
            Layout.fillWidth: true
        }

        // Sunday - Saturday
        RowLayout {
            Layout.alignment: Qt.AlignHCenter
            Layout.fillWidth: true
            spacing: 4

            Repeater {
                model: 7
                Rectangle { // just for spacing
                    width: 40
                    height: 40
                    color: "transparent"

                    Text {
                        anchors.centerIn: parent
                        Layout.fillWidth: true
                        text: new Date(2020, 0, index - 2).toLocaleDateString(Qt.locale(), "ddd").slice(0, 1)
                        font.pixelSize: 16
                        horizontalAlignment: Text.AlignHCenter
                    }
                }
            }
        }

        // calendar
        GridLayout {
            id: grid
            columns: 7
            rows: 6
            columnSpacing: 4
            rowSpacing: 4

            Repeater {
                model: 42

                delegate: Rectangle {
                    color: default_color()
                    radius: 20

                    border.width: 1
                    border.color: is_selected() ? Material.accent : "transparent"

                    width: 40
                    height: 40

                    Text {
                        anchors.centerIn: parent
                        text: get_day()
                        color: in_current_month() ? 'black' : 'gray'
                    }

                    MouseArea {
                        anchors.fill: parent
                        hoverEnabled: true
                        onEntered: {
                            cursorShape = Qt.PointingHandCursor
                            color = Material.color(Material.accent, Material.Shade200)
                        }
                        onExited: {
                            cursorShape = Qt.ArrowCursor
                            color = default_color()
                        }
                        onClicked: {
                            var _day = get_day()
                            if (!in_current_month()){
                                if (index < _start_weekday) {
                                    set_month(month - 1)
                                } else {
                                    set_month(month + 1)
                                }
                            }
                            set_day(_day)
                        }
                    }

                    function default_color() {
                        return 'transparent'
                    }

                    function in_current_month() {
                        return index >= _start_weekday && (index - _start_weekday) < daysInMonth
                    }

                    function is_selected() {
                        return day == get_day() && in_current_month()
                    }

                    function get_day() {
                        var this_day = index - _start_weekday + 1
                        if (this_day > daysInMonth) {
                            return this_day - daysInMonth
                        } else if (this_day < 1) {
                            return new Date(year, month, 0).getDate() + this_day
                        } else {
                            return this_day
                        }
                    }
                }
            }
        }
    }

    function set_month(month) {
        var days_in = new Date(year, month + 1, 0).getDate()
        var new_day = Math.min(day, days_in)
        selectedDate = new Date(year, month, new_day)
    }

    function set_day(day) {
        day = Math.min(day, daysInMonth)
        selectedDate = new Date(year, month, day)
    }
}

Upvotes: 1

Lenil K V
Lenil K V

Reputation: 31

**Code for DatePicker. Try this one **

*TextField {
    id: textDate
    x: 10
    y: 42
    width: 175
    height: 33
    placeholderText: qsTr("Text Field")
    text:Qt.formatDate(cal.selectedDate, "dd-MM-yyyy")
    font.bold: true
    font.family:"times new roman"
    font.pointSize: 12
}
Button {
    id: button
    x: 198
    y: 42
    width: 25
    height: 29
    Image {
        x: -4
        y: -4
        id: img
        width: 36
            height: 44
            source: "/Images/calendar-512.png"
    }
    onClicked:{
        cal.visible=true
    }
}
Calendar{
           id:cal
           x: 10
           y: 82
           width: 220
           height: 205
           visible: false
           selectedDate: new Date()
           onClicked:  {
               textDate.text=Qt.formatDate(cal.selectedDate, "dd-MM-yyyy");
                cal.visible=false
           }
}*

Upvotes: 3

cmolina
cmolina

Reputation: 1378

Well, I had to make my own control. It is called Datepicker.

Datepicker example

It is intented to used in this way:

import QtQuick.Controls 1.1

ApplicationWindow {
    id: main

    Datepicker {
        id: myDate
        activeWindow: main
        width: 200
    }
}

It asumes you are using it from a Window object, and needs the parent reference to show the datepicker in the correct position (it shows a calendar in a new window).

You can download the source code from: https://bitbucket.org/camolin3/datepicker

This is the first version and need a lot of polish to be ready, but is a start point.

Upvotes: 7

Related Questions