QT基础学习


前言

命名规范:类名首字母大写,单词与单词之间大写;函数名首字母小写,单词与单词之间大写

  • 快捷键:

  • 注释:ctrl+/

  • 运行: ctrl+r

  • 编译:ctrl+b

  • 整行移动:ctrl+shift+上or下

  • 帮助文档:F1

  • 自动对齐:ctrl+i

  • xxx.cpp文件和xxx.h文件之间快速切换:F4

一、第一个QT程序

创建一个桌面QT应用程序,选择如下

choose下一步

不能含有中文路径

继续下一步

这里有三个选择分别是QMainWindow,QDialog,Qwidget,这里的QWidget相当于其他两个父类,选择QWidget就是一个空的窗口,选择QMainWindow会在空窗口的基础上多了菜单栏,QDialog就是对话窗类,下面有个创建界面,如果不勾选就是自己编写程序的窗口各种组件,如果勾选了就可以类似MFC在一个空的窗口自己添加各种组件设计界面。继续下一步完成创建

打开文件中的widget.ui文件就会跳转到添加组件界面,这里添加两个组件

在旁别的视图会显示出当前添加组件的类

先打开01_learn.pro文件添加语句

添加QT       += core gui texttospeech

QT       += core gui texttospeech

然在在ui界面右击按钮,选择跳转到槽,然后选择clicked,然后会跳转到相应的控制组件的相应语句在其实添加事件处理程序

x->say(ui->lineEdit->text()); 

再编写Wdiget的构造函数添加语句

由于这里使用了QTextTOSpeeh所以还要在widget.h文件中添加该类的头文件

最后在运行程序

在文本框中输入文字,点击按钮就会语音播报出这段文字

二、基本认识

文件目录

.pro文件

第一个pro是项目工程文件文件

#-------------------------------------------------
#
# Project created by QtCreator 2022-11-21T19:30:51
#
#-------------------------------------------------

QT       += core gui texttospeech #QT包含的模块,这个时候里面有三个模块分别是core gui texttospeech

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets    #大于4版本包含widget模块

TARGET = hello #目标 生成.exe可执行文件的名称
TEMPLATE = app #模板 应用程序模板,默认生成的是app模板,也有别的一些模板

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS    #表示当Qt的某些功能被标记为过时的,那么编译器会发出警告。

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += \ #源文件
        main.cpp \
        widget.cpp

HEADERS += \ #头文件
        widget.h

FORMS += \  #ui文件
        widget.ui

Qt5所包含的主要模块

main.cpp

main.cpp是主函数文件,里面包含了主要应用程序的入口函数,和C/C++一般写法一样,QT界面的main()函数也有固定的格式

int main(int argc,char **argv){
	QApplication a(argc,argv);
	
	return a.exec();
}

图中的main()函数代码解析:

  • 1~2行:由于在main()函数中分别定义了 QApplication和Widget类的对象,因此要引入两个文件的头文件。由于widget.h是我们自己创建的,所以引用的时候要用 “ “;QApplication是QT提供的所以用 < >;

  • 7行:Widget是自定义的类,继承自QWidget,QWidget类是所有用户界面对象的基类,所有Widget也是,w是实例化出的一个用户界面

    如果在创建一个就会显示两个

  • 8行: 在默认的情况下,QT所提供的所有组件都是隐藏的不会自动显示出来。通过调用show()方法,w用户界面就可以在程序运行后显示出来

#include "widget.h" //用户自定义的头文件,名字可以在创建的时候更改
#include <QApplication> //应用程序头文件,

int main(int argc, char *argv[])// argc是命令个数,argv是命令参数
{
    QApplication a(argc, argv); //定义一个应用程序类,并且在每个QT文件中有且仅有一个应用程序类
    //它的构造函数接受和main函数一样的参数,相当于c/c++程序中的程序入口,这个是QT图形化程序入口
    Widget w;//创建一个窗口
    w.show();//默认不会显示窗口,显示窗口

    return a.exec();//会进入QT程序的事件循环函数等待用户的操作,图形程序需要与用户交互所以不会自动退出,当且仅当点击“X”之后就会返回一个0值关闭窗口
}

widget.cpp和widget.h

创建项目的时候定义了继承自QWidget的用户界面类,使用的默认名称widget,该类的定义部分位于widget.h头文件中,实现部分在widget.cpp文件中

