qt5-入门-使用拖动方式创建Dialog

参考:

C++ GUI Programming with Qt 4, Second Edition

本地环境:

win10专业版,64位,Qt5.12


目录

实现效果

打码的是logo。

基本流程

创建dialog的流程:

  1. 创建和初始化子部件;
  2. 把子部件放进布局中;
  3. 设置tab顺序;
  4. 连接信号和槽;
  5. 实现自定义的槽。

逐步实操

现在一步一步操作:

**注意:**我一开始是用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中这样写:

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

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

cpp 复制代码
#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(),也就是会蒋objectNamesignalName()连接起来,不用另外写。

因此,上面新增了槽函数on_lineEdit_textChanged()等于执行到setupUi()时,自动实现了这个连接:
connect(lineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(on_lineEdit_textChanged()));

所以只需要实现这个槽函数,就能实现lineEdit内容改变后的自动处理过程。

cpp 复制代码
#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需要做一点修改:

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但不显示

可能有问题的地方:

  1. 前缀写错

  2. 使用了错误的文件格式

    icon不支持ico格式,换成jpg或者png即可。

  3. 使用拖动方式,在designer中设置icon时,要选选择资源,不要选选择文件!!

  4. 图片文件的路径写错

    在这篇文章里qt5-入门-信号槽理解+QMainWindow,我的路径是这样写的:openAction->setIcon(QIcon(":/pic.jpg"));,但是我现在把文件放到专门的文件夹下了,文件结构如下图:

    如果直接写:/resources/img/xxx_logo.png,其实是访问不到的。更简单的方法是editor中查看res.qrc,右键复制path,可以看到复制结果是:://resources/img/xxx_logo.png,然后直接在代码里写:

    cpp 复制代码
    this->setWindowIcon(QIcon("://resources/img/xxx_logo.png"));
相关推荐
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner2 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz7 天前
QML Hello World 入门示例
qt
xcyxiner10 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner11 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner11 天前
DicomViewer (添加模型类)3
qt
xcyxiner12 天前
DicomViewer (目录调整) 2
qt
xcyxiner12 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
桥田智能14 天前
桥田智能 QT-650S:面向白车身焊装的 800kg 重载快换解决方案
开发语言·qt·系统架构
森G14 天前
75、服务器源码解析---------云视频服务项目
linux·服务器·网络·c++·qt