QML 中的时间选择器
Time Picker in QML
我需要让用户能够 select QML 应用程序中的日期和时间。对于 selection 日期,QtQuick 控件中有 Calendar
。
我还没有找到类似的控件来让用户 select 一天中的时间。
互联网上有几个例子,例如 Grog or Harmattan。
然而,我假设它们不像其他 QtQuick 控件那样与本机外观和感觉集成。
是否有我不知道的标准方法、我没有遇到过的好的替代方法或有关选择的建议?
从 Qt 5.5 开始,所谓的 Qt Quick Enterprise Controls will be available also in the community edition of Qt under the name Qt Quick Extras. Among the others, the Tumbler
似乎是满足您要求的可行解决方案:您可以轻松设置两列,一列用于小时,一列用于分钟。
如果您仍然对循环 selection 感兴趣(或者想实现您自己的不倒翁),您可以采用不同的方法,例如创建您自己的继承自 QQuickItem
or QQuickPaintedItem
or exploiting a custom view with PathView
的组件。后者是我将在这个答案中介绍的情况。有关自定义组件创建的示例,请参阅提供的链接。
引用 PathView
的文档:
The view has a model, which defines the data to be displayed, and a delegate, which defines how the data should be displayed. The delegate is instantiated for each item on the path. The items may be flicked to move them along the path.
因此,路径定义了项目在屏幕上的布局方式,即使是以圆形方式。路径可以通过 Path
type, i.e. a sequence of path segments of different kind. PathArc
构建,这是我们感兴趣的路径,因为它提供了所需的圆形。
以下示例使用这些元素来定义循环时间选择器。每个路径都是通过利用委托的 currentIndex
构造的:一个整数用作 PathView
s 的模型 - 12
用于小时视图,6
用于分钟视图, 分别。代表的文本是通过利用 index
附加的 属性 并对其进行操作以生成小时和 10 分钟的间隔值来生成的(请参阅代表 Text
项目)。最后,当前元素的文本(即currentItem
)绑定到window中心的时间标签:随着currentIndex
和currentItem
的变化,也标签得到更新。
整体组件如下所示:
highlight
组件(蓝色和绿色圆圈)用于图形表示时间的编辑:可见时可以编辑时间,即路径的另一个Item
可以是select编辑。单击中心的时间标签可在正常模式和编辑模式之间切换。
在编辑模式下,用户只需将不同的 hours/minutes 值悬停在 select 上即可。如果单击新 selected hour/minute,则针对该特定 PathView
的编辑将被禁用,相应的突出显示圆圈将消失。
这段代码显然只是一个玩具示例,目的是让您了解 PathView
的用途。可以做一些改进,例如动画,更好的数字定位,详细的分钟表示,漂亮的背景等等。但是它们超出了范围 w.r.t。这个问题并没有被考虑。
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls.Styles 1.3
import QtQuick.Layouts 1.1
Window {
visible: true
width: 280; height: 280
RowLayout { // centre time label
anchors.centerIn: parent
Text {
id: h
font.pixelSize: 30
font.bold: true
text: outer.currentItem.text
}
Text {
id: div
font.pixelSize: 30
font.bold: true
text: qsTr(":")
}
Text {
id: m
font.pixelSize: 30
font.bold: true
text: inner.currentItem.text
}
MouseArea {
anchors.fill: parent
onClicked: outer.choiceActive = inner.choiceActive = !outer.choiceActive
}
}
PathView { // hours path
id: outer
property bool pressed: false
model: 12
interactive: false
highlightRangeMode: PathView.NoHighlightRange
property bool choiceActive: false
highlight: Rectangle {
id: rect
width: 30 * 1.5
height: width
radius: width / 2
border.color: "darkgray"
color: "steelblue"
visible: outer.choiceActive
}
delegate: Item {
id: del
width: 30
height: 30
property bool currentItem: PathView.view.currentIndex == index
property alias text : textHou.text
Text {
id: textHou
anchors.centerIn: parent
font.pixelSize: 24
font.bold: currentItem
text: index + 1
color: currentItem ? "black" : "gray"
}
MouseArea {
anchors.fill: parent
enabled: outer.choiceActive
onClicked: outer.choiceActive = false
hoverEnabled: true
onEntered: outer.currentIndex = index
}
}
path: Path {
startX: 200; startY: 40
PathArc {
x: 80; y: 240
radiusX: 110; radiusY: 110
useLargeArc: false
}
PathArc {
x: 200; y: 40
radiusX: 110; radiusY: 110
useLargeArc: false
}
}
}
PathView { // minutes path
id: inner
property bool pressed: false
model: 6
interactive: false
highlightRangeMode: PathView.NoHighlightRange
property bool choiceActive: false
highlight: Rectangle {
width: 30 * 1.5
height: width
radius: width / 2
border.color: "darkgray"
color: "lightgreen"
visible: inner.choiceActive
}
delegate: Item {
width: 30
height: 30
property bool currentItem: PathView.view.currentIndex == index
property alias text : textMin.text
Text {
id: textMin
anchors.centerIn: parent
font.pixelSize: 24
font.bold: currentItem
text: index * 10
color: currentItem ? "black" : "gray"
}
MouseArea {
anchors.fill: parent
enabled: inner.choiceActive
onClicked: inner.choiceActive = false
hoverEnabled: true
onEntered: inner.currentIndex = index
}
}
path: Path {
startX: 140; startY: 60
PathArc {
x: 140; y: 220
radiusX: 40; radiusY: 40
useLargeArc: false
}
PathArc {
x: 140; y: 60
radiusX: 40; radiusY: 40
useLargeArc: false
}
}
}
// to set current time!
onVisibleChanged: {
var d = new Date();
outer.currentIndex = d.getUTCHours() % 12
inner.currentIndex = d.getMinutes() / 10
}
}
我认为我自己的时间选择器很好,你可以根据自己的喜好扩展它的波斯语方向你需要稍微交换一下东西或使用一些布局镜像:
UButton.qml
import QtQuick 2.4
import QtQuick.Controls 2.4
import QtQuick.Controls.Universal 2.4
Button {
id:root
Universal.accent: Universal.Cobalt
Universal.foreground: "white"
highlighted: true
font.family: "B Nazanin"
font.pointSize: 12
}
UCard.qml
import QtQuick 2.4
import QtQuick.Controls 2.4
import QtQuick.Controls.Universal 2.4
import QtGraphicalEffects 1.0
Item{
property alias radius : morakhasiRect.radius
property alias color : morakhasiRect.color
implicitWidth: 150
implicitHeight: 150
Rectangle{
anchors.rightMargin: 1
anchors.leftMargin: 1
anchors.bottomMargin: 1
anchors.topMargin: 1
id:morakhasiRect
anchors.fill: parent
color: "#f5f5f5"
}
DropShadow {
anchors.fill: morakhasiRect
radius: 9.0
samples: 17
color: "#80000000"
source: morakhasiRect
}
}
URect.qml
Rectangle{
color: "transparent"
border.color: Universal.color(Universal.Cobalt)
border.width: 1
}
UTumbler.qml
import QtQuick 2.0
import QtQuick.Controls.Universal 2.4
import QtQuick.Controls 2.4
Tumbler{
id:hourSpin
wrap: false
delegate: Text{
font.pointSize: 12
text: modelData
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
opacity: 1.0 - Math.abs(Tumbler.displacement) / (hourSpin.visibleItemCount / 2)
}
Rectangle {
anchors.horizontalCenter: hourSpin.horizontalCenter
y: hourSpin.height * 0.4
width: 40
height: 1
color: Universal.color(Universal.Cobalt)
}
Rectangle {
anchors.horizontalCenter: hourSpin.horizontalCenter
y: hourSpin.height * 0.6
width: 40
height: 1
color: Universal.color(Universal.Cobalt)
}
}
UTimeDialog
import QtQuick 2.0
import QtQuick.Controls 2.4
import QtQuick.Controls.Universal 2.4
Item{
id:root
property alias hour : hourSpin.currentIndex
property alias minute : minuteSpin.currentIndex
signal open
signal close
signal accepted
signal rejected
visible: element.opened
onOpen: element.open()
onClose: element.close()
implicitWidth: 200
implicitHeight: 200
Dialog {
id: element
modal: true
width: parent.width
height: parent.height
padding: 5
margins: 5
background: Item{
}
onAccepted: {
root.accepted()
}
onRejected: {
root.rejected()
}
contentItem: UCard{
anchors.fill: parent
radius: 10
}
Column{
id: column
spacing: 30
anchors.centerIn: parent
Row{
id: row
spacing: 20
anchors.horizontalCenter: parent.horizontalCenter
Column{
id: column1
spacing: 15
height: 80
width: 50
clip:true
UTumbler{
id:hourSpin
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
model: 24
}
}
Text{
text: ":"
font.pointSize: 12
anchors.verticalCenter: parent.verticalCenter
font.family: "B Nazanin"
}
Column{
id: column2
spacing: 15
height: 80
width: 50
clip:true
UTumbler{
id:minuteSpin
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
model: 60
}
}
}
Row{
anchors.horizontalCenter: parent.horizontalCenter
spacing: 40
UButton{
text:"select"
onClicked: {
element.reject()
}
}
UButton{
text: "cancel"
onClicked: {
element.accept()
}
}
}
}
}
}
UIcoButton.qml
import QtQuick 2.4
import QtQuick.Controls 2.4
import QtQuick.Controls.Universal 2.4
import QtGraphicalEffects 1.0
FocusScope{
id:focusScope
signal clicked
property alias font : icoText.font.family
property alias icon : icoText.text
property alias size : icoText.font.pixelSize
property alias caption : captionTxt.text
property alias spacing : row.spacing
property string colorEnter :Universal.color(Universal.Cobalt)
property string colorExit :"#00171f"
property alias state: root.state
implicitWidth: captionTxt.text!= "" ? 100 : 35
implicitHeight: 40
Rectangle {
id: root
radius: 0
anchors.fill: parent
color: colorExit
state: "default"
focus: true
onFocusChanged: {
if(focus){
root.border.width = 1
root.border.color = Universal.color( Universal.Cobalt)
}
else{
root.border.width = 0
root.border.color = "transparent"
}
}
Row{
id: row
anchors.rightMargin: 5
anchors.leftMargin: 5
anchors.bottomMargin: 5
anchors.topMargin: 5
anchors.fill: parent
layoutDirection: Qt.RightToLeft
spacing: 15
Text {
id: icoText
text: ""
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 25
font.family: "fontawesome"
color: "white"
}
Text{
id:captionTxt
text: ""
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: icoText.font.pixelSize * 55 /100
font.family: "B Nazanin"
color: "white"
visible: text!= ""
}
}
InnerShadow {
id:shadow
anchors.fill: row
radius: 1.0
samples: 17
horizontalOffset: 1
color: colorExit
source: row
visible: false
}
// Glow {
// id:shadow
// anchors.fill: row
// radius: 6
// samples: 25
// color: "white"
// source: row
// visible: false
// }
MouseArea{
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onEntered: {
if(root.state == "default")
root.color = colorEnter
else{
icoText.color = colorEnter
captionTxt.color = colorEnter
}
}
onExited: {
if(root.state == "default")
root.color = colorExit
else{
icoText.color = colorExit
captionTxt.color = colorExit
}
}
onPressed: {
shadow.visible = true
}
onReleased: {
shadow.visible = false
}
onClicked: {
focusScope.clicked()
}
}
states: [
State {
name: "transparent"
PropertyChanges {
target: root
color:"transparent"
}
PropertyChanges {
target: icoText
color:colorExit
}
PropertyChanges {
target: captionTxt
color:colorExit
}
},
State{
name: "default"
PropertyChanges {
target: root
color:"#00171f"
}
PropertyChanges {
target: icoText
color:"white"
}
PropertyChanges {
target: captionTxt
color:"white"
}
}
]
}
}
UTimePicker
import QtQuick 2.4
import QtQuick.Controls 2.4
import QtQuick.Controls.Universal 2.4
Item {
id: scope
clip: true
QtObject{
id:variables
property var time: ({hour: 0, minute: 0})
onTimeChanged: {
refreshDialogTime()
}
}
signal changed
property alias caption : captionTxt.text
property size size : Qt.size(30,70)
property string splitter : ":"
property alias spacing : row.spacing
Component.onCompleted: {
var q = new Date()
var curtime = q.toLocaleTimeString().substring(0,5);
if(splitter != ":"){
curtime.replace(':',splitter)
}
var vars = curtime.split(':')
setTime(vars[0],vars[1])
refreshDialogTime()
}
function refreshDialogTime(){
dialog.hour = variables.time.hour
dialog.minute = variables.time.minute
}
function getTime(){
return variables.time;
}
function setTimeString(time){
textArea.text= time
}
function setTime(hour,minute){
var _hour = hour
if(_hour<10){
_hour = "0"+hour.toString()
}
else{
_hour = hour.toString()
}
var _minute = minute
if(_minute <10){
_minute = "0"+minute.toString()
}
else{
_minute = minute.toString()
}
var time = _hour+":"+_minute
textArea.text = time
}
implicitHeight: 50
implicitWidth: 200
Row{
id: row
width: parent.width
height: parent.height
spacing: 25
layoutDirection: Qt.RightToLeft
Text{
font.bold: true
id: captionTxt
font.pointSize: 12
horizontalAlignment: Text.AlignRight
anchors.verticalCenter: parent.verticalCenter
width: scope.size.width * scope.width /100 - scope.spacing/2
verticalAlignment: Text.AlignVCenter
font.family: "B Nazanin"
}
Item{
id: element
anchors.verticalCenter: parent.verticalCenter
height: parent.height
width: scope.size.height * scope.width /100 - scope.spacing/2
Rectangle{
id:backrec
height: parent.height
anchors.verticalCenter: parent.verticalCenter
width: parent.width
border.width: 1
border.color: "black"
TextField{
id:textArea
selectByMouse: true
anchors.verticalCenter: parent.verticalCenter
height: parent.height
rightPadding: 5
bottomPadding: 5
topPadding: 5
padding: 5
verticalAlignment: Text.AlignVCenter
onFocusChanged: {
if(focus){
captionTxt.color = Universal.color( Universal.Cobalt)
backrec.border.color = Universal.color( Universal.Cobalt)
}
else{
captionTxt.color = "black"
backrec.border.color = "black"
}
}
background: URect{
color: "transparent"
border.color: "black"
border.width: 0
}
onTextChanged: {
var _temp = text.split(splitter)
if(_temp.length>0){
variables.time.hour =_temp[0]==""?0: _temp[0]
variables.time.minute = _temp[1]==""?0:_temp[1]
}
changed()
}
placeholderText : "HH:mm"
anchors.right: parent.right
anchors.left: iconBtn.right
font.family: "B Nazanin"
font.pointSize: 12
inputMask: "99:99"
validator: RegExpValidator { regExp: /^([0-1\s]?[0-9\s]|2[0-3\s]):([0-5\s][0-9\s])$ / }
}
IcoButton{
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 2
id:iconBtn
caption: ""
size: 30
icon: "\uf017"
state: "transparent"
onClicked: {
textArea.focus = true
dialog.open()
}
}
}
}
}
UTimeDialog{
id:dialog
x:iconBtn.x
y:iconBtn.y+ scope.height
onAccepted: {
setTime(hour,minute)
}
}
}
例子
UTimePicker{
x: 285
width: 200
spacing: 15
size: Qt.size(35,65)
caption: "time"
onChanged: {
var i = getTime()
console.log(i.hour)
console.log(i.minute)
}
}
看起来像这样:
用于镜像:
LayoutMirroring.enabled: true
LayoutMirroring.childrenInherit: true
如果有人感兴趣,我可以为此共享图书馆
这是iphone选时风格
Rectangle {
id:clockid
width: frame.implicitWidth + 10
height: frame.implicitHeight + 10
anchors.centerIn: parent
color: "cornsilk"
function formatText(count, modelData) {
var data = count === 12 ? modelData + 1 : modelData;
return data.toString().length < 2 ? "0" + data : data;
}
FontMetrics {
id: fontMetrics
font.pixelSize: 10
}
Component {
id: delegateComponent
Label {
text: clockid.formatText(Tumbler.tumbler.count, modelData)
opacity: 1.0 - Math.abs(Tumbler.displacement) / (Tumbler.tumbler.visibleItemCount / 2)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: fontMetrics.font.pixelSize * 1.25
}
}
Frame {
id: frame
padding: 0
anchors.centerIn: parent
Row {
id: row_clock
Tumbler {
id: hoursTumbler
model: 12
delegate: delegateComponent
visibleItemCount: 5
}
Tumbler {
id: minutesTumbler
model: 60
delegate: delegateComponent
visibleItemCount: 5
}
Tumbler {
id: amPmTumbler
model: ["AM", "PM"]
delegate: delegateComponent
}
}
}
}
我需要让用户能够 select QML 应用程序中的日期和时间。对于 selection 日期,QtQuick 控件中有 Calendar
。
我还没有找到类似的控件来让用户 select 一天中的时间。
互联网上有几个例子,例如 Grog or Harmattan。 然而,我假设它们不像其他 QtQuick 控件那样与本机外观和感觉集成。
是否有我不知道的标准方法、我没有遇到过的好的替代方法或有关选择的建议?
从 Qt 5.5 开始,所谓的 Qt Quick Enterprise Controls will be available also in the community edition of Qt under the name Qt Quick Extras. Among the others, the Tumbler
似乎是满足您要求的可行解决方案:您可以轻松设置两列,一列用于小时,一列用于分钟。
如果您仍然对循环 selection 感兴趣(或者想实现您自己的不倒翁),您可以采用不同的方法,例如创建您自己的继承自 QQuickItem
or QQuickPaintedItem
or exploiting a custom view with PathView
的组件。后者是我将在这个答案中介绍的情况。有关自定义组件创建的示例,请参阅提供的链接。
引用 PathView
的文档:
The view has a model, which defines the data to be displayed, and a delegate, which defines how the data should be displayed. The delegate is instantiated for each item on the path. The items may be flicked to move them along the path.
因此,路径定义了项目在屏幕上的布局方式,即使是以圆形方式。路径可以通过 Path
type, i.e. a sequence of path segments of different kind. PathArc
构建,这是我们感兴趣的路径,因为它提供了所需的圆形。
以下示例使用这些元素来定义循环时间选择器。每个路径都是通过利用委托的 currentIndex
构造的:一个整数用作 PathView
s 的模型 - 12
用于小时视图,6
用于分钟视图, 分别。代表的文本是通过利用 index
附加的 属性 并对其进行操作以生成小时和 10 分钟的间隔值来生成的(请参阅代表 Text
项目)。最后,当前元素的文本(即currentItem
)绑定到window中心的时间标签:随着currentIndex
和currentItem
的变化,也标签得到更新。
整体组件如下所示:
highlight
组件(蓝色和绿色圆圈)用于图形表示时间的编辑:可见时可以编辑时间,即路径的另一个Item
可以是select编辑。单击中心的时间标签可在正常模式和编辑模式之间切换。
在编辑模式下,用户只需将不同的 hours/minutes 值悬停在 select 上即可。如果单击新 selected hour/minute,则针对该特定 PathView
的编辑将被禁用,相应的突出显示圆圈将消失。
这段代码显然只是一个玩具示例,目的是让您了解 PathView
的用途。可以做一些改进,例如动画,更好的数字定位,详细的分钟表示,漂亮的背景等等。但是它们超出了范围 w.r.t。这个问题并没有被考虑。
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls.Styles 1.3
import QtQuick.Layouts 1.1
Window {
visible: true
width: 280; height: 280
RowLayout { // centre time label
anchors.centerIn: parent
Text {
id: h
font.pixelSize: 30
font.bold: true
text: outer.currentItem.text
}
Text {
id: div
font.pixelSize: 30
font.bold: true
text: qsTr(":")
}
Text {
id: m
font.pixelSize: 30
font.bold: true
text: inner.currentItem.text
}
MouseArea {
anchors.fill: parent
onClicked: outer.choiceActive = inner.choiceActive = !outer.choiceActive
}
}
PathView { // hours path
id: outer
property bool pressed: false
model: 12
interactive: false
highlightRangeMode: PathView.NoHighlightRange
property bool choiceActive: false
highlight: Rectangle {
id: rect
width: 30 * 1.5
height: width
radius: width / 2
border.color: "darkgray"
color: "steelblue"
visible: outer.choiceActive
}
delegate: Item {
id: del
width: 30
height: 30
property bool currentItem: PathView.view.currentIndex == index
property alias text : textHou.text
Text {
id: textHou
anchors.centerIn: parent
font.pixelSize: 24
font.bold: currentItem
text: index + 1
color: currentItem ? "black" : "gray"
}
MouseArea {
anchors.fill: parent
enabled: outer.choiceActive
onClicked: outer.choiceActive = false
hoverEnabled: true
onEntered: outer.currentIndex = index
}
}
path: Path {
startX: 200; startY: 40
PathArc {
x: 80; y: 240
radiusX: 110; radiusY: 110
useLargeArc: false
}
PathArc {
x: 200; y: 40
radiusX: 110; radiusY: 110
useLargeArc: false
}
}
}
PathView { // minutes path
id: inner
property bool pressed: false
model: 6
interactive: false
highlightRangeMode: PathView.NoHighlightRange
property bool choiceActive: false
highlight: Rectangle {
width: 30 * 1.5
height: width
radius: width / 2
border.color: "darkgray"
color: "lightgreen"
visible: inner.choiceActive
}
delegate: Item {
width: 30
height: 30
property bool currentItem: PathView.view.currentIndex == index
property alias text : textMin.text
Text {
id: textMin
anchors.centerIn: parent
font.pixelSize: 24
font.bold: currentItem
text: index * 10
color: currentItem ? "black" : "gray"
}
MouseArea {
anchors.fill: parent
enabled: inner.choiceActive
onClicked: inner.choiceActive = false
hoverEnabled: true
onEntered: inner.currentIndex = index
}
}
path: Path {
startX: 140; startY: 60
PathArc {
x: 140; y: 220
radiusX: 40; radiusY: 40
useLargeArc: false
}
PathArc {
x: 140; y: 60
radiusX: 40; radiusY: 40
useLargeArc: false
}
}
}
// to set current time!
onVisibleChanged: {
var d = new Date();
outer.currentIndex = d.getUTCHours() % 12
inner.currentIndex = d.getMinutes() / 10
}
}
我认为我自己的时间选择器很好,你可以根据自己的喜好扩展它的波斯语方向你需要稍微交换一下东西或使用一些布局镜像:
UButton.qml
import QtQuick 2.4
import QtQuick.Controls 2.4
import QtQuick.Controls.Universal 2.4
Button {
id:root
Universal.accent: Universal.Cobalt
Universal.foreground: "white"
highlighted: true
font.family: "B Nazanin"
font.pointSize: 12
}
UCard.qml
import QtQuick 2.4
import QtQuick.Controls 2.4
import QtQuick.Controls.Universal 2.4
import QtGraphicalEffects 1.0
Item{
property alias radius : morakhasiRect.radius
property alias color : morakhasiRect.color
implicitWidth: 150
implicitHeight: 150
Rectangle{
anchors.rightMargin: 1
anchors.leftMargin: 1
anchors.bottomMargin: 1
anchors.topMargin: 1
id:morakhasiRect
anchors.fill: parent
color: "#f5f5f5"
}
DropShadow {
anchors.fill: morakhasiRect
radius: 9.0
samples: 17
color: "#80000000"
source: morakhasiRect
}
}
URect.qml
Rectangle{
color: "transparent"
border.color: Universal.color(Universal.Cobalt)
border.width: 1
}
UTumbler.qml
import QtQuick 2.0
import QtQuick.Controls.Universal 2.4
import QtQuick.Controls 2.4
Tumbler{
id:hourSpin
wrap: false
delegate: Text{
font.pointSize: 12
text: modelData
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
opacity: 1.0 - Math.abs(Tumbler.displacement) / (hourSpin.visibleItemCount / 2)
}
Rectangle {
anchors.horizontalCenter: hourSpin.horizontalCenter
y: hourSpin.height * 0.4
width: 40
height: 1
color: Universal.color(Universal.Cobalt)
}
Rectangle {
anchors.horizontalCenter: hourSpin.horizontalCenter
y: hourSpin.height * 0.6
width: 40
height: 1
color: Universal.color(Universal.Cobalt)
}
}
UTimeDialog
import QtQuick 2.0
import QtQuick.Controls 2.4
import QtQuick.Controls.Universal 2.4
Item{
id:root
property alias hour : hourSpin.currentIndex
property alias minute : minuteSpin.currentIndex
signal open
signal close
signal accepted
signal rejected
visible: element.opened
onOpen: element.open()
onClose: element.close()
implicitWidth: 200
implicitHeight: 200
Dialog {
id: element
modal: true
width: parent.width
height: parent.height
padding: 5
margins: 5
background: Item{
}
onAccepted: {
root.accepted()
}
onRejected: {
root.rejected()
}
contentItem: UCard{
anchors.fill: parent
radius: 10
}
Column{
id: column
spacing: 30
anchors.centerIn: parent
Row{
id: row
spacing: 20
anchors.horizontalCenter: parent.horizontalCenter
Column{
id: column1
spacing: 15
height: 80
width: 50
clip:true
UTumbler{
id:hourSpin
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
model: 24
}
}
Text{
text: ":"
font.pointSize: 12
anchors.verticalCenter: parent.verticalCenter
font.family: "B Nazanin"
}
Column{
id: column2
spacing: 15
height: 80
width: 50
clip:true
UTumbler{
id:minuteSpin
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
model: 60
}
}
}
Row{
anchors.horizontalCenter: parent.horizontalCenter
spacing: 40
UButton{
text:"select"
onClicked: {
element.reject()
}
}
UButton{
text: "cancel"
onClicked: {
element.accept()
}
}
}
}
}
}
UIcoButton.qml
import QtQuick 2.4
import QtQuick.Controls 2.4
import QtQuick.Controls.Universal 2.4
import QtGraphicalEffects 1.0
FocusScope{
id:focusScope
signal clicked
property alias font : icoText.font.family
property alias icon : icoText.text
property alias size : icoText.font.pixelSize
property alias caption : captionTxt.text
property alias spacing : row.spacing
property string colorEnter :Universal.color(Universal.Cobalt)
property string colorExit :"#00171f"
property alias state: root.state
implicitWidth: captionTxt.text!= "" ? 100 : 35
implicitHeight: 40
Rectangle {
id: root
radius: 0
anchors.fill: parent
color: colorExit
state: "default"
focus: true
onFocusChanged: {
if(focus){
root.border.width = 1
root.border.color = Universal.color( Universal.Cobalt)
}
else{
root.border.width = 0
root.border.color = "transparent"
}
}
Row{
id: row
anchors.rightMargin: 5
anchors.leftMargin: 5
anchors.bottomMargin: 5
anchors.topMargin: 5
anchors.fill: parent
layoutDirection: Qt.RightToLeft
spacing: 15
Text {
id: icoText
text: ""
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 25
font.family: "fontawesome"
color: "white"
}
Text{
id:captionTxt
text: ""
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: icoText.font.pixelSize * 55 /100
font.family: "B Nazanin"
color: "white"
visible: text!= ""
}
}
InnerShadow {
id:shadow
anchors.fill: row
radius: 1.0
samples: 17
horizontalOffset: 1
color: colorExit
source: row
visible: false
}
// Glow {
// id:shadow
// anchors.fill: row
// radius: 6
// samples: 25
// color: "white"
// source: row
// visible: false
// }
MouseArea{
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onEntered: {
if(root.state == "default")
root.color = colorEnter
else{
icoText.color = colorEnter
captionTxt.color = colorEnter
}
}
onExited: {
if(root.state == "default")
root.color = colorExit
else{
icoText.color = colorExit
captionTxt.color = colorExit
}
}
onPressed: {
shadow.visible = true
}
onReleased: {
shadow.visible = false
}
onClicked: {
focusScope.clicked()
}
}
states: [
State {
name: "transparent"
PropertyChanges {
target: root
color:"transparent"
}
PropertyChanges {
target: icoText
color:colorExit
}
PropertyChanges {
target: captionTxt
color:colorExit
}
},
State{
name: "default"
PropertyChanges {
target: root
color:"#00171f"
}
PropertyChanges {
target: icoText
color:"white"
}
PropertyChanges {
target: captionTxt
color:"white"
}
}
]
}
}
UTimePicker
import QtQuick 2.4
import QtQuick.Controls 2.4
import QtQuick.Controls.Universal 2.4
Item {
id: scope
clip: true
QtObject{
id:variables
property var time: ({hour: 0, minute: 0})
onTimeChanged: {
refreshDialogTime()
}
}
signal changed
property alias caption : captionTxt.text
property size size : Qt.size(30,70)
property string splitter : ":"
property alias spacing : row.spacing
Component.onCompleted: {
var q = new Date()
var curtime = q.toLocaleTimeString().substring(0,5);
if(splitter != ":"){
curtime.replace(':',splitter)
}
var vars = curtime.split(':')
setTime(vars[0],vars[1])
refreshDialogTime()
}
function refreshDialogTime(){
dialog.hour = variables.time.hour
dialog.minute = variables.time.minute
}
function getTime(){
return variables.time;
}
function setTimeString(time){
textArea.text= time
}
function setTime(hour,minute){
var _hour = hour
if(_hour<10){
_hour = "0"+hour.toString()
}
else{
_hour = hour.toString()
}
var _minute = minute
if(_minute <10){
_minute = "0"+minute.toString()
}
else{
_minute = minute.toString()
}
var time = _hour+":"+_minute
textArea.text = time
}
implicitHeight: 50
implicitWidth: 200
Row{
id: row
width: parent.width
height: parent.height
spacing: 25
layoutDirection: Qt.RightToLeft
Text{
font.bold: true
id: captionTxt
font.pointSize: 12
horizontalAlignment: Text.AlignRight
anchors.verticalCenter: parent.verticalCenter
width: scope.size.width * scope.width /100 - scope.spacing/2
verticalAlignment: Text.AlignVCenter
font.family: "B Nazanin"
}
Item{
id: element
anchors.verticalCenter: parent.verticalCenter
height: parent.height
width: scope.size.height * scope.width /100 - scope.spacing/2
Rectangle{
id:backrec
height: parent.height
anchors.verticalCenter: parent.verticalCenter
width: parent.width
border.width: 1
border.color: "black"
TextField{
id:textArea
selectByMouse: true
anchors.verticalCenter: parent.verticalCenter
height: parent.height
rightPadding: 5
bottomPadding: 5
topPadding: 5
padding: 5
verticalAlignment: Text.AlignVCenter
onFocusChanged: {
if(focus){
captionTxt.color = Universal.color( Universal.Cobalt)
backrec.border.color = Universal.color( Universal.Cobalt)
}
else{
captionTxt.color = "black"
backrec.border.color = "black"
}
}
background: URect{
color: "transparent"
border.color: "black"
border.width: 0
}
onTextChanged: {
var _temp = text.split(splitter)
if(_temp.length>0){
variables.time.hour =_temp[0]==""?0: _temp[0]
variables.time.minute = _temp[1]==""?0:_temp[1]
}
changed()
}
placeholderText : "HH:mm"
anchors.right: parent.right
anchors.left: iconBtn.right
font.family: "B Nazanin"
font.pointSize: 12
inputMask: "99:99"
validator: RegExpValidator { regExp: /^([0-1\s]?[0-9\s]|2[0-3\s]):([0-5\s][0-9\s])$ / }
}
IcoButton{
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 2
id:iconBtn
caption: ""
size: 30
icon: "\uf017"
state: "transparent"
onClicked: {
textArea.focus = true
dialog.open()
}
}
}
}
}
UTimeDialog{
id:dialog
x:iconBtn.x
y:iconBtn.y+ scope.height
onAccepted: {
setTime(hour,minute)
}
}
}
例子
UTimePicker{
x: 285
width: 200
spacing: 15
size: Qt.size(35,65)
caption: "time"
onChanged: {
var i = getTime()
console.log(i.hour)
console.log(i.minute)
}
}
看起来像这样:
用于镜像:
LayoutMirroring.enabled: true
LayoutMirroring.childrenInherit: true
如果有人感兴趣,我可以为此共享图书馆
这是iphone选时风格
Rectangle {
id:clockid
width: frame.implicitWidth + 10
height: frame.implicitHeight + 10
anchors.centerIn: parent
color: "cornsilk"
function formatText(count, modelData) {
var data = count === 12 ? modelData + 1 : modelData;
return data.toString().length < 2 ? "0" + data : data;
}
FontMetrics {
id: fontMetrics
font.pixelSize: 10
}
Component {
id: delegateComponent
Label {
text: clockid.formatText(Tumbler.tumbler.count, modelData)
opacity: 1.0 - Math.abs(Tumbler.displacement) / (Tumbler.tumbler.visibleItemCount / 2)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: fontMetrics.font.pixelSize * 1.25
}
}
Frame {
id: frame
padding: 0
anchors.centerIn: parent
Row {
id: row_clock
Tumbler {
id: hoursTumbler
model: 12
delegate: delegateComponent
visibleItemCount: 5
}
Tumbler {
id: minutesTumbler
model: 60
delegate: delegateComponent
visibleItemCount: 5
}
Tumbler {
id: amPmTumbler
model: ["AM", "PM"]
delegate: delegateComponent
}
}
}
}