//
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget> //添加的窗口类
#include <QTextToSpeech> //说话类

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT //定义好的宏,允许使用信号和槽机制

public:
    explicit Widget(QWidget *parent = 0);  //构造函数
    ~Widget();  //析构函数

private slots:
    void on_pushButton_clicked(); //按钮

private:
    Ui::Widget *ui; 

    QTextToSpeech *x; //创建说话对象
};

#endif // WIDGET_H

---------------------------------
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    x = new QTextToSpeech;
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_pushButton_clicked()
{
    x->say(ui->lineEdit->text()); //提取框中文字语音播报
}

在初始的状态下widget类是由Q_OBJECT,构造函数还有析构函数组成的

  • Q_OBJECT:本质是一个已经定义好的宏,所有需要的”信号和槽”功能组件都必须将Q_OBJECT作为private属性的成员引入类中。
  • 带参数的构造函数:QWidget是所有组件的基类,借助parent指针,可以为当前窗口指定父窗口,如果删除父窗口,里面所有的子窗口都会关掉

后面两个prviate是自己添加的组件时QT自动添加的

运行结果在w主窗口中有两个自己添加的组件

widget.ui

这个文件中就是设计图形界面的,在这里添加的组件QT都会自动在相应的文件中生成,这时候只需要去对应的代码区写事件处理程序。

三、创建一个QPushButton

先创建一个新的项目my_PushButton,这次设置不创建界面,通过API接口添加组件。

如果第一次接触一个组件不知都怎么使用可以使用QT的界面中的帮助选项,这里以QPushButton为例

查看帮助界面

在QPushButton Class一栏中包含了使用所需要在文件中添加的内容

Header: #include <QPushButton>   //使用所包含的头文件
qmake: QT += widgets             //使用要添加的模块
Inherits: QAbstractButton		 //QPUshButton的父类
Inherited By: QCommandLinkButton //QPushButton的子类

在widget.cpp文件中添加控件,注意不是main.cpp

#include "widget.h"
#include<QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    //创建一个按钮
    QPushButton *bt=new QPushButton; //这里要采用new的方式创建组件
    
}

Widget::~Widget()
{

}

这样就创建好了一个简单的按钮,但是运行编译发现,界面并没有出现按钮,之前说过默认是不会显示窗口的,那我们用show试一下

加一句bt->show();

我们发现是没有在一个窗口上的,我们所期望的是按钮的就在我们初始创建的窗口上,所以我们把令bt的对象指向初始窗口

bt->setParent(this);//因为在窗口类里创建的对象,所以用this指针就可以指向窗口

在窗口中间生成一个按钮

设置这个按钮的文本

bt->setText("我的按钮");

这样创建其实是蛮麻烦的,QPushButton类中有多个重载的构造函数,利用重载构造函数我们可以快速创建出一个按钮组件

根据构造函数参数表我们所用第二个就可以了

我的按照第一个方式创建的组件是在窗口中心的,有的版本可能是和第二按钮一样在左上角,导致重合,不过都不要紧,反正位置可以调的 ,通过调用move函数移动按钮位置,以下是完整代码

#include "widget.h"
#include<QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    //创建一个按钮
    QPushButton *bt1=new QPushButton; //这里要采用new的方式创建组件
    bt1->show();//show()以顶层的方式弹出窗口控件
    bt1->setParent(this);//因为在窗口类里创建的对象,所以用this指针就可以指向窗口
    bt1->setText("我的第一个按钮");
    //创建第二个按钮
    QPushButton *bt2=new QPushButton("我的第二个按钮",this);
    bt1->move(100,100);//移动第二个窗口
    resize(640,400);//设置窗口大小
    setFixedSize(640,400);//固定窗口大小,可以拖拽,不能缩放
    setWindowTitle("我的第一个窗口");//设置窗口名称
}

Widget::~Widget()
{

}

运行结果

总结:

  • 创建按钮:QPushButton *bt1=new QPushButton;
  • 设置父亲:setParent(this);
  • 设置文本:setText(“文本”);
  • 设置位置:move(宽,高);
  • 重新指定窗口大小: resize
  • 设置窗口标题:setwindowTitle
  • 设置窗口固定大小:setFixedsize

