Qt学习笔记

Posted 如何写出最优雅的代码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt学习笔记相关的知识,希望对你有一定的参考价值。

Qt学习笔记整理,内容主要包含:

  • QT的概述
  • 创建QT的项目(hello qt)
  • 第一个窗口及窗口属性
  • 第一个按钮
  • 信号与槽机制
  • 带菜单栏的窗口
  • 对话框
  • 布局
  • 常见的控件
  • QT消息机制以及事件
  • 绘图与绘图设备

笔记整理时间:2023年3月24日~2023年3月29日
代码仓库:https://gitee.com/wwyybtt/qt

文章目录

1. Qt概述

1.1 什么是Qt

Qt是一个跨平台C++图形用户界面应用程序框架。它为应用程序开发者提供建立艺术级图形界面所需的所有功能。它是完全面向对象的,很容易扩展,并且允许真正的组件编程。

常见GUI:

  • Qt:支持多平台开发;支持CSS;面向对象特性体现突出;发展趋势良好。
  • MFC:仅在Windows开发;运行效率高;库安全性好。

1.2 Qt的发展史

  • 1991年Qt最早由奇趣科技开发
  • 1996年进入商业领域,它也是目前流行的linux桌面环境KDE的基础
  • 2008年奇趣科技被诺基亚公司收购,Qt称为诺基亚旗下的编程语言
  • 2012年Qt又被 Digia公司收购
  • 2014年4月跨平台的集成开发环境Qt Creator3.1.0发布,同年5月20日配发了Qt5.3正式版,至此Qt实现了对i0S、android、WP等各平台的全面支持。当前Qt最新版本为5.13.2(2019.12之前)

1.3 支持的平台

  • Windows - XP、Vista、Win7、Win8、Win2008、Win10
  • Uinux/X11 - Linux、Sun Solaris、HP-UX、Compaq Tru64 UNIX、IBM AIX、SGI IRIX、FreeBSD、BSD/OS、和其他很多X11平台
  • Macintosh - Mac 0s x
  • Embedded -有帧缓冲支持的嵌入式Linux平台,Windows CE

1.4 优点

  • 跨平台,几乎支持所有的平台
  • 接口简单,容易上手,学习QT框架对学习其他框架有参考意义。
  • 一定程度上简化了内存回收机制
  • 开发效率高,能够快速的构建应用程序。
  • 有很好的社区氛围,市场份额在缓慢上升。可以进行嵌入式开发。

1.5 成功案例

  • Linux桌面环境KDE
  • Skype 网络电话
  • Google Earth谷歌地图
  • VLC多媒体播放器
  • virtualBox虚拟机软件
  • 咪咕音乐
  • WPS Office
  • 极品飞车

1.6 Qt的下载与安装

下载地址:https://download.qt.io/archive/qt/

安装流程参考:http://t.csdn.cn/sb407

这里以5.13版本为例:

  • 下载对应平台的安装包
    • 我选择的是:qt-opensource-windows-x86-5.13.2.exe
  • 执行安装程序
  • 注册登录账户
  • 选择安装路径
    • 我选择的是:D:\\ProgramFiles\\Qt\\Qt5.13.2
  • 组件选择
    • 预计使用6G左右空间
  • 安装完成

1.7 QtCreator介绍

Qt和QtCreator的区别:

  • Qt:通俗来说,开发工具包
  • QtCreator:集成的编译器,Qt的桌面环境

QtCreator主页面:

  • 欢迎选项
    • 工程:创建工程、打开工程
    • 示例:demo程序,可下载运行研读代码
    • 教程:一般需要翻墙才能看
  • 编辑选项:
    • 编辑项目文件
  • 设计选项:
    • 设计UI
  • Debug选项:
    • 调试
  • 项目设置选项:
    • 一般不设置
  • 帮助选项:
    • 帮助手册
    • 可以查询

2. 创建Qt项目

创建项目的方式:

  • 方式1:欢迎->Projects->New Project
  • 方式2:菜单栏->文件->新建文件或项目

打开项目:

  • 打开之前创建的项目
  • 方式1:欢迎->Projects->Open Project
  • 方式2:菜单栏->文件->打开文件或项目

