前言
Qt 是一个著名的 C 应用程序框架
本质上来讲,Qt 是一套 C 的代码库(类库)与工具集,与开发人员的关系就像军火库对于军人的关系一样,也好比预制构件库对于建筑工程师的关系一样,可以提供各种现成的组件来高效便捷地实现 C 应用 Tip: 虽然 Qt 常被用来开发图形界面应用,但它并不仅仅局限于 GUI 应用
Qt 是一个跨平台的框架
Qt is a cross-platform application development framework for desktop, embedded and mobile. Supported Platforms include Linux, OS X, Windows, VxWorks, QNX, Android, iOS, BlackBerry, Sailfish OS and others. 一般有三种策略实现跨平台GUI :
- API 映射:界面库使用同一套 API,将其映射到不同的底层平台上面
- API 模拟:API 映射会“缺失”不同平台的特定功能,而 API 模拟可以解决这一问题,不同平台上有差异的 API,使用工具库自己的代码模拟出来
- GUI 模拟:任何平台都提供了图形绘制函数,例如画点、画线、画面等,工具库利用这些基本函数,再绘制出自己的组件,这就是 GUI 模拟
所以可想而知,同一套 Qt 代码在不同平台上生成的应用,界面风格将会迥异(随平台而定)
Qt 是 C 编程思想的集大成者,从中可以习得很多优秀的编程最佳实践
前面一篇使用 Qt 实现了一个简单的 helloworld 窗口,下使用 Qt 制作一个简单的计算器
Tip: 当前的最新版本为 Qt 5.8 ,实验使用 Qt 4.8.6,此文中的基础概念参看了 《QT 的信号与槽机制介绍》 和 《Qt 学习之路 2》
概要
平台与环境
应用的开发无法脱离具体的平台与环境,即便声称为跨平台的框架,在现实情况中,同样一套代码,在不同的平台与环境中也不一定会获得相同的效果
代码语言:javascript复制[emacs@h102 ~]$ cat /etc/issue
CentOS release 6.6 (Final)
Kernel r on an m
[emacs@h102 ~]$ uname -a
Linux h102.temp 2.6.32-504.el6.x86_64 #1 SMP Wed Oct 15 04:27:16 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
[emacs@h102 ~]$ gcc -v
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c ,objc,obj-c ,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC)
[emacs@h102 ~]$ qmake -v
QMake version 2.01a
Using Qt version 4.8.6 in /usr/local/Trolltech/Qt-4.8.6/lib
[emacs@h102 ~]$
Tip: 虽然 Qt 的最新版本为 Qt 5.8 ,但是这里实验依旧使用的 Qt version 4.8.6
计算器
要求
- 使用 Qt 写一个 calc 的GUI程序
创建项目
实际上就是创建一个专用的文件夹
代码语言:javascript复制[emacs@h102 demo]$ pwd
/home/emacs/demo
[emacs@h102 demo]$ mkdir calc
[emacs@h102 demo]$ ls
calc hello
[emacs@h102 demo]$
设计界面
使用 designer
进行 UI 界面设计
[emacs@h102 calc]$ designer
...
...
Tip: 这条命令在我的具体平台和环境下绝对路径为
/usr/local/Trolltech/Qt-4.8.6/bin/designer
,决定于 Qt 的安装路径,为了方便使用,要将bin目录添加到PATH环境变量中来,以高效调用
最开始会有如下界面:
对话窗口提示创建对象
设计界面
具体的设计方法就是各种托拽,大小调整和布局调整,下面就是一个丑陋的最终产物(实践证明本宝宝在UI的美化上还有很长的路要走)
保存退出后,最终的产物是一个 *.ui
文件
在这个例子中是 calc.ui
[emacs@h102 calc]$ ls calc.ui
calc.ui
[emacs@h102 calc]$ file calc.ui
calc.ui: XML document text
[emacs@h102 calc]$ cat calc.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Calc</class>
<widget class="QDialog" name="Calc">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>254</width>
<height>233</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QPushButton" name="pbC">
<property name="geometry">
<rect>
<x>11</x>
<y>51</y>
<width>53</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>C</string>
</property>
</widget>
<widget class="QPushButton" name="pbD">
<property name="geometry">
<rect>
<x>70</x>
<y>51</y>
<width>53</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>D</string>
</property>
</widget>
<widget class="QPushButton" name="pbDiv">
<property name="geometry">
<rect>
<x>129</x>
<y>51</y>
<width>53</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>/</string>
</property>
</widget>
<widget class="QPushButton" name="pbMul">
<property name="geometry">
<rect>
<x>188</x>
<y>51</y>
<width>52</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>x</string>
</property>
</widget>
<widget class="QPushButton" name="pb7">
<property name="geometry">
<rect>
<x>11</x>
<y>87</y>
<width>53</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>7</string>
</property>
</widget>
<widget class="QPushButton" name="pb8">
<property name="geometry">
<rect>
<x>70</x>
<y>87</y>
<width>53</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>8</string>
</property>
</widget>
<widget class="QPushButton" name="pb9">
<property name="geometry">
<rect>
<x>129</x>
<y>87</y>
<width>53</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>9</string>
</property>
</widget>
<widget class="QPushButton" name="pbMin">
<property name="geometry">
<rect>
<x>188</x>
<y>87</y>
<width>52</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>-</string>
</property>
</widget>
<widget class="QPushButton" name="pb4">
<property name="geometry">
<rect>
<x>11</x>
<y>123</y>
<width>53</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>4</string>
</property>
</widget>
<widget class="QPushButton" name="pb5">
<property name="geometry">
<rect>
<x>70</x>
<y>123</y>
<width>53</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>5</string>
</property>
</widget>
<widget class="QPushButton" name="pb6">
<property name="geometry">
<rect>
<x>129</x>
<y>123</y>
<width>53</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>6</string>
</property>
</widget>
<widget class="QPushButton" name="pbAdd">
<property name="geometry">
<rect>
<x>188</x>
<y>123</y>
<width>52</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string> </string>
</property>
</widget>
<widget class="QPushButton" name="pb1">
<property name="geometry">
<rect>
<x>11</x>
<y>159</y>
<width>53</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>1</string>
</property>
</widget>
<widget class="QPushButton" name="pb2">
<property name="geometry">
<rect>
<x>70</x>
<y>159</y>
<width>53</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>2</string>
</property>
</widget>
<widget class="QPushButton" name="pb3">
<property name="geometry">
<rect>
<x>129</x>
<y>159</y>
<width>53</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>3</string>
</property>
</widget>
<widget class="QPushButton" name="pbEq">
<property name="geometry">
<rect>
<x>188</x>
<y>159</y>
<width>52</width>
<height>61</height>
</rect>
</property>
<property name="text">
<string>=</string>
</property>
</widget>
<widget class="QPushButton" name="pbMod">
<property name="geometry">
<rect>
<x>11</x>
<y>195</y>
<width>53</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>%</string>
</property>
</widget>
<widget class="QPushButton" name="pb0">
<property name="geometry">
<rect>
<x>70</x>
<y>195</y>
<width>53</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>0</string>
</property>
</widget>
<widget class="QPushButton" name="pbPoint">
<property name="geometry">
<rect>
<x>129</x>
<y>195</y>
<width>53</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>.</string>
</property>
</widget>
<widget class="QLineEdit" name="le">
<property name="geometry">
<rect>
<x>40</x>
<y>10</y>
<width>201</width>
<height>31</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="lbOp">
<property name="geometry">
<rect>
<x>20</x>
<y>20</y>
<width>16</width>
<height>18</height>
</rect>
</property>
<property name="text">
<string>=</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>
[emacs@h102 calc]$