在创建的组件是使用new的主要有两个原因,一就是非new在栈上,所以空间有限,能分配的空间相对小,再就是由于非new在栈上,所以会随着所在块的结束,也就是所在大括号{}之后会销毁,如果有局部自动变量,在退出构造函数之后这些自动变量就会被销毁,这样 你的窗口调用show的时候也不会显示组件了

我们通过new创建了两个按钮组件,但是在我们所写函数并没有添加相应的delete()函数,这主要是由于在QT中 对象树的概念,我们在创建按钮组件的时候把他父类指定了QWidget,而在QT中存在一个chidren表,两个按钮组件就放在chidren表中,当关闭窗口的时候QWidget析构的时候也会把在它chidren表中的控件析构

Qt对象树

也就是如果在用new创建的对象指定的父类是QObject或者是QObject的子类对象是可以不用管理内存的释放的

四、信号和槽

简单使用

QT中的信号和槽机制可以简单的理解为:张三想要像李四表白,张三先在微信给李四发了表白消息,然后李四就拒绝了嘛

这里张三就是信号的发送者 在微信发的消息就是发送的信号,李四就是信号的接受者,李四拒绝就是处理的槽函数

现在实现点击按钮关闭窗口的实例

首先需要一个connect函数用来连接以上参数


//需求:点击我的第一个按钮关闭窗口
    //参数1: 信号的发送者 参数二: 发送的信号(函数地址,这个函数地址可以理解成微信,就是要用哪种方式表白,这里就是用哪种组件的函数发送信号)
    //参数3: 信号的接收者 参数4:处理的参函数
   connect(bt1,&QPushButton::clicked,this,&Widget::close);//QPushButton发出点击的信号,Widget执行槽函数关闭窗口

QPushButton发出的信号可以在帮助文档中查询

QPushButton的信号

Widget是继承于QWidget的,所以可以在帮助文档查找QWidget的槽函数

每个槽函数可以点击查看作用

自定义信号和槽

新创建一个文件夹SignalAndSlot

添加一个Class,命名teacher,继承QObject

然后再用类似的方法创建一个Student类,我们这里定义teacher发送信号,student执行槽函数

实现功能:当下课了,老师饿了,学生请老师吃饭

student.h

#ifndef STUDENT_H
#define STUDENT_H

#include <QObject>

class Student : public QObject
{
    Q_OBJECT
public:
    explicit Student(QObject *parent = nullptr);

signals:

public slots:
    //在这里写槽函数
    //返回值是void,需要声明,也需要实现
    //可以有参数,可以有重载
    void treat();
};

#endif // STUDENT_H

teacher.h

#ifndef TEACHER_H
#define TEACHER_H

#include <QObject>

class Teacher : public QObject
{
    Q_OBJECT
public:
    explicit Teacher(QObject *parent = nullptr);

signals:
    //自定义信号  写在signal下
    //返回值是void,只需要声明,不需要实现
    //可以有参数,可以重载
    void hungry();
public slots:
};

#endif // TEACHER_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "teacher.h"
#include "student.h"
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private:
    Teacher* zt;//定义类成员
    Student* st;//定义类成员
    Ui::Widget *ui;
    void ClassIsOver();//定义下课了条件函数
};

#endif // WIDGET_H

student.cpp

#include "student.h"
#include <QDebug>//调试类

Student::Student(QObject *parent) : QObject(parent)
{

}

void Student::treat(){
    qDebug()<<"on my treat today";//打印调试信息
}

teacher.cpp

#include "teacher.h"

Teacher::Teacher(QObject *parent) : QObject(parent)
{
    //什么都不用写
}

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    //创建老师对象
    this->zt =new Teacher(this);//把这个Teacher指定为Widget,放入对象树,就不用担心内存释放的问题
    //创建学生对象
    this->st =new Student(this);
    //自定义的信号与槽
    connect(zt,&Teacher::hungry,st,&Student::treat);
    //添加下课了的前提
    ClassIsOver(); //这个不能放在自定义信号于槽的语句前面,这里的逻辑是先有了信号了,然后条件达成触发信号

    ui->setupUi(this);
}

void Widget::ClassIsOver(){
    //下课了,老师饿了,触发信号
    emit zt->hungry();
}

Widget::~Widget()
{
    delete ui;
}