创建工程时需要注意:

  • 项目名称
    • 一般不要有特殊符号,不要有中文
    • 选择Application->Qt Widgets Application
    • 例:01_demo
  • 创建路径(项目保存路径)
    • 路径不要带中文
    • 更改为:D:\\2021code\\Qt,设置为默认的项目路径
  • 创建类的基类:
    • 三种基类(Base class)
      • QMainWindow:带菜单栏的窗口
      • QWidget:空白窗口
      • QDialog:对话窗口
    • 首次创建项目,我们选择:Details->Base calss->Qwidget;Source file->取消勾选Generate form(即不使用ui)
    • 创建类的时候,类名首字母大写
  • 编译和运行

Qt项目框架及文件介绍:

  • .pro文件:工程文件,是qmake自动生成的用于生产makfile的配置文件
QT       += core gui //包含的模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets //大于Qt4版本才包含此模块
CONFIG += c++11
DEFINES += QT_DEPRECATED_WARNINGS //定义编译选项,表示有些功能被标记为过时了,编译器就会发出警告
SOURCES += \\
    main.cpp \\ //源文件
    widget.cpp

HEADERS += \\
    widget.h //头文件
  • main.cpp
#include "widget.h" //Qt中一个类对应一个头文件,类名就是头文件名

#include <QApplication> //Qt系统提供的标准类名声明头文件

int main(int argc, char *argv[])

    QApplication a(argc, argv); //应用程序类(整个后台管理的命脉,处理应用程序的初始化和结束,事件处理调度。注意不管有多少窗口,一个QApplication类就可)
    Widget w; //实例化对象,调用构造函数
    w.show(); //显示图形界面
    return a.exec(); //主事件循环,在exec函数中,Qt接受并处理用户和系统的事件并且将他们传递给适当的窗口控件

  • widget.cpp
#include "widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)



Widget::~Widget()


  • widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class Widget : public QWidget

    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
;
#endif // WIDGET_H

2.1 快捷键

代码自动对齐:Ctrl + i

快速添加/取消注释:Ctrl + /

3. 设置窗口属性

3.1 确定代码书写位置

.pro文件用于生成可执行文件,.main.cpp主函数,widget.cpp类的函数,widget.h类和头文件。

一般情况下,窗口的属性和添加控件、对控件的操作都会在类的构造函数中书写

  • 优点:可以让主程序中无多余代码

3.2 帮助手册如何查看

  • 方法1:帮助->定位到索引->输入要查询的内容
  • 方法2:Assistant,Qt助手

帮助手册如何查看,以QWidget类为例:

  • 索引->对应的类
    • 类的说明:类的头文件、组件、基类、派生类
    • 类的内容(查找函数的途径):公有函数(Public Funcations)、重载公有函数(Reimplemented Public Functions)、公有的槽函数(Public Slots)……
    • 注意:如果有些函数在类中未找到,还可以去基类中查找。

3.3 设置窗口属性及中文乱码解决

中文乱码解决:

  • 在创建项目之前,Qt主界面->工具->选项->文本编辑器->行为->默认编码,选择UTF-8,Apply->OK

设置窗口属性:在widget.cpp中

Widget::Widget(QWidget *parent)
    : QWidget(parent)

    //修改窗口的标题(第一个窗口)
    this->setWindowTitle("第一个窗口");
    //设置窗口的大小,设置完成可以拉伸
    //this->resize(800, 600);
    //设置窗口固定大小,设置完成不可以拉伸
    this->setFixedSize(500, 500);

4. 第一个按钮

新建工程:02_demo

4.1 创建第一个按钮

使用帮助手册查找QPushButton类

  • #include

创建按钮的步骤:

  1. 包含头文件(.cpo)及模块(.pro)
#include <QPushButton>	//.cpp
QT += widgets		//.pro
  1. 调用类的构造函数创建并显示按钮
//创建按钮方式1
QPushButton* button = new QPushButton;
//button->show();//会新开一个窗口显示按钮

//设置按钮的父对象为窗口,使按钮在窗口上显示
button->setParent(this);
  1. 设置按钮的属性
//----------设置按钮的属性
//设置按钮的文字、内容
button->setText("第一个按钮");
//设置按钮的显示位置
button->move(100, 100);
//设置按钮的大小
button->setFixedSize(400, 400);
  1. 创建按钮的第二种方法
