Qt第六章 多窗口编程

2023-11-12

一、QMessageBox 消息对话框(掌握)

QMessageBox继承自QDialog,是一个Qt内置的用来展示信息或询问用户一个问题的模态对话框。

预设了四种类型:

像那些已经写好的窗口,这些现成的东西都会有一些特性,就是他们的对象都不需要new或者说他们就不需要拿到对象,他们为了方便我们使用会用一个静态成员函数就可以把弹窗显示出来。上面的四种类型想要显示就需要用对应的静态成员函数

四种弹窗的参数和返回值基本一致:

参数1:父窗口

参数2:标题文字

参数3:展示信息内容

返回值:用户点击的按钮,默认情况下只有question类型的弹窗有必要接收返回值

只要是预设的对话框他们想要拿数据他一定是通过返回值拿数据 静态成员函数的返回值

不是Q开头的大概路是枚举

我们这个对话框只有只有yes和no所以只有要判断返回值是yes还是no可以判断用户点击的是什么

示例代码下载链接:百度网盘 请输入提取码

提取码:hqyj

--来自百度网盘超级会员V6的分享

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

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

    group = new QButtonGroup(this);
    group->addButton(ui->btnInfomation,1);
    group->addButton(ui->btnWarning,2);
    group->addButton(ui->btnCritical,3);
    group->addButton(ui->btnQuestion,4);
    group->addButton(ui->btnCustom,5);

    connect(group,SIGNAL(buttonClicked(int)),
            this,SLOT(btnsClickedSlot(int)));
}

Dialog::~Dialog()
{
    delete group;
    delete ui;
}

void Dialog::custom()
{
    // 创建自定义的QMessageBox对象
    QMessageBox* box = new QMessageBox(this);
    // 设置标题
    box->setWindowTitle("自定义QMessageBox");
    // 准备一个图片对象
    QPixmap pic(":/new/prefix1/new_year.png");
    // 设置图标
    box->setIconPixmap(pic);
    // 设置消息内容
    box->setText("2023年即将到来,你感到快乐吗?");
    // 创建两个按钮对象
    QPushButton* btn1 = new QPushButton("快乐",box);
    QPushButton* btn2 = new QPushButton("不快乐",box);
    // 添加按钮到弹窗的正确位置
    box->addButton(btn1,QMessageBox::YesRole);
    box->addButton(btn2,QMessageBox::NoRole);
    // 展示弹窗
    box->show();
}

void Dialog::btnsClickedSlot(int id)
{
    if(id == 1)
        QMessageBox::information(this,"information","网络已连接!");
    else if(id == 2)
        QMessageBox::warning(this,"warning","网络波动!");
    else if(id == 3)
        QMessageBox::critical(this,"critical","无法检测到网络!");
    else if(id == 4)
    {
        QMessageBox::StandardButton result = QMessageBox::question(this,"question","您是否没插网线?");
        if(result == QMessageBox::Yes)
            qDebug() << "我是无线我插什么网线?";
        else if(result == QMessageBox::No)
            qDebug() << "有线性能一定比无线好。";
    }
    else if(id == 5)
        custom();
}

二、常见的窗口类(掌握)

本次Qt学习到的窗口类之间的继承关系如下图所示。

  • QObject

        所有Qt类的基类,本身并不是窗口类。

  • QWidget

        如果创建时制定parent参数的值,此时QWidget对象会作为制定参数对应的窗口内部的组件;如果创建时不传入parent参数的值,此时QWidget对象会作为一个独立的窗口。

  • QMainWindow

        通常使用此类作为应用程序的主窗口,主窗口包含菜单栏、工具栏、中心组件与状态栏。因为使用相对复杂,所以一直讲课未用。

  • QDialog

        通常作为子窗口存在的对话框窗口,特点是组成简单。比较简单的程序可以使用此类型作为主窗口。

  • QMessageBox

        QDialog的一个派生类,主要用于消息展示和提问。

  • QFileDialog

        QDialog一个派生类,主要用于浏览本地磁盘的文件并选择。

所有的窗口类共有一些属性和函数,例如:

  • windowTitle : QString

所有窗口的标题,可以通过getter和setter进行读写。

void QWidget::setWindowState(Qt::WindowStates windowState)

设置窗口状态,参数值如下:

  • windowFlags : Qt::WindowFlags

窗口标记,支持同时通过setter设定多个标记,多个标记之间使用|分割

常用的标记有:

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    // 设置窗口
    setWindowTitle("哈哈哈哈哈哈哈哈");
    // 设置窗口状态(全屏)
