Qt应用开发的基本模式(面向对象)
- 继承QDailog
gkdialog.h
#ifndef GK_DIALOG_H
#define GK_DIALOG_H
#include <QtWidgets/QDialog>
class GKDialog: public QDialog{
public:
GKDialog(QWidget *parent=0);
~GKDialog();
};
#endif
gkdialog.cpp
#include "gkdialog.h"
#include <iostream>
GKDialog::GKDialog(QWidget *parent):
QDialog(parent){
std::cout << "对话框初始化" << std::endl;
}
GKDialog::~GKDialog(){
std::cout << "释放" << std::endl;
}
- QApplication
gkapp.h
#ifndef GK_APP_H
#define GK_APP_H
#include <QtWidgets/QApplication>
#include "gkdialog.h"
class GKApp : public QApplication{
public:
GKApp(int argc, char **argv);
~GKApp();
private:
GKDialog *dlg;
};
#endif
gkapp.cpp
#include "gkapp.h"
#include <iostream>
GKApp::GKApp(int argc, char **argv):
QApplication(argc, argv),
dlg(new GKDialog()){ // 构造初始化列表
dlg = new GKDialog();
dlg->resize(600, 400);
dlg->move(200, 200);
dlg->show();
std::cout << "应用初始化" << std::endl;
}
GKApp::~GKApp(){
std::cout << "应用释放" << std::endl;
delete dlg;
}
- main.cpp
#include "gkapp.h"
// #include "gkdialog.h"
int main(int argc, char **argv){
// 创建Qt应用
GKApp app(argc, argv);
// 创建对话框
// 消息循环
// 返回状态码
return app.exec();
}
- Makefile
INCLUDES = /I "C:/Qt/Qt5.13.0/5.13.0/msvc2017_64/include"
LIBS = /LIBPATH:"C:/Qt/Qt5.13.0/5.13.0/msvc2017_64/lib" \
/DYNAMICBASE \
"Qt5Widgets.lib" \
"Qt5Gui.lib" \
"Qt5Core.lib"
CL_ARGS = /EHsc \
/MD \
/source-charset:utf-8 \
/execution-charset:utf-8 \
/nologo
LINK_ARGS = /MACHINE:X64 /NOLOGO
main:main.cpp gkapp.cpp gkdialog.cpp
@cl /c $(CL_ARGS) /Fo:main.obj $(INCLUDES) main.cpp
@cl /c $(CL_ARGS) /Fo:app.obj $(INCLUDES) gkapp.cpp
@cl /c $(CL_ARGS) /Fo:dialog.obj $(INCLUDES) gkdialog.cpp
@link $(LINK_ARGS) $(LIBS) /OUT:main.exe main.obj app.obj dialog.obj
clean:
@del *.exe *.obj *.exp 2>/Nul
- 说明:
- 三种使用模式的体会:
- 第一种对话框与应用程序并列呈现,我们通常不采用这种并列的方式
- 第二种(即为上面的代码形式),对话框与应用程序为包含关系,这种方式可控性强、风险低。
- 三种使用模式的体会:
设计UI(Qt Designer)
代码实现
-
定义成员
-
创建对象
-
设置属性
工具实现
- Qt Designer(Qt设计大师)
-
步骤1:创建模板,保存为ui文件
-
拖组件满足功能
-
外观的设计
-
命名规范
-
交互设计
- 设计槽(slot)函数
- 组件的信号与槽函数关联
使用UI
- 条件是*.ui文件
-
编译ui文件为.h文件
uic [options] [uifile]
-o 输出的文件
: 建议文件输出为.h文件
-
创建ui对象
-
使用ui对象的setupUi绑定我们的对话框
ui->setupUi(this); -
实现ui设计中的槽函数
-
所有定义了槽函数的头文件需要编译成moc的cpp文件。
-
cpp需要编译与链接
-
注意事项;定义槽函数或者是信号的类,需要添加一个宏,Q_OBJECT
-
moc [options] [header-file]
- 选项:
-o 输出的文件moc_***.cpp
- 选项:
-
Qt画图
-
Qt应用
QApplication- QDialog
-
绘制事件
-
完成绘图编程模式
-
QPainter
-
-
键盘事件
- 通过键盘控制=图形的活动
-
代码
hwdialog.h
#ifndef HW_DIALOG_H
#define HW_DIALOG_H
#include <QtWidgets/QDialog>
#include <QtGui/QkeyEvent>
class HWDialog: public QDialog{
public:
HWDialog(QWidget *parent=0);
~HWDialog();
public:
virtual void paintEvent(QPaintEvent *e);
virtual void keyPressEvevt(QKeyEvent *e);
private:
int x, y;
};
#endif
hwdialog.cpp
#include "hwdialog.h"
#include <iostream>
#include <QtGui/QPainter>
HWDialog::HWDialog(QWidget *parent):
QDialog(parent),
x(100), y(100){
}
HWDialog::~HWDialog(){
}
void HWDialog::paintEvent(QPaintEvent *e){
QPainter painter(this);
QColor color(255, 0, 0, 255);
QPen pen(color);
painter.setPen(pen);
painter.drawRoundedRect(x, y, 100,200,20, 15);
}
void HWDialog::keyPressEvevt(QKeyEvent *e){
if(e->modifiers() == Qt::ControlModifier && e->key() == Qt::Key_Up){
y -= 2;
}
if(e->modifiers() == Qt::ControlModifier && e->key() == Qt::Key_Down){
y += 2;
}
if(e->modifiers() == Qt::ControlModifier && e->key() == Qt::Key_Left){
x -= 2;
}
if(e->modifiers() == Qt::ControlModifier && e->key() == Qt::Key_Right){
x += 2;
}
this->repaint();
}
-
QApplication、main.cpp、Makefile三部分代码与Qt开发的基本模式相同,在此不再进行展示。
-
运行展示
Qt多线程
- 使用线程完成数据同步处理
- 代码
thdialog.h
#ifndef TH_DIALOG_H
#define TH_DIALOG_H
#include <QtWidgets/QDialog>
#include <QtGui/QKeyEvent>
#include "thfish.h"
class THDialog: public QDialog{
public:
THDialog(QWidget *parent=0);
~THDialog();
public:
virtual void paintEvent(QPaintEvent *e);
virtual void keyPressEvent(QKeyEvent *e);
private:
THFish *fish;
THFish *fish2;
};
#endif
thdialog.cpp
#include "thdialog.h"
#include <iostream>
#include <QtGui/QPainter>
THDialog::THDialog(QWidget *parent):
QDialog(parent),
fish(new THFish(100, 100)),
fish2(new THFish(200, 100)){
fish->start(); // 线程启动
fish2->start();
}
THDialog::~THDialog(){
}
// override绘制函数
void THDialog::paintEvent(QPaintEvent *e){
// 在这里完成绘制工作
QPainter painter(this);
fish->showFish(&painter);
fish2->showFish(&painter);
}
void THDialog::keyPressEvent(QKeyEvent *e){
if(e->modifiers() == Qt::ControlModifier && e->key() == Qt::Key_Up){
// std::cout << "up" << std::endl;
fish->changeDir(90);
fish->swim();
}
if(e->modifiers() == Qt::ControlModifier && e->key() == Qt::Key_Down){
// std::cout << "down" << std::endl;
fish->changeDir(270);
fish->swim();
}
if(e->modifiers() == Qt::ControlModifier && e->key() == Qt::Key_Left){
// std::cout << "left" << std::endl;
fish->changeDir(180);
fish->swim();
}
if(e->modifiers() == Qt::ControlModifier && e->key() == Qt::Key_Right){
// std::cout << "right" << std::endl;
fish->changeDir(0);
fish->swim();
}
this->repaint();
}
thfish.h
#ifndef TH_FISH_H
#define TH_FISH_H
#include <QtCore/QThread>
#include <QtGui/QPainter>
class THFish : public QThread{
Q_OBJECT
public:
THFish(int x=0, int y=0, int m=45, int d=0);
void openMouth();
void changeDir(int dir);
void swim();
void showFish(QPainter *painter);
protected:
virtual void run();
private:
int mouth;
int pos_x, pos_y;
int dir;
bool isopen;
};
#endif
thfish.cpp
#include "thfish.h"
THFish::THFish(int x, int y, int m, int d):
mouth(m), isopen(false),
pos_x(x), pos_y(y),
dir(d){
}
void THFish::run(){
while(true){
openMouth();
QThread::usleep(100000);
}
}
void THFish::openMouth(){
if(isopen){
mouth += 5;
if(mouth >= 45){
isopen=!isopen;
mouth = 45;
}
}else{
mouth -= 5;
if(mouth <= 0){
isopen=!isopen;
mouth = 0;
}
}
}
void THFish::changeDir(int dir){
this->dir = dir;
}
void THFish::swim(){
if(this->dir == 0){
pos_x += 2;
}
if(this->dir == 90){
pos_y -= 2;
}
if(this->dir == 180){
pos_x -= 2;
}
if(this->dir == 270){
pos_y += 2;
}
}
void THFish::showFish(QPainter *painter){
QColor color(255, 0, 0, 255);
QPen pen(color);
painter->setPen(pen);
painter->drawPie(pos_x, pos_y, 50, 50, mouth * 16 + dir * 16, (360 - 2 * mouth) *16);
}
-
通信机制:信号与槽
- 定义信号
在fish.h文件的类中定义:-
signals: void sign_open();
-
- 发送信号
在fish.cpp文件的run()函数中发送:-
emit sign_open();
-
- 绑定信号到目标
- 目标需要有一个slot函数处理信息
在dialog.cpp文件中,线程启动前绑定:-
QObject::connect(fish, SIGNAL(sign_open()), this, SLOT(repaint())); QObject::connect(fish2, SIGNAL(sign_open()), this, SLOT(repaint()));
-
- 定义信号
-
绘制刷新实现动画
-
运行展示