//创建按钮方式2
QPushButton* button2 = new QPushButton("第二个按钮", this);
this->resize(600, 400);

创建按钮两种方式的区别:

  • 方式1:窗口默认大小,按钮显示在左上角
  • 方式2:窗口根据按钮的大小来创建,使用方法2,一般还需要调用resize函数重置窗口大小

4.2 对象树(对象模型)

在Qt中创建对象的时候会提供一个Parent对象指针,下面来解释这个parent到底是干什么的。

概念:Qt对象间父子关系。

  • QObject是以对象树的形式组织起来的。
    • 当你创建一个QObject对象时,会看到QObject_的构造函数接收一个QObject指针作为参数,这个参数就是parent,也就是父对象指针。这相当于,在创建QObject对象时,可以提供一个其父对象,我们创建的这个QObject对象会自动添加到其父对象的children()列表。
    • 当父对象析构的时候,这个列表中的所有对象也会被析构。(注意,这里的父对象并不是继承意义上的父类! )
  • QWidget是能够在屏幕上显示的一切组件的父类。
    • QWidget继承自QObject,因此也继承了这种对象树关系。一个孩子自动地成为父组件的一个子组件。因此,它会显示在父组件的坐标系统中,被父组件的边界剪裁。例如,当用户关闭一个对话框的时候,应用程序将其删除,那么,我们希望属于这个对话框的按钮、图标等应该一起被删除。事实就是如此,因为这些都是对话框的子组件。
    • 当然,我们也可以自己删除子对象,它们会自动从其父对象列表中删除。比如,当我们删除了一个工具栏时,其所在的主窗口会自动将该工具栏从其子对象列表中删除,并且自动调整屏幕显示。

解决问题:Qt引对象树的概念,在一定程度上解决了内存问题。

  • 当一个QObject对象在堆上创建的时候,Qt会同时为其创建一个对象树。不过,对象树中对象的顺序是没有定义的。这意味着,销毁这些对象的顺序也是未定义的。
  • 任何对象树中的QObject对象 delete 的时候,如果这个对象有parent,则自动将其从parent 的children()列表中删除;如果有孩子,则自动delete每一个孩子。Qt保证没有QObject会被delete 两次,这是由析构顺序决定的。
  • 如果QObject在栈上创建,Qt保持同样的行为。正常情况下,这也不会发生什么问题。

4.3 对象树使用注意

C++在栈上创建对象时,是后创建的先析构,对于Qt的对象树,有以下需要注意的地方:

// 代码1
QWidget window;
QPushButton button = QPushButton("退出", &window);

// 代码2
QPushButton quit("Quit");
QWidget window;
quit.setParent(&window);
  • 代码1无问题:
    • 因为栈一般先构造的后析构,代码1中执行结束后会先析构button,同时将button从window的子对象列表删除,然后析构window。因为window中已经无button子对象,仅析构window。
  • 代码2有问题:
    • 代码执行结束后会先析构window,而析构window时,会先析构它的子对象quit,然后析构window。接下来会再次析构quit,会导致二次析构,程序崩溃!
  • 如何解决:在Qt中,尽量在构造的时候就指定parent对象,并且大胆地在堆上创建!

4.4 Qt窗口坐标体系

窗口坐标体系:

  • 注意:对于嵌套窗口,其坐标是相对于父窗口来说的。

5. 信号与槽机制

5.1 信号与槽机制介绍

信号槽是Qt 框架引以为豪的机制之一。所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个**函数(称为槽(slot))**绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。

  • 这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。
  • 优点:松散耦合,信号发出端和接受端可以毫无关联,如果要关联就用connect函数

5.2 connect函数与系统自带的信号和槽函数

5.2.1 connect函数常用的格式

connect()函数是QObject类中的公有函数,其声明如下:

QMetaObject::Connection connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type = Qt::AutoConnection) const

connect()函数最常用的一般形式:

connect(sender, signal, receiver, slot);
  • sender:发出信号的对象
  • signal:发送对象发出的信号
  • receiver:接收信号的对象
  • slot:接收对象在接收到信号之后所需要调用的函数(槽函数)

5.2.2 系统自带的信号与槽函数