运行结果

自定义信号和槽的重载情况

分别在teacher和student类中编写重载版本

在teacher.h中添加一句

void hungry(QString foodname);

student.h添加

void treat(QString foodname);

在student的cpp文件编写函数

void treat(QString foodname){
	qDebug()<<"Reload version"<<foodname;
}

修改widget.cpp

重载版本的参数不能直接在connect中指定,要分别写两个函数的函数指针,通过函数指针访问

运行结果

这里的food输出的带有双引号但是我们写的程序并没有添加双引号

qDebug()<<"Reload version"<<foodname;

这里通过强转,将QString转换成char* 类型就可以了

qDebug()<<"Reload version"<<foodname.toUtf8().data();

运行结果

转换过程:先用toUTf8()转换成QByteArray,再把用data()把QByteArray转换成char*

信号连接信号

这个时候我们是一运行老师就饿了,然后输出了调试信息,现在添加一个按钮,当点击了按钮输出调试按钮

别忘记了添加头文件#include

现在就可以实现了点击按钮输出调试信息

接下来是通过信号连接信号的方式,创建两个按钮,按“有参调试”输出:Reload version food,按“无参调试”输出:on my treat today

widget.cpp完整代码

#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>


Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    //创建老师对象
    this->zt =new Teacher(this);//把这个Teacher指定为Widget,放入对象树,就不用担心内存释放的问题
    //创建学生对象
    this->st =new Student(this);
    //自定义的信号与槽
    //connect(zt,&Teacher::hungry,st,&Student::treat);

    //连接带有参数的信号和槽
    //函数指针->函数地址
    void(Teacher:: *teacherSignal)(QString)=&Teacher::hungry;
    void(Student:: *studentSlot)(QString)=&Student::treat;
    connect(zt,teacherSignal,st,studentSlot);
    QPushButton* bt1=new QPushButton("有参调试",this);
    bt1->move(100,100);//移动按钮
    connect(bt1,QPushButton::clicked,this,Widget::ClassIsOver);//当点击按钮,触发ClassISOver
    //添加下课了的前提
    //ClassIsOver(); //这个不能放在自定义信号于槽的语句前面,这里的逻辑是先有了信号了,然后条件达成触发信号

    void(Teacher:: *teacherSignal2)(void)=&Teacher::hungry;//
    void(Student:: *studentSlot2)(void)=&Student::treat;//先用函数指针指定使用的函数
    connect(zt,teacherSignal2,st,studentSlot2);//创建信号与槽的连接
    QPushButton* bt2=new QPushButton("无参调试",this);//创建按钮
    bt2->move(100,200);//移动按钮
    connect(bt2,QPushButton::clicked,zt,teacherSignal2);  //信号连接信号
    ui->setupUi(this);
}

void Widget::ClassIsOver(){
    //下课了,老师饿了,触发信号
    //emit zt->hungry();
    emit zt->hungry("food");
}

Widget::~Widget()
{
    delete ui;
}

运行结果

在使用完一个信号连接后是可以断开的使用disconnect()断开连接,参数和要断开的连接一样

lambda表达式

在lambda表达式中实现一个信号对应多个槽

先创建一个按钮,实现在点击按钮的时候关闭窗口,并输出调试信息

//lamdba表达式
QPushButton* bt3=new QPushButton("lambda",this);
bt3->move(100,300);
connect(bt3,QPushButton::clicked,[=](){  //如果在使用lambda的时候如果第三个参数是this,可以省略不写
    this->close();
    this->ClassIsOver();
});

点击lambda会关闭窗口输出调试信息

五、QMainWindow

新建一个项目,选择QMainWindow,现在mainwindow.cpp添加以下头文件

#include "mainwindow.h"
#include <QMenuBar>
#include <QMenu>
#include <QToolBar>
#include <QDebug>
#include <QPushButton>
#include <QStatusBar>
#include <QLabel>
#include <QDockWidget>
#include <QTextEdit>

菜单栏

在QMainWindow类窗口中添加一个菜单栏,在MainWindow的构造函数添加以下两句即可显示出一个简单的菜单栏,最多只有一个

QMenuBar* bar = menuBar();//新建一个菜单,这里是不需要设置this指针的
setMenuBar(bar);//显示菜单栏

现在是空的,什么都没有

