镜缘浮影 小人本住在 苏州的城外 家里有屋又有田 生活乐无边

QT(三).电子相册

2017-02-26
wilmosfang
qt
 
原文地址 http://soft.dog/2017/02/26/qt-basic-03/

前言

Qt 是一个著名的 C++ 应用程序框架

Tip: 虽然 Qt 常被用来开发图形界面应用,但它并不仅仅局限于 GUI 应用

Qt 是一个跨平台的框架

QtC++ 编程思想的集大成者,从中可以习得很多优秀的编程最佳实践

前面一篇使用 Qt 实现了一个简单的计算器,下面使用 Qt 制作一个简单的电子相册

Tip: 当前的最新版本为 Qt 5.8 ,实验使用 Qt 4.8.6


概要


平台与环境

应用的开发无法脱离具体的平台与环境,即便声称为跨平台的框架,在现实情况中,同样一套代码,在不同的平台与环境中也不一定会获得相同的效果

[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 写一个电子相册的GUI程序

创建项目

实际上就是创建一个专用的文件夹

[emacs@h102 demo]$ pwd
/home/emacs/demo
[emacs@h102 demo]$ mkdir pic
[emacs@h102 demo]$ ls
calc  hello  pic
[emacs@h102 demo]$  

设计界面

使用 designer 进行 UI 界面设计

[emacs@h102 pic]$ designer
...
...

Tip: 这条命令在我的具体平台和环境下绝对路径为 /usr/local/Trolltech/Qt-4.8.6/bin/designer ,决定于 Qt 的安装路径,为了方便使用,要将bin目录添加到PATH环境变量中来,以高效调用

最开始会有如下界面:

对话窗口提示创建对象

calc1.png

设计界面

calc2.png

具体的设计方法就是各种托拽,大小调整和布局调整,下面就是一个丑陋的最终产物(实践证明本宝宝在UI的美化上还有很长的路要走)

pic1.png

保存退出后,最终的产物是一个 *.ui 文件

在这个例子中是 pic.ui

[emacs@h102 pic]$ ls pic.ui 
pic.ui
[emacs@h102 pic]$ file pic.ui 
pic.ui: XML  document text
[emacs@h102 pic]$ cat pic.ui 
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Pic</class>
 <widget class="QDialog" name="pic">
  <property name="enabled">
   <bool>true</bool>
  </property>
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>656</width>
    <height>356</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Dialog</string>
  </property>
  <widget class="QGroupBox" name="gbMode">
   <property name="enabled">
    <bool>true</bool>
   </property>
   <property name="geometry">
    <rect>
     <x>530</x>
     <y>0</y>
     <width>111</width>
     <height>111</height>
    </rect>
   </property>
   <property name="autoFillBackground">
    <bool>false</bool>
   </property>
   <property name="title">
    <string>mode</string>
   </property>
   <property name="flat">
    <bool>false</bool>
   </property>
   <property name="checkable">
    <bool>false</bool>
   </property>
   <widget class="QRadioButton" name="rbMan">
    <property name="geometry">
     <rect>
      <x>11</x>
      <y>30</y>
      <width>76</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>manual</string>
    </property>
   </widget>
   <widget class="QRadioButton" name="rbAuto">
    <property name="geometry">
     <rect>
      <x>11</x>
      <y>68</y>
      <width>55</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>auto</string>
    </property>
   </widget>
  </widget>
  <widget class="QGroupBox" name="gbMan">
   <property name="enabled">
    <bool>true</bool>
   </property>
   <property name="geometry">
    <rect>
     <x>530</x>
     <y>170</y>
     <width>111</width>
     <height>171</height>
    </rect>
   </property>
   <property name="title">
    <string>manual</string>
   </property>
   <widget class="QPushButton" name="pbFirst">
    <property name="geometry">
     <rect>
      <x>11</x>
      <y>21</y>
      <width>77</width>
      <height>30</height>
     </rect>
    </property>
    <property name="text">
     <string>|&lt;</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pbPre">
    <property name="geometry">
     <rect>
      <x>11</x>
      <y>57</y>
      <width>77</width>
      <height>30</height>
     </rect>
    </property>
    <property name="text">
     <string>&lt;</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pbNext">
    <property name="geometry">
     <rect>
      <x>11</x>
      <y>93</y>
      <width>77</width>
      <height>30</height>
     </rect>
    </property>
    <property name="text">
     <string>&gt;</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pbLast">
    <property name="geometry">
     <rect>
      <x>11</x>
      <y>129</y>
      <width>77</width>
      <height>30</height>
     </rect>
    </property>
    <property name="text">
     <string>&gt;|</string>
    </property>
   </widget>
  </widget>
  <widget class="QLabel" name="lbPic">
   <property name="geometry">
    <rect>
     <x>20</x>
     <y>40</y>
     <width>481</width>
     <height>301</height>
    </rect>
   </property>
   <property name="autoFillBackground">
    <bool>false</bool>
   </property>
   <property name="text">
    <string>pic</string>
   </property>
   <property name="scaledContents">
    <bool>true</bool>
   </property>
  </widget>
  <widget class="QGroupBox" name="gbAuto">
   <property name="enabled">
    <bool>true</bool>
   </property>
   <property name="geometry">
    <rect>
     <x>530</x>
     <y>110</y>
     <width>111</width>
     <height>61</height>
    </rect>
   </property>
   <property name="title">
    <string>auto</string>
   </property>
   <widget class="QLineEdit" name="le">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>20</y>
      <width>91</width>
      <height>25</height>
     </rect>
    </property>
   </widget>
  </widget>
  <widget class="QLabel" name="lbTime">
   <property name="geometry">
    <rect>
     <x>20</x>
     <y>10</y>
     <width>271</width>
     <height>18</height>
    </rect>
   </property>
   <property name="text">
    <string>now</string>
   </property>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>
[emacs@h102 pic]$ 

从中可知,这是一个 XML 文件

内容是在描述各个控件的参数

Qt 就是通过这些参数来绘制图形的

代码示例

main.cpp

#include <QtGui/QApplication> //QApplication 类管理图形用户界面应用程序的控制流和主要设置
#include <QtCore/QTextCodec> //用来进行字符集转化
#include "pic.h"

int main(int argc, char** argv)
{
	QApplication app(argc, argv); //构建一个 QApplication 对象 app,这个操作整个运行期间有且只能有一次,并且要在所有其它组件生成之前构建

	QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")) ; //设定要转化的字符集为UTF-8,但是在Qt内部,其实还是使用的Unicode进行存储
	app.setFont(QFont("simsun", 10)); //设定字体

	Pic p; //定义一个Pic类对象,这个类在Pic.h有详细声明
    	p.show(); //调用show方法,这个方法继承于QWidget,QWidget::show ,将窗口和它的子对象进行显示,这个方法相当于setVisible(true)

	return app.exec(); //进入主事件循环,这是应用逻辑的进入点
}

pic.h

#ifndef PIC_H //这个条件编译是一种很好的编程习惯,加强了代码的健壮性,在大项目中可以有效避免冲突
#define PIC_H

#include <QDialog> //QDialog对象一般是最顶层的窗口
#include <QWidget> //QWidget类是所有UI对象的基类
#include <QTimer>  //为了进行重复任务,这个需要定时器
#include <QString> //提供Unicode的字符串

#include "ui_pic.h" //ui头文件

class Pic: public QDialog,public Ui_Pic  //继承自QDialog 和 Ui_Pic, Ui_Pic 是从哪里来的呢,这个后面交代
{
	Q_OBJECT //这个宏不可或缺,否则这个类无法使用QT中的signal和slot机制
public:
	Pic(QWidget *parent = 0); //构造函数  parent = 0 代表新窗口
	~Pic(); //析构函数

signals:

public slots:

	void fMan();
	void fAuto();
	void jtFirst();
	void jtLast();
	void jtPre();
	void jtNext();
	void showTime();
	void fAuto(const QString &);  //定义的各种slots函数,以便触发后产生相应操作

private:

	QTimer * time;  //定义一个定时器,方便进行图片自动切换
	QTimer * systime; //定义一个定时器,方便更新时间
};

#endif

pic.cpp

#include <QDateTime> //这个类用来提供日期和时间
#include <stdio.h> //printf 在这里面声明
#include "pic.h"

QString pic[5]={"pics/p0.jpg","pics/p1.jpg","pics/p2.jpg","pics/p3.jpg","pics/p4.jpg"}; //定义图片的路径
int i=0; //索引变量
const int n=5; //图片数量

Pic::Pic(QWidget *parent):QDialog(parent) //构造函数的实现,parent = 0 为默认值,代表这是一个新的窗口
{
  setupUi(this);  //这个函数是Ui_Pic类的一个内联函数,用来设置自身的界面布局和组件分布,还有组件和窗口的形状大小和位置,参数信息来源于之前使用designer生成的XML文件pic.ui,这个文件会经uic生成一个ui_pic.h文件

  QPixmap p(pic[0]);  //用第一张照片定义一个QPixmap对象
  lbPic->setPixmap(p); //将这个图片显示在lbPic中

  rbMan->setChecked(true); //将手动按钮设定为选中状态
  gbAuto->setEnabled(false);  //将自动按钮组禁用掉

  time = new QTimer; //申请一个定时器,用作切换图片
  systime = new QTimer; //申请一个定时器,用作更新时间
  systime->start(1000); //将更新时间的间隔设定为1s(1000ms)

  le->setText(QString::number(1));  //将自动切换图片的初始时间设定为1s
  
  connect(rbMan,SIGNAL(clicked()),this,SLOT(fMan())); //手动
  connect(rbAuto,SIGNAL(clicked()),this,SLOT(fAuto())); //自动
  //connect(le,SIGNAL(editingFinished()),this,SLOT(fAuto())); //这种方式也可以修改切换时间,但是修改完成后,要敲入回车才开始生效
  connect(le,SIGNAL(textEdited(const QString &)),this,SLOT(fAuto(const QString &))); //修改完切换时间后,自动更新切换时间
  connect(pbFirst,SIGNAL(clicked()),this,SLOT(jtFirst())); //第一张图片
  connect(pbLast,SIGNAL(clicked()),this,SLOT(jtLast())); //最后一张图片
  connect(pbPre,SIGNAL(clicked()),this,SLOT(jtPre())); //前面一张图片
  connect(pbNext,SIGNAL(clicked()),this,SLOT(jtNext())); //后面一张图片
  connect(time,SIGNAL(timeout()),this,SLOT(jtNext())); //自动切换图片
  connect(systime,SIGNAL(timeout()),this,SLOT(showTime())); //更新系统时间
 
}

Pic::~Pic() //析构
{
  delete time;
  delete systime;  
}

void Pic::fMan() //手动
{  
  gbAuto->setEnabled(false); //禁用自动组
  gbMan->setEnabled(true); //启用手动组
  time->stop(); //停止定时器,停止自动切换图片
}

void Pic::fAuto() //自动
{
  int sec=1; //定义一个秒数变量
  gbMan->setEnabled(false); //禁用手动组
  gbAuto->setEnabled(true); //启用自动组
  sec=le->text().toInt(); //将配置框中的内容化整,赋给sec
  time->start(1000*sec); //设定切换周期,并且启动定时器
}


void Pic::fAuto(const QString & ) //修改间隔更新
{
  int sec=1; //定义一个秒数变量
  sec=le->text().toInt();  //将配置框中的内容化整,赋给sec
  time->start(1000*sec); //设定切换周期,并且重启定时器
}

void Pic::jtFirst() //跳到第一张
{
  i=0; //将索引置0
  printf("i=%d n=%d\n",i,n); //终端中显示此时的索引值与图片总张数
  QPixmap p(pic[i]); //根据索引定义图片
  lbPic->setPixmap(p); //显示设定的图片
}

void Pic::jtLast() //跳到最后一张
{
  i=n-1; //将索引置末
  printf("i=%d n=%d\n",i,n); //终端中显示此时的索引值与图片总张数
  QPixmap p(pic[i]); //根据索引定义图片
  lbPic->setPixmap(p); //显示设定的图片
}

void Pic::jtPre() //跳到前一张
{
  i--; //将索引自减
  if(-1 == i) i=n-1; //进行循环处理,避免超出索引范围
  printf("i=%d n=%d\n",i,n); //终端中显示此时的索引值与图片总张数
  QPixmap p(pic[i]); //根据索引定义图片
  lbPic->setPixmap(p); //显示设定的图片
}

void Pic::jtNext() //跳到下一张
{
  i++; //将索引自增
  if(n == i)i=0; //进行循环处理,避免超出索引范围
  printf("i=%d n=%d\n",i,n); //终端中显示此时的索引值与图片总张数
  QPixmap p(pic[i]); //根据索引定义图片
  lbPic->setPixmap(p); //显示设定的图片
}

void Pic::showTime() //显示时间
{
  QDateTime now = QDateTime::currentDateTime();   //申请一个QDateTime对象保存当前时间
  QString str = now.toString("yyyy-MM-dd hh:mm:ss");  //对当前时间以指定格式转化为字符串
  lbTime->setText(str); //进行更新与显示
}

编译执行

[emacs@h102 pic]$ ls
main.cpp  pic.cpp  pic.h  pics  pic.ui
[emacs@h102 pic]$ ll pics/
total 2620
-rw-rw-r-- 1 emacs emacs 146550 Feb 26 13:51 p0.jpg
-rw-rw-r-- 1 emacs emacs 915481 Feb 26 13:51 p1.jpg
-rw-rw-r-- 1 emacs emacs 871733 Feb 26 13:51 p2.jpg
-rw-rw-r-- 1 emacs emacs 404207 Feb 26 13:51 p3.jpg
-rw-rw-r-- 1 emacs emacs 312867 Feb 26 13:51 p4.jpg
-rw-rw-r-- 1 emacs emacs  20992 Feb 26 13:51 Thumbs.db
[emacs@h102 pic]$ alias gtt
alias gtt='qmake -project ; qmake ; make'
[emacs@h102 pic]$ qmake -project
[emacs@h102 pic]$ ls
main.cpp  pic.cpp  pic.h  pic.pro  pics  pic.ui
[emacs@h102 pic]$ qmake 
[emacs@h102 pic]$ ls
main.cpp  Makefile  pic.cpp  pic.h  pic.pro  pics  pic.ui
[emacs@h102 pic]$ make 
/usr/local/Trolltech/Qt-4.8.6/bin/uic pic.ui -o ui_pic.h
g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/local/Trolltech/Qt-4.8.6/mkspecs/linux-g++ -I. -I/usr/local/Trolltech/Qt-4.8.6/include/QtCore -I/usr/local/Trolltech/Qt-4.8.6/include/QtGui -I/usr/local/Trolltech/Qt-4.8.6/include -I. -I. -I. -o main.o main.cpp
g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/local/Trolltech/Qt-4.8.6/mkspecs/linux-g++ -I. -I/usr/local/Trolltech/Qt-4.8.6/include/QtCore -I/usr/local/Trolltech/Qt-4.8.6/include/QtGui -I/usr/local/Trolltech/Qt-4.8.6/include -I. -I. -I. -o pic.o pic.cpp
/usr/local/Trolltech/Qt-4.8.6/bin/moc -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/local/Trolltech/Qt-4.8.6/mkspecs/linux-g++ -I. -I/usr/local/Trolltech/Qt-4.8.6/include/QtCore -I/usr/local/Trolltech/Qt-4.8.6/include/QtGui -I/usr/local/Trolltech/Qt-4.8.6/include -I. -I. -I. pic.h -o moc_pic.cpp
g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/local/Trolltech/Qt-4.8.6/mkspecs/linux-g++ -I. -I/usr/local/Trolltech/Qt-4.8.6/include/QtCore -I/usr/local/Trolltech/Qt-4.8.6/include/QtGui -I/usr/local/Trolltech/Qt-4.8.6/include -I. -I. -I. -o moc_pic.o moc_pic.cpp
g++ -Wl,-O1 -Wl,-rpath,/usr/local/Trolltech/Qt-4.8.6/lib -o pic main.o pic.o moc_pic.o    -L/usr/local/Trolltech/Qt-4.8.6/lib -lQtGui -L/usr/local/Trolltech/Qt-4.8.6/lib -L/usr/X11R6/lib -lQtCore -lpthread 
[emacs@h102 pic]$ echo $?
0
[emacs@h102 pic]$ ls
main.cpp  Makefile     moc_pic.o  pic.cpp  pic.o    pics    ui_pic.h
main.o    moc_pic.cpp  pic        pic.h    pic.pro  pic.ui
[emacs@h102 pic]$ ./pic 
...
...

会弹出一个小窗口

pic2.png

编译执行过程中没有报错,从结果来看,符合预期

进行操作检查,功能也相对完备


编译过程

从make的编译过程可以看出如下信息

[emacs@h102 pic]$ make 
/usr/local/Trolltech/Qt-4.8.6/bin/uic pic.ui -o ui_pic.h
g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/local/Trolltech/Qt-4.8.6/mkspecs/linux-g++ -I. -I/usr/local/Trolltech/Qt-4.8.6/include/QtCore -I/usr/local/Trolltech/Qt-4.8.6/include/QtGui -I/usr/local/Trolltech/Qt-4.8.6/include -I. -I. -I. -o main.o main.cpp
g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/local/Trolltech/Qt-4.8.6/mkspecs/linux-g++ -I. -I/usr/local/Trolltech/Qt-4.8.6/include/QtCore -I/usr/local/Trolltech/Qt-4.8.6/include/QtGui -I/usr/local/Trolltech/Qt-4.8.6/include -I. -I. -I. -o pic.o pic.cpp
/usr/local/Trolltech/Qt-4.8.6/bin/moc -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/local/Trolltech/Qt-4.8.6/mkspecs/linux-g++ -I. -I/usr/local/Trolltech/Qt-4.8.6/include/QtCore -I/usr/local/Trolltech/Qt-4.8.6/include/QtGui -I/usr/local/Trolltech/Qt-4.8.6/include -I. -I. -I. pic.h -o moc_pic.cpp
g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/local/Trolltech/Qt-4.8.6/mkspecs/linux-g++ -I. -I/usr/local/Trolltech/Qt-4.8.6/include/QtCore -I/usr/local/Trolltech/Qt-4.8.6/include/QtGui -I/usr/local/Trolltech/Qt-4.8.6/include -I. -I. -I. -o moc_pic.o moc_pic.cpp
g++ -Wl,-O1 -Wl,-rpath,/usr/local/Trolltech/Qt-4.8.6/lib -o pic main.o pic.o moc_pic.o    -L/usr/local/Trolltech/Qt-4.8.6/lib -lQtGui -L/usr/local/Trolltech/Qt-4.8.6/lib -L/usr/X11R6/lib -lQtCore -lpthread 
[emacs@h102 pic]$ echo $?
0
[emacs@h102 pic]$
  • 1.uic : pic.ui->ui_pic.h
  • 2.g++ : main.cpp->main.o
  • 3.g++ : pic.cpp->pic.o
  • 4.moc : pic.h->moc_pic.cpp
  • 5.g++ : moc_pic.cpp->moc_pic.o
  • 6.g++ : main.o pic.o moc_pic.o ->pic

生成关系

相互之间的生成关系为

pic.ui->ui_pic.h
main.cpp->main.o---------------|
pic.cpp->pic.o-----------------|->pic
pic.h->moc_pic.cpp->moc_pic.o--|

依赖关系

从源码中的依赖关系可知

[emacs@h102 pic]$ grep include main.cpp 
#include <QtGui/QApplication>
#include <QtCore/QTextCodec>
#include "pic.h"
[emacs@h102 pic]$ grep include pic.cpp 
#include <QDateTime>
#include <stdio.h>
#include "pic.h"
[emacs@h102 pic]$ grep include pic.h
#include <QDialog>
#include <QWidget>
#include <QTimer>
#include <QString>
#include "ui_pic.h"
[emacs@h102 pic]$

相互之间的依存关系为

pic.ui-[uic]->ui_pic.h    |->main.cpp-[g++]->main.o---------------|
                    |->pic.h-[moc]->moc_pic.cpp-[g++]->moc_pic.o--|->pic
                          |->pic.cpp-[g++]->pic.o-----------------|

*.pro 文件与 Makefile 文件的关系如下

source-[qmake -project]->*.pro-[qmake]->Makefile--|-[make]->target
    |---------------------------------------------|

ui_*.h

这个文件由 uic 根据 *.ui 生成的

我们来看看其中的内容

[emacs@h102 pic]$ cat ui_pic.h 
/********************************************************************************
** Form generated from reading UI file 'pic.ui'
**
** Created by: Qt User Interface Compiler version 4.8.6
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/

#ifndef UI_PIC_H
#define UI_PIC_H

#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QDialog>
#include <QtGui/QGroupBox>
#include <QtGui/QHeaderView>
#include <QtGui/QLabel>
#include <QtGui/QLineEdit>
#include <QtGui/QPushButton>
#include <QtGui/QRadioButton>

QT_BEGIN_NAMESPACE

class Ui_Pic
{
public:
    QGroupBox *gbMode;
    QRadioButton *rbMan;
    QRadioButton *rbAuto;
    QGroupBox *gbMan;
    QPushButton *pbFirst;
    QPushButton *pbPre;
    QPushButton *pbNext;
    QPushButton *pbLast;
    QLabel *lbPic;
    QGroupBox *gbAuto;
    QLineEdit *le;
    QLabel *lbTime;

    void setupUi(QDialog *pic)
    {
        if (pic->objectName().isEmpty())
            pic->setObjectName(QString::fromUtf8("pic"));
        pic->setEnabled(true);
        pic->resize(656, 356);
        gbMode = new QGroupBox(pic);
        gbMode->setObjectName(QString::fromUtf8("gbMode"));
        gbMode->setEnabled(true);
        gbMode->setGeometry(QRect(530, 0, 111, 111));
        gbMode->setAutoFillBackground(false);
        gbMode->setFlat(false);
        gbMode->setCheckable(false);
        rbMan = new QRadioButton(gbMode);
        rbMan->setObjectName(QString::fromUtf8("rbMan"));
        rbMan->setGeometry(QRect(11, 30, 76, 23));
        rbAuto = new QRadioButton(gbMode);
        rbAuto->setObjectName(QString::fromUtf8("rbAuto"));
        rbAuto->setGeometry(QRect(11, 68, 55, 23));
        gbMan = new QGroupBox(pic);
        gbMan->setObjectName(QString::fromUtf8("gbMan"));
        gbMan->setEnabled(true);
        gbMan->setGeometry(QRect(530, 170, 111, 171));
        pbFirst = new QPushButton(gbMan);
        pbFirst->setObjectName(QString::fromUtf8("pbFirst"));
        pbFirst->setGeometry(QRect(11, 21, 77, 30));
        pbPre = new QPushButton(gbMan);
        pbPre->setObjectName(QString::fromUtf8("pbPre"));
        pbPre->setGeometry(QRect(11, 57, 77, 30));
        pbNext = new QPushButton(gbMan);
        pbNext->setObjectName(QString::fromUtf8("pbNext"));
        pbNext->setGeometry(QRect(11, 93, 77, 30));
        pbLast = new QPushButton(gbMan);
        pbLast->setObjectName(QString::fromUtf8("pbLast"));
        pbLast->setGeometry(QRect(11, 129, 77, 30));
        lbPic = new QLabel(pic);
        lbPic->setObjectName(QString::fromUtf8("lbPic"));
        lbPic->setGeometry(QRect(20, 40, 481, 301));
        lbPic->setAutoFillBackground(false);
        lbPic->setScaledContents(true);
        gbAuto = new QGroupBox(pic);
        gbAuto->setObjectName(QString::fromUtf8("gbAuto"));
        gbAuto->setEnabled(true);
        gbAuto->setGeometry(QRect(530, 110, 111, 61));
        le = new QLineEdit(gbAuto);
        le->setObjectName(QString::fromUtf8("le"));
        le->setGeometry(QRect(10, 20, 91, 25));
        lbTime = new QLabel(pic);
        lbTime->setObjectName(QString::fromUtf8("lbTime"));
        lbTime->setGeometry(QRect(20, 10, 271, 18));

        retranslateUi(pic);

        QMetaObject::connectSlotsByName(pic);
    } // setupUi

    void retranslateUi(QDialog *pic)
    {
        pic->setWindowTitle(QApplication::translate("Pic", "Dialog", 0, QApplication::UnicodeUTF8));
        gbMode->setTitle(QApplication::translate("Pic", "mode", 0, QApplication::UnicodeUTF8));
        rbMan->setText(QApplication::translate("Pic", "manual", 0, QApplication::UnicodeUTF8));
        rbAuto->setText(QApplication::translate("Pic", "auto", 0, QApplication::UnicodeUTF8));
        gbMan->setTitle(QApplication::translate("Pic", "manual", 0, QApplication::UnicodeUTF8));
        pbFirst->setText(QApplication::translate("Pic", "|<", 0, QApplication::UnicodeUTF8));
        pbPre->setText(QApplication::translate("Pic", "<", 0, QApplication::UnicodeUTF8));
        pbNext->setText(QApplication::translate("Pic", ">", 0, QApplication::UnicodeUTF8));
        pbLast->setText(QApplication::translate("Pic", ">|", 0, QApplication::UnicodeUTF8));
        lbPic->setText(QApplication::translate("Pic", "pic", 0, QApplication::UnicodeUTF8));
        gbAuto->setTitle(QApplication::translate("Pic", "auto", 0, QApplication::UnicodeUTF8));
        lbTime->setText(QApplication::translate("Pic", "now", 0, QApplication::UnicodeUTF8));
    } // retranslateUi

};

namespace Ui {
    class Pic: public Ui_Pic {};
} // namespace Ui

QT_END_NAMESPACE

#endif // UI_PIC_H
[emacs@h102 pic]$

头部注释中告诉我们这个文件是由 pic.ui 生成的

Qt UI 编译器的版本为 4.8.6

然后我们不要手动修改,因为重编译的过程中这些改动会丢失

需要注意的是,这里面定义了一个 Ui_Pic 类 , 这个类我们之前在 pic.h 中见过

class Pic: public QDialog,public Ui_Pic
{
  setupUi(this);
...
...
}

Pic 就是继承于 QDialogUi_Pic

通过这个文件的内容,可以看出,这个类在 public 中定义了各个控件的指针,然后定义了两个内联函数 setupUiretranslateUi

在 Pic 的构造函数中,首先就调用了 setupUi ,这个函数对控件的形象进行了配置


QDateTime

这个类用来提供日期和时间

The QDateTime class provides date and time functions

QDateTime 是 QDate 和 QTime 的组合,还提供各种对时间的计算与操作

A QDateTime object contains a calendar date and a clock time (a “datetime”). It is a combination of the QDate and QTime classes. It can read the current datetime from the system clock. It provides functions for comparing datetimes and for manipulating a datetime by adding a number of seconds, days, months, or years

QDateTime::currentDateTime

QDateTime QDateTime::currentDateTime () [static]

用来返回当前时间(作为系统时间返回的,以当前的时区)

Returns the current datetime, as reported by the system clock, in the local time zone

  • QDate::currentDate() : 返回日期
  • QTime::currentTime() : 返回时间
  • QDateTime::toTimeSpec : 返回秒数

QDateTime::toString

QString QDateTime::toString ( const QString & format ) const

以字符串的形式返回时间

Returns the datetime as a string. The format parameter determines the format of the result string

相关的格式可以参考官方API文档


QPixmap

继承自 QPaintDevice

QPixmap 用来保有图片信息

The QPixmap class is an off-screen image representation that can be used as a paint device

除了QPixmap ,Qt还有三种表示图片的类,QImage 、QBitmap 和 QPicture

  • QImage 经过了IO优化,是设计用来直接操作像素的
  • QPixmap 用来显示图片
  • QBitmap 继承自QPixmap 图个方便
  • QPicture 可以用来作画和绘图

Qt provides four classes for handling image data: QImage, QPixmap, QBitmap and QPicture. QImage is designed and optimized for I/O, and for direct pixel access and manipulation, while QPixmap is designed and optimized for showing images on screen. QBitmap is only a convenience class that inherits QPixmap, ensuring a depth of 1. The isQBitmap() function returns true if a QPixmap object is really a bitmap, otherwise returns false. Finally, the QPicture class is a paint device that records and replays QPainter commands

QPixmap::QPixmap

构造函数

QPixmap::QPixmap ( const QString & fileName, const char * format = 0, Qt::ImageConversionFlags flags = Qt::AutoColor )

通过文件名来构造

Constructs a pixmap from the file with the given fileName. If the file does not exist or is of an unknown format, the pixmap becomes a null pixmap

如果不指定图片格式,加载过程会根据文件的头部信息进行自动判断

The loader attempts to read the pixmap using the specified format. If the format is not specified (which is the default), the loader probes the file for a header to guess the file format

QLabel::setPixmap

这个函数可以将一个QPixmap 放到QLabel中进行显示

This property holds the label’s pixmap, If no pixmap has been set this will return 0


QRadioButton

继承自 QAbstractButton

单选按钮,在一组对象中,最多只能有一个单选按钮被选中,按钮的变化是自动排他的

The QRadioButton widget provides a radio button with a text label

A QRadioButton is an option button that can be switched on (checked) or off (unchecked). Radio buttons typically present the user with a “one of many” choice. In a group of radio buttons only one radio button at a time can be checked; if the user selects another button, the previously selected button is switched off.

我们需要做的就是将它们放到一个组中

QAbstractButton::setChecked

bool isChecked () const 
void setChecked ( bool ) 

使对象处于选中状态

Only checkable buttons can be checked. By default, the button is unchecked


QButtonGroup

继承自QObject

这个类的对象可以提供一个容器将若干按钮组织起来

The QButtonGroup class provides a container to organize groups of button widgets

其主要的意义在于可以统一管理这一组对象的状态

QButtonGroup provides an abstract container into which button widgets can be placed. It does not provide a visual representation of this container (see QGroupBox for a container widget), but instead manages the states of each of the buttons in the group.

QRadioButtons 可以利用这个特性来进行排他选择

An exclusive button group switches off all checkable (toggle) buttons except the one that was clicked. By default, a button group is exclusive. The buttons in a button group are usually checkable QPushButton’s, QCheckBoxes (normally for non-exclusive button groups), or QRadioButtons. If you create an exclusive button group, you should ensure that one of the buttons in the group is initially checked; otherwise, the group will initially be in a state where no buttons are checked


QTimer

继承自 QObject

QTimer 提供重复的或一次性的计时器

The QTimer class provides repetitive and single-shot timers

通过 timeout() 信号和 start() 就可以重复触发槽函数

The QTimer class provides a high-level programming interface for timers. To use it, create a QTimer, connect its timeout() signal to the appropriate slots, and call start(). From then on it will emit the timeout() signal at constant intervals

     QTimer *timer = new QTimer(this);
     connect(timer, SIGNAL(timeout()), this, SLOT(update()));
     timer->start(1000);

timeout()

超时信号

void QTimer::timeout () [signal]

超时后触发信号

This signal is emitted when the timer times out

start()

void QTimer::start ( int msec ) [slot]

以指定的周期启动或重启计时器,单位是毫秒

Starts or restarts the timer with a timeout interval of msec milliseconds

stop()

void QTimer::stop () [slot]

停止定时器


总结

掌握如下概念对Qt的学习非常有用

  • 信号

如下类是Qt中常用的类,掌握它们的属性和方法很有必要

  • QDateTime
  • QPixmap
  • QRadioButton
  • QButtonGroup
  • QTimer

以下函数和宏非常重要

  • connect
  • SIGNAL
  • SLOT
  • Q_OBJECT
原文地址 http://soft.dog/2017/02/26/qt-basic-03/

评论