大部分的类都存在槽函数和信号,打开帮助手册,以QWidget为例:

  • Public Slots:公有的槽函数
  • Signals:信号,有时类中没有Signals时,可以查找其基类

5.2.3 实例

要求:创建一个按钮,点击按钮能实现关闭窗口的功能。

新建项目:03_demo

//创建按钮
QPushButton* button = new QPushButton("点击关闭窗口", this);
//重置窗口大小
this->resize(600, 400);

//信号与槽函数
connect(button, &QPushButton::clicked, this, &Widget::close);

5.3 自定义信号和槽

5.3.1 无参的信号与槽

所在项目:03_demo

步骤1:确定场景

  • 老师饿了,学生请客(以这个为例)
  • 小哥敲门,家人开门(自己练习实现)

步骤2:添加老师类和学生类

步骤3:

  • 在老师类中声明信号(声明即可)
    • teacher.h
    • 信号一般在类声明中的signals下写
    • 信号返回值为void,参数可以添加或为空
    • 仅声明,不实现
    • 一般情况下可以重载
  • 并且在学生类中声明槽函数(声明并实现)
    • 在student.h声明
    • 槽函数声明一般在类声明中的public slots下写(对于高版本的Qt,也可以写到public或者全局)
    • 槽函数返回值为void,参数可以添加或者为空
    • 槽函数声明且实现
    • 槽函数定义实现在student.cpp中
//teacher.h
signals:
    void hungury();

//student.h
public slots:
    void treat();

//student.cpp
void Student::treat()
   
    qDebug() << "请吃饭"; //包含头文件:#include <QDebug>

步骤4:创建老师对象和学生对象,并使用connect连接

  • 在widget.cpp中创建并连接
this->tea = new Teacher(this);
this->stu = new Student(this);
connect(tea, &Teacher::hungury, stu, &Student::treat);

步骤5:触发信号

  • widget.h中声明触发信号的成员函数
  • widget.cpp定义触发信号的成员函数
  • 调用该函数
//widget.h
public:
    void ClassOver();

//widget.cpp
void Widget::ClassOver()

    emit tea->hungury();


//调用
ClassOver();

补充:

  • 点击按钮,请老师吃饭
connect(button, &QPushButton::clicked, this, &Widget::ClassOver);

this->tea = new Teacher(this);
this->stu = new Student(this);
connect(tea, &Teacher::hungury, stu, &Student::treat);
  • 信号连接信号
this->tea = new Teacher(this);
this->stu = new Student(this);
connect(tea, &Teacher::hungury, stu, &Student::treat);

connect(button, &QPushButton::clicked, tea, &Teacher::hungury);

5.3.2 重载自定义信号与槽(有参)

步骤1:重新写信号(带参数)

void hungury(QString food);

步骤2:重新写槽函数声明及定义(带参数)

void treat(QString food);

void Student::treat(QString food)

    qDebug() << "请老师吃饭:" << food;

步骤3:由于函数重载了,所以需要利用函数指针指向函数地址,然后再作连接

//定义函数指针
void (Teacher::*teachersignal)(QString) = &Teacher::hungury;
void (Student::*studentslot)(QString) = &Student::treat;

connect(tea, teachersignal, stu, studentslot);
ClassOver();

5.4 信号与槽总结

自定义信号与槽注意事项:

  • 发送者与接受者需要是QObject的子类(槽函数全局,lambda除外)。
  • 信号与槽函数返回值都是void。
  • 信号需要声明,不需要定义实现。槽函数需要声明也需要定义实现。
  • 槽函数是普通的成员函数,作为成员函数,会受到public、private、protected的影响。
  • 使用emit在恰当的位置发送信号。
  • 使用connect()函数连接信号和槽。
  • 任何成员函数、static函数、全局函数和Lambda 表达式都可以作为槽函数。
  • 信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致。
  • 如果信号和槽的参数不一致,允许的情况是,槽函数的参数可以比信号的少,即便如此,槽函数存在的那些参数的顺序也必须和信号的前面几个一致起来。这是因为,你可以在槽函数中选择忽略信号传来的数据(也就是槽函数的参数比信号的少)。