在菜单栏添加菜单

QMenu* fileMenu = bar->addMenu("file");//创建一个文件菜单
QMenu* newMenu = bar->addMenu("new");//创建一个新建菜单
QMenu* delMenu =bar->addMenu("del");//创建一个删除菜单

如果是在Window系统下添加之后不显示,检查一下是否创建了图形界面

运行结果

菜单项

在菜单中的单个选项添加菜单项

fileMenu->addAction("last one");//创建文件下的一个菜单项
fileMenu->addSeparator();       //添加一跳分割线
fileMenu->addAction("before one");//创建文件下的一个菜单项

运行结果

工具栏

添加一个工具栏

QToolBar* toolbar= new QToolBar(this);//这里还是要设置this指针
addToolBar(Qt::LeftToolBarArea,toolbar);//设置工具栏默认显示位置

这里使用的是addToolBar的一个重载函数,第一个参数可以设置为默认位置上下左右四个位置

运行结果

创建完成不设置工具栏是可以随意拖动的,甚至可以拖动到窗口中间

设置一下浮动并让窗口只能停靠在左边或者右边

需要使用的函数在QToolBar中可以找到

toolbar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);//设置只能显示在左边或者右边
toolbar->setFloatable(false);//设置浮动这样就可以使工具栏不显示在窗口中间

设置移动,设置之后工具栏就不可以移动了

toolbar->setMovable(false);

然后设置工具栏的内容

   toolbar->addAction("tool1");
toolbar->addSeparator();
   toolbar->addAction("tool2");

在工具栏添加一个按钮

toolbar->addSeparator();
QPushButton* bt = new QPushButton("tool3",this);
toolbar->addWidget(bt);

状态栏

跟菜单栏一样也只能有一个

设置一个状态栏

QStatusBar* stbar = new QStatusBar;//这里也是不用this,可以理解为由于只能设置一个QT已经帮我们设置好了
setStatusBar(stbar); //设置到窗口

由于没在状态栏添加东西所以显示的是空的

添加控件标签

QLabel* lab1 = new QLabel("提示左侧信息",this);
stbar->addWidget(lab1);//在左侧显示一个标签
QLabel* lab2 = new QLabel("提示右侧信息",this);
stbar->addPermanentWidget(lab2);

设置浮动铆接部件

QDockWidget* dock1 = new QDockWidget("浮动",this);
addDockWidget(Qt::BottomDockWidgetArea,dock1);//第一个参数填设置位置,与工具栏类似
dock1->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea); //设置只能在上下显示

这里设置的位置是下方

其他位置的设置可以参考帮助文档

参数表

虽然设置的是下方但是由于主界面没有内容,这个下方定义的是在内容之下,所以仍然显示的是最上方

在窗口内添加一个中心部件,中心部件也只能设置一个

QTextEdit* edi1 = new QTextEdit(this);
setCentralWidget(edi1);

这时铆接部件就显示在下方的

这一节中有的控件是只能添加一个的,有的可以设置多个,可以根据使用对应的函数记忆,用set创建的就只能有一个,用add创建的就可以有多个

完整代码

