如何编写整洁的Qml代码

如何编写整洁的Qml代码

无疑,使用Qml技术能够开发出符合当前趋势的杰出的用户界面。Qml语言有着简洁和易学的语法,但代码并非天然就有清晰的层次。如果不注意,很容易搞乱。因此,需要学习如何编写整洁的Qml代码,以使你的程序易于维护。进而节省成本和时间。

Qml代码整洁的关键

到底是什么使得Qml代码整洁?本文从这一问题出发。代码会一团糟吗?是的,如果你不意识到这一点,会不小心在很多地方做错。

Qml代码格式

代码的风格主是代码格式化的方式。是代码看起来的样子。我发现这个定义非常平实易懂。它虽然不影响程序的运行,但它确实影响了代码的可读性。所以,它影响了程序的可维护性,也会耗费开发者未来做出改变的时间。
代码的格式涉及缩进、空格及换行的使用、代码分组及组织。这大多关乎个人习惯,没必要为诸如括号应该在哪儿这样的小问题较真。目标是在整个项目中有一致的代码格式。我见过有的软件开发者自已都没有一致的代码格式,那在多人在同一代码库中协同开发时就更显困难。这是尝试自动代码格式的原因。

Tip #1 更好的代码格式

Qml 代码倾向于有许多嵌套级别,并且代码很快就会向右延伸太多。因此,我的第一个建议是,将缩进减至2个空格以降低影响。
为了能实现这个目的,进入Qt Creator 的Tools->Options菜单,并找到Qt Quick设置。会找到一个关于代码风格的Tab页。你无法修改默认风格,但可以点Copy铵钮以创建自己的风格。
为自己新建的代码风格命名后,点击Edit按钮来为新风格修改细节。这里可以调整更多细节,但至少先将缩进做下修改。你会看到缩进和Tab的大小都是4。将它们减至2。这些更改应会反映在代码编辑器和重新格式化文件等工具中。

Tip #2 更好的代码格式

另一个提示就是使用 QML/JS重新格式文件 工具。它是如何工作的?它将你的代码重新模式化并让其看上去更好一些。看下下面的组件。

  1. import QtQuick 2.0 
  2.  
  3. Item 
  4. { 
  5. id: root 
  6.  
  7. width:30;height:50; 
  8.  
  9. Text { 
  10. id: textItem 
  11. font.pixelSize: 48; wrapMode: Text.WordWrap 
  12. lineHeight: 0.75 
  13. Behavior on color { ColorAnimation { duration: 120; easing.type: Easing.OutElastic} } 
  14. states: [State { 
  15. name: "pressed" 
  16. when: mouse.pressed 
  17. PropertyChanges { 
  18. target: textItem 
  19. color :Qt.lighter(root.color) 
  20. }} 
  21. ] 
  22. } 
  23.  
  24. MouseArea { 
  25. id: mouse 
  26. anchors.fill: parent 
  27. onClicked: { 
  28. // ... 
  29. } 
  30. } 
  31.  
  32. function foo() 
  33. { 
  34. // ... 
  35. }} 

这肯定不是你见过的最漂亮的代码。它有很多问题,包括每行的缩进都不同、错误的花括号位置、有时缺失空格、有时又有多余的空格。想快速修复它,从Qt Creator的顶部菜单栏找到Tools菜单,然后在QML/JS组里找到Reformat file。运行这个工具可以节省大量时间。

  1. import QtQuick 2.0 
  2.  
  3. Item { 
  4. id: root 
  5.  
  6. width: 30 
  7. height: 50 
  8.  
  9. Text { 
  10. id: textItem 
  11. font.pixelSize: 48 
  12. wrapMode: Text.WordWrap 
  13. lineHeight: 0.75 
  14. Behavior on color { 
  15. ColorAnimation { 
  16. duration: 120 
  17. easing.type: Easing.OutElastic 
  18. } 
  19. } 
  20. states: [ 
  21. State { 
  22. name: "pressed" 
  23. when: mouse.pressed 
  24. PropertyChanges { 
  25. target: textItem 
  26. color: Qt.lighter(root.color) 
  27. } 
  28. } 
  29. ] 
  30. } 
  31.  
  32. MouseArea { 
  33. id: mouse 
  34. anchors.fill: parent 
  35. onClicked: { 
  36. // ... 
  37. } 
  38. } 
  39.  
  40. function foo() {// ... 
  41. } 
  42. } 

