参考:
C++ GUI Programming with Qt 4, Second Edition
本地环境:
win10专业版,64位,Qt5.12
目录
- 实现效果
- 基本流程
- 逐步实操
- 1)创建和初始化子部件
- 2)把子部件放进布局中
- 3)设置tab顺序
- 4)连接信号和槽 5)实现自定义的槽
- 使用QDialogButtonBox
- 拖动绘制
- 代码
- 排错
- 设置了windowIcon但不显示
实现效果
打码的是logo。
基本流程
创建dialog的流程:
- 创建和初始化子部件;
- 把子部件放进布局中;
- 设置tab顺序;
- 连接信号和槽;
- 实现自定义的槽。
逐步实操
现在一步一步操作:
**注意:**我一开始是用Qt Creator的设计页面做的,所以截图都是设计页面,但是Qt Creator没有预览,稍微有点不方便,因此第三步我换到Qt Designer了,操作是一样的。
1)创建和初始化子部件
先新建一个dialog。
然后打开设计页面,放置几个小组件,如下图所示。不要在意对齐,后面会使用自动对齐:
各个对象的名称和所属的类如下图所示:
需要修改的属性有:
- 左侧是okButton,修改
text
为OK,设置enable
为false,设置default
为true。default表示按回车会触发。 - 右侧是cancelButton,需改
text
为cancel
然后需要设置label的buddy是lineEdit。
点击菜单栏-编辑-Edit buddies,然后左键点击label,出现箭头后拖动,连接到lineEdit上,如下图所示。
这样buddy就设置成功了。点击编辑菜单栏返回,也可以点击上方的工具条:
2)把子部件放进布局中
按住ctrl,然后依次选择label和lineEdit,单击工具条上的水平布局,此时布局成功:
然后对spacer和两个按钮做水平布局。随后,反选,单击垂直布局:
现在变成:
可以看到,窗口大小似乎偏大,点击工具条上的调整大小按钮,变成了最优尺寸:
3)设置tab顺序
设置tab顺序就是部件接受焦点(focus)的顺序,点击的是工具条上带数字的灰色按钮:
因为想要预览效果,我用Qt Designer打开了文件。
点击窗体-预览,可以看到各种风格下的效果。
windowsvista风格:
windows风格
fushion风格
那么如何套用这个格式呢?
在main.cpp中这样写:
#include <QApplication>
#include "ui_toolbasic.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Ui::toolBasic ui;
QDialog *dialog = new QDialog;
ui.setupUi(dialog);
dialog->show();
return a.exec();
}
显示效果:logo显示正确。
代码说明:
ui_toolbasic.h是前面拖动后自动产生的文件,打开可以看到很多关于布局、绘制的代码:
4)连接信号和槽 5)实现自定义的槽
要实现的效果:限制lineEdit的输入格式,要求以字母开始,后跟一个数字,再跟0-2个数字。只有满足要求时,OK按钮才生效。
main.cpp
#include <QApplication>
//#include "ui_toolbasic.h"
#include "toolbasic.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
toolBasic* tb = new toolBasic;
tb->show();
return a.exec();
}
toolbasic.h
#ifndef TOOLBASIC_H
#define TOOLBASIC_H
#include <QDialog>
// 增加ui这一行,第一步生成form时是没有的
#include "ui_toolbasic.h"
namespace Ui {
class toolBasic;
}
// 声明
class QWidget;
class toolBasic : public QDialog, public Ui::toolBasic
{
Q_OBJECT
public:
//explicit toolBasic(QWidget *parent = nullptr);
// 注释掉自动生成的构造函数,重写一个
toolBasic(QWidget *parent = 0);
~toolBasic();
private:
Ui::toolBasic *ui;
// 新增槽函数
private slots:
void on_lineEdit_textChanged();
};
#endif // TOOLBASIC_H
toolBasic.cpp
需要注意的是, setupUi()会自动连接一些槽函数,只要槽函数满足格式:on_objectName_signalName()
,也就是会蒋objectName
和signalName()
连接起来,不用另外写。
因此,上面新增了槽函数on_lineEdit_textChanged()等于执行到setupUi()时,自动实现了这个连接:
connect(lineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(on_lineEdit_textChanged()));
所以只需要实现这个槽函数,就能实现lineEdit内容改变后的自动处理过程。
#include "toolbasic.h"
#include <QRegularExpressionValidator>
#include <QWidget>
toolBasic::toolBasic(QWidget *parent) :
QDialog(parent),
ui(new Ui::toolBasic)
{
// setupUi()会自动连接一些槽函数,只要槽函数满足格式:on_objectName_signalName()
setupUi(this);
// 要求:以字母开头,后跟一个数字(1-9),然后跟0-2个数字(0-9)
QRegularExpression regExp("[A-Za-z][1-9][0-9]{0,2}");
lineEdit->setValidator(new QRegularExpressionValidator(regExp, this));
// 把okButton连到QDialog::accept()槽函数.
// accept()关闭对话框,但是设置dialog的结果是QDialog::Accepted,也就是1
connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
// 把cancelButton连到QDialog::reject()
// reject()也关闭对话框,但是设置结果为QDialog::Rejected,也就是0
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
}
toolBasic::~toolBasic()
{
delete ui;
}
void toolBasic::on_lineEdit_textChanged() {
// lineEdit有合法输入时,开启ok按钮
okButton->setEnabled(lineEdit->hasAcceptableInput());
}
使用QDialogButtonBox
效果:
在创建界面时选择:Dialog with Buttons Bottom,起名myDialog。 (不要用这个,会报错)diyDialog。
拖动绘制
与前面相似,就是两个button变成了一个buttonBox。如果需要特殊一点的对齐,需要把预先出现在面板上的buttonBox删掉,不然spacer是放不好的。如果不删的话,上面两个connect也是自动实现了的,不用写。
另外,调整最佳尺寸的按钮会失效,需要手动调整尺寸。(自动的会很小,因为只有两个小组件)
代码
diydialog.h和main.cpp跟前面类似,不再重复。diydialog.cpp需要做一点修改:
#include <QRegularExpressionValidator>
#include <QWidget>
#include <QPushButton>
#include <QDialogButtonBox>
#include "diydialog.h"
diyDialog::diyDialog(QWidget *parent) :
QDialog(parent)
{
setupUi(this);
QRegularExpression regExp("[A-Za-z][1-9][0-9]{0,2}");
lineEdit->setValidator(new QRegularExpressionValidator(regExp, this));
// 这里需要修改
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
}
diyDialog::~diyDialog()
{
delete ui;
}
void diyDialog::on_lineEdit_textChanged(){
// 修改
buttonBox->button(QDialogButtonBox::Ok)->setEnabled(
lineEdit->hasAcceptableInput());
}
注意,如果buttonBox->button
这里提示invalid use of incomplete type 'class QPushButton'
,可能是没有引入<QPushButton>
的原因,include上就解决了。
排错
设置了windowIcon但不显示
可能有问题的地方:
-
前缀写错
-
使用了错误的文件格式
icon不支持ico格式,换成jpg或者png即可。 -
使用拖动方式,在designer中设置icon时,要选
选择资源
,不要选选择文件
!!
-
图片文件的路径写错
在这篇文章里qt5-入门-信号槽理解+QMainWindow,我的路径是这样写的:openAction->setIcon(QIcon(":/pic.jpg"));
,但是我现在把文件放到专门的文件夹下了,文件结构如下图:
如果直接写:/resources/img/xxx_logo.png
,其实是访问不到的。更简单的方法是editor中查看res.qrc,右键复制path,可以看到复制结果是:://resources/img/xxx_logo.png
,然后直接在代码里写:this->setWindowIcon(QIcon("://resources/img/xxx_logo.png"));