#include "mainwindow.h"
#include <QMenuBar>
#include <QMenu>
#include <QToolBar>
#include <QDebug>
#include <QPushButton>
#include <QStatusBar>
#include <QLabel>
#include <QDockWidget>
#include <QTextEdit>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{

    resize(640,400);
    QMenuBar* bar = menuBar();//新建一个菜单,这里是不需要设置this指针的
    setMenuBar(bar);//显示菜单栏
    QMenu* fileMenu = bar->addMenu("file");//创建一个文件菜单
    QMenu* newMenu = bar->addMenu("new");//创建一个新建菜单
    QMenu* delMenu =bar->addMenu("del");//创建一个删除菜单
    //添加菜单项----------------------------------------------------------
    fileMenu->addAction("last one");//创建文件下的一个菜单项
    fileMenu->addSeparator();       //添加一跳分割线
    fileMenu->addAction("before one");//创建文件下的一个菜单项
    //添加工具栏----------------------------------------------------------
    QToolBar* toolbar= new QToolBar(this);//这里还是要设置this指针
    addToolBar(Qt::LeftToolBarArea,toolbar);//设置工具栏默认显示位置
    toolbar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);//设置只能显示在左边或者右边
    toolbar->setFloatable(false);//设置浮动这样就可以使工具栏不显示在窗口中间
    //设置移动,设置之后工具栏就不可以移动了
    toolbar->setMovable(false);
    //设置工具栏内容
    toolbar->addAction("tool1");
    toolbar->addSeparator();
    toolbar->addAction("tool2");
    //在工具栏添加控件
    toolbar->addSeparator();
    QPushButton* bt = new QPushButton("tool3",this);
    toolbar->addWidget(bt);
    //添加状态栏---------------------------------------------------------
    QStatusBar* stbar = new QStatusBar;//这里也是不用this,可以理解为由于只能设置一个QT已经帮我们设置hao
    setStatusBar(stbar); //设置到窗口
    //放标签控件
    QLabel* lab1 = new QLabel("提示左侧信息",this);
    stbar->addWidget(lab1);//在左侧显示一个标签
    QLabel* lab2 = new QLabel("提示右侧信息",this);
    stbar->addPermanentWidget(lab2);
    //铆接部件(浮动窗口)
    QDockWidget* dock1 = new QDockWidget("浮动",this);
    addDockWidget(Qt::BottomDockWidgetArea,dock1);//第一个参数填设置位置,与工具栏类似
    dock1->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea); //设置只能在上下显示
    //设置中心部件,只能一个
    QTextEdit* edi1 = new QTextEdit(this);
    setCentralWidget(edi1);
}

MainWindow::~MainWindow()
{

}

六、添加资源文件

新建一个项目My_Res,勾选图形界面创建

先用UI界面创建如下窗口

右击文件目录,选择在Explore中显示,跳转到文件目录,把要填加的资源文件放在目录下,这里以存放图片为例

image包含了要使用了图片资源

然后右击项目根目录选择添加新文件

勾选这个选项

然后进入相应文件

先点击添加前缀 / 就可以了,然后点击天机文件,选择刚在放在项目文件夹目录的Image,全选添加

然后点击编译

如图显示就添加成功了

为菜单项添加图标

ui->actionedit->setIcon(QIcon(":/Image/Sunny.jpg"));
ui->actiondel->setIcon(QIcon(":/Image/Frame.jpg"));//这两句要放在ui->setupUi(this);的下面,不然运行不了的

运行结果

七、对话框

新建一个项目My_QDig,先用图形界面创建以下界面

参数

模态对话框

模态对话框:弹出后就不可以对其他窗口做操作

实现功能:点击tool,弹出一个模态对话框

connect(ui->actiontool,&QAction::triggered,[=](){//建立连接,当触发tool弹出窗口
//模态对话框------------------------------------------
QDialog dia1(this);//创建一个窗口
dia1.resize(520,300);//设置弹出的窗口大小
dia1.exec();//显示模态对话框
});

connect第二个参数是QAction里的信号

非模态对话框

非模态对话框:弹出后可以对其他的窗口操作

实现功能:点击tool2弹出一个非模态对话框

    connect(ui->actiontool2,&QAction::triggered,[=](){//建立连接,当触发tool2弹出窗口
    //非模态对话框----------------------------------------
    //QDialog dia2(this);不能使用这种方式创建,这样创建窗口会一闪而过
    QDialog *dia2 = new QDialog(this);//创建一个窗口,
    dia2->resize(520,300);
    dia2->setAttribute(Qt::WA_DeleteOnClose); //55号属性
    dia2->show();//显示非模态对话框
    });
}

QDialog dia2(this);不能使用这种方式创建,这样创建窗口会一闪而过,所以应该创建在堆区,由于模态对话框会有一个堵塞的特性,不会退出connect函数所以可以直接创建

dia2->setAttribute(Qt::WA_DeleteOnClose); ,由于创建在堆区,所以如果要是一直创建非模态对话框,在程序还在运行时内存是不会释放的,有可能引起内存泄漏,使用这句保证在每次创建的非模态对话框删除时清理内存

消息对话框

根据上述方法分别在菜单项的编辑添加模态对话框,删除添加非模态对话框