//    setWindowState(Qt::WindowFullScreen);
    // 设置窗口标记     关闭缺省的标题窗口栏      创建无边框窗口
    setWindowFlags(Qt::WindowStaysOnTopHint|Qt::FramelessWindowHint);
}

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

 

三、QMainWindow 主窗口

QMainWindow非常适合作为程序的主窗口因为程序的各种功能可以设置到菜单栏和工具栏中,同时状态栏可以显示当前软件的信息。

QMainWindow主要由四部分组成:

这四个部分的初始化设置可以通过Designer完成,也可以在C++代码中完成

QMenuBar中的每个菜单对应类型是QMenuQMenu中可以放置各种触发效果,每个触发效果的类型是QAction

 

你加了这个新建以后它叫做QAction 每个触发效果的类型是 QAction

新建变成了二级菜单 只有最终能点击触发效果的才会变成QAction  

QAction的配置在Designer中通过专属的面板完成:

在上面的面板中找到要编辑的QAction对象,双击即可配置参数。

QAction有以下信号函数:

可以使用拖拽的方式把QAction编程工具栏中的按钮,最好给QAction提前设置好图标。

关于状态栏QStatusBar有两个常用的槽函数:

void QStatusBar::clearMessage() [slot]

清空状态栏信息显示

void QStatusBar::showMessage(const QString & message, 
                             int timeout = 0) [slot]

设置状态栏信息显示

参数1:显示的文字信息

参数2:显示的时长,单位毫秒,0表示持续显示

示例代码下载链接:https://pan.baidu.com/s/15DZlTkMDviC6J5_p0NTL4A 

提取码:hqyj

--来自百度网盘超级会员V6的分享

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

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

    // 肉眼可见的对象都归ui指针管理
    connect(ui->actionNew,SIGNAL(triggered()),
            this,SLOT(triggeredSlot()));

    connect(ui->pushButtonShow,SIGNAL(clicked()),
            this,SLOT(btnShowClickedSlot()));
    connect(ui->pushButtonClear,SIGNAL(clicked()),
            this,SLOT(btnClearClickedSlot()));
}

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

void MainWindow::triggeredSlot()
{
    QMessageBox::information(this,"提示","已新建文件!!!!!!");
}

void MainWindow::btnShowClickedSlot()
{
    ui->statusBar->showMessage("哈哈哈哈哈哈哈",5000);
}

void MainWindow::btnClearClickedSlot()
{
    ui->statusBar->clearMessage();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMessageBox>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private:
    Ui::MainWindow *ui;

private slots:
//    与void triggered()信号连接
    void triggeredSlot();

    // 两个按钮点击的槽函数
    void btnShowClickedSlot();
    void btnClearClickedSlot();
};

#endif // MAINWINDOW_H

四、内存管理

Qt的内存管理机制与C++不同,几乎所有的Qt类的构造函数都有一个名为parent的参数,此参数表示设置当前对象的父对象父对象不仅仅表示子组件与父窗口之间的显示关系,更表示在内存回收上的依赖关系。

建议尽量给对象传入parent参数,以便于保持Qt的内存回收机制;如果不传入parent参数则需要留意内存回收的时机。

堆内存对象尽量传parent

示例代码下载链接:https://pan.baidu.com/s/1Ed7T4CzPSC6DJJXH-hfOCg 

提取码:hqyj

--来自百度网盘超级会员V6的分享

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

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

    connect(ui->pushButtonYes,SIGNAL(clicked()),
            this,SLOT(btnYesClickedSlot()));
    connect(ui->pushButtonNo,SIGNAL(clicked()),
            this,SLOT(btnNoClickedSlot()));
}

Dialog::~Dialog()
{
    delete ui;
    qDebug() << "析构函数";
}

void Dialog::btnYesClickedSlot()
{
    // 创建一个子窗口对象并展示,使用parent参数
    Dialog* d = new Dialog(this);
    d->show();
}

void Dialog::btnNoClickedSlot()
{
    // 创建一个子窗口对象并展示,不使用parent参数
    Dialog* d = new Dialog;
    d->show();
}

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QDebug>

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

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

private:
    Ui::Dialog *ui;

private slots:
    void btnYesClickedSlot();
    void btnNoClickedSlot();
};

#endif // DIALOG_H

传入parent参数打开的窗口 后面的会依赖前面的哪一个如果前面的窗口关闭后面的也会关闭

不传入parent参数每个窗口都是独立的没有依赖关系  但是回收时需要手动回收 堆内存对象手动delete 栈内存对象无所谓  主要是针对堆内存  

加了parent就不用考虑手动回收了

