背景
这几天遇到一个问题,需要在2、3天之内给一个已经编写好的简单C++命令行程序编写一个简单的图形界面。
由于之前没有接触过图形界面编程,所以不知道能不能搞定。后来询问了一些群友,在群友的推荐下,使用了QT这个框架(他们说MFC的API的设计不太好)。记录一下两三天速成图形界面的过程,希望能给一些想速成图形界面的读者带来帮助。
由于是速成的,而且只花了两三天,所以这篇博客不会包含原理类的东西,比如槽和信号的原理(想要了解原理的请自行学习),而且只使用了简单的控件,比如按钮、文本框等。
QT的安装不做简介,使用的QT的是QT 5.14.1,Community中文版。
过程
新建项目
打开QT Creator,点击左上角的文件->新建文件或项目,在弹出的窗口中选择Qt Widgets Application。
在设置Details时,Bass class选择QMainWindow
,并且一定要勾选Generate form。其它随意(我这里全部使用默认值)。项目保存的路径里不要有中文。
成功创建项目后,大概是这样:
需要用到的是:mainwindow.h
(编写代码)、mainwindow.cpp
(编写代码)和mainwindow.ui
(做界面)文件。
程序移植
由于我的是简单的命令行程序,所以将所有的代码都放到了MainWindow类里,移植时请注意变量生命周期。
设计图形界面
双击“项目”中“Forms文件夹”下的.ui
文件,启动QT Designer,然后就可以通过拖拽的方式设计界面了。
默认已经创建了一个内容空白、有状态栏和菜单栏的窗口(状态栏和菜单栏均可以删除),可以从左侧的控件菜单中将控件拖动到窗口里并自由排版。在右下角的属性窗口设置控件的具体属性,在右上角的对象查看器中可以浏览和编辑当前窗体的层次。
我的图形界面只用到了文本输入框(Text Edit)、标签(Label)、文本浏览框(Text Browser)、按钮(Push Button)这四个控件(使用其它控件的步骤也是差不多的),界面如下:
添加功能
信号和槽
设置完界面后,就希望添加各种功能,比如点一下按钮就做开始处理这个,当文本输入框中的文字改变后校验一下文字符不符合要求之类的。要实现这样的功能,就需要用到QT的信号和槽机制,信号是有对象或控件发送的消息,槽可以接受和响应信号,本质上是函数或方法。每个控件都自带了很多信号(也可以自定义,请自行百度),可以自己编写槽函数,将信号绑定到槽函数上。
比如点击按钮然后释放,就会发出clicked信号,可以自己编写一个函数,将这个clicked信号绑定到这个函数上,即可实现点击按钮处理事务的功能。
查看信号
- 每个控件都属于一个类,可以到百度上搜索这个类有哪些信号,也可以查阅官方文档。
- 可以使用QT Designer查看每个控件拥有的信号(参考博客在下一步)。
绑定信号和槽
参考博客:Qt信号和槽函数的四种实现方式
推荐第三种,使用connect的方法,毕竟可以自定义方法名。
以第三种方法和这个项目为例,介绍一下实现过程:
在QT Designer左上角的对象查看器中的可以查到按钮的对象名为pushButton
。假设我现在需要用到该按钮的clicked
信号,希望点击按钮后能执行myFunc
函数,myFunc函数会对窗口做一系列的操作。
在mainwindow.h的MainWindow
类(如果你定义了类名的话就不是这个类了)的定义中添加代码:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots: //添加
void myFunc(void); //添加,没有参数,我写的时候是把要用到的参数都放到了类里
private:
Ui::MainWindow *ui;
};
在mainwindows.cpp中实现myFuc函数:
void MainWindow::myFunc(void){
//总的来说操作窗口控件就是通过指针调用方法。
ui->label->setText("111"); //修改Label标签显示的值为111
QString inText=ui->textEdit->document()->toPlainText(); //获取Text Edit中的内容(简单文本内容),并保存为Qstring类型
QMessageBox::information (NULL,"成功","你成功了!"); //弹出一个自带一个确认按钮的消息框,需要 #include <QMessageBox>
}
在MainWindows类的构造函数中添加:
connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(myFunc()));
若需在使用槽函数时传递参数,如果要使用信号自带的参数时,可以参考这篇博客:信号槽如何传递参数。如果想要自定义参数,可以参考这篇博客:Qt中connect函数不能传递参数的两种解决方法。当然也可以把需要用到的数据都保存到类里,然后在执行函数时读取。
需要注意的一些问题
很多控件使用的不是String类型的字符串或char*型的C字符串(比如Label的setText()方法),而是QString类型,这是QT自带的类,用于字符串处理。所以需要进行转换,转换请自行百度。比如这篇:0022:Qt常用类 - QString(01,QString的编码方式和初始化)
编译和发布应用
在QT Creator的左下角可以选择编译器和编译类型,如果是要最终发布,请选择构建类型为Release,然后点击那个锤子形状的图标。
发布应用参考博客:Windows平台上的应用程序发布