5.5 信号槽的扩展

  • 一个信号可以和多个槽相连
    • 如果是这种情况,这些槽会一个接一个的被调用,但是它们的调用顺序是不确定的。
  • 多个信号可以连接到一个槽
    • 只要任意一个信号发出,这个槽就会被调用。
  • 一个信号可以连接到另外的一个信号
    • 当第一个信号发出时,第二个信号被发出。除此之外,这种信号-信号的形式和信号-槽的形式没有什么区别。
  • 槽可以被断开连接,使用disconnect。
  • 槽也可以被取消连接(当一个对象delete了,就会取消这个对象上的槽)
  • 使用C++11中的lambda表达式

6. Lambda表达式

6.1 Lambda表达式的介绍

概念:C++11中的Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作。

语法:

[capture](parameters) mutable ->return-typestatement;
1[capture]捕获列表,捕获的是那些到定义Lambda为止时Lambda所在作用范围内可见的局部变量
2(parameters)参数列表,与普通函数的参数列表一致的。
3mutable可修改标示符,按值传递捕获列表参数时(默认仅读权限),加上mutable修饰符后,可以修改按值传递进来的拷贝
4->return-type返回值类型
5statement函数体,内容跟普通函数一致
6、分号不能省略

注意:

  • [] 标识一个Lambda的开始,这部分必须存在,不能省略。
  • () 参数列表,如果不需要传递参数的话,()可以一同省略。
  • 如果使用mutable,参数列表 () 不能省略的即使参数为空;如果使用mutable,修改拷贝,而不是值本身。
  • 返回值类型,如果不需要,->return-type都可省略。
  • 函数体,可以使用参数列表,也可以使用捕获列表。

补充:对于捕获列表[]的参数形式,有如下情况

  • 空。没有使用任何函数对象参数。
  • =。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda 所在类的this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。
  • &。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的 this),并且是引用传递方式(相当于编译器自动为我们按引用传递了所有局部变量)。
  • this。函数体内可以使用Lambda所在类中的成员变量。
  • a。将a按值进行传递。按值进行传递时,函数体内不能修改传递进来的的拷贝,因为默认情况下函数是const_的。要修改传递进来的a的拷贝,可以添加mutable修饰符。
  • &a。将a 按引用进行传递。
  • a,&b。将a按值进行传递,b按引用进行传递。
  • =,&a,&b。除a和b 按引用进行传递外,其他参数都按值进行传递。
  • &,a, b。除 a和b按值进行传递外,其他参数都按引用进行传递。

6.2 Lambda表达式的使用

一个简单的lambda表达式:

auto fun = []()
    qDebug() << "Lambda is running!";
;

fun();

//
[]
	qDebug() << "Lambda is running!";
();

一个带参数和返回值的lambda:

auto fun = [](int a, int b)
    qDebug() << "Lambda is running!";
    return a + b;
;

int sum = fun(100, 200);
qDebug() << sum;

对于mutable:如果缺少mutable,下列代码将报错;省略()也会报错

    int m = 10;

    auto fun = [m]()mutable
        qDebug() << "Lambda is running!";
        m = 300;
    ;

结合信号与槽:槽函数可以使用lambda,但后面的分号要省略

QPushButton* myBtn = new QPushButton("点击", this);
this->resize(600, 400);

connect(myBtn, &QPushButton::clicked, this, [=]()qDebug() << "按钮被按下";);   //这里的lambda省略了;

7. 带菜单栏的窗口

7.1 QMainWindow概述

QMainWindow是一个为用户提供主窗口程序的类,包含一个菜单栏(menu bar)、多个工具栏(tool bars)、多个铆接部件(dock widgets)、一个状态栏(status bary及一个中心部件(central widget)。

以Qt界面为例,说明各个部件:

  • 铆接部件:浮动窗口
  • 中心部件:写代码的地方

7.2 QMainWindow菜单栏

创建新的项目:04_demo

菜单栏类:QMenuBar

菜单类:QMenu

QAction类:充当子菜单(菜单项)

菜单栏创建方法:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)

    resize(800, 600);

    //创建菜单栏
    QMenuBar* menubar = new QMenuBar(this);//使用new创建
    //QMenuBar* menubar = menuBar();//使用成员函数创建
    this->setMenuBar(menubar);

    //创建菜单
    QMenu* menu1 = new QMenu("文件");
    QMenu* menu2 = new QMenu("编辑");
    QMenu* menu3 = new QMenu("构建");

    //添加菜单到菜单栏
    menubar->addMenu(menu1);
    menubar->addMenu(menu2);
    menubar->addMenu(menu3);

    //创建菜单项/子菜单
    QAction* act1 = new QAction("打开文件");
    QAction* act2 = new QAction("另存为");
    QAction* act3 = 事件(event)