如果你有足够的决心放弃Qt Creator对Qml代码格式的一些控制,那么试着设置“Reform file”工具,以便在文件保存时自动运行。

QML代码规范

代码规范/约定超越了代码格式的范畴。Qml代码可以被格式化,从代码整洁的角度看上去很好,但它仍需要打磨。官方的规范是非常好的开始,请按官方建议来做。
以下是我们遵循的,以提供高质量Qt Qml软件开发服务和整洁的Qml代码为目的的规范。我们也会要求应聘者完成技术分工时遵循这些规范。

1.根项id

为了提高可读性和可追溯性,建议将文件中的顶级元素命名为root。然后,在每个文件中,你就会知道 root是指向的是顶级元素。

  1. import QtQuick 2.0 
  2.  
  3. Item { 
  4. id: root 
  5. } 

2.Qml字符转换

对用户可见的字符应该都被qsTr()函数包含。 此外,不要使用结束翻译作为默认显示的字符串,而是使用 THIS_NOTATION。比如,不要写成qsTr("This is displayed"),而应该写成qsTr("THIS_IS_DISPLAYED")。多亏了这种方法,如果任何字符串缺少翻译,我们可以立即在 UI 中看到。

3.有私有对象

在 Qml 代码里,封装和适当的范围界定很重要。就象在C++ 中不能让类的所有成员都是公有的,在Qml代码中也是一样。并非所有的属性与函数都对外可见。经常有一些帮助属性或方法,它们没有值,甚至当从外部访问时会产生危害。因此建议将其包装成内部Qt对象。

  1. QtObject { 
  2. id: _ // or id: internal 
  3.  
  4. readonly property real timeout: 1000 
  5. property bool isExpanded: false 
  6.  
  7. function addDestination() { 
  8. // ... 
  9. } 
  10. } 

4.各类属性的顺序

官方的规范里涵盖了属性顺序,我们定义的略微不同,且更为细节。这在大型项目中会有回报。

  1. import QtQuick 2.15 
  2. import QtQuick.Controls 2.15 // Qt modules first 
  3. import com.scythestudio.ownmodule 1.0 // then own modules 
  4. import "./controls/" // then local directories 
  5.  
  6. // A hypothetical custom button item. 
  7. Item { 
  8. id: root 
  9.  
  10. /// The text to be placed on the button 
  11. property string title: "title" // properties declaration 
  12. /// The button's background color 
  13. property alias color: button.color 
  14.  
  15. signal buttonClicked() // signal declaration 
  16.  
  17. Button { // child items 
  18. id: button 
  19.  
  20. width: parent.width // properties derived from Item 
  21. height: parent.height 
  22.  
  23. icon.color: "black" // Button's own properties 
  24.  
  25. onClicked: { 
  26. root.buttonClicked() 
  27. } 
  28. } 
  29.  
  30. states: State { // states 
  31. name: "selected" 
  32. PropertyChanges { target: button; icon.color: "red" } 
  33. } 
  34.  
  35. transitions: Transition { // transitions 
  36. from: "" 
  37. to: "selected" 
  38. ColorAnimation { target: button; duration: 200 } 
  39. } 
  40.  
  41. PropertyAnimation { // special items 
  42. id: closeDelayAnimation 
  43. // ... 
  44. } 
  45.  
  46. Timer { // special items 
  47.  
  48. } 
  49.  
  50. Connections { // special items 
  51. target: someCppController 
  52.  
  53. function onProcessFailed() { 
  54. // ... 
  55. } 
  56. } 
  57.  
  58. QtObject { // private item 
  59. id: _ 
  60.  
  61. readonly property real timeout: 1000 
  62. property bool isExpanded: false 
  63.  
  64. function addDestination() { 
  65. // ... 
  66. } 
  67. } 
  68.  
  69. onWidthChanged: { // slots 
  70.  
  71. } 
  72.  
  73. function close() { // public functions 
  74. isExpanded = false 
  75. closeDelayAnimation.start() 
  76. } 
  77. } 

