一、Xmind整理:
二、上课笔记整理:
1.消息对话框(QMessageBox)
①基于属性版本的API
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;
}
②基于静态成员函数版本
[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);
2.对话框案例
头文件:
#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_quesBtn_clicked();
void on_warnBtn_clicked();
void on_critBtn_clicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
源文件:
#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); //设置默认按钮
//2、执行对话框
int ret = box.exec();
//3、对用户点击的按钮进行判断
if(ret == QMessageBox::Yes)
{
qDebug() << "好的,没问题!";
}
else
{
qDebug() << "我就不!";
}
}
void Widget::on_quesBtn_clicked()
{
//1、使用QMessageBox实例化一个类对象
QMessageBox box(QMessageBox::Question, //图标
"问题", //对话框标题
"真的要关闭吗?", //对话框提示信息
QMessageBox::Yes|QMessageBox::No, //对话框提供的按钮
this); //父组件
//2、执行对话框
int ret = box.exec();
//3、对用户点击的按钮进行判断
if(ret == QMessageBox::Yes)
{
this->close();
}
else
{
}
}
//警告按钮对应的槽函数
void Widget::on_warnBtn_clicked()
{
//无需实例化对象,直接调用静态成员函数即可
int ret = QMessageBox::warning(this, //父组件
"警告", //对话框标题
"放学别走!", //对话框文本内容
QMessageBox::Yes|QMessageBox::No, //提供的按钮
QMessageBox::Yes); //默认选中的按钮
//对用户点击的按钮进行判断
if(ret == QMessageBox::Yes)
{
qDebug() << "等着就等着!";
}
else
{
qDebug() << "我就不,略略略!";
}
}
void Widget::on_critBtn_clicked()
{
//无需实例化对象,直接调用静态成员函数即可
int ret = QMessageBox::critical(this, //父组件
"错误", //对话框标题
"操作错误!", //对话框文本内容
QMessageBox::Yes|QMessageBox::No, //提供的按钮
QMessageBox::Yes); //默认选中的按钮
//对用户点击的按钮进行判断
if(ret == QMessageBox::Yes)
{
this->close();
}
else
{
}
}
3.完善登录框
点击登录按钮后,判断账号(admin)和密码(123456)是否一致,如果匹配失败,则弹出错误对话框,文本内容“账号密码不匹配,是否重新登录”,给定两个按钮ok和cancel,点击ok后,会清除密码框中的内容,继续进行登录;如果点击cancel按钮,则关闭界面。
如果账号和密码匹配,则弹出信息对话框,给出提示信息为“登录成功”,给出一个按钮ok,点击ok后,关闭整个登录界面,跳转到其他界面
点击取消按钮后,弹出问题对话框,询问是否确定要退出登录,给出两个按钮,yes|no,点击yes,则直接关闭整个登录界面,如果点击no则进行进行登录
要求:对象版和静态成员函数版至少各实现一个
#include "widget.h"
#include "ui_widget.h"
#include <QDebug> //输出函数对应的头文件
#include <QIcon>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//信号函数也可以连接信号函数
//connect(ui->jumpBtn,&QPushButton::clicked,this,&Widget::jump)
this->setFixedSize(540,410); //设置固定尺寸
this->setWindowTitle("小徐的聊天室"); //窗口标题
this->setWindowIcon(QIcon(":/wodepeizhenshi.png")); //设置窗口的icon
//1、实例化标签
lab1 = new QLabel("LOGO",this);
lab1->resize(540,220);
lab1->setPixmap(QPixmap(":/logo.png"));
lab1->setScaledContents(true); //设置内容自适应
lab2 = new QLabel("账号",this);
lab2->resize(35,35);
lab2->move(115,230);
lab2->setPixmap(QPixmap(":/userName.jpg"));
lab2->setScaledContents(true);
lab3 = new QLabel("密码",this);
lab3->resize(35,35);
lab3->move(lab2->x(),lab2->y()+65);
lab3->setPixmap(QPixmap(":/passwd.jpg"));
lab3->setScaledContents(true);
//2、构造行编辑器,构造时给定父组件
edit1 = new QLineEdit(this);
edit1->setPlaceholderText("QQ/手机/邮箱"); //设置编辑器的占位文本
edit1->resize(230,40); //设置尺寸
edit1->move(lab2->x()+80,lab2->y()); //移动位置
//3、构造行编辑器,构造时给定父组件以及文本内容
edit2 = new QLineEdit(this);
edit2->setPlaceholderText("密码"); //设置编辑器的占位文本
edit2->resize(230,40); //设置尺寸
edit2->move(lab3->x()+80,lab2->y()); //移动位置
edit2->resize(edit1->size());
edit2->move(edit1->x(),edit1->y()+60);
edit2->setEchoMode(QLineEdit::Password); //设置回显模式
//4、使用无参构造添加一个按钮
btn1 = new QPushButton; //无参构造
btn1->setParent(this); //给组件指定父组件,让其依附于界面而存在
btn1->setText("登录"); //给组件设置文本内容
btn1->resize(QSize(90,35)); //设置按钮组件的大小
btn1->move(195,360); //移动组件位置
btn1->setIcon(QIcon(":/login.png"));
//5、构造按钮时,指定父组件
btn2 = new QPushButton(this); //将当前界面设置成父组件
btn2->setText("取消");
btn2->resize(btn1->size()); //使用其他按钮的大小设置该组件的大小
btn2->move(btn1->x()+140,btn1->y());
btn2->setIcon(QIcon(":/cancel.png")); //设置图标
connect(btn1,&QPushButton::clicked,this,&Widget::my_slot);
connect(this,&Widget::my_signal,this,&Widget::close);
connect(btn2,SIGNAL(clicked()),this,SLOT(close()));
}
//处理登录按钮对应槽函数的实现
void Widget::my_slot()
{
if(edit1->text()=="admin" &&edit2->text()=="123456")
{
//1、使用QMessageBox实例化一个类对象
QMessageBox box(QMessageBox::Information, //图标
"信息", //对话框标题
"登录成功", //对话框提示信息
QMessageBox::Ok, //对话框提供的按钮
this); //父组件
//2、执行对话框
int ret = box.exec();
//3、对用户点击的按钮进行判断
if(ret == QMessageBox::Ok)
{
this->close();
emit jump();
}
}
else
{
int ret = QMessageBox::critical(this, //父组件
"错误", //对话框标题
"账号密码不匹配,是否重新登录!", //对话框文本内容
QMessageBox::Ok|QMessageBox::Cancel, //提供的按钮
QMessageBox::Ok); //默认选中的按钮
//对用户点击的按钮进行判断
if(ret == QMessageBox::Ok)
{
this->edit2->clear();
}
else
{
this->close();
}
}
}
void Widget::cancel_slot()
{
//1、使用QMessageBox实例化一个类对象
QMessageBox box(QMessageBox::Question, //图标
"问题", //对话框标题
"是否确定要退出登录?", //对话框提示信息
QMessageBox::Yes|QMessageBox::No, //对话框提供的按钮
this); //父组件
//2、执行对话框
int ret = box.exec();
//3、对用户点击的按钮进行判断
if(ret == QMessageBox::Yes)
{
this->close();
}
else
{
}
}
Widget::~Widget()
{
delete ui;
}
4.字体对话框(QFontDialog)、颜色对话框(QColorDialog)、文件对话框(QFileDialog)
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();
5.对话框案例(文本编辑器)
头文件:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QFont> // 字体类
#include <QFontDialog> // 字体对话框类
#include <QDebug>
#include <QMessageBox> //消息对话框类
#include <QColor>
#include <QColorDialog>
#include <QFileDialog>
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();
void on_saveBtn_clicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
源文件:
#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::ReadOnly))
{
return;
}
//4、读取文件中的内容
QByteArray msg = file.readAll();
//将内容展示到ui界面
ui->textEdit->setText(QString::fromLocal8Bit(msg));
// //获取文本编辑器中的内容
// ui->textEdit->toPlainText();
//5、关闭文件
file.close();
}
void Widget::on_saveBtn_clicked()
{
//调用QFileDialog的静态成员函数getSaveFileName来获取选中文件的路径
QString filename = QFileDialog::getSaveFileName(this, //父组件
"保存文件", //对话框标题
"./", //起始路径
"all file(*.*);;Text(*.txt);;Image(*.png,*.jpg,*.gif)"); //过滤器
if(filename.isNull())
{
QMessageBox::information(this,"提示","您取消了选择文件");
return;
}
//输出文件路径
qDebug() << filename;
//文件操作
QFile file(filename); //使用获取到的文件路径,实例化一个文件对象,后期对文件的操作都是基于该对象
//打开文件
if(!file.open(QFile::Append))
{
return;
}
//获取textEdit中的内容
QString msg = ui->textEdit->toPlainText();
//将textEdit中的内容写入到filename中
file.write(msg.toLocal8Bit());
//关闭文件
file.close();
}
6.事件处理(核心机制)
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> 组件的使用者所关心的往往是定义什么样的槽处理什么样的信号,
而组件的实现者更关心覆盖哪些事件处理函数
7.事件处理函数由来
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");
}
8.鼠标和键盘事件
头文件:
#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
源文件:
#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()-10);
}
break;
case 'S' :
{
if(ui->label->y() >= this->height())
{
ui->label->move(ui->label->x(),0);
}
ui->label->move(ui->label->x(),ui->label->y()+10);
}
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());
}
break;
case 'D' :
{
if(ui->label->x() >= this->width())
{
ui->label->move(0,ui->label->y());
}
ui->label->move(ui->label->x()+10,ui->label->y());
}
break;
}
}
//键盘抬起事件处理函数的定义
void Widget::keyReleaseEvent(QKeyEvent *event)
{
}