Qt
、 Qml
、 Time
、 时间
、 系统
欢迎来到我们的 QML & C++ 项目!这个项目结合了 QML(Qt Meta-Object Language)和 C++ 的强大功能,旨在开发出色的用户界面和高性能的后端逻辑。
在项目中,我们利用 QML 的声明式语法和可视化设计能力创建出现代化的用户界面。通过直观的编码和可重用的组件,我们能够迅速开发出丰富多样的界面效果和动画效果。同时,我们利用 QML 强大的集成能力,轻松将 C++ 的底层逻辑和数据模型集成到前端界面中。
在后端方面,我们使用 C++ 编写高性能的算法、数据处理和计算逻辑。C++ 是一种强大的编程语言,能够提供卓越的性能和可扩展性。我们的团队致力于优化代码,减少资源消耗,以确保我们的项目在各种平台和设备上都能够高效运行。
无论您是对 QML 和 C++ 开发感兴趣,还是需要我们为您构建复杂的用户界面和后端逻辑,我们都随时准备为您提供支持。请随时联系我们,让我们一同打造现代化、高性能的 QML & C++ 项目!
重要说明☝
☀该专栏在第三代软开发更新完将涨价
因为Qt目前好像没有针对这个的库,所以目前的实现是基于Linux的,准确是是Ubuntu22.04版本。
这是来之我们公司小伙伴的作品,我们今天就学习一下。顺带Review一下,看看能不能发现什么BUG。
其实之前这位小伙伴搞复杂了,想着用什么控件啥的,其实Linux是啥,最便捷的就只指令代码,我最开始给他的就是前端qml吧界面撸出来,后端发个指令设置下时间就OK了,不过看他第一版的时候好像整了不少东西,后面好像改成指令。
你看看,少叮嘱一句也不行,上来就给我手撸一个Tumbler
;
这里要给大家推荐一下Qt Desing Studio
,不是说这个有多香,反正我是不喜欢用,qml 我都是纯手撸代码,如果我们不知道一个东西Qt 到底有没有给我们实现的时候,可以用它看看。
你看,这不Qt已经为咱们写了吗。
不过小伙伴写都写了,咱们还是看一下吧
import QtQuick 2.12
import QtQuick.Layouts 1.12
Rectangle {
id: rootRec
color: "transparent"
property int min: -1
property int max: -1
property int current: -1
property int zero: 0
//获取最终结果
function getResult(){
return (myPathView.currentIndex + root.min)
}
ColumnLayout{
anchors.fill: parent
Item {
Layout.fillHeight: true
Layout.fillWidth: true
Layout.margins: 10
PathView{
id: myPathView
anchors.fill: parent
currentIndex: (-1 === rootRec.current) ? 0 : (rootRec.current - rootRec.min)
onCurrentIndexChanged: { rootRec.current = currentIndex + rootRec.min; }
model: (rootRec.max - rootRec.min + 1)
delegate: Item{//
width:myPathView.width/2
height:myPathView.height/myPathView.pathItemCount
scale: PathView.iconScale!==undefined?PathView.iconScale:1
opacity: PathView.iconOpacity!==undefined?PathView.iconOpacity:1
z:PathView.iconZ!==undefined?PathView.iconZ:1
transform: Rotation {
origin.x: width/2
origin.y: height/2
axis.x: 1
axis.y: 0
axis.z: 0
angle: PathView.iconAngle!==undefined?PathView.iconAngle:0
}
Text{
id:timeText
anchors.centerIn: parent
text: String(Number(modelData) + rootRec.min).padStart(rootRec.zero, '0')
color: PathView.isCurrentItem ? "#0099ff" : Qt.lighter("#FFFFFF")
font.pixelSize: 20
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
}
pathItemCount: 5
preferredHighlightBegin: 0.5
preferredHighlightEnd: 0.5
highlightRangeMode: PathView.StrictlyEnforceRange
//交互属性,支持拖动等……
interactive: true
//滑动速度
maximumFlickVelocity:100
path :pathVertical
Path{//------------垂直变化------------
id:pathVertical
property int height: myPathView.height
startX: myPathView.width/2
PathLine { id:line1; x: pathVertical.startX; y: pathVertical.startY; }
PathAttribute { name: "iconZ"; value: 1 }
PathAttribute { name: "iconScale"; value: 0.6 }
PathAttribute { name: "iconOpacity"; value: 0.3 }
PathAttribute { name: "iconAngle"; value: 80 }
PathPercent { value: 0 }
// start scaling up
PathLine { id:line2; x: line1.x; y: line1.y + pathVertical.height; }
PathAttribute { name: "iconZ"; value: 2 }
PathAttribute { name: "iconScale"; value: 0.8 }
PathAttribute { name: "iconOpacity"; value: 0.4 }
PathAttribute { name: "iconAngle"; value: 50 }
PathPercent { value: 1/4 }
// middle point
PathLine { x: line2.x; y: line2.y; }
PathAttribute { name: "iconZ"; value: 5 }
PathAttribute { name: "iconScale"; value: 1.0 }
PathAttribute { name: "iconOpacity"; value:1.0 }
PathAttribute { name: "iconAngle"; value: 0 }
PathPercent { value: 2/4}
// start scaling down
PathLine { x: line2.x; y: line2.y; }
PathAttribute { name: "iconZ"; value: 2 }
PathAttribute { name: "iconScale"; value: 0.8}
PathAttribute { name: "iconOpacity"; value: 0.4 }
PathAttribute { name: "iconAngle"; value: -50 }
PathPercent { value: 3/4 }
// last point
PathLine { x: line2.x; y: line2.y; }
PathAttribute { name: "iconZ"; value: 1 }
PathAttribute { name: "iconScale"; value: 0.6 }
PathAttribute { name: "iconOpacity"; value:0.3 }
PathAttribute { name: "iconAngle"; value: -80 }
PathPercent { value: 1}
}
}
}
}
}
通过帮助文档,咱们可以看到有两个版本的 Tumbler,如下图所示
示例代码如下:
import QtQuick 2.12
import QtQuick.Window 2.2
import QtQuick.Controls 2.12
Rectangle {
width: frame.implicitWidth + 10
height: frame.implicitHeight + 10
function formatText(count, modelData) {
var data = count === 12 ? modelData + 1 : modelData;
return data.toString().length < 2 ? "0" + data : data;
}
FontMetrics {
id: fontMetrics
}
Component {
id: delegateComponent
Label {
text: 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
Tumbler {
id: hoursTumbler
model: 12
delegate: delegateComponent
}
Tumbler {
id: minutesTumbler
model: 60
delegate: delegateComponent
}
Tumbler {
id: amPmTumbler
model: ["AM", "PM"]
delegate: delegateComponent
}
}
}
}
当然,我们也可以自定义 Tumbler,官方示例如下:
import QtQuick 2.12
import QtQuick.Controls 2.12
Tumbler {
id: control
model: 15
background: Item {
Rectangle {
opacity: control.enabled ? 0.2 : 0.1
border.color: "#000000"
width: parent.width
height: 1
anchors.top: parent.top
}
Rectangle {
opacity: control.enabled ? 0.2 : 0.1
border.color: "#000000"
width: parent.width
height: 1
anchors.bottom: parent.bottom
}
}
delegate: Text {
text: qsTr("Item %1").arg(modelData + 1)
font: control.font
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
opacity: 1.0 - Math.abs(Tumbler.displacement) / (control.visibleItemCount / 2)
}
Rectangle {
anchors.horizontalCenter: control.horizontalCenter
y: control.height * 0.4
width: 40
height: 1
color: "#21be2b"
}
Rectangle {
anchors.horizontalCenter: control.horizontalCenter
y: control.height * 0.6
width: 40
height: 1
color: "#21be2b"
}
}
这里还有两个更高级的版本,不过我没有用过,咱们帖一下,占点字符空间哈
If you want to define your own contentItem, use either a ListView or PathView as the root item. For a wrapping Tumbler, use PathView:
Tumbler { id: tumbler contentItem: PathView { id: pathView model: tumbler.model delegate: tumbler.delegate clip: true pathItemCount: tumbler.visibleItemCount + 1 preferredHighlightBegin: 0.5 preferredHighlightEnd: 0.5 dragMargin: width / 2 path: Path { startX: pathView.width / 2 startY: -pathView.delegateHeight / 2 PathLine { x: pathView.width / 2 y: pathView.pathItemCount * pathView.delegateHeight - pathView.delegateHeight / 2 } } property real delegateHeight: tumbler.availableHeight / tumbler.visibleItemCount } }
For a non-wrapping Tumbler, use ListView:
Tumbler { id: tumbler contentItem: ListView { model: tumbler.model delegate: tumbler.delegate snapMode: ListView.SnapToItem highlightRangeMode: ListView.StrictlyEnforceRange preferredHighlightBegin: height / 2 - (height / tumbler.visibleItemCount / 2) preferredHighlightEnd: height / 2 + (height / tumbler.visibleItemCount / 2) clip: true } }
官方示例如下:
The Tumbler control is used with one or more TumblerColumn items, which define the content of each column:
Tumbler {
TumblerColumn {
model: 5
}
TumblerColumn {
model: [0, 1, 2, 3, 4]
}
TumblerColumn {
model: ["A", "B", "C", "D", "E"]
}
}
You can also use a traditional model with roles:
Rectangle {
width: 220
height: 350
color: "#494d53"
ListModel {
id: listModel
ListElement {
foo: "A"
bar: "B"
baz: "C"
}
ListElement {
foo: "A"
bar: "B"
baz: "C"
}
ListElement {
foo: "A"
bar: "B"
baz: "C"
}
}
Tumbler {
anchors.centerIn: parent
TumblerColumn {
model: listModel
role: "foo"
}
TumblerColumn {
model: listModel
role: "bar"
}
TumblerColumn {
model: listModel
role: "baz"
}
}
}
哎,甭管那些了,总之目前是实现了功能了,咱们还是看看C++端的实现代码吧,后期如果有机会,我在尝试下
/**
* @brief XXXX::updateTime
* @param strTime
* @return
* 更新时间
*/
int XXXX::updateTime(QString strTime)
{
QString strDate = strTime.split(" ").at(0);
QString strTimer = strTime.split(" ").at(1);
QString year = strDate.split("-").at(0); //年
QString month = strDate.split("-").at(1); //月
QString day = strDate.split("-").at(2); //日
QString hour = strTimer.split(":").at(0); //时
QString min = strTimer.split(":").at(1); //分
QString second = strTimer.split(":").at(2); //秒
QString a = "date -s" + year + "/" + month + "/" + day;
QString b = "date -s" + hour + ":" + min + ":" + second;
char *ch;
QByteArray ba = a.toLatin1();
ch = ba.data();
char *ch_2;
QByteArray ba_2 = b.toLatin1();
ch_2 = ba_2.data();
system(ch);
system(ch_2);
//强制写入到CMOS
system("hwclock -w");
return 1;
}
如我所愿,最后还是还是用了指令的方式实现了。
不尽人意。目前功能开发工作量比较大,先这么滴吧,以实现功能优先,后期再重构。目前这个我也只能分享官方的示例代码,我没有实际写过这个模块。小弟也没有问我,而我也在忙着撸自己的KPI,没有及时Review他的代码,看到实现功能就给过了,没想到呀,不过其实也如你所愿,可能我们的领导并不关注我们的实现方式是否合理,在某一特定条件下,他可能更看重结果。不顾纸是包不住火的,在他时间宽裕的时候,总是会在回头看看的,所以小伙伴们,在条件的允许的情况下,还是要确保你的代码尽可能的合理。