connect(ui->actionedit,&QAction::triggered,[=](){//建立连接,当触发编辑弹出窗口
//模态对话框------------------------------------------
QDialog dia3(this);//创建一个窗口
dia3.resize(520,300);//设置弹出的窗口大小
dia3.exec();//显示模态对话框
});
connect(ui->actiondel,&QAction::triggered,[=](){//建立连接,当触发删除弹出窗口
//非模态对话框----------------------------------------
QDialog *dia4 = new QDialog(this);//创建一个窗口,
dia4->resize(520,300);
dia4->setAttribute(Qt::WA_DeleteOnClose); //55号属性
dia4->show();//显示非模态对话框
});

实现功能:点击tool弹出错误消息,点击tool2弹出对话消息,点击编辑弹出提问消息,点击删除弹出警告信息

点击tool弹出错误消息:

connect(ui->actiontool,&QAction::triggered,[=](){//建立连接,当触发tool弹出窗口
//模态对话框------------------------------------------
//QDialog dia1(this);//创建一个窗口
//dia1.resize(520,300);//设置弹出的窗口大小
//dia1.exec();//显示模态对话框
QMessageBox::critical(this,"error","错误");//点击弹出错误信息
});

点击tool2弹出对话信息:

connect(ui->actiontool2,&QAction::triggered,[=](){//建立连接,当触发tool2弹出窗口
   //非模态对话框----------------------------------------
   //QDialog dia2(this);不能使用这种方式创建,这样创建窗口会一闪而过
   //QDialog *dia2 = new QDialog(this);//创建一个窗口,
   //dia2->resize(520,300);
   //dia2->setAttribute(Qt::WA_DeleteOnClose); //55号属性
   //dia2->show();//显示非模态对话框
   QMessageBox::information(this,"info","Hello World");//点击弹出消息信息
   });

点击编辑弹出提问消息:

connect(ui->actionedit,&QAction::triggered,[=](){//建立连接,当触发编辑弹出窗口
//模态对话框------------------------------------------
//QDialog dia3(this);//创建一个窗口
//dia3.resize(520,300);//设置弹出的窗口大小
//dia3.exec();//显示模态对话框
    if(QMessageBox::Yes == QMessageBox::question(this,"edit","是否编辑",QMessageBox::Yes | QMessageBox::Yes,QMessageBox::No)){
        qDebug()<<"开始编辑";QMessageBox::No
    }else{
        qDebug()<<"退出编辑";
    }

});

点击yes弹出开始编辑消息,点击no弹出退出编辑消息

点击删除弹出警告信息:

connect(ui->actiondel,&QAction::triggered,[=](){//建立连接,当触发删除弹出窗口
//非模态对话框----------------------------------------
//QDialog *dia4 = new QDialog(this);//创建一个窗口,
//dia4->resize(520,300);
//dia4->setAttribute(Qt::WA_DeleteOnClose); //55号属性
//dia4->show();//显示非模态对话框
  QMessageBox::warning(this,"warning","可能没有成功删除");
});

总结

使用函数的参数

QWidget* parent:指定父类

const QString &title:窗口标题

const QString &text: 窗口内容

StandardButton buttons:选择使用的按钮,这里只有question使用了这个

所有按钮

StandardButton defaultButton = NoButton:设置第四个窗口使用的默认值,比如上面的 question例子,默认值是

QMessageBox::No,也是就说如果不做选择直接回车会默认选择no运行

颜色对话框

实现功能:点击选择颜色,弹出颜色选择栏,选择后并输出调试信息

connect(ui->actioncolor,&QAction::triggered,[=](){//建立连接,当触发删除弹出窗口
    //返回值是QColor而不是QcolorDialog
    //QColor 参数一:red 参数二:green 参数三:blue 参数四:透明度
    QColor color1 = QColorDialog::getColor(QColor(255,0,0,255));
    qDebug() <<"r="<<color1.red()<<"g="<<color1.green()<<"b="<<color1.blue();
});

文件对话框

实现功能:点击选择文件,弹出指定的文件目录,并再选择文件后输出文件路径

connect(ui->actionfile,&QAction::triggered,[=](){
    //返回值string,是打开文件的路径
    //getOpenFileName 参数一:指定父亲 参数二:窗口名称 参数三:打开路径 参数四:筛选文件类型
    QString cwd = QFileDialog::getOpenFileName(this,"打开桌面txt文件","E:/资源/桌面","*.txt");
    qDebug() <<cwd;
});

字体对话框