一般来说,使用Qt编程时,我们并不会把主要精力放在事件上,因为在Qt中,需要我们关心的事件总会发出一个信号。比如,我们关心的是QPushButton的鼠标点击,但我们不需要关心这个鼠标点击事件,而是关心它的clicked()信号。这与其他的一些框架不同:在MFC中,你所要关心的是鼠标左键按下这个事件。总的来说,如果我们使用组件,我们关心的是信号槽;如果我们自定义组件,我们关心的是事件。因为我们可以通过事件来改变组件的默认操作。比如,如果我们要自定义一个QPushButton,那么我们就需要重写它的鼠标点击事件和键盘处理事件,并且在恰当的时候发出clicked()信号。

 1 #include "mainwindow.h"
 2 #include <QtGui/QApplication>
 3 
 4 #include <QMouseEvent> 
 5 
 6 class EventLabel:public QLabel
 7 {
 8 protected:
 9     void mouseMoveEvent(QMouseEvent *ev);
10     void mousePressEvent(QMouseEvent *ev);
11     void mouseReleaseEvent(QMouseEvent *ev);
12     
13 };
14 
15 void EventLabel::mouseMoveEvent(QMouseEvent *ev)
16 {
17     this->setText(QString("<center><h1>Move: (%1, %2)</h1></center>") 
18         .arg(QString::number(ev->x()), QString::number(ev->y()))); 
19 }
20 
21 void EventLabel::mousePressEvent(QMouseEvent *ev)
22 {
23    QString text;
24    text.sprintf("<center><h1>Move: (%d, %d)</h1></center>",ev->x(),ev->y());
25    this->setText(text);
26 }
27 
28 void EventLabel::mouseReleaseEvent(QMouseEvent *ev)
29 {
30     this->setText(QString("<center><h1>Move: (%1, %2)</h1></center>").arg(QString::number(ev->x()),QString::number(ev->y())));
31 
32 }
33 
34 
35 int main(int argc, char *argv[])
36 {
37     QApplication a(argc, argv);
38     /*MainWindow w;
39     w.show();*/
40     EventLabel *eventLabel=new EventLabel;
41     eventLabel->setWindowTitle("my title");
42     eventLabel->resize(300,200);
43     eventLabel->show();
44     return a.exec();
45 }

运行结果:

技术分享

 

忽略事件:判断点击的按钮是左键还是右键,忽略事件调用父类的响应函数即可。

 1 void EventLabel::mousePressEvent(QMouseEvent *ev)
 2 {
 3     if(ev->button() == Qt::RightButton) 
 4     {
 5         QString text;
 6         text.sprintf("<center><h1>Move: (%d, %d)</h1></center>",ev->x(),ev->y());
 7         this->setText(text);
 8     } else 
 9     {
10         QLabel::mousePressEvent(ev);
11     }
12 
13   
14 }

退出窗口选择:

 1 void MainWindow::closeEvent(QCloseEvent * event)
 2 {
 3     if(continueToClose()) 
 4     {
 5         event->accept();
 6     } else {
 7         event->ignore();
 8     }
 9 }
10 
11 bool MainWindow::continueToClose()
12 {
13     if(QMessageBox::question(this,
14         tr("Quit"),
15         tr("Are you sure to quit this application?"),
16         QMessageBox::Yes | QMessageBox::No,
17         QMessageBox::No)
18         == QMessageBox::Yes) {
19             return true;
20     } else {
21         return false;
22     }
23 }

 

以上是关于Qt学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

《Qt5 开发与实例(第三版)》学习笔记

《Qt5 开发与实例(第三版)》学习笔记

《Qt5 开发与实例(第三版)》学习笔记

《Qt5 开发与实例(第三版)》学习笔记

《Qt5 开发与实例(第三版)》学习笔记

《Qt5 开发与实例(第三版)》学习笔记