Qt---对话框 事件处理 如何发布自己写的软件

目录

一、对话框

[1.1 消息对话框(QMessageBox)](#1.1 消息对话框(QMessageBox))

[1> 消息对话框提供了一个模态的对话框,用来提示用户信息,或者询问用户问题并得到回答](#1> 消息对话框提供了一个模态的对话框,用来提示用户信息,或者询问用户问题并得到回答)

[2> 基于属性版本的API](#2> 基于属性版本的API)

[3> 基于静态成员函数版本](#3> 基于静态成员函数版本)

[4> 对话框案例](#4> 对话框案例)

1、ui界面

2、头文件

3、源文件

练习:完善登录框

form.h

widget.h

form.cpp

main.cpp

widget.cpp

form.ui

运行结果:

[1.2 字体对话框(QFontDialog)、颜色对话框(QColorDialog)、文件对话框(QFileDialog)](#1.2 字体对话框(QFontDialog)、颜色对话框(QColorDialog)、文件对话框(QFileDialog))

[1.3 对话框案例(文本编辑器)](#1.3 对话框案例(文本编辑器))

[1> ui界面](#1> ui界面)

[2> 头文件](#2> 头文件)

[3> 源文件](#3> 源文件)

二、发布软件

[1> 配置系统环境变量,将QT安装路径中的相关bin目录放入系统环境变量中](#1> 配置系统环境变量,将QT安装路径中的相关bin目录放入系统环境变量中)

[2> 将自己的程序以release的形式运行一次](#2> 将自己的程序以release的形式运行一次)

[3> 将发布后的relsaes文件夹内的可执行程序复制到一个新的文件夹中](#3> 将发布后的relsaes文件夹内的可执行程序复制到一个新的文件夹中)

[4> 在新文件夹的空白处,按shift+右键 ---->选择"在此处打开powershell窗口"](#4> 在新文件夹的空白处,按shift+右键 ---->选择“在此处打开powershell窗口”)

[5> 在窗口中输入指令:windeployqt.exe .\可执行文件名.exe](#5> 在窗口中输入指令:windeployqt.exe .\可执行文件名.exe)

[6> 此时,就可以执行可执行程序,也可以打包发给朋友](#6> 此时,就可以执行可执行程序,也可以打包发给朋友)

三、事件处理(核心机制)

[3.1 事件处理简介](#3.1 事件处理简介)

[3.2 事件处理函数由来](#3.2 事件处理函数由来)

[3.3 鼠标和键盘事件](#3.3 鼠标和键盘事件)

头文件

源文件

练习:

1.Qt文本编辑实现字体和颜色的改变,可进行打开读取和另存为的操作

widget.h

main.cpp

widget.cpp

widget.ui

演示:

[2.实现一个lable 通过键盘控制 wasd 实现上下左右移动](#2.实现一个lable 通过键盘控制 wasd 实现上下左右移动)

sbjp.h

main.cpp

sbjp.cpp

sbjp.ui

演示:


一、对话框

消息对话框、字体对话框、颜色对话框、文件对话框

1.1 消息对话框(QMessageBox)

1> 消息对话框提供了一个模态的对话框,用来提示用户信息,或者询问用户问题并得到回答

2> 基于属性版本的API

1、使用该类调用构造函数,构造一个类对象

2、调用成员函数exec进入执行态

3、对用户点击的按钮进行进一步处理即可,通过对exec的返回值得到用户点击的按钮

cpp 复制代码
QMessageBox::QMessageBox(                           //有参构造函数名
    QMessageBox::Icon icon,                          //图标
    const QString &title,                             //对话框标题
    const QString &text,                              //对话框提示信息文本
    QMessageBox::StandardButtons buttons = NoButton,  //对话框提供的按钮
    QWidget *parent = nullptr)                        //父组件

参数1的介绍:是对话框提供的图标

内容                        值                描述
QMessageBox::NoIcon         0                没有任何图标的对话框           
QMessageBox::Question       4                带一个问号的对话框 
QMessageBox::Information    1                带一个i符号图标的对话框
QMessageBox::Warning        2                带一个感叹号图标的对话框
QMessageBox::Critical       3                带一个叉号图标的对话框

参数4的介绍:对话框提供的按钮

Constant                  Value              Description
QMessageBox::Ok           0x00000400          提供确定按钮
QMessageBox::Open         0x00002000          提供打开按钮.
QMessageBox::Save         0x00000800          提供保存按钮.
QMessageBox::Cancel       0x00400000          提供取消按钮.

 举个例子:
  QMessageBox msgBox;
  msgBox.setText("The document has been modified.");
  msgBox.setInformativeText("Do you want to save your changes?");
  msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
  msgBox.setDefaultButton(QMessageBox::Save);
  int ret = msgBox.exec();
  
     switch (ret) {
    case QMessageBox::Save:
        // Save was clicked
        break;
    case QMessageBox::Discard:
        // Don't Save was clicked
        break;
    case QMessageBox::Cancel:
        // Cancel was clicked
        break;
    default:
        // should never be reached
        break;
  }

3> 基于静态成员函数版本

1、由于静态成员函数独立于类对象而存在,所以,无需实例化对象,直接通过类名进行调用

2、静态成员函数版本提供四个,分别是information(), question(), warning(), and critical()

3、静态成员函数调用后,之间展示对话框,无需使用exec

3、解析其中warning()

cpp 复制代码
[static] QMessageBox::StandardButton              //函数返回值类型,返回的是对话框上用户按下的按钮
    QMessageBox::warning(                         //函数名
        QWidget *parent,                          //父组件
        const QString &title,                     //对话框标题
        const QString &text,                       //对话框文本内容
        QMessageBox::StandardButtons buttons = Ok,  //提供的按钮
        QMessageBox::StandardButton defaultButton = NoButton)  //默认按钮
举个例子:
 int ret = QMessageBox::warning(this, tr("My Application"),
                                 tr("The document has been modified.\n"
                                    "Do you want to save your changes?"),
                                 QMessageBox::Save | QMessageBox::Discard
                                 | QMessageBox::Cancel,
                                 QMessageBox::Save);

4> 对话框案例

1、ui界面

2、头文件

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H


#include <QWidget>
#include<QMessageBox>            //消息对话框类
#include<QDebug>


QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE


class Widget : public QWidget
{
    Q_OBJECT


public:
    Widget(QWidget *parent = nullptr);
    ~Widget();


private slots:
    void on_infoBtn_clicked();


    void on_warnBtn_clicked();


private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

3、源文件

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"


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


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




//信息按钮对应的槽函数
void Widget::on_infoBtn_clicked()
{
    //1、使用QMessageBox实例化一个类对象
    QMessageBox box(QMessageBox::Information,           //图标
                    "信息",                               //对话框标题
                    "中午一起吃个饭!",                     //对话框提示信息
                    QMessageBox::Yes|QMessageBox::No,      //对话框的提供的按钮
                    this);                                 //父组件


    box.setDefaultButton(QMessageBox::No);          //将no设置成默认按钮
    //box.setDetailedText("啦啦啦拉拉阿拉啦");
    box.setButtonText(QMessageBox::No,"拒绝");


    //2、执行对话框
    int ret = box.exec();


    //3、对用户点击的按钮进行判断
    if(ret == QMessageBox::Yes)
    {
        qDebug()<<"好的,没问题,老地方见!";
    }else
    {
        qDebug()<<"不好意思,我已经有约了,下次一定";
    }
}


//警告按钮对应的槽函数
void Widget::on_warnBtn_clicked()
{
    //无需实例化对象,直接调用静态成员函数即可
    int ret =  QMessageBox::warning(this,                        //父组件
                         "警告",                       //对话框标题
                         "放学别走,等着哈!",           //对话框文本内容
                         QMessageBox::Yes|QMessageBox::No,  //提供的按钮
                         QMessageBox::Yes);               //默认选中的按钮


    //对用户点击的按钮进行判断
    if(ret == QMessageBox::Yes)
    {
        qDebug()<<"等着就等着,荤的还是素的尽你挑";
    }else
    {
        qDebug()<<"你永远是我大哥";
    }
}

练习:完善登录框

点击登录按钮后,判断账号(admin)和密码(123456)是否一致,如果匹配失败,则弹出错误对话框,文本内容"账号密码不匹配,是否重新登录",给定两个按钮ok和cancel,点击ok后,会清除密码框中的内容,继续进行登录;如果点击cancel按钮,则关闭界面。

如果账号和密码匹配,则弹出信息对话框,给出提示信息为"登录成功",给出一个按钮ok,点击ok后,关闭整个登录界面,跳转到其他界面

点击取消按钮后,弹出问题对话框,询问是否确定要退出登录,给出两个按钮,yes|no,点击yes,则直接关闭整个登录界面,如果点击no则进行进行登录

要求:对象版和静态成员函数版至少各实现一个

form.h

cpp 复制代码
#ifndef FORM_H
#define FORM_H

#include <QWidget>

namespace Ui {
class Form;
}

class Form : public QWidget
{
    Q_OBJECT

public:
    explicit Form(QWidget *parent = nullptr);
    ~Form();


signals:
    void jump();
public slots:
    void jump_slot();



private slots:
    void on_pushButton_clicked();

private:
    Ui::Form *ui;
};

#endif // FORM_H

widget.h

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QPushButton>
#include <QDebug>
#include <QIcon>
#include <QLabel>
#include <QPixmap>
#include <QLineEdit>
#include <QMessageBox>
class Widget : public QWidget
{
    Q_OBJECT     //信号与槽的元对象
signals:
    //自定义信号函数
    void jump();
    //void btn_1_clicked();

public slots:
    //自定义的槽函数
    void btn_1_clicked();
    void btn_2_clicked();
    void jump_slot();
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    QLabel *lab2;
    QLabel *lab3;
    QLabel *lab1;
    QLineEdit *edit1;
    QLineEdit *edit2;
    QPushButton *btn1;
    QPushButton *btn2;
};
#endif // WIDGET_H

form.cpp

cpp 复制代码
#include "form.h"
#include "ui_form.h"

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

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

void Form::jump_slot()
{
    this->show();
}



void Form::on_pushButton_clicked()
{
    emit jump();
    this->close();
}

main.cpp

cpp 复制代码
#include "widget.h"
#include "form.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    Form m;
    QObject::connect(&w,&Widget::jump ,&m,&Form::jump_slot);
    QObject::connect(&m,&Form::jump ,&w,&Widget::jump_slot);
    return a.exec();
}

widget.cpp

cpp 复制代码
#include "widget.h"
#include "form.h"
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    this->setFixedSize(900, 800);          //设置固定尺寸
    //3、窗口标题
    this->setWindowTitle("My First Window");
    //4、设置窗口的icon
    this->setWindowIcon(QIcon(":/new/prefix1/icon/wodepeizhenshi.png"));
    //5、设置背景色,一般使用样式表完成
    this->setStyleSheet("background-color:rgb(226,227,228);");
    //标签
    lab1 = new QLabel(this);
    lab1->setGeometry(0, 0, 900, 458);
    lab1->setPixmap(QPixmap(":/new/prefix1/icon/logo1.png"));
    lab1->setScaledContents(true);

    lab2 = new QLabel(this);
    lab2->setGeometry(270, 500, 40, 40);
    lab2->setPixmap(QPixmap(":/new/prefix1/icon/userName.jpg"));
    lab2->setScaledContents(true);

    lab3 = new QLabel(this);
    lab3->setGeometry(270, 580, 40, 40);
    lab3->setPixmap(QPixmap(":/new/prefix1/icon/passwd.jpg"));
    lab3->setScaledContents(true);

    //行编辑器
    //1、构造一个行编辑器,构造时给定父组件
    edit1
            = new QLineEdit(this);
    edit2 = new QLineEdit(this);
    edit1->setPlaceholderText("QQ/手机/邮箱");        //设置编辑器的占位文本
    edit2->setPlaceholderText("密码");
    edit1->resize(200,40);            //设置尺寸
    edit2->resize(200,40);
    edit1->move(350,500);       //移动位置
    edit2->move(350,580);
    edit2->setEchoMode(QLineEdit::Password); //设置回显模式

    //按钮组件
    btn1 = new QPushButton("登录", this);
    btn2 = new QPushButton("取消", this);
    btn1->resize(110,60);
    btn1->move(320,650);
    btn2->resize(110,60);
    btn2->move(450,650);
    btn1->setIcon(QIcon(":/new/prefix1/icon/login.png"));
    btn2->setIcon(QIcon(":/new/prefix1/icon/cancel.png"));
    //使用qt5版本连接
    connect(btn1,&QPushButton::clicked,this,&Widget::btn_1_clicked);
    //使用qt4版本连接
    connect(btn2,SIGNAL(pressed()),this,SLOT(close()));
}

Widget::~Widget()
{
}
void Widget::btn_1_clicked()
{
    if(edit1->text() == "admin" && edit2->text() == "123456")
    {
        //使用QMwssageBox实例化一个类对象
        QMessageBox msgbox1(QMessageBox::Information,   //图标
                           "信息",                      //对话框标题
                           "登录成功",              //对话框提示信息
                           QMessageBox::Ok|QMessageBox::Cancel,     //对黄框的提供的按钮
                           this);                 //父组件
        msgbox1.setDefaultButton(QMessageBox::Ok);   //将no设置成默认按钮 ,该按键会有蓝色框标识
        //msgbox.setDetailedText("啦啦啦啦");   //很少会用到这个提示框

        //执行对话框
        int ret = msgbox1.exec();

        //对用户点击的按钮进行判断
        if(ret == QMessageBox::Ok)
        {
            emit jump();
            this->close();
        }else
        {
            //使用QMwssageBox实例化一个类对象
            QMessageBox msgbox2(QMessageBox::Information,   //图标
                               "问题",                      //对话框标题
                               "是否确定要退出登录",              //对话框提示信息
                               QMessageBox::Yes|QMessageBox::No,     //对黄框的提供的按钮
                               this);                 //父组件
            msgbox2.setDefaultButton(QMessageBox::Yes);   //将no设置成默认按钮 ,该按键会有蓝色框标识
            //msgbox.setDetailedText("啦啦啦啦");   //很少会用到这个提示框

            //执行对话框
            int ret = msgbox2.exec();

            //对用户点击的按钮进行判断
            if(ret == QMessageBox::Yes)
            {
                this->close();
            }else
            {
                emit jump();
                this->close();
            }
        }


    }
    else
    {
        //无需实例化对象,直接调用静态成员函数即可
        int ret = QMessageBox::warning(this,              //父组件
                             "警告",             //对话框标题
                             "账号密码不匹配,是否重新登录",  //对话框文本内容
                             QMessageBox::Ok|QMessageBox::Cancel,  //提供的按钮
                             QMessageBox::Ok);         //默认选中的按钮
        //对用户点击的按钮进行判断
        if(ret == QMessageBox::Ok)
        {
            edit1->clear();
            edit2->clear();
        }else
        {
            this->close();
        }

    }
}

void Widget::btn_2_clicked()
{
    this->close();
}
void Widget::jump_slot()
{
    this->show();
}

form.ui

运行结果:

1.2 字体对话框(QFontDialog)、颜色对话框(QColorDialog)、文件对话框(QFileDialog)

cpp 复制代码
1、字体对话框,可以使用QFontDialog类提供的静态成员函数getFont来完成
    当调用了该函数后,就会弹出一个字体选择框,该函数返回的是用户选择的字体
    如果用户取消了选择,则参数1为假,如果用户选择了字体,则参数1的值为真
    所需类:QFontDialog、QFont
[static] QFont                               //函数返回值类型,是用户选择的字体  该函数是一个静态成员函数
    QFontDialog::getFont(                     //函数名
        bool *ok,                             //返回用户是否选中字体
        const QFont &initial,                 //初始字体
        QWidget *parent = nullptr,             //父组件
        const QString &title = QString())      //对话框标题
举个例子:
  bool ok;
  QFont font = QFontDialog::getFont(&ok, QFont("Times", 12), this);
  if (ok) {
      // font is set to the font the user selected
  } else {
      // the user canceled the dialog; font is set to the initial
      // value, in this case Times, 12.
  }
  
  2、颜色对话框,可以使用QColorDialog类中的静态成员函数getColor来调取颜色对话框
      该函数返回用户选中的颜色,如果用户选择了取消,则返回一个非法的颜色,可以通过成员函数isValid来进行判断
[static] QColor                               //返回用户选中的颜色   该函数是一个静态成员函数
    QColorDialog::getColor(                      //函数名
        const QColor &initial = Qt::white,       //初始颜色
        QWidget *parent = nullptr,              //父组件
        const QString &title = QString())       //对话框标题
举个例子:
    //调用静态成员函数,获取系统中的颜色对话框
    QColor c = QColorDialog::getColor(QColor("pink"),
                                      this,
                                      "选择颜色");

    //对选中的颜色判断合法性
    if(c.isValid())
    {
        //颜色合法,直接使用即可
        //ui->textEdit->setTextColor(c);
        ui->textEdit->setTextBackgroundColor(c);


    }else
    {
        //颜色不合法
        QMessageBox::information(this,"提示","您取消了选择颜色");
    }

3、文件对话框,可以通过QFileDialog类中的静态成员函数,来获取要打开的文件路径
    所需类:QFileDialog
    [static] QString                                //返回值类型是用户选中的文件的路径
        QFileDialog::getOpenFileName(              //函数名
            QWidget *parent = nullptr,                //父组件
            const QString &caption = QString(),     //对话框标题
            const QString &dir = QString(),          //起始路径
            const QString &filter = QString(),       //过滤器
            QString *selectedFilter = nullptr)     //默认选中的过滤器
    注意:该函数返回的是选中文件的路径
        过滤器如果有多个,中间使用两个分号隔开:"Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
举个例子:
  QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
                                                  "/home",
                                                  tr("Images (*.png *.xpm *.jpg)"));
 获取保存文件路径的函数:
 [static] QString QFileDialog::getSaveFileName(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString())                                                 
                                                  

4、文件相关操作
    1>    使用QFile类实例化一个对象,通过该对象可以操作整个文件,该类的构造函数需要给定文件的路径
    2>    可以使用exists函数判断文件是否存在,如果存在,则可以对文件进行相关操作
    3>    使用该类中的成员函数open函数,用于打开文件,打开时需要给定打开模式
    4>    可以使用read、readLine、readAll从文件中读取数据,使用write函数,将数据写入文件
    5>    使用成员函数close关闭文件
    6>    所需类:QFile
举个例子:
 //1、实例化一个文件对象
    QFile file(fileName);     //使用获取到的文件路径,实例化一个文件对象,后期对文件的操作都是基于该对象

    //2、判断文件是否存在
    if(!file.exists())
    {
        return;
    }
    //3、打开文件
    if(!file.open(QFile::ReadWrite))
    {
        return;
    }

    //4、读取文件中的内容
    QByteArray msg = file.readAll();


    //将内容展示到ui界面
    ui->textEdit->setText(msg);    
    //获取文本编辑器中的内容
    //ui->textEdit->toPlainText();
    //5、关闭文件
    file.close();

1.3 对话框案例(文本编辑器)

1> ui界面

2> 头文件

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H


#include <QWidget>
#include<QFont>             //字体类
#include<QFontDialog>         //字体对话框类
#include<QDebug>
#include<QMessageBox>            //消息对话框类
#include<QColor>               //颜色类
#include<QColorDialog>           //颜色对话框类
#include<QFileDialog>               //文件对话框
#include<QFile>                  //文件类


QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE


class Widget : public QWidget
{
    Q_OBJECT


public:
    Widget(QWidget *parent = nullptr);
    ~Widget();


private slots:
    void on_fontBtn_clicked();


    void on_colorBtn_clicked();


    void on_openBtn_clicked();


private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

3> 源文件

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"


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


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


//字体按钮对应的槽函数
void Widget::on_fontBtn_clicked()
{
    //调用QFontDialog类中的静态成员函数,getFont函数来调取系统提供的字体对话框
    bool ok;                //用于接受用户是否选中了字体
    QFont f = QFontDialog::getFont(&ok,                    //返回是否选中字体
                         QFont("隶书", 10, 10, false),       //初始字体
                         this,                              //父组件
                         "选择字体");                       //对话框标题


    //将选中的字体进行使用
    if(ok)
    {
        //选中了字体,将字体设置到文本上
        //ui->textEdit->setFont(f);
        ui->textEdit->setCurrentFont(f);




    }else
    {
        //没选中字体
        QMessageBox::information(this, "提示", "您取消了选择字体");
    }
}




//颜色按钮对应的槽函数
void Widget::on_colorBtn_clicked()
{
    //调用静态成员函数,获取系统中的颜色对话框
    QColor c = QColorDialog::getColor(QColor("pink"),      //初始颜色
                                      this,                  //父组件
                                      "选择颜色");            //对话框标题


    //对选中的颜色判断合法性
    if(c.isValid())
    {
        //颜色合法,直接使用即可
        //ui->textEdit->setTextColor(c);
        ui->textEdit->setTextBackgroundColor(c);


    }else
    {
        //颜色不合法
        QMessageBox::information(this,"提示","您取消了选择颜色");
    }
}






//打开文件按钮对应的槽函数
void Widget::on_openBtn_clicked()
{
    //调用QFileDialog的静态成员函数getOpenFileName来获取选中文件的路径
    QString fileName = QFileDialog::getOpenFileName(this,               //父组件
                                                    "选择文件",          //对话框标题
                                                    "./",               //起始路径
                                 "Image File(*.png *.jpg *bmp);;Text File(*.txt);;All(*.*)");  //过滤器


    //判断是否选中文件
    if(fileName.isNull())
    {
        QMessageBox::information(this,"提示","您取消了选择文件");
        return;
    }


    //输出文件路径
    qDebug()<<fileName;


    //1、实例化一个文件对象
    QFile file(fileName);     //使用获取到的文件路径,实例化一个文件对象,后期对文件的操作都是基于该对象


    //2、判断文件是否存在
    if(!file.exists())
    {
        return;
    }


    //3、打开文件
    if(!file.open(QFile::ReadWrite))
    {
        return;
    }


    //4、读取文件中的内容
    QByteArray msg = file.readAll();


    //将内容展示到ui界面
    ui->textEdit->setText(msg);
    
    //获取文本编辑器中的内容
    //ui->textEdit->toPlainText();


    //5、关闭文件
    file.close();


}

二、发布软件

1> 配置系统环境变量,将QT安装路径中的相关bin目录放入系统环境变量中

2> 将自己的程序以release的形式运行一次

3> 将发布后的relsaes文件夹内的可执行程序复制到一个新的文件夹中

4> 在新文件夹的空白处,按shift+右键 ---->选择"在此处打开powershell窗口"

5> 在窗口中输入指令:windeployqt.exe .\可执行文件名.exe

6> 此时,就可以执行可执行程序,也可以打包发给朋友

三、事件处理(核心机制)

3.1 事件处理简介

cpp 复制代码
1. 什么是事件?  (重点)
    事件是由窗口系统或者自身产生的,用以响应所发生的
各类事情,比如用户按下并释放了键盘或者鼠标、窗口因
暴露而需要重绘、定时器到时而应有所动作,等等

    从某种意义上讲,事件比信号更原始,甚至可以认为大多
数信号其实都是由事件产生的。比如一个下压式按钮首先
感受到的是鼠标事件,
    在进行必要的处理以产生按钮下沉
继而弹起的视觉效果之后,才会发射 clicked()信号

2. 如何处理事件?  (重点)
   myWnd(自定义类) -继承-> QWidget -继承-> QObject    
   1> 当事件发生时,首先被调用的是QObject类中的虚函数event(),
   其 QEvent型参数标识了具体的事件类型
       bool QObject:: event (QEvent* e)
       {
           if (e == mouseEvent)
           {
               void QWidget::mousePressEvent (QMouseEvent* e)
               void QWidget:: mouseReleaseEvent (QMouseEvent* e)
           }
           if(e == keyEvent){
               void QWidget::keyPressEvent (QMouseEvent* e)
               void QWidget:: keyReleaseEvent (QMouseEvent* e)
           }
       }
   2> 作为QObject类的子类, QWidget类覆盖了其基类中的
   event()虚函数,并根据具体事件调用具体事件处理函数
       void QWidget::mousePressEvent (QMouseEvent* e)
       void QWidget::mouseReleaseEvent (QMouseEvent* e)
       void QWidget::keyPressEvent (QMouseEvent* e)
       void QWidget:: keyReleaseEvent (QMouseEvent* e)
       void QWidget::paintEvent (QPaintEvent* e):
   3> 而这些事件处理函数同样也是虚函数,也可以被 QWidget类
   的子类覆盖,以提供针对不同窗口部件类型的事件处理

   4> 组件的使用者所关心的往往是定义什么样的槽处理什么样的信号,
   而组件的实现者更关心覆盖哪些事件处理函数

3.2 事件处理函数由来

cpp 复制代码
QObject类 提供了那些可以重写的虚函数
    [virtual] bool QObject::event(QEvent *e) 
            // 参数:事件的类型

QWidgets类, 提供了那些可以重写的虚函数
    [override virtual protected] bool QWidget::event(QEvent *event)
    
    [virtual protected] void QWidget::keyPressEvent(QKeyEvent *event)
    [virtual protected] void QWidget::keyReleaseEvent(QKeyEvent *event)
    [virtual protected] void QWidget::mouseMoveEvent(QMouseEvent *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 QObject::timerEvent(QTimerEvent *event)

QPainter类 ---> 画家类
     void SimpleExampleWidget::paintEvent(QPaintEvent *)
     {
         QPainter painter(this);
         painter.setPen(Qt::blue);
         painter.setFont(QFont("Arial", 30));
         painter.drawText(rect(), Qt::AlignCenter, "Qt");
     }

3.3 鼠标和键盘事件

头文件

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H


#include <QWidget>
#include<QKeyEvent>          //键盘事件处理头文件
#include<QDebug>


QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE


class Widget : public QWidget
{
    Q_OBJECT


public:
    Widget(QWidget *parent = nullptr);
    ~Widget();


    void keyPressEvent(QKeyEvent *event) override;          //键盘按下事件处理函数
    void keyReleaseEvent(QKeyEvent *event) override;       //键盘抬起事件处理函数




private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

源文件

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"


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


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


//键盘按下事件处理函数的定义
void Widget::keyPressEvent(QKeyEvent *event)
{
    //qDebug()<<"键盘被按下了"<<event->text()<<"键值为:"<<event->key();


    switch(event->key())
    {
        case 'W':
        {
            if(ui->label->y() <= 0-ui->label->height())
            {
                ui->label->move(ui->label->x(), this->height());
            }
            ui->label->move(ui->label->x(), ui->label->y()-1);
        }
        break;
    }


}


//键盘抬起事件处理韩寒说的定义
void Widget::keyReleaseEvent(QKeyEvent *event)
{


}

练习:

1.Qt文本编辑实现字体和颜色的改变,可进行打开读取和另存为的操作

widget.h

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QMainWindow>
#include <QFont>        //字体类
#include <QFontDialog>  //字体对话框类
#include <QDebug>
#include <QMessageBox>   //消息对话框
#include <QColor>        //颜色类
#include <QColorDialog>  //颜色对话框类
#include <QFileDialog>   //文件对话框
#include <QFile>          //文明类
#include <QTextCodec>
QT_BEGIN_NAMESPACE
namespace Ui { class widget; }
QT_END_NAMESPACE

class widget : public QMainWindow
{
    Q_OBJECT

public:
    widget(QWidget *parent = nullptr);
    ~widget();

private slots:
    void on_fontBtn_clicked();

    void on_colorBtn_clicked();

    void on_openBtn_clicked();

    void on_pushButton_4_clicked();

private:
    Ui::widget *ui;
};
#endif // WIDGET_H

main.cpp

cpp 复制代码
#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    //解决汉字乱码问题
        QTextCodec *codec = QTextCodec::codecForName("UTF-8");
        QTextCodec::setCodecForLocale(codec);


    QApplication a(argc, argv);
    widget w;
    w.show();
    return a.exec();
}

widget.cpp

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"

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

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

//字体按钮的槽函数
void widget::on_fontBtn_clicked()
{
    //调用QFontDialog类中的静态成员函数,getFont函数来调取系统提供的对话框
    bool ok;           //用于接收用户是否选中了字体
    QFont f = QFontDialog::getFont(&ok,       //返回是否选中字体
                         QFont("楷体",10,10,false),   //初始字体
                         this,                      //父组件
                         "选择字体");                 //对话框标题
    //将选中的字体进行使用
    if(ok)     //选中了字体,将字体设置到文本上
    {
        //ui->textEdit->setFont(f);
        ui->textEdit->setCurrentFont(f);
    }else         //没选中字体
    {
        QMessageBox::information(this,"提示","您取消了字体");
    }
}
//颜色按钮对应的槽函数
void widget::on_colorBtn_clicked()
{
    //调用静态成员函数,获取系统中的颜色对话框
    QColor c = QColorDialog::getColor(QColor("pink"),
                                      this,
                                      "选择颜色");
    //对选中的颜色判断合法性
    if(c.isValid())
    {
        //颜色合法,直接使用即可
        //ui->textEdit->setTextColor(c);
        ui->textEdit->setTextBackgroundColor(c);
    }else
    {
        //颜色不合法
        QMessageBox::information(this,"提示","您取消了选择颜色");
    }
}
//打开文件按钮对应的槽函数
void widget::on_openBtn_clicked()
{
    //调用QFileDialog的静态成员函数getOpenFileName来获取选中文件的路径
    QString fileName = QFileDialog::getOpenFileName(this,       //父组件
                                                    "选择文件",   //对话框标题
                                                    "./",        //起始路径
          "Image File(*.png *.jpg *bmp);;Text File(*.txt);;All(*.*)");  //过滤器
    //判断是否选中文件
    if(fileName.isNull())
    {
        QMessageBox::information(this,"提示","您取消了选择文件");
        return;
    }
    //输出文件路径
    qDebug() << fileName;
    //1.实例化一个文件对象
    QFile file(fileName);  //使用获取到的文件路径,实例化一个文件对象,后期对文件的操作都是基于该对象
    //2.判断文件是否存在
    if(!file.exists())
    {
        return;
    }
    //3.打开文件
    if(!file.open(QFile::ReadWrite))
    {
        return;
    }
    //4.读取文件中的内容
    QByteArray msg = file.readAll();
    //5.将读取到的内容展示到ui界面
    ui->textEdit->setText(QString::fromLocal8Bit(msg));
    //6.关闭文件
    file.close();
    //获取文本编辑器中的内容返回是Qstring
    //ui->textEdit->toPlainText();
}
//另存为文件按钮对应的槽函数
void widget::on_pushButton_4_clicked()
{
    //调用QFileDialog的静态成员函数getOpenFileName来获取选中文件的路径
    QString fileName = QFileDialog::getSaveFileName(this,       //父组件
                                                    "选择文件",   //对话框标题
                                                    "./",        //起始路径
          "Image File(*.png *.jpg *bmp);;Text File(*.txt);;All(*.*)");  //过滤器
    //判断是否选中文件
    if(fileName.isNull())
    {
        QMessageBox::information(this,"提示","您取消了选择文件");
        return;
    }
    //输出文件路径
    qDebug() << fileName;
    //1.实例化一个文件对象
    QFile file(fileName);  //使用获取到的文件路径,实例化一个文件对象,后期对文件的操作都是基于该对象
    //2.判断文件是否存在
    if(!file.exists())
    {
        return;
    }
    //3.打开文件
    if(file.open(QFile::ReadWrite|QFile::Truncate))
    {
        //获取文本编辑器中的内容返回是Qstring
        QString msg = ui->textEdit->toPlainText();
        file.write(msg.toLocal8Bit());
        QMessageBox::information(this,"提示","文件保存成功");
    }
    else {
        QMessageBox::information(this,"提示","文件保存失败");
    }
    //6.关闭文件
    file.close();
}

widget.ui

演示:

2.实现一个lable 通过键盘控制 wasd 实现上下左右移动

sbjp.h

cpp 复制代码
#ifndef SBJP_H
#define SBJP_H

#include <QWidget>
#include<QKeyEvent>          //键盘事件处理头文件
#include<QDebug>
QT_BEGIN_NAMESPACE
namespace Ui { class SBJP; }
QT_END_NAMESPACE

class SBJP : public QWidget
{
    Q_OBJECT

public:
    SBJP(QWidget *parent = nullptr);
    ~SBJP();
public:
    void keyPressEvent(QKeyEvent *event) override;          //键盘按下事件处理函数
    void keyReleaseEvent(QKeyEvent *event) override;       //键盘抬起事件处理函数
    void sahbi();
private:
    Ui::SBJP *ui;
};
#endif // SBJP_H

main.cpp

cpp 复制代码
#include "sbjp.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    SBJP w;
    w.show();
    return a.exec();
}

sbjp.cpp

cpp 复制代码
#include "sbjp.h"
#include "ui_sbjp.h"

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

SBJP::~SBJP()
{
    delete ui;
}
//键盘按下时间处理函数的定义
void SBJP::keyPressEvent(QKeyEvent *event)
{
    //qDebug()<<"键盘被按下了"<<event->text()<<"键值为:"<<event->key();

    //qDebug() << this->height();
    switch(event->key())
    {
        case 'W':
        {
            if(ui->label->y() <= 0-ui->label->height())
            {
                ui->label->move(ui->label->x(), this->height());
            }
            ui->label->move(ui->label->x(), ui->label->y()-10);
            qDebug() << ui->label->pos().x() << "," << ui->label->pos().y();
        }
        break;
        case 'S':
        {

        if(ui->label->y() >= this->height()+ui->label->height())
            {
                ui->label->move(ui->label->x(),0);
            }
            ui->label->move(ui->label->x(), ui->label->y()+10);
            qDebug() << ui->label->pos().x() << "," << ui->label->pos().y();
        }
        break;
        case 'A':
        {
            if(ui->label->x() <= 0-ui->label->width())
            {
             ui->label->move(this->width(),ui->label->y());
            }
            ui->label->move(ui->label->x()-10, ui->label->y());
            qDebug() << ui->label->pos().x() << "," << ui->label->pos().y();
        }
        break;
        case 'D':
        {
            if(ui->label->x() >= this->width())
            {
                ui->label->move(0-ui->label->width(),ui->label->y());
            }
            ui->label->move(ui->label->x()+10, ui->label->y());
            qDebug() << ui->label->pos().x() << "," << ui->label->pos().y();
        }
        break;
    }

}
//键盘抬起事件处理函数说的定义
void SBJP::keyReleaseEvent(QKeyEvent *event)
{

}

sbjp.ui

演示:

相关推荐
白总Server20 分钟前
MySQL在大数据场景应用
大数据·开发语言·数据库·后端·mysql·golang·php
c语言鹌鹑蛋22 分钟前
C++进阶 --- 多继承中的虚表问题
开发语言·c++
姑苏老陈27 分钟前
【Python基础】Python文件处理
开发语言·python·python文件操作
luoluoal30 分钟前
java项目之企业级工位管理系统源码(springboot)
java·开发语言·spring boot
ch_s_t31 分钟前
新峰商城之购物车(一)
java·开发语言
学步_技术1 小时前
Python编码系列—Python工厂方法模式:构建灵活对象的秘诀
开发语言·python·工厂方法模式
Deryck_德瑞克1 小时前
Java集合笔记
java·开发语言·笔记
MengYiKeNan1 小时前
C++二分函数lower_bound和upper_bound的用法
开发语言·c++·算法
会发paper的学渣1 小时前
python 单例模式实现
开发语言·python·单例模式
学步_技术2 小时前
Python编码系列—Python桥接模式:连接抽象与实现的桥梁
开发语言·python·桥接模式