以上代码片段可以得出很多规范,这里强调三条:

  • 函数定义倾向于放在文件底部,以便首先看清组件的子项,并快速理解元素是如何构建的。
  • 状态和转换往往会快速增长,这就是为什么它们应该放在子项的下面,尽管它们也是属性;
  • 组件的公有API应该被详细记录

Qml最佳实践

Qt框架文档中,可以找到Qml和Qt Quick的最佳实践。这些非常有用,且其中不少的要义是关于代码整洁的。最为关键的一条是将UI与逻辑分离的原则。当写Qml代码时,可能会尝试使用Qml和JavaScript实现很多事情,包括应用程序逻辑和网络交互。
应该将这些事情放在C++ 中处理,这样前端写的Qml和后端写的C++ 才有清晰的分界线。也因此,程序结构会有更好的可扩展性。数据模型几乎总是应该在C++ 中实现。仅当模型数据是静态的时,才有可能在Qml代码中处理。否则,可能将在处理Qml模型高级操作而浪费时间,或在C++ 重写模型。
另一个好的做法是使用qmllint 工具,有助于定位Qml代码中问题。这是一个相当有用的工具,可以警告很多问题,包括未使用导入和对属性的不例规访问。Qt公司现正为此工具与Qt Creator IDE更好地结合而努力。

整洁的代码为何至关重要

这一点上你应该理解整洁的代码意味着什么,以及你应该如何来确保所写代码符合规范。接下来我们来回答为何编写整洁的代码至关重要。这实际上是为了高质量的代码。当遵循一系列的规范和约定,很容易来定位问题,也会节省大量时间。此外,由于干净的代码概念包括良好的实践,遵循这些指引的开发人员编写代码具有艺术性。在审查过程中不需要费多大劲。
当编写代码时,需要做出许多微小的决定,并且在一段时间后查看相同的代码之后,您宁愿不知道为什么要以特定方式编写代码。另一方面,当您遵循干净的 Qml 代码规则时,您会将这些小决定外包给代码。它可以释放你的思维资源。
最后,当然,编写干净的 Qml 代码最重要的原因是它显着提高了项目的可维护性。有人说你写了一次代码,但它被读了多次。因此,你需要关心代码的可读性以及所有良好实践。然后,你和其他开发人员更容易进入项目,了解特定部分并进行更改。
现在你可能会问你的团队应该对遵循干净的 Qml 代码规则有多严格。好吧,这一切都取决于你当前正在进行的项目的规模。未来有多少人参与或将参与也很重要。我的观点是,在确保高质量代码方面努力永无止境。即使你准备了一个小演示来展示哪些代码将被公开,遵循所有这些规则以最终对你的工作结果感到满意是件好事。一段时间后,它进入血液,开发人员甚至不再将其视为额外的努力。
如果你在维护一个长期项目,例如 Qt 框架,您有很多理由对代码质量进行严格限制。我在一篇博文中描述了我在 Qt Charts in Qt 6.2 做贡献的经历。有很多约定和规则要遵循,实际上一开始很难习惯它们。虽然有 CI/CD 机制可以节省审阅者的时间,例如,寻找错别字。一开始,让我的代码符合所有这些要求是一件很困难的事。尽管如此,我知道这是这个项目的必备品,我可以说它甚至是令人愉快的。

要点和一般规则

  • 维护一个干净的 Qml 代码库是一个健康的 Qt 项目的一个重要方面;
  • KISS--保持简短和简单。不是为你,而是为读者。始终选择更简单的实现选项而不是更复杂的实现选项;
  • 记录已创建项目的公共接口 (API);
  • 不要添加描述如何实现某事的注释。如果读者无法从您的代码中推断出这一点,那么代码就需要重构。注释如果写的解决方案不明显,可能看起来令人莫名其妙;
  • 不要重新造轮子;
  • 代码应适配现有的代码库。如果有改进想法,请先与其他开发人员讨论;
  • 遵循编码以及良好Qml实践的规范。

参考:How to write clean Qml code in 2022?

posted @ 2022-04-23 02:57  sammy621  阅读(1588)  评论(0编辑  收藏  举报