太兴奋了,花了一天时间,终于把一个demo调通了,掉了无数个坑,无论是看书还是看网络上的一些帖子,坑无数。本人也是刚接触Qt,就四五天吧。现在经过一些坑的洗礼,终于可以慢慢入门了,兴奋啊,吼啊,不禁让我在朋友圈分享了一首FB的歌呢。当然网上不全是坑,也发现了非常精华的内容,比如这篇博客《Qt资料大全》,非常适合Qt小白。
本人极力推荐《Qt Creator快速入门》以及配套的相关代码,我已经将这些资料以及我的demo上传到我的GitHub上供大家学习。如果大家喜欢的话,就帮我在GitHub上点个star吧,蟹蟹大噶!
本文的主要内容
- 软件环境配置以及安装
- 多窗口切换的Qt技术以及需要注意的地方
- 实战代码以及实现效果
1. 软件环境配置以及安装
我采用的是visual studio 2017 + Qt 5.9.2。我是根据这篇博客《VS2017专业版使用最新版Qt5.9.2教程(最新教材)》安装的,一步步来,绝对没有问题。
2. 多窗口切换的Qt技术以及需要注意的地方
由于我之前没接触过Qt,因此对它非常陌生,连基本的需要建立哪些文件,也是懵逼的,而且我发现网上好多博客坑的地方在于,不贴相关的图,简单粗暴的上代码,上代码就不多提了,关键还上错误的代码,心中一万匹草泥马在狂奔。因此本文绝对要做到图文并茂,让Qt小白学到真东西,不掉坑。
首先我粘上我的vs解决方案管理器里的文件,让大家明白我主要都用到了啥:
多窗口切换顾名思义就是至少要有两个窗口,因此你首先需要建立至少两个.ui文件,我的demo总共包括四个窗口,因此我建立了,四个.ui文件
,四个头文件,四个cpp文件
。其中main.cpp
文件是用来运行总的软件的,main_window.cpp
是用来作为主窗口,另外三个child_Windowx.cpp
作为子窗口。
这儿有一个地方特别需要注意:在vs里面你使用Qt,每建立一个.ui
文件,你点击.ui文件并右键选择编译
在Generated Files
里面都会产生一个ui_filename.h
形式的文件,这个文件,你只能到代码的工程文件夹里面找(在管理器里打不开),这个文件是Qt自动为我们设计的ui头文件,我们要让设计好的界面显示出来只要设法调用某个类的setupUi
函数就可以了。具体的解释说明可以见Qt中ui文件的使用
接下来讲几点多窗口切换的几个关键技术点:
- 信号和槽
- 窗口、子部件以及窗口类型的表示
- 模态和非模态的对话框
- 手动关联信号和槽:
connect函数
- 自动关联信号和槽:
on命名方式
2.1 信号和槽
信号和槽都是函数,例如 单击窗口上的一个按钮想要弹出一个对话框,那么可以将这个按钮的单击信号和定义的槽关联起来,在这个槽中可以创建一个对话框并且显示。这样单击按钮就会发射信号,并且执行这个槽显示一个对话框。
其中label就是图标的名字,objectName是在代码文件中作为槽的说明即slots
在源文件中为槽快速添加申明的方式:单击showChildDialog() 槽
,然后同时按下Alt+Enter 键,弹出mywidget.cpp添加申明的选项,然后回车Enter,编辑器转到mywidget.cpp文件中,并且创建好了槽的定义。
2.2 窗口、子部件以及窗口类型的表示
QMainWindow
是带有菜单栏和工具栏的主窗口类型, QDialog
是各种对话框的基类,前面两种窗口类型都是继承自QWidget
类型
2.3 模态与非模态的对话框
模态对话框,先弹出对话框再弹出主窗口,代码:QDialog dialog(this);dialog.exec();
非模态对话框,先弹出主窗口再弹出对话框,代码:QDialog *dialog =new QDialog(this);dialog->show();
2.4 模态与非模态的对话框
使用connect
函数将按钮的单击信号clicked()
与新建的槽进行关联,clicked()
信号在QPushButton
类进行了定义,connect()
是QObject
类中的函数,因为类继承自QObject
,所以可以直接使用。在函数中四个参数分别是:发送信号的对象,发送的信号,接受的信号,要执行的槽,信号和槽用SIGNAL()和SLOT()
宏括起来。
2.5 自动关联信号和槽:on
命名方式
自动关联就是将关联函数整合到槽命名中,但必须使用Qt
部件已经提供的信号,比如前面的槽就可以表示为:on_showChildButton_clicked()
,就是由字符on 和发射信号部件对象还有信号名组成。这样就可以去掉关联函数connect
了。
3. 实战代码以及实现效果
实战代码我已经上传到我的GitHub上了,大家感兴趣可以去下载,顺便给我点个star。我在这贴出比较典型的几个代码片:
一个是主窗口的头文件
#pragma once
#ifndef MAIN_WINDOW_H
#define MAIN_WINDOW_H
#include <QWidget>
#include <QMainWindow>
#include <QPushButton>
#include "child_Window1.h" // 包含子窗口的头文件
#include "child_Window2.h"
#include "child_Window3.h"
namespace Ui {
class main_window;
}
class main_window :public QMainWindow {
Q_OBJECT
public:
explicit main_window(QWidget *parent = 0);
~main_window();
private slots:
void on_fileselect_clicked(); //采用自动关联
private:
Ui::main_window *ui_main;
child_window1 cw1; // 创建子窗口的实例
child_window2 cw2;
child_window3 cw3;
QPushButton fileselect; // 创建的按钮 父窗口的一个成员
QPushButton functionkey;
QPushButton report;
};
#endif // !MAIN_WINDOW_H
主窗口的cpp文件:
#include "ui_main_window.h"
#include "main_window.h"
#include <QDebug>
#include "child_Window1.h"
#include "child_Window2.h"
#include "child_Window3.h"
main_window::main_window(QWidget *parent):
QMainWindow(parent),
ui_main(new Ui::main_window)
{
ui_main->setupUi(this);
//fileselect.setParent(this); //设置按钮父对象 是main_window
//connect(&fileselect,&QPushButton::clicked,this,&main_window::ChangeToFileSelect); //按钮绑定自定义的槽函数,当点击父窗口的按钮就会触发函数
//connect(&cw1, &child_window1::mysignal, this, &main_window::show);
/*functionkey.setParent(this);
connect(&functionkey, &QPushButton::clicked, this, &main_window::ChangeToFunctionKey);
report.setParent(this);
connect(&report, &QPushButton::clicked, this, &main_window::ChangeToReport);*/
connect(&cw1, &child_window1::showmainwindow, this, &main_window::show);
}
//显示子窗口 同时将主窗口 隐藏
void main_window::on_fileselect_clicked() {
this->hide();
cw1.show();
}
//void main_window::ChangeToFileSelect() {
// this->hide();
// cw1.show();
//}
//void main_window::ChangeToFunctionKey() {
// this->hide();
// cw2.show();
//}
//void main_window::ChangeToReport() {
// this->hide();
// cw3.show();
//}
main_window::~main_window() {
delete ui_main;
}
//connect(ui->fileselect,SIGNAL(clicked()),this,SLOT())
实现的效果