实现功能:点击选择字体,弹出字体选择对话框,并输出选择后的字体信息

connect(ui->actionfont,&QAction::triggered,[=](){
    bool flag;
    //返回值是QFont而不是QFontDialog
    //QFont 参数一:默认的字体 参数二:默认的大小
    QFont font = QFontDialog::getFont(&flag,QFont("宋体",36));
    qDebug()<<"字体:"<<font.family()<<"字号:"<<font.pointSize()<<"是否加粗"<<font.bold()<<"是否斜体"<<font.italic();
});

完整代码

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>
#include <QMessageBox>
#include <QDebug>
#include <QColorDialog>
#include <QFileDialog>
#include <QFontDialog>
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    resize(640,400);//设置主窗口大小
    connect(ui->actiontool,&QAction::triggered,[=](){//建立连接,当触发tool弹出窗口
    //模态对话框------------------------------------------
    //QDialog dia1(this);//创建一个窗口
    //dia1.resize(520,300);//设置弹出的窗口大小
    //dia1.exec();//显示模态对话框
    QMessageBox::critical(this,"error","错误");//点击弹出错误信息==============================消息对话框
    });
    connect(ui->actiontool2,&QAction::triggered,[=](){//建立连接,当触发tool2弹出窗口
    //非模态对话框----------------------------------------
    //QDialog dia2(this);不能使用这种方式创建,这样创建窗口会一闪而过
    //QDialog *dia2 = new QDialog(this);//创建一个窗口,
    //dia2->resize(520,300);
    //dia2->setAttribute(Qt::WA_DeleteOnClose); //55号属性
    //dia2->show();//显示非模态对话框
    QMessageBox::information(this,"info","Hello World");//点击弹出消息信息====================消息对话框
    });
    connect(ui->actionedit,&QAction::triggered,[=](){//建立连接,当触发编辑弹出窗口
    //模态对话框------------------------------------------
    //QDialog dia3(this);//创建一个窗口
    //dia3.resize(520,300);//设置弹出的窗口大小
    //dia3.exec();//显示模态对话框
        if(QMessageBox::Yes == QMessageBox::question(this,"edit","是否编辑",QMessageBox::Yes | QMessageBox::Yes,QMessageBox::No)){
            qDebug()<<"开始编辑";
        }else{
            qDebug()<<"退出编辑";
        }//=================================================================================消息对话框
    });
    connect(ui->actiondel,&QAction::triggered,[=](){//建立连接,当触发删除弹出窗口
    //非模态对话框----------------------------------------
//    QDialog *dia4 = new QDialog(this);//创建一个窗口,
//    dia4->resize(520,300);
//    dia4->setAttribute(Qt::WA_DeleteOnClose); //55号属性
//    dia4->show();//显示非模态对话框
      QMessageBox::warning(this,"warning","可能没有成功删除");//===============================消息对话框
    });

    //颜色对话框----------------------------------------------------------------------------
    connect(ui->actioncolor,&QAction::triggered,[=](){//建立连接,当触发删除弹出窗口
        //返回值是QColor而不是QcolorDialog
        //QColor 参数一:red 参数二:green 参数三:blue 参数四:透明度 填参数是选择打开后的默认颜色
        QColor color1 = QColorDialog::getColor(QColor(255,0,0,255));
        qDebug() <<"r="<<color1.red()<<"g="<<color1.green()<<"b="<<color1.blue();
    });
    //文件对话框----------------------------------------------------------------------------
    connect(ui->actionfile,&QAction::triggered,[=](){
        QString cwd = QFileDialog::getOpenFileName(this,"打开桌面txt文件","E:/资源/桌面","*.txt");
        qDebug() <<cwd;
    });
    //字体对话框----------------------------------------------------------------------------
    connect(ui->actionfont,&QAction::triggered,[=](){
        bool flag;
        QFont font = QFontDialog::getFont(&flag,QFont("宋体",36));
        qDebug()<<"字体:"<<font.family()<<"字号:"<<font.pointSize()<<"是否加粗"<<font.bold()<<"是否斜体"<<font.italic();
    });

}

MainWindow::~MainWindow()
{
    delete ui;
}

八、自定义控件

QT里的各种已有的控件使用方法推荐观看视频

控件P24-P28


文章作者: zhang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 zhang !
  目录