11.2 QDialog 多窗口使用
本节介绍 QDialog 类内容,并使用 QDialog 派生类实现多窗口使用,子窗口可以采用模态对话框显示,也可以使用非模态对话框显示。
11.2.1 QDialog 类
QDialog 是所有对话框(**Dialog)类的基类,之前章节使用的 QFileDialog 和 QMessageBox 都是 QDialog
派生类,本章后面会学习更多的 Qt 通用对话框。
QDialog
及其派生类总是顶层窗口,而不会作为窗口内嵌子控件存在。对话框通常用于短期任务,并简要与用户进行交互信息。对话框可以是模态的,也可以是非模态的。对话框可以提供返回
值,也可以设置默认按钮(界面按 Enter 回车键,就等于点击默认按钮)。
对话框与其父类 QWidget 窗口的标题栏外观不同, QWidget
窗口标题栏右上角是最小化、最大化和关闭三个按钮,而对话框标题栏右上角是帮助按钮和关闭按 钮,如下图所示:
点击标题栏的帮助按钮,鼠标变成问号鼠标形式,再点击对话框子控件,就会显示子控件的 whatsThis 属性,就是子控件的帮助信息,例如 Haha
按钮的帮助信息:
对话框的标题栏没有最小化、最大化按钮,但是尺寸可以拉动边框改变。默认情况下,对话框右下角不会显示尺寸手柄(QSizeGrip,就是上图右下角 的三角形图
案,6个小点构成),可以通过调用 setSizeGripEnabled(bool) 函数设置是否显示尺寸手柄。
QDialog 类构造函数如下:
QDialog(QWidget * parent = 0,
Qt::WindowFlags f = 0)
QDialog 对话框以及其他窗口类 flags 标志位包含 Qt::Dialog 标志的窗口,总是以顶层窗口显示,而不会作为子控件。QDialog
对话框的 parent 指针如果为 NULL,那么它以桌面为背景,以桌面中心为参考弹出显示;parent
指针为其他窗口,那么以父窗口为背景,以父窗口中心为参考弹出显示。使用 setParent() 函数可以更改对话框的归属父窗口。
QDialog 作为模态对话框时,会强制占据前台焦点,不关闭模态对话框,就无法回到父窗口操作。模态对话框通常使用下面函数弹窗:
int QDialog::exec()
//槽函数,应用程序级的模态显示,带有返回值
void QDialog::open() // 槽函数,窗口级别的模态显示,这个函数没有返回值
通常使用 exec() 函数的情况更多,exec() 弹窗关闭时,会返回一个数值供父窗口判断。常见的对话框返回值如下:
QDialog::Accepted ,数值为 1 ;
QDialog::Rejected ,数值为 0 。
通常调用下面槽函数时,自动关闭模态对话框,并设置相应结果值:
void QDialog::accept()
//槽函数,设置结果值为 1,exec() 返回该数值
void QDialog::reject() //槽函数,设置结果值为
0,exec() 返回该数值
void QDialog::done(int r) //槽函数,设置结果值为 r ,exec() 返回该数值
除了 exec() 能够获取返回的结果值,对话框也可以用下面函数获取或者修改返回值:
int QDialog::result() //获取结果数值
void QDialog::setResult(int i) //设置结果数值
对话框有三个信号,与关闭对话框的槽函数有关:
void QDialog::accepted() //当调用 accept()
或 done() 或用户有接受操作,并且结果值为 QDialog::Accepted 时触发该信号
void QDialog::rejected() //当调用 reject() 或
done() 或用户有拒绝操作,并且结果值为 QDialog::Rejected 时触发该信号
void QDialog::finished(int result) //当调用 done(), accept(),
reject() 或用户有结束操作,结果值已设置时触发该信号
上面三个信号主要根据对话框 done(), accept(), reject()
三个槽函数触发,如果按钮关联到这三个槽函数,用户点击了按钮,也会触发这些信号。但是函数 hide() 和 setVisible(false)
不会触发上面信号。
返回值一般用于模态对话框,模态对话框强制占据前台焦点,使得用户必须有反馈操作,操作关闭对话框之后,形成接受或拒绝的返回值,再回到父窗口。
实际应用中,如果需要长时间处理某些任务,可以使用 QProgressDialog 进度对话框,进度对话框的模态显示与其他对话框不同,通常使用下面的函数:
void setModal(bool modal)
//一般用于长时间进度对话框模态显示
将 setModal( true ) 和 show() 函数配合使用,也是显示模态对话框。
如果使用非模态的对话框,就不会强制占据前台焦点,非模态对话框和父窗口可以自由切换,非模态对话框显示直接使用 show() 或 setVisible()
函数:
void QDialog::setVisible(bool visible)
void QWidget::show() //基类显示函数
QDialog 对话框有两个特殊按键,就是键盘上的 Enter 键和 Esc 键:
① 当使用 QPushButton::setDefault(), QPushButton::isDefault() 和
QPushButton::autoDefault() 设置默认按钮后, Enter 键会自动触发默认按钮的点击操作。
② 对话框界面 Esc 按键总是触发 QDialog::reject() 槽函数,这是内定的特性,在任何对话框界面按 Esc
键都会关闭对话框,并且设置 QDialog::Rejected 结果值。
QDialog 类的内容介绍到这,下面我们通过一个示例,为一个主窗口新建两个子对话框。
11.2.2 QDialog 多窗口示例
我们编写一个图片预览例子,新建两个子对话框, 使用一个非模态对话框进行图片缩放,使用另一个模态对话框进行图片旋转,模态对话框返回值就是旋转度数。
我们打开 QtCreator,新建一个 Qt Widgets Application 项目,在新建项目的向导里填写:
①项目名称 imagetransform,创建路径 D:\QtProjects\ch11,点击下一步;
②套件选择里面选择全部套件,点击下一步;
③基类选择 QWidget,注意修改主窗口类名为 ImageTransformWidget,这
样与后续的子窗口类名作区分,然后点击下一步;
④项目管理不修改,点击完成。
主窗口类名为 ImageTransformWidget,对应的界面文件、头文件、源文件名就是
imagetransformwidget.ui、imagetransformwidget.h、imagetransformwidget.cpp 。
接下来我们在项目管理器右击项目根 imagetransform,右键菜单选择“添加新文件...”,进入新建文件对话框:
上图左边一栏选择“Qt”,中间一栏选择“Qt设计师界面类”,点击“Choose...”按钮,进入界面类模板选择:
在中间一栏上面选择“Dialog without Buttons”模板,点击“下一步”按钮,进入类名的编辑:
我们将类名修改为 ResizeImageDialog,点击“下一步”按钮,进入项目管理界面:
点击“完成”按钮,这样就为项目新增了 ResizeImageDialog 对话框类,头文件、源文件、界面文件都添加到了项目里面。新建该类后,先关闭 ui
设计界面,我们回到 QtCreator 编辑界面。
我们重新在项目管理器右击项目根 imagetransform,右键菜单选择“添加新文件...”,按照上面流程,添加“Dialog without
Buttons”模板的对话框,对话框类名为 RotateImageDialog,也完成该对话框的新建。这样
项目就有三套窗口类文件,一套是 主窗口类,另外两套是 ResizeImageDialog 和 RotateImageDialog 对话框类。
下面我们从主窗口界面开始编辑,打开 imagetransformwidget.ui,拖入控件:
界面左边是一个滚动区域 scrollArea,右侧是三个按钮,“打开图片”按钮 pushButtonOpen,“缩放图片”按钮
pushButtonResize,“旋转图片”按钮 pushButtonRotate 。
界面首先将右侧三个按钮选中,进行垂直布局;
然后在右边对象树选择根 ImageTransformWidget,点击水平布局按钮,就完成窗口整体布局,窗口尺寸是默认的 400*300。
完成布局后,我们依次右击三个按钮,为按钮添加 clicked() 信号对应的槽函数,这样就有三个槽函数添加到主窗口类里面。我们保存并关闭
imagetransformwidget.ui 。
我们打开 resizeimagedialog.ui 文件,进行缩放尺寸对话框界面编辑,拖入控件:
对话框第一行是标签“现在的尺寸”,单行编辑器 lineEditOldSize。
第二行是标签“宽度×高度”,旋钮框 spinBoxWidthNew,旋钮框 spinBoxHeightNew,“设置新尺寸”按钮
pushButtonSetNewSize 。
选中两个旋钮框,将它们的 sizePolicy 属性中的水平策略改为 Expanding 。
第一行控件采用水平布局器排布;第二行也是采用水平布局器排布;
然后选择对象树根 ResizeImageDialog,点击垂直布局按钮,窗口整体采用垂直布局,窗口大小修改为 320*200 。
我们右击“设置新尺寸”按钮,为按钮添加 clicked() 信号对应的槽函数。完成这些编辑后,我们保存并关闭 resizeimagedialog.ui
文件。
下面我们编辑第三个界面文件 rotateimagedialog.ui,就是旋转图片对话框,拖入控件:
只有一行控件,标签“顺时针旋转角度”,旋钮框 spinBoxAngle,“执行旋转”按钮 pushButtonRotating。
选中旋钮框 spinBoxAngle,修改它的 sizePolicy 属性中的水平策略为 Expanding。
在右边选中对象树根 RotateImageDialog,点击上面的水平布局按钮,就完成了窗口整体布局。
窗口的大小修改为 320*100。
然后我们右击“执行旋转”按钮,为按钮添加 clicked() 信号对应的槽函数。
完成这些操作后,我们保存并关闭 rotateimagedialog.ui 界面文件。
对于缩放图片对话框,使用非模态显示,与主窗口采用信号和槽函数通信:
对于旋转图片对话框,使用模态显示,我们调用 exec() 函数后,该函数直接返回需要旋转的角度,不需要信号和槽函数进行通信。exec()
属于子对话框的公有函数,对话框的 result() 和 setResult(int i) 函数也可以进行数据传递。
信号和槽函数机制可以传输数据,成对的读写公有函数也可以传递数据,都是多个窗口之间可行的通信方式。
模态对话框都是短时间强制占据前台获取用户输入,得到用户输入后就关闭对话框,模态对话框不会长时间显示。模态对话框弹出一次就是获取一次性数据,因
此使用公有函 数方式更简洁。Qt 的通用对话框通常都是模态对话框,一次性获取输入数据并返回结果信息。
信号和槽函数机制更有利于模块的独立性,就是松耦合设计。比如主窗口调用子窗口公有函数比较合理,但是如果同时子窗口又需要调用父窗口
函数,那么交
叉调用函数就使得父窗口模块与子窗口模块互相依赖,子窗口就难以单独使用,失去了独立性。如果子窗口发射信号,由信号去触发父窗口的槽函数,那么子窗口就脱离了交
叉依赖,可以作为独立模块,对移植到其他项目使用更为有利。
下面我们开始编辑代码,先打开主窗口的头文件 imagetransformwidget.h,编辑代码如下:
#ifndef
IMAGETRANSFORMWIDGET_H
#define IMAGETRANSFORMWIDGET_H
#include <QWidget>
#include <QLabel>
#include <QPixmap> //图片操作类
#include <QFileDialog> //文件选择对话框
#include <QMatrix> //变换矩阵类
#include "resizeimagedialog.h" //缩放尺寸对话框
#include "rotateimagedialog.h" //旋转图片对话框
namespace Ui {
class ImageTransformWidget;
}
class ImageTransformWidget : public QWidget
{
Q_OBJECT
public:
explicit ImageTransformWidget(QWidget *parent = 0);
~ImageTransformWidget();
signals:
//发送旧的宽度高度给子对话框
void SendOldSize(int nOldWidth, int nOldHeight);
private slots:
void on_pushButtonOpen_clicked();
void on_pushButtonResize_clicked();
void on_pushButtonRotate_clicked();
//收到新尺寸后进行缩放
void RecvNewSizeAndResize(int nNewWidth, int nNewHeight);
private:
Ui::ImageTransformWidget *ui;
//图片显示的标签
QLabel *m_pLabelImage;
//图片操作类
QPixmap m_image;
//图片文件名
QString m_strFileName;
//缩放尺寸对话框
ResizeImageDialog *m_pResizeDlg;
//旋转图片对话框
RotateImageDialog *m_pRotateDlg;
//初始化函数
void Init();
};
#endif // IMAGETRANSFORMWIDGET_H
我们为头文件添加了多个类包含:
QLabel 用于显示图片,QPixmap用于打开图片文件,保存图片内容,QFileDialog 用于选择图片文件名,QMatrix 是变换矩阵,用于旋转图片,然后是两个子对话框的头文件包含。
我们为主窗口类添加了信号 SendOldSize(int nOldWidth, int nOldHeight),用于给缩放图片对话框传递图片旧尺寸。
在三个按钮槽函数之后,我们手动添加了一个槽函数 RecvNewSizeAndResize(int nNewWidth, int nNewHeight),用于从缩放图片对话框接收新的尺寸,并进行实际的图片缩放操作。
添加了 m_pLabelImage,保存显示图片的标签对象;
m_image 就是图片对象内容;
m_strFileName 保存打开的文件名;
m_pResizeDlg 是缩放尺寸的子对话框;
m_pRotateDlg 是旋转图片的子对话框;
最后是用于对话框初始化的函数 Init() 。
下面我们分段编辑主窗口的源文件 imagetransformwidget.cpp,首先是构造函数和初始化部分:
#include "imagetransformwidget.h"
#include "ui_imagetransformwidget.h"
#include <QDebug>
#include <QMessageBox>
ImageTransformWidget::ImageTransformWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::ImageTransformWidget)
{
ui->setupUi(this);
//初始化
Init();
}
ImageTransformWidget::~ImageTransformWidget()
{
delete m_pResizeDlg; m_pResizeDlg = NULL;
delete m_pRotateDlg; m_pRotateDlg = NULL;
delete ui;
}
//初始化函数
void ImageTransformWidget::Init()
{
//新建标签对象
m_pLabelImage = new QLabel();
//标签内容对齐方式,左上角对齐
m_pLabelImage->setAlignment( Qt::AlignLeft | Qt::AlignTop );
m_pLabelImage->setStyleSheet( "background-color: lightgray;" ) ;
//把标签设置给滚动区域,该标签隶属于滚动区域,滚动区域销毁时,也销毁该标签
ui->scrollArea->setWidget(m_pLabelImage);
//新建缩放尺寸对话框
m_pResizeDlg = new ResizeImageDialog(this);
//主窗口发送旧尺寸给子对话框
connect(this, SIGNAL(SendOldSize(int,int)),
m_pResizeDlg, SLOT(RecvOldSize(int,int)) );
//子对话框发送新尺寸给主窗口
connect(m_pResizeDlg, SIGNAL(SendNewSize(int,int)),
this, SLOT(RecvNewSizeAndResize(int,int)) );
//新建旋转图片对话框
m_pRotateDlg = new RotateImageDialog(this);
//模态对话框,要求用户输入角度后,由 exec() 函数返回角度,不需要信号和槽传递
//使用子窗口的公有函数也可以进行数据传递
}
构造函数里面添加了 Init() 函数调用,析构函数里面删除了新建的两个子对话框。
Init() 函数里面,新建了标签存到 m_pLabelImage,并设置内容显示对齐为左上角对齐,设置背景色为浅灰色,然后把标签设置给滚动区域对象,由滚动区域对象负责管理和显示标签。
然后新建了缩放图片对话框 m_pResizeDlg,并将缩放图片对话框和主窗口的信号、槽函数关联,主窗口发送旧尺寸给子对话框,子对话框将新尺寸发给主窗口。
然后新建了旋转图片子对话框 m_pRotateDlg ,这个模态对话框用 exec() 函数返回旋转角度值。
接下来我们编辑“打开图片”按钮对应的槽函数:
//打开图片
void ImageTransformWidget::on_pushButtonOpen_clicked()
{
//获取图片文件名
QString strFile = QFileDialog::getOpenFileName(this, tr("打开图片文件"),
tr(""), tr("Image files(*.png *.jpg *.bmp)"));
if( strFile.isEmpty() )
{
return; //没有文件名
}
//正常图片
bool bLoadOK = m_image.load( strFile );
if( ! bLoadOK )
{
QMessageBox::warning(this, tr("加载图片文件"), tr("加载图片文件失败,请检查文件格式。"));
return;
}
//加载正常,保存文件名
m_strFileName = strFile;
//将新图片设置给标签显示
m_pLabelImage->setPixmap( m_image );
//窗口标题栏设置为文件名
setWindowTitle( tr("预览文件为 %1").arg(m_strFileName) );
}
我们使用 QFileDialog 类的静态函数获取要打开的文件名,存到 strFile;
判断 strFile 如果为空就返回,不操作;如果不为空就进行后面操作。
使用 m_image.load( strFile ) 尝试加载图片内容,如果返回值为 false,加载失败,就弹窗提示加载失败,返回。
如果加载成功,保存文件名到 m_strFileName;
将图片对象设置给 m_pLabelImage,显示图片内容;
并在窗口标题栏显示预览的文件名。
接下来编辑“缩放图片”按钮对应的槽函数:
//缩放图片
void ImageTransformWidget::on_pushButtonResize_clicked()
{
if( m_image.isNull() ) //没有图片
{
return;
}
//有图片时,发送旧尺寸给子对话框
emit SendOldSize(m_image.width(), m_image.height());
//显示子对话框
m_pResizeDlg->show();
m_pResizeDlg->raise();
}
函数先判断 m_image 对象内容,如果为空就返回;
如果图片内容不为空,那么触发 SendOldSize() 信号,将现有图片的宽度、高度发给子对话框;
调用 m_pResizeDlg 的 show() 和 raise() 显示该对话框,并放到顶层显示。
将旧尺寸发送给缩放图片对话框之后,用户在子对话框操作,设置的新尺寸会由子对话框发回给主窗口,这时候槽函数 RecvNewSizeAndResize() 接收新尺寸,
并进行实际的缩放操作,如下面代码所示:
//收到新尺寸后进行缩放
void ImageTransformWidget::RecvNewSizeAndResize(int nNewWidth, int nNewHeight)
{
//如果尺寸没变,直接返回
if( (m_image.width() == nNewWidth) &&
(m_image.height() == nNewHeight) )
{
return;
}
//缩放到新尺寸
QPixmap imgNew = m_image.scaled(nNewWidth, nNewHeight);
//存到成员变量
m_image = imgNew;
//显示新图片
m_pLabelImage->setPixmap( m_image );
}
该函数先判断新尺寸是否与原先尺寸一样大,如果是一样的就返回,不需要操作。
如果尺寸发生了变化,那么使用 m_image.scaled(nNewWidth, nNewHeight) 缩放尺寸,形成新图片 imgNew ;然后把 imgNew 复制给成员变量 m_image;
最后将缩放后的新图片 m_image 设置给标签对象进行显示。
接下来我们编辑“旋转图片”按钮对应的槽函数:
//旋转图片
void ImageTransformWidget::on_pushButtonRotate_clicked()
{
if( m_image.isNull() ) //没有图片
{
return;
}
int nAngle = m_pRotateDlg->exec();
if( 0 == nAngle )
{
return; // 没旋转
}
//旋转变换矩阵
QMatrix mxRotate;
mxRotate.rotate( nAngle );
//执行旋转变换
QPixmap imgNew = m_image.transformed( mxRotate );
//保存到成员
m_image = imgNew;
//显示
m_pLabelImage->setPixmap(m_image);
}
该函数首先检查 m_image 图片是否为空,为空就返回,不处理。
图片对象非空时,显示模态对话框 m_pRotateDlg->exec(),返回值就是需要旋转的角度,存到 nAngle;
判断角度是否为 0 度,如果是 0 度就返回,不需要旋转。
如果不是 0 度,定义变换矩阵 mxRotate,操作其按照 nAngle 角度旋转,得到旋转图片需要的矩阵;
然后调用 m_image.transformed( mxRotate ) ,让图片按照矩阵进行旋转变换,结果就是将图片顺时针旋转 nAngle 角度。将旋转后的图片保存到 m_image。
最后把新图片 m_image 设置给标签显示。
主窗口的代码介绍完了,
下面我们编辑缩放图片的对话框头文件 resizeimagedialog.h :
#ifndef RESIZEIMAGEDIALOG_H
#define RESIZEIMAGEDIALOG_H
#include <QDialog>
namespace Ui {
class ResizeImageDialog;
}
class ResizeImageDialog : public QDialog
{
Q_OBJECT
public:
explicit ResizeImageDialog(QWidget *parent = 0);
~ResizeImageDialog();
signals:
//发送新的尺寸给主窗口,由主窗口完成缩放
void SendNewSize(int nNewWidth, int nNewHeight);
private slots:
void on_pushButtonSetNewSize_clicked();
//接收图片旧尺寸并显示
void RecvOldSize(int nOldWidth, int nOldHeight);
private:
Ui::ResizeImageDialog *ui;
//初始化函数
void Init();
};
#endif // RESIZEIMAGEDIALOG_H
我们为该对话框添加信号 SendNewSize(int nNewWidth, int nNewHeight),用于发送新尺寸给主窗口。
在按钮槽函数之后,手动添加了槽函数 RecvOldSize(int nOldWidth, int nOldHeight),用于从主窗口接收旧的图片尺寸。类声明末尾添加了初始化函数 Init() 。
下面我们分段编辑缩放图片对话框的源文件 resizeimagedialog.cpp,
首先是构造函数和初始化内容:
#include "resizeimagedialog.h"
#include "ui_resizeimagedialog.h"
ResizeImageDialog::ResizeImageDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::ResizeImageDialog)
{
ui->setupUi(this);
//初始化
Init();
}
ResizeImageDialog::~ResizeImageDialog()
{
delete ui;
}
//初始化函数
void ResizeImageDialog::Init()
{
//旧尺寸编辑器设置为只读
ui->lineEditOldSize->setReadOnly(true);
ui->lineEditOldSize->setStyleSheet( "background-color: lightgray;" );
//限定新的宽度高度数值范围
ui->spinBoxWidthNew->setRange(1, 10000);
ui->spinBoxHeightNew->setRange(1, 10000);
//设置标题栏
setWindowTitle(tr("缩放图片尺寸"));
}
构造函数添加了初始化函数调用。
Init() 函数先设置旧尺寸单行编辑器为只读,并设置背景色为浅灰色。
然后设置宽度旋钮框和高度旋钮框的数值范围 1 到 10000;
设置窗口标题栏文本为 "缩放图片尺寸" 。
接下来我们编辑接收旧尺寸的槽函数:
//接收图片旧尺寸并显示
void ResizeImageDialog::RecvOldSize(int nOldWidth, int nOldHeight)
{
//构造旧尺寸字符串并显示
QString strOldSize = tr("%1 X %2").arg(nOldWidth).arg(nOldHeight);
ui->lineEditOldSize->setText( strOldSize );
//把两个旋钮框默认值改为现在的数值
ui->spinBoxWidthNew->setValue(nOldWidth);
ui->spinBoxHeightNew->setValue(nOldHeight);
}
从主窗口收到旧的尺寸后,我们构造旧尺寸字符串,并显示到单行编辑器 ui->lineEditOldSize ;
并把旧的宽度和高度设置给宽度旋钮框、高度旋钮框,方便用户根据旧尺寸调整新尺寸。
接下来我们编辑“设置新尺寸”按钮对应的槽函数:
//设置新尺寸,交给主窗口完成缩放
void ResizeImageDialog::on_pushButtonSetNewSize_clicked()
{
int nNewWidth = ui->spinBoxWidthNew->value();
int nNewHeight = ui->spinBoxHeightNew->value();
//触发信号
emit SendNewSize(nNewWidth, nNewHeight);
//更新尺寸字符串
QString strSize = tr("%1 X %2").arg(nNewWidth).arg(nNewHeight);
ui->lineEditOldSize->setText( strSize );
}
用户编辑好新的尺寸后,点击“设置新尺寸”按钮就会触发上面槽函数。
槽函数获取新的宽度、高度,并触发信号 SendNewSize(nNewWidth, nNewHeight),从而让主窗口完成实际的缩放图片操作。
之后我们将新的宽度、高度显示到对话框上面的单行编辑器,与新图片的尺寸同步。
这个对话框是非模态显示,用户可以在对话框界面连续多次缩放图片尺寸,主窗口进行实际的缩放操作,主窗口与子对话框始终保持同步操作。
最后我们编辑旋转图片对话框的代码,头文件 rotateimagedialog.h 内容如下:
#ifndef ROTATEIMAGEDIALOG_H
#define ROTATEIMAGEDIALOG_H
#include <QDialog>
namespace Ui {
class RotateImageDialog;
}
class RotateImageDialog : public QDialog
{
Q_OBJECT
public:
explicit RotateImageDialog(QWidget *parent = 0);
~RotateImageDialog();
private slots:
void on_pushButtonRotating_clicked();
private:
Ui::RotateImageDialog *ui;
//初始化函数
void Init();
};
#endif // ROTATEIMAGEDIALOG_H
这个模态对话框内容更简单,角度数值通过基类的 exec() 函数传递,不需要自定义函数来传递信息。在类声明末尾添加了一个初始化函数 Init(),其他代码是自动生成的。
旋转图片对话框的源文件 rotateimagedialog.cpp 内容也很简单,该源文件的全部内容如下:
#include "rotateimagedialog.h"
#include "ui_rotateimagedialog.h"
RotateImageDialog::RotateImageDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::RotateImageDialog)
{
ui->setupUi(this);
//初始化函数
Init();
}
RotateImageDialog::~RotateImageDialog()
{
delete ui;
}
//初始化函数
void RotateImageDialog::Init()
{
//一圈的范围
ui->spinBoxAngle->setRange(0, 360);
ui->spinBoxAngle->setSuffix( tr("°") ); //单位:度
//设置标题栏
setWindowTitle(tr("旋转图片"));
}
//执行旋转
void RotateImageDialog::on_pushButtonRotating_clicked()
{
int nAngle = ui->spinBoxAngle->value();
done(nAngle); //角度由 exec() 返回
}
构造函数里面添加了初始化函数 Init() 调用。
Init() 函数先设置角度旋钮的数值范围 0 到 360 度,并设置数值单位后缀为 "°" ;
设置标题栏文本为 "旋转图片" 。
“执行旋转”按钮的槽函数代码也非常简单,从角度旋钮框获取数值,然后调用对话框 done(nAngle) 函数,这个函数会关闭模态对话框,并设置 exec() 结果值为 nAngle 。主窗口获得角度值后进行实际的旋转操作。
该项目全部代码讲解完了,我们生成项目,运行示例,并打开一个图片文件:
点击“缩放图片”按钮,弹出非模态对话框:
原始尺寸200*200,我们把宽度修改为 300,高度不变,点击“设置新尺寸”按钮:
可以看到主窗口图片拉伸到 300*200 尺寸了,明显变宽了。
我们在缩放图片对话框界面按 Esc 键,该对话框就关闭了,回到主窗口。
我们在主窗口点击“旋转图片”按钮,弹出模态对话框:
我们设置角度 90 度,点击“执行旋转”按钮,模态对话框自动关闭,并且主窗口做出相应角度的旋转:
示例的内容讲解到这,我们下一节开始学习 Qt 自带的各种功能对话框。