目录
1. QMessageBox 消息对话框
QMessageBox继承自QDialog,显示一个模态对话框,用于用户前台信息通知或询问用户问题并且接收问题答案。
QMessageBox可以直接使用四种预设的风格格式:
QDialog的Qt源码中的派生类往往都是一些在特定场合下预设好的对话框窗口,这些窗口的使用无需创建对象,直接使用静态成员函数弹窗,使用函数的返回值作为这个窗口的结果。
QMessageBox类的弹窗函数如下:
// 参数1 parent参数
// 参数2 窗口标题
// 参数3 信息内容
// 返回值 用户点击按钮的类型
StandardButton QMessageBox::critical|information|question|warning
(
QWidget * parent,
const QString & title,
const QString & text)[static]
// 构造函数
// 参数 parent
QMessageBox(QWidget * parent = 0)
// 向自定义QMessageBox窗口添加按钮
// 参数1 抽象按钮类,传入派生类
// 参数2 按钮的放置规则
void QMessageBox::addButton(QAbstractButton * button, ButtonRole role)
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QButtonGroup>
#include <QMessageBox>
#include <QPushButton>
#include <QPixmap>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private:
Ui::Dialog *ui;
QButtonGroup *group;
QMessageBox *box;
QPushButton* btn1;
QPushButton* btn2;
QPushButton* btn3;
// 创建并展示一个自定义的QMessageBox的函数
void customMessageBox();
private slots:
// 与void buttonClicked(int id)连接
void btnsClickedSlot(int);
};
#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);
group = new QButtonGroup(this);
group->addButton(ui->pushButton_Ques,1);
group->addButton(ui->pushButton_info,2);
group->addButton(ui->pushButton_warn,3);
group->addButton(ui->pushButton_crit,4);
group->addButton(ui->pushButton_custom,5);
connect(group,SIGNAL(buttonClicked(int)),
this,SLOT(btnsClickedSlot(int)));
}
Dialog::~Dialog()
{
delete ui;
}
// 自定义弹窗
void Dialog::customMessageBox()
{
// 创建一个QMessageBox对象
box = new QMessageBox(this);
// 设置标题
box->setWindowTitle("肯德基特惠");
// 图片对象
QPixmap map(":/new/prefix1/kfc.png");
// 设置图片
box->setIconPixmap(map);
// 设置文本
box->setText("5.20-5.22肯德基蛋挞20元6个");
btn1 = new QPushButton("吃",box);
btn2 = new QPushButton("不吃",box);
btn3 = new QPushButton("猛吃",box);
// 把按钮放到QMessageBox的规定位置
box->addButton(btn1,QMessageBox::YesRole);
box->addButton(btn2,QMessageBox::NoRole);
box->addButton(btn3,QMessageBox::DestructiveRole);
// 显示对话框
box->show();
}
void Dialog::btnsClickedSlot(int id)
{
if(id == 1)
{
QMessageBox::StandardButton result =
QMessageBox::question(this,"问题","你今早吃了吗?");
if(result == QMessageBox::Yes)
{
close();
}else if (result == QMessageBox::No)
{
lower();
}
}else if(id == 2)
{
QMessageBox::information(this,"信息","今天早上吃的甜沫 油旋");
}else if(id == 3)
{
QMessageBox::warning(this,"警告","甜沫有点不新鲜!");
}else if(id == 4)
{
QMessageBox::critical(this,"错误","食物中毒了");
}else if(id == 5)
{
customMessageBox();
}else
{
}
}
2. QWidget类
QWidget类是所有窗口和组件的基类,之前更多是在组件的角度认识他,实际上QWidget身为所有窗口的基类,也具有很多窗口的属性,窗口类的继承结构如下:
新建项目,使自带窗口类继承QWidget:
此时的项目自带的窗口类Widget继承了QWidget,在主函数创建并展示。
QWidget类作为所有窗口的基类,内部也规定了很多窗口特性:
● windowTitle : QString
窗口标题
● windowFlags : Qt::WindowFlags
在使用setWindowFlags设置多个窗口标记时,使用 | 风格(多个窗口状态可能会出现冲突)
// 设置窗口标记
// 参数为窗口标记的枚举
void setWindowFlags(Qt::WindowFlags type)
// 设置窗口状态
// 参数为窗口状态的枚举
void QWidget::setWindowState(Qt::WindowStates windowState)
窗口状态有时会与窗口标记冲突。
dialog.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
setWindowTitle("我的窗口");
// 设置最上层无边框
setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
// 设置为全屏
setWindowState(Qt::WindowFullScreen);
}
Widget::~Widget()
{
delete ui;
}
3. parent参数
目前对parent参数有以下几点理解:
● parent参数表示子组件位于那个窗口中
● parent参数决定了QWIdget对象是独立窗口还是内嵌窗口
实际上parent参数还表示Qt的内存回收机制,如果a对象作为b对象构造时的parent参数,表示a对象是b对象的父对象(非继承),是一种内存回收的依赖关系。b对象会跟随a对象一并销毁,此时无需控制b对象的销毁过程。(无需手动调用delete)。
如果创建堆内存对象创建时不传递parent参数,表示此对象需要程序员手动delete。
绝大多数下,建议堆内存对象创建时传递parent参数。
dialog.hj
#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 btnYesClicked();
void btnNoClicked();
};
#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);
connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(btnYesClicked()));
connect(ui->pushButton_2,SIGNAL(clicked()),this,SLOT(btnNoClicked()));
}
Dialog::~Dialog()
{
qDebug() << "析构函数";
delete ui;
}
void Dialog::btnYesClicked()
{
// 传递Parent参数,在创建一个Dialog对象
Dialog *d = new Dialog(this);
d->show();
}
void Dialog::btnNoClicked()
{
// 不传递Parent参数,在创建一个Dialog对象
Dialog *d = new Dialog();
d->show();
}
4. 堆栈窗口QStackedWidget
通常作为独立窗口的内嵌窗口,与QListWidget进行联动。
// 添加一个item
void QListWidget::addItem(const QString & label)
// 当前页改变
void currentRowChanged(int currentRow)[signal]
// 设置当前页
void QStackedWidget::setCurrentIndex(int index)[slot]
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
// 向QListWidget添加item
ui->listWidget->addItem("蓝");
ui->listWidget->addItem("绿");
ui->listWidget->addItem("红");
// 把ListWidget和QStackedWidget联动
connect(ui->listWidget,SIGNAL(currentRowChanged(int)),
ui->stackedWidget,SLOT(setCurrentIndex(int)));
}
Dialog::~Dialog()
{
delete ui;
}
5. QMainWindow主窗口类
新建项目时选择QMainWindow。
QMainWindow是最适合作为主窗口的类型,因为其包含多个部分:
5.1 QMenuBar 菜单栏
菜单栏的组成如下所示:
菜单栏的构建可以使用Designer,也可以使用C++代码实现,但是不能混用。
相关C++函数:
// 向菜单栏添加一级菜单
// 参数为菜单的文字
// 返回值是添加的菜单对象
QMenu * QMenuBar::addMenu(const QString & title)
// 向菜单中添加动作
// 参数为动作的文字
// 返回值是添加的动作的对象
QAction * QMenu::addAction(const QString & text)
// 向菜单中添加下一级菜单
// 参数为菜单的文字
// 返回值是添加的下一级菜单对象
QMenu * QMenu:: addMenu(const QString & title)
为了使QAction点击之后有触发效果,需要使用对应的信号连接槽函数,QAction的信号函数如下:
5.2 QToolBar 工具栏
工具栏按钮往往使用菜单栏下的QAction对象,但是需要给QAction设置图标:
可通过下面的函数(C++代码)或Designer拖拽的效果设置工具栏按钮。
// 添加一个已有的QAction对象到工具栏
void QToolBar::addAction(QAction * action)
5.3 状态栏QStatusBar
QStatusBar支持自定义格式,可以添加组件:
void QStatusBar::addWidget(QWidget * widget, int stretch = 0)
普通使用可以通过下面两个槽函数进行信息的显示和消除
// 在状态栏展示信息
// 参数1 展示信息的内容
// 参数2 信息显示的时间(单位是毫秒),默认值0表示一直显示
void QStatusBar::showMessage(const QString & message, int timeout = 0)[slot]
// 清空显示
void QStatusBar::clearMessage()
dialog.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
private slots:
void actionNewTriggledSlot(); // 点击新建项目
void actionCppTriggledSlot(); // 点击hello.cpp
};
#endif // MAINWINDOW_H
dialog.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// QMenu * menuFile = ui->menuBar->addMenu("文件");
// QMenu * menuEdit = ui->menuBar->addMenu("编辑");
// // 向一级菜单中添加动作
// QAction * actionNew = menuFile->addAction("新建项目与文件");
// QAction * actionOpen = menuFile->addAction("打开文件或项目");
// // 向一级菜单中添加二级菜单
// QMenu * menuRecent = menuFile->addMenu("最近访问的文件...");
// // 向二级菜单中添加动作
// QAction * actionCpp = menuRecent->addAction("dialog.cpp");
// QAction * actionH = menuRecent->addAction("dialog.h");
connect(ui->action,SIGNAL(triggered(bool)),
this,SLOT(actionNewTriggledSlot()));
connect(ui->actionDialog_cpp,SIGNAL(triggered(bool)),
this,SLOT(actionCppTriggledSlot()));
ui->mainToolBar->addAction(ui->action_2);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::actionNewTriggledSlot()
{
ui->plainTextEdit->appendPlainText("新建了一个文档!");
ui->statusBar->showMessage("新建了一个文档!",3000);
}
void MainWindow::actionCppTriggledSlot()
{
ui->plainTextEdit->appendPlainText("打开了hello.cpp!");
}
6. 新建一个自定义窗口
自定义Qt窗口类的步骤如下:
1. 在Qt Creator选中项目名称,鼠标右键,点击“添加新文件”。
2. 在弹出的窗口中,如下所示进行操作。
3. 在弹出的窗口,选择界面模板后,点击“下一步”。
4.在弹出的窗口中,输入类名后,点击“下一步”。
5. 在项目管理界面,直接点击“完成”。可以看到新的窗口类文件就已经添加到项目中了。
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#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
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()));
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::btnClickedSlot()
{
// 创建MyDialog对象并展示
MyDialog *md = new MyDialog(this);
md->show();
// 限制按钮只能点一次
ui->pushButton->setEnabled(false);
}
7.对象传值
7.1 父对象→子对象
此处指的是Qt的Parent参数的依赖关系,并非继承关系!!!后文同。
这种情况最佳解决方案是使用C++的成员函数传参
【例】 转动紫球,绿球跟着转
7.2 子对象→父对象
【例】转动绿球,紫球跟着转
这种情况最佳的解决方案是信号槽传参,子对象发射带参数的信号函数,父对象使用带参数的槽函数接收。
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#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;
private slots:
void btnClickedSlot(); // 点击按钮的槽函数
void valueChangedSlot(int); //紫球数值改变调用的槽函数
void valueSlot(int); // 接收MyDialog对象发射的信号
};
#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);
md = new MyDialog(this);
connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(btnClickedSlot()));
connect(ui->dial,SIGNAL(valueChanged(int)),
this,SLOT(valueChangedSlot(int)));
connect(md,SIGNAL(valueSignal(int)),this,SLOT(valueSlot(int)));
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::btnClickedSlot()
{
// 创建MyDialog对象并展示
md->show();
// 限制按钮只能点一次
ui->pushButton->setEnabled(false);
}
void Dialog::valueChangedSlot(int value)
{
// 把数值传给子窗口
md->setGDialValue(value);
}
void Dialog::valueSlot(int value)
{
// 设置紫球数值
ui->dial->setValue(value);
}
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();
// 这里用public是因为父子窗口不是继承关系
void setGDialValue(int);
private:
Ui::MyDialog *ui;
signals:
void valueSignal(int); // 发射value值的信号
private slots:
void valueChangedSlot(int); // 接收绿球转动的槽函数
};
#endif // MYDIALOG_H
mydialog.cpp
#include "mydialog.h"
#include "ui_mydialog.h"
MyDialog::MyDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::MyDialog)
{
ui->setupUi(this);
connect(ui->dial,SIGNAL(valueChanged(int)),
this,SLOT(valueChangedSlot(int)));
}
MyDialog::~MyDialog()
{
delete ui;
}
void MyDialog::setGDialValue(int value)
{
ui->dial->setValue(value);
}
void MyDialog::valueChangedSlot(int value)
{
// 发射带参数的自定义信号
emit valueSignal(value);
}
8. 事件机制
事件是Qt的一个底层机制,通过层层传递,程序员可以在传递的层级中检测或处理这些时间。
本次学习主要在窗口类实现事件函数,从而检测事件的传递。利用实践的触发时间,从而实现一些特定的效果,事件函数众多,包括但不限于:
// 绘制事件
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]
事件函数的基础使用只需要在对应的类中覆盖基类的事件即可。事件函数的参数就是包含了当前事件的数据对象。
【问题】事件函数与信号槽的区别?
● 事件由具体对象进行处理
● 信号由具体对象主动产生
● 改写事件处理函数可能导致程序行为发生改变
● 信号是否存在对应的槽函数不会改变程序行为
// 绘制图片
// 参数1 横轴坐标
// 参数2 纵轴坐标
// 参数3 绘制宽度
// 参数4 绘制高度
// 参数5 绘制内容
void drawPixmap(int x, int y, int width, int height, const QPixmap & pixmap)
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QDebug>
#include <QPainter> // 画家类
#include <QKeyEvent>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private:
Ui::Dialog *ui;
protected:
void paintEvent(QPaintEvent * event);
void keyPressEvent(QKeyEvent * event);
};
#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;
}
void Dialog::paintEvent(QPaintEvent *event)
{
// 创建一个画家对象
QPainter painter(this);
QPixmap map(":/new/prefix1/bg.jpg");
// 绘制图片
// 参数1 横轴坐标
// 参数2 纵轴坐标
// 参数3 绘制宽度
// 参数4 绘制高度
// 参数5 绘制内容
painter.drawPixmap(0,0,width(),height(),map);
qDebug() << this->width() << this->height();
qDebug() << this->x() << this->y();
}
void Dialog::keyPressEvent(QKeyEvent *event)
{
if(event->key() == Qt::Key_A) // 如果按键是A
{
int value = ui->progressBar->value();
ui->progressBar->setValue(--value);
}else if(event->key() == Qt::Key_S) // 如果按键是S
{
ui->progressBar->setValue(0);
}else if(event->key() == Qt::Key_W) // 如果按键是W
{
ui->progressBar->setValue(100);
}else if(event->key() == Qt::Key_D) // 如果按键是D
{
int value = ui->progressBar->value();
ui->progressBar->setValue(++ value);
}
}