五、自定义窗口类

下面手动创建一个自定义窗口类对象,操作步骤如下:

1. 选中项目名称,鼠标右键,点击“添加新文件”

2. 在弹出的窗口中,按照下图所示进行操作。

3. 在弹出的窗口中,先选择要创建的窗口类型,再点击“下一步”。

4. 在新弹出的窗口中,给类命名后,点击“下一步”。

5. 在项目管理界面,直接点击“完成”。可以看到项目中多了一个窗口类的头文件、源文件和界面文件。

示例代码下载链接:百度网盘 请输入提取码

提取码:hqyj

--来自百度网盘超级会员V6的分享

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
// 引入MyDialog类的头文件
#include "mydialog.h"

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

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

private:
    Ui::Dialog *ui;

private slots:
    // 点击按钮触发的槽函数
    void btnClickedSlot();
};

#endif // DIALOG_H

mydialog.h

#ifndef MYDIALOG_H
#define MYDIALOG_H

#include <QDialog>

namespace Ui {
class MyDialog;
}

class MyDialog : public QDialog
{
    Q_OBJECT

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

private:
    Ui::MyDialog *ui;
};

#endif // MYDIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

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

    connect(ui->pushButton,SIGNAL(clicked()),
            this,SLOT(btnClickedSlot()));
}

void Dialog::btnClickedSlot()
{
    // 创建MyDialog类对象
    MyDialog* md = new MyDialog(this);
    // 展示
    md->show();
}

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

上述功能为点击dialog界面的按钮会打开mydialog窗口

六、参数传递

6.1 成员函数传参

【例子】转动上面代码中的绿色QDial,橙色QDial跟随绿色QDial一起转动。

示例代码下载链接:https://pan.baidu.com/s/1OpgiIiyV6WjQFLhlBsF4pw 

提取码:hqyj

--来自百度网盘超级会员V6的分享

主窗口去主导 然后子窗口跟着动一般使用成员函数 或者构造函数

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
// 引入MyDialog类的头文件
#include "mydialog.h"

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

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

private:
    Ui::Dialog *ui;
    MyDialog* md = NULL; // 子窗口对象 要写成成员的 局部的拿不到主窗口传的数值

private slots:
    // 点击按钮触发的槽函数
    void btnClickedSlot();
    // 检测绿色QDial转动的槽函数void	valueChanged(int value)
    void valueChangedSlot(int);
};

#endif // DIALOG_H

mydialog.h

#ifndef MYDIALOG_H
#define MYDIALOG_H

#include <QDialog>

namespace Ui {
class MyDialog;
}

class MyDialog : public QDialog
{
    Q_OBJECT

public:
    explicit MyDialog(QWidget *parent = 0,int value = 0);//构造函数传参 要遵循向右原则 第一个//参数赋值 后面的必须赋值 还要注意 声明定义在一个地方赋值就行
//保证两个的起始位置在一个地方, 第二个参数就是创建完盖子窗口时子窗口的初始位置
    ~MyDialog();
    // 公开一个函数可以设置橙色QDial的数值
    void setValue(int);
    //注意上面的成员函数不能写成私有的 因为写的这个函数要给主窗口里面去调用实在类外调用的

private:
    Ui::MyDialog *ui;
};

#endif // MYDIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

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

    connect(ui->pushButton,SIGNAL(clicked()),
            this,SLOT(btnClickedSlot()));
    connect(ui->dial,SIGNAL(valueChanged(int)),
            this,SLOT(valueChangedSlot(int)));
}

void Dialog::btnClickedSlot()
{
    //因为主窗口可以拿到子窗口的一个对象 就可以很方便的去调用子窗口里面的任意一个函数
    // 创建MyDialog类对象 要写成成员的不然别的函数调用不了
    md = new MyDialog(this,ui->dial->value());
    // 展示
    md->show();
    // 屏蔽按钮  原因你只能操控一个子窗口多的操作不了
    ui->pushButton->setEnabled(false);
}

void Dialog::valueChangedSlot(int value)
{
    if(md != NULL)//防止没创建子窗口时就转导致的程序异常 因为你转的话会调用该槽函数 这里面的md没有创建出来  加了该代码就不会走下面的代码
        // 把参数值传递给第二个窗口对象
        md->setValue(value);
}

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

mydialog.cpp

#include "mydialog.h"
#include "ui_mydialog.h"

MyDialog::MyDialog(QWidget *parent,int value) ://因为在声明处赋予初始值了 这里就不用再写了
    QDialog(parent),
    ui(new Ui::MyDialog)
{
    ui->setupUi(this);
    // 初始化QDial的数值
    ui->dial->setValue(value);//构造函数传参
}

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

void MyDialog::setValue(int value)
{
    // 设置显示的数值
    ui->dial->setValue(value);
}

6.2 信号槽传参

【例子】转动上面代码中的橙色QDial,绿色QDial跟随橙色QDial一起转动。

就是右边的东西发送到左边来

链接:https://pan.baidu.com/s/1owM93_UPSQpAqQ7NRqZafA 

提取码:hqyj

--来自百度网盘超级会员V6的分享

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
// 引入MyDialog类的头文件
#include "mydialog.h"
#include <QDebug>

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

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

private:
    Ui::Dialog *ui;
    MyDialog* md = NULL; // 子窗口对象

private slots:
    // 点击按钮触发的槽函数
    void btnClickedSlot();
    // 检测绿色QDial转动的槽函数void	valueChanged(int value)
    void valueChangedSlot(int);
    // 接收子窗口发来的信号的槽函数
    void valueSlot(int);
};

#endif // DIALOG_H

mydialog.h

#ifndef MYDIALOG_H
#define MYDIALOG_H

#include <QDialog>

namespace Ui {
class MyDialog;
}

class MyDialog : public QDialog
{
    Q_OBJECT

public:
    explicit MyDialog(QWidget *parent = 0,int value = 0);
    ~MyDialog();
    // 公开一个函数可以设置橙色QDial的数值
    void setValue(int);

private:
    Ui::MyDialog *ui;

private slots:
    // 接收橙色QDial数值变化的槽函数
    void valueChangedSlot(int);

signals:
    // 发射橙色QDial数值的信号函数(声明完就可以用) 什么时候发射每一次橙色数值变化的时候就发射
    void valueSignal(int);
};

#endif // MYDIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

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

    connect(ui->pushButton,SIGNAL(clicked()),
            this,SLOT(btnClickedSlot()));
    connect(ui->dial,SIGNAL(valueChanged(int)),
            this,SLOT(valueChangedSlot(int)));
}

void Dialog::btnClickedSlot()
{
    // 创建MyDialog类对象  为啥后面是ui->dial->value()是因为通过定义是的默认参数value=0 这个就是获得那个默认参数
    md = new MyDialog(this,ui->dial->value());
    // 建立两个窗口间通信的信号槽连接
    connect(md,SIGNAL(valueSignal(int)),
            this,SLOT(valueSlot(int)));

    // 展示
    md->show();
    // 屏蔽按钮
    ui->pushButton->setEnabled(false);
}

void Dialog::valueChangedSlot(int value)
{
    if(md != NULL)
        // 把参数值传递给第二个窗口对象
        md->setValue(value);
}

void Dialog::valueSlot(int value)
{
    // 更新显示
    ui->dial->setValue(value);
}

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

mydialog.cpp

#include "mydialog.h"
#include "ui_mydialog.h"

MyDialog::MyDialog(QWidget *parent,int value) :
    QDialog(parent),
    ui(new Ui::MyDialog)
{
    ui->setupUi(this);
    // 初始化QDial的数值
    ui->dial->setValue(value);
    // 连接QDial数值监听的信号槽  发送出去然后第一个界面来接收
    connect(ui->dial,SIGNAL(valueChanged(int)),
            this,SLOT(valueChangedSlot(int)));
}

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

void MyDialog::setValue(int value)
{
    // 设置显示的数值
    ui->dial->setValue(value);
}

void MyDialog::valueChangedSlot(int value)
{
    // 发射自定义信号
    emit valueSignal(value);
}

七、事件机制

7.1 事件机制原理

事件机制是Qt的核心逻辑,事件是程序运行的过程中的某些操作,这些操作会在操作系统与应用程序中逐层传递。

上图表示的是从用户操作到操作系统,再到应用程序的传递过程,对于Qt开发的应用程序而言,事件也会在应用程序内部逐层传递,如下所示。

操作系统发送给应用程序的大管家 再发给当前正在获取焦点的子组件 最后把事件给父组件(比如按钮子组件 处理完事情后给最后给窗口 窗口时父组件

7.2 事件函数

本次授课在事件传递的最后一个环节,即父窗口中使用事件函数检测事件传递。

所有事件函数的用法基本相同,常用的事件函数如下:

// 绘制
void QWidget::paintEvent(QPaintEvent * event) [virtual protected] 
// 大小改变
void QWidget::resizeEvent(QResizeEvent * event) [virtual protected] 
// 鼠标按下
void QWidget::mousePressEvent(QMouseEvent * event) [virtual protected]
// 鼠标释放
void QWidget::mouseReleaseEvent(QMouseEvent * event) [virtual protected]
// 鼠标双击
void QWidget::mouseDoubleClickEvent(QMouseEvent * event) [virtual protected]
// 鼠标指针移动
void QWidget::mouseMoveEvent(QMouseEvent * event) [virtual protected]
// 组件本身移动
void QWidget::moveEvent(QMoveEvent * event) [virtual protected]
// 按键按压
void QWidget::keyPressEvent(QKeyEvent * event) [virtual protected]
// 按键释放
void QWidget::keyReleaseEvent(QKeyEvent * event) [virtual protected]
// 获取焦点
void QWidget::focusInEvent(QFocusEvent * event) [virtual protected]
// 失去焦点
void QWidget::focusOutEvent(QFocusEvent * event) [virtual protected]
// 关闭
void QWidget::closeEvent(QCloseEvent * event) [virtual protected]
// 鼠标进入
void QWidget::enterEvent(QEvent * event) [virtual protected]
// 鼠标离开
void QWidget::leaveEvent(QEvent * event) [virtual protected]

QPainter是画家类,可以在QPaintDevice的派生类上绘制各种各种的图形,QPaintDevice是QWidget的基类,即QWidget及其所有派生类都可以被QPainter对象进行绘制。

QPainter::QPainter(QPaintDevice * device)

QPainter的构造函数,参数是在哪个对象上作画。

void QPainter::drawPixmap(int x, int y, int width, int height, const QPixmap & pixmap)

绘制QPixmap的内容。

参数1:绘制内容的横坐标,定位点是绘制内容的左上角

参数2:绘制内容的纵坐标,定位点是绘制内容的左上角

参数3:绘制内容的宽度

参数4:绘制内容的高度

参数5:绘制的内容

示例代码下载链接:百度网盘 请输入提取码

提取码:hqyj

--来自百度网盘超级会员V6的分享

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
// 头文件
#include <QDebug>
#include <QPixmap>    //图片类
#include <QPainter> // 画家类
#include <QKeyEvent> // 按键事件类
#include <QMessageBox> //信息弹窗类

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

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

    // 声明事件函数,为了覆盖事件函数  因为他们是虚函数
protected:
    void paintEvent(QPaintEvent*);//绘制事件
    void keyPressEvent(QKeyEvent*);//键盘按下事件

private:
    Ui::Dialog *ui;
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

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

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

/**
 * @brief Dialog::paintEvent
 * 1. 组件从无到有,从有到无会触发
 * 2. 大小改变会触发,移动不会触发
 */
void Dialog::paintEvent(QPaintEvent *)
{
    qDebug() << width() << "*" << height(); //打印窗口的宽高
    qDebug() << x() << "," << y();           //打印窗口坐标
    QPixmap map(":/new/prefix1/yuandan.jpg");
    QPainter painter(this); // 一个在窗口上绘制的画家对象
    // 开始绘制
    /*
    参数1:绘制内容的横坐标,定位点是绘制内容的左上角
    参数2:绘制内容的纵坐标,定位点是绘制内容的左上角    
    参数3:绘制内容的宽度
    参数4:绘制内容的高度
    参数5:绘制的内容
*/
    painter.drawPixmap(0,0,width(),height(),map);
}

/**
 * @brief Dialog::keyPressEvent
 * @param event 包含当前事件的相关信息,QKeyEvent包含按键编码
 */
void Dialog::keyPressEvent(QKeyEvent * event)
{
    if(Qt::Key_A == event->key()) // 如果是A键
    {
        // 获得进度条当前数值
        int value = ui->progressBar->value();
        if(value == 0)
        {
            QMessageBox::information(this,"提示","拒绝emo");
            return;
        }
        ui->progressBar->setValue(--value);
    }else if(Qt::Key_D == event->key())
    {
        // 获得进度条当前数值
        int value = ui->progressBar->value();
        if(value == 100)
        {
            QMessageBox::information(this,"提示","快乐无边!");
            return;
        }
        ui->progressBar->setValue(++value);
    }
}

7.3 事件过滤器

事件过滤器可以在父组件对象中检测子组件对象传递的事件。

使用事件过滤器需要给监控的子组件注册事件过滤器后,在父组件对象中覆盖下面的函数。

bool QObject::eventFilter(QObject * watched, QEvent * event) [virtual protected]

参数1:被观察的子组件对象

参数2:当前检测的事件对象

返回值:是否拦截事件的传递,建议初学者不要写固定值,此处调用原基类被覆盖的函数返回值。

d9b1f0af01f5c21257cd260c12ec80a0.png

22ebabfe60f6eda2463bb6d7c605d7f3.png

Type QEvent::type() const

返回当前事件的类型

示例代码下载链接:百度网盘 请输入提取码

提取码:hqyj

--来自百度网盘超级会员V6的分享

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

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

    // 给第一个输入框注册事件过滤器  installEventFilter安装注册使用
    ui->lineEdit->installEventFilter(this);
}

Dialog::~Dialog()
{
    delete ui;
}
//参数1:被观察的子组件对象
//参数2:当前检测的事件对象

bool Dialog::eventFilter(QObject * watched, QEvent * event)
{
    // 先判断是哪个组件,再判断当前组件的事件类型  FocusIn 获取焦点   event->type()返回当前事件的类型
    if(watched == ui->lineEdit && QEvent::FocusIn == event->type())
    {
        qDebug() << "第一个输入框获取了焦点!";
        //FocusOut 失去焦点              这个事件类型去第一个图片找
    }else if(watched == ui->lineEdit && QEvent::FocusOut == event->type())
    {
        qDebug() << "第一个输入框失去了焦点!";
    }

    // 调用基类覆盖的函数  这个函数有返回值
    return QDialog::eventFilter(watched,event);
}

dialog.h  

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QDebug>

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

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

protected:
    // 声明事件过滤器函数 bool QObject::eventFilter(QObject * watched, QEvent * event) [virtual protected]
    bool eventFilter(QObject *, QEvent *);

private:
    Ui::Dialog *ui;
};

#endif // DIALOG_H

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt第六章 多窗口编程 的相关文章

  • 打开和关闭附加窗口 (QML)

    目前我有一个通过以下方式打开的窗口 property variant win Button id testButton MouseArea onClicked var component Qt createComponent test qm
  • Qml 和模糊图像

    我想使用 QML 实现模糊效果 我找到了有关 效果 模糊 的参考资料 例子 http qt gitorious org lscunha qt components lscunha qt components blobs d78feec567
  • Qt 人工鼠标点击无法正常工作

    小玩具应用程序可以在这里找到 http gist github com 517445 http gist github com 517445 我正在尝试将人工鼠标事件发送到小部件 我使用QApplication sendEvent为此 接下
  • 用 C++/Qt 编写的程序中的 RTF / doc / docx 文本提取

    我正在写一些程序Qt https en wikipedia org wiki Qt 28software 29 C 我需要从中读取文本微软Word https en wikipedia org wiki Microsoft Word RTF
  • QComboBox 下拉项边距

    我想设计我的风格QComboBox为下拉项目留出边距 现在是这样的 我想要这样的东西 我尝试过 QComboBox QAbstractItemView item margin 3px 但它不起作用 你能帮我解决这个问题吗 您想在项目之间设置
  • 在 QtCreator 中使用 .pro 和 .pri 正确(树)显示 Qt 项目

    是否可以使用项目包含文件 pri 显示不止一个额外级别 例如如果 pro文件包括 pri文件包含两个 pri files pro pri pri pri 在 QtCreator 项目 中显示具有误导性 pro pri pri pri 它根本
  • new 运算符(以及 malloc)无法分配约 450 MB 的内存 [重复]

    这个问题在这里已经有答案了 我正在开发一个程序 该程序在内存中存储大约 2 2 亿个短值的数组 该数据块的分配方式如下 short arrayName new short SIZE OF ARRAY 然后将文件的内容读入内存 在团队中的另一
  • 第一次信号发射后自动断开

    我正在从文件加载网页 然后替换其中的一些 html self template web page QtWebKit QWebPage self template web page mainFrame load QtCore QUrl tem
  • QT:删除QGridLayout中QLabel之间的空格

    我将一些具有不同颜色的 QLabels 添加到 QGridLayout 作为 QWidget 的布局 现在我在每个 Qlabel 与下一个 Qlabel 之间有一个间距 我想将其删除 我尝试将标签的边距设置为 0 将 GridLayout
  • 使用 CMake 编译时更改头文件位置会导致缺少 vtable 错误

    对于一个大型 C 项目 我需要从 qmake 过渡到 CMake 但是在处理一个玩具示例时 我遇到了一些我不理解的行为 示例代码具有单个头文件 当该头文件移动到子目录中时 我收到 MainWindow 类缺少 vtable 的错误 CMak
  • Mac OS X 上的 Qt 字体系列和样式

    我有一个基于 Qt PyQt 的 GUI 应用程序 在 Mac OS X 和其他平台 上运行 它允许用户选择字体并具有粗体和斜体选项的复选框 在更新到新的基于 Cocoa 的 Qt 时 用户发现QFontComboBox不再显示不同的字体样
  • 即使我在单独的线程中运行,QT GUI 也会冻结

    我有一个小型聊天应用程序 其中使用 SQLite 数据库来存储所有对话 我注意到该应用程序随机冻结 然后我必须最小化和最大化它才能使其再次工作 我认为问题可能是 SQLite 选择 插入导致 gui 冻结 我决定尝试将所有 SQLite 方
  • Qt(在 Windows 上)将权限级别设置为“requireAdministrator”

    我正在使用 Qt Creator 并努力制作 exe文件默认以管理员身份运行 在线阅读所有解决方案我试图将这一行放入我的 pro file QMAKE LFLAGS MANIFESTUAC level requireAdministrato
  • Q风格所有权

    在 Qt 应用程序中使用样式时 我遇到了一个有趣的问题QStyle所有权 QStyle继承自QObject 通常接受QObject parent作为构造函数参数来管理其子级的生命周期 但QStyle的构造函数没有此构造函数参数 第一个问题
  • QAbstractItemModel 如何表示树?

    我仍然很难理解 QAbstractItemModel 对项目的表示 有两种返回 QModelIndex 项的方法对我来说没有任何意义 QModelIndex QAbstractItemModel index int row int colu
  • 使 QLabel 的像素图透明

    我有一个带有 QLabel 和像素图的主窗口 我想让它透明 或不那么不透明 我正在使用下面的代码 ui gt label gt setAttribute Qt WA TranslucentBackground ui gt label gt
  • 在 Qt GraphicsView 中创建长线(或十字线)光标的最佳方法

    创建长十字线光标 与视口一样长 的简单方法是创建一条十字线graphicsItem 当鼠标移动时 设置该项目的pos财产 但是当场景复杂时这种方式会很慢 因为它要更新整个视口来更新光标的pos 另一种简单的方法是setCursor QCur
  • QFileDialog::getOpenFileName 调试时崩溃,显然是由项目名称引起的?

    我遇到了一个让我非常困惑的问题 我在 Windows 7 上使用 Qt Creator 3 1 2 和 Qt 5 3 使用 MSVC 10 0 编译器和 Windows 8 1 调试工具中的 CDB 不确定我是否应该寻找特定于 Window
  • QThread - 使用槽 quit() 退出线程

    我想在线程完成运行时通知对象 但是 我无法让线程正确退出 我有以下代码 处理器 cpp thread new QThread tw new ThreadWorker connect tw SIGNAL updateStatus QStrin
  • 使用 qbs 构建 qt 应用程序

    我想知道在 Linux 上使用 qbs 编译 构建和创建 Android Qt 应用程序的步骤 我拥有所有必要的工具 目前我可以使用 qmake 创建 apk Qbs 目前不支持构建 Qt Android 应用程序 Qbs v1 4 中引入

随机推荐

  • Apple 允许您指定在您死后谁可以访问您的账户

    在周一的WWDC 2021活动中 Apple 宣布 从今年秋季的 iOS 15 和 macOS Monterey 操作系统更新开始 将可以指定在您死亡的情况下谁可以访问您的账户 新功能称为数字遗产 它使亲戚或朋友更容易访问已故亲人拥有的数码
  • ZYNQ7000系列 DDR读取正确性

    摘要 使用ZYNQ或者MPSoC的好处是可以通过PL逻辑设计硬件加速器 对功能进行硬件加速 加速器和ARM之间的交互信息一般包含自定义加速指令传递 待计算数据以及计算结果 这三种交互信息 使用ZYNQ或者MPSoC的好处是可以通过PL逻辑设
  • java 档案整理 生成归档章 透明背景图片

    import javax imageio ImageIO import java awt import java awt image BufferedImage import java io File import java io IOEx
  • unity3d鼠标点击,获取世界坐标

    unity中有关于鼠标位置的函数 Input mousePosition 但不得不说 这个函数不到位 可以用一个print函数输出一下这个坐标会发现 只有X Y值在改变 Z值没有发生变化 并且在屏幕的左下角固定为 0 0 0 查看文档后发现
  • 类加载器是否为空

    package com bzu csh 项目名称 Test1 类名称 Test2 类描述 创建人 admin 创建时间 2017年1月7日 下午9 41 36 修改人 admin 修改时间 2017年1月7日 下午9 41 36 修改备注
  • 数据可视化之折线图绘制

    使用python中的matplotlib绘制折线图 环境需求 python 或者anaconda pycharm 和第三方库matplotlib 首次先绘制简单的折线图 其他的参数可以在使用熟练后一点一点的加入 import matplot
  • 计算机网络课程笔记

    学习MOOC华南理工计算机网络课程笔记 第1章 概述 1 1 为什么要学习计算机网络 1 2 互联网发展史 1 3 常用的基本概念 1 4 参考模型 1 5 参考模型相关概念 1 6 本课程的组织 第2章 物理层 2 1 物理层概述 2 2
  • JNI编程—JNI基础

    什么是JNI 怎么使用 JNI Java Native Interface 它是Java平台的一个特性 并不是Android系统特有的 其实主要是定义了一些JNI函数 让开发者可以通过调用这些函数实现Java代码调用C C 的代码 C C
  • python 如何编写一个自己的包

    python 如何编写一个自己的包 先写function 内容 package wadepypk ls init py f1 py f2 py f1 py def show print in pkg f show f2 py def sho
  • unix bsd linux gun   粗略解释

    最早的unix是开放的 很多组织对unix都有修改 期中比较有名的就是伯克利大学的修改版本 叫做bsd 是unix的分支 由于bsd的协议允许你直接使用 修改他的代码 并且可以作为商业用途 所以很多公司的unix都是从bsd衍生过来的 比如
  • mongodb学习笔记一:mongodb安装与介绍

    一 前言 最近开始学习非关系型数据库MongoDB 却在博客园上找不到比较系统的教程 很多资料都要去查阅英文网站 效率比较低下 本人不才 借着自学的机会把心得体会都记录下来 方便感兴趣的童鞋分享讨论 部分资源出自其他博客 旨将零散知识点集中
  • C/C++函数模板template

    1 说明 当函数处理功能相似 函数名相同 但是参数个数或者类型有区别 我们知道实现的方式是依靠函数重载 overload 但是如果仅函数参数或返回数的类型不同 我们想到靠函数模板解决这个问题 不仅节省内存 而且不用复杂声明多个函数 函数模板
  • 为线程池中的每个线程设置UncaughtExceptionHandler

    参考了 java并发编程实战 P134内容 每当线程池需要创建一个线程时 都是通过调用线程工厂方法来完成的 默认的线程工厂方法将创建一个新的 非守护的线程 并且不包好特殊的配置信息 如果你希望在线程运行之前 之后 或者运行中如果发生异常等情
  • Linux 系统 lscpu 命令详解

    文章目录 前言 lscpu 命令详解 命令 1 查看物理 CPU 个数 2 查看每个物理 CPU 核数 3 查看总线程数 4 查看内存信息 5 查看 linux 系统版本 前言 Linux 系统查看系统相关信息方法很多 以下详细介绍 lsc
  • 一颗二叉树代码(图解)

    什么是二叉树 树结构是一种非线性存储结构 存储的是具有一对多关系的数据的集合 而树形结构的一种抽象出来的数据结构往往是二叉树的形式 满足以下两个条件的树就是二叉树 本身是有序树 树中包含的各个节点的度不能超过 2即只能是 0或者1 或者 2
  • 项目时间管理-架构真题(二十四)

    1 霍尔提出了系统方法的三维结构体系 通常称为霍尔三维结构 这就是系统工程方法论的基础 霍尔三维结构以时间堆 堆 知识堆组成的立体结构概括性表示出系统工程在各阶段 各步骤以及所涉及的知识范围 其中时间维是系统的工作进程 对于一个具体的工程项
  • 计算机网络面试八股文攻略(二)—— TCP 与 UDP

    一 基础概念 TCP 与 UDP 是活跃于 运输层 的数据传输协议 TCP 传输控制协议 Transmission Control Protocol 提供面向连接的 可靠的数据传输服务 具体来说就是一种要建立双端连接才能发送数据 能确保传输
  • react拖拽排序、js列表拖拽

    列表拖动排序的解决方案有多种 个人感觉最简单的就是zent 提供的 Sortable 组件了 一 zent Sortable 拖拽排序 推荐 简单明了 zent 官网 https zent contrib gitee io zent zh
  • 1139: 输出最短字符串java

    import java util Scanner public class Main public static void main String args Scanner input new Scanner System in int n
  • Qt第六章 多窗口编程

    一 QMessageBox 消息对话框 掌握 QMessageBox继承自QDialog 是一个Qt内置的用来展示信息或询问用户一个问题的模态对话框 预设了四种类型 像那些已经写好的窗口 这些现成的东西都会有一些特性 就是他们的对象都不需要