Qt:在C++应用程序中使用Qt Designer UI文件

1059 篇文章 274 订阅

Qt设计器UI文件以xml格式表示表单的小部件树。可以处理窗体:

  • 在编译时间,这意味着窗体转换为可编译的C++代码
  • 在运行时间,这意味着窗体由QUiLoader类处理,该类在解析XML文件时动态构建小部件树

编译时间窗体处理

使用Qt Designer创建用户界面组件,并使用Qt的集成构建工具qmakeuic在应用程序构建时为它们生成代码。生成的代码包含窗体的用户界面对象。它是一个C++结构,包含:

  • 指向窗体小部件、布局、布局项、按钮组和操作的指针。
  • 一个名为setupUi()的成员函数,用于在父小部件上构建小部件树。
  • 一个名为retranslateUi()的成员函数,用于处理窗体的字符串属性的转换。

生成的代码可以包含在您的应用程序中并直接使用。或者,您可以使用它来扩展标准小部件的子类。

编译时间处理窗体可以在您的应用程序中使用,方法如下:

  • 直接方法:构建一个小部件,用作组件的占位符,并在其内部设置用户界面
  • 单一继承方法:将窗体的基类(例如QWidget或QDialog)子类划分为子类,并包含表单用户界面对象的私有实例。
  • 多重继承方法:您将窗体的基类和表单的用户界面对象分为子类。这允许窗体中定义的小部件直接从子类的范围内使用。

为了演示,我们创建了一个简单的计算器表单应用程序。它基于原始计算器表单示例。

该应用程序由一个源文件main.cpp和一个 UI 文件组成

使用Qt 设计器设计的文件calculatorform.ui如下所示:
在这里插入图片描述
我们将用于构建可执行文件,因此我们需要编写文件:qmake.pro

HEADERS     = calculatorform.h

此文件的特殊功能是FORMS声明,它告诉qmake使用uic处理哪些文件。在这种情况下calculatorform.ui文件用于创建ui_calculatorform.h文件,该文件可由SOURCES声明中列出的任何文件使用。

注意:您可以使用Qt Creator创建计算器窗体项目。它会自动生成main.cpp,UI和.pro文件,然后可以修改这些文件。

直接方法

  • ui_calculatorform.h直接引入main.cpp
#include "ui_calculatorform.h"

main函数通过构造一个标准的QWidget来创建计算器小部件,我们用它来承载calculatorform.ui文件。

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWidget widget;
    Ui::CalculatorForm ui;
    ui.setupUi(&widget);

    widget.show();
    return app.exec();
}

此时,Ui::CalculatorFormui_calculatorform.h文件中的接口描述对象,它用于设置对话框的所有小部件以及其信号和槽之间的连接

直接方法提供了在应用程序中使用简单、自成一体的组件的快速简便方法。但是,使用Qt Designer创建的组件通常需要与应用程序代码的其余部分紧密集成。例如,上面提供的代码将进行编译和运行,但QSpinBox对象不会与QLabel交互,因为我们需要一个自定义插槽来执行添加操作并在QLabel中显示结果。为了实现这一目标,我们需要采用单一的继承方法。

单一继承方法

为了使用单一继承方法,我们对标准Qt小部件进行子类化,并包含表单用户界面对象的私有实例。这可以采取以下形式:

  • 成员变量
  • 指针成员变量

使用成员变量

在这种方法中,我们将Qt小部件实例化,并从构造函数中设置用户界面。以这种方法使用的组件将窗体使用的小部件和布局公开给Qt小部件子类,并提供一个标准系统,用于在用户界面和应用程序中的其他对象之间建立信号和槽连接,生成的Ui::CalculatorForm 是类的成员

此方法用于计算器表单示例。

为了确保可以使用用户界面,我们需要在引用Ui::CalculatorForm之前包含uic生成的头文件:

#include "ui_calculatorform.h"

这意味着.pro文件必须更新以包含calculatorform.h:

HEADERS     = calculatorform.h

子类的定义方式如下:

class CalculatorForm : public QWidget
{
    Q_OBJECT

public:
    explicit CalculatorForm(QWidget *parent = nullptr);

private slots:
    void on_inputSpinBox1_valueChanged(int value);
    void on_inputSpinBox2_valueChanged(int value);

private:
    Ui::CalculatorForm ui;
};

类的重要特征是私有ui对象,它提供用于设置和管理用户界面的代码

子类的构建函数通过调用ui对象setupUi函数来构造和配置对话框的所有小部件和布局。完成后,可以根据需要修改用户界面

CalculatorForm::CalculatorForm(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);
}

我们可以通过添加on_<object name>前缀,以通常的方式连接用户界面小部件中的信号和槽。更多信息,请参考这里

这种方法的优点是简单使用继承来提供基于QWidget的界面,以及它对数据成员内用户界面小部件变量的封装。我们可以使用此方法定义同一小部件中的多个用户界面,每个界面都包含在自己的命名空间中,并叠加(或撰写)它们。

使用指针成员变量

Ui::CalculatorForm结构可以作为类的指针成员。头文件如下所示:

namespace Ui {
    class CalculatorForm;
}

class CalculatorForm : public QWidget
...
virtual ~CalculatorForm();
...
private:
    Ui::CalculatorForm *ui;
...

源文件如下:

#include "ui_calculatorform.h"

CalculatorForm::CalculatorForm(QWidget *parent) :
    QWidget(parent), ui(new Ui::CalculatorForm)
{
    ui->setupUi(this);
}

CalculatorForm::~CalculatorForm()
{
    delete ui;
}

这种方法的优点是可以向前声明用户界面对象,这意味着我们不必在头文件中包含生成的ui_calculatorform.h文件。然后可以更改表单,而无需重新编译依赖源文件。如果类受到二进制兼容性限制,这一点尤为重要。

对于库和大型应用程序,我们通常推荐这种方法。有关详细信息,请参见创建共享库

多重继承方法

使用Qt designer创建的窗体可以与基于QWidget的标准类一起子类化。这种方法使表单中定义的所有用户界面组件都可以在子类的范围内直接访问,并使用connect()函数以通常的方式进行信号和插槽连接。

此方法用于多重继承示例。

我们需要包含uic根据calculatorform.ui生成的头文件

#include "ui_calculatorform.h"

该类的定义方式与单继承方法中使用的类似,只是这次我们继承了QWidget和Ui::CalculatorForm,如下所示:

class CalculatorForm : public QWidget, private Ui::CalculatorForm
{
    Q_OBJECT

public:
    explicit CalculatorForm(QWidget *parent = nullptr);

private slots:
    void on_inputSpinBox1_valueChanged(int value);
    void on_inputSpinBox2_valueChanged(int value);
};

我们私有地继承Ui::CalculatorForm,以确保用户界面对象在我们的子类中是私有的。我们还可以用public或protected关键字来继承它,就像我们在前面的例子中可以将ui设置为public或protected一样。

子类的构造函数执行许多与单个继承示例中使用的构造函数相同的任务:

CalculatorForm::CalculatorForm(QWidget *parent)
    : QWidget(parent)
{
    setupUi(this);
}

在这种情况下,用户界面中使用的小部件可以像手工在代码中创建的小部件一样进行访问。我们不再需要ui前缀来访问它们。

对语言变化的反应

Qt通过发送QEvent::LanguageChange类型的事件来通知应用程序用户界面语言是否更改。为了调用用户界面对象的成员函数retranslateUi(),请在窗体类中重新实现QWidget::changeEvent()

void CalculatorForm::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
   }
}

运行时间窗体处理

窗体可以在允许是处理:生成动态生成的用户界面。这可以通过QtUiTools模块来完成,QtUiTools模块提供QUiLoader类来处理使用Qt Designer创建的表单

UiTool方法

在运行时处理表单需要包含UI文件的资源文件,此外,应用程序还需要配置为使用QtUiTools模块,这是通过在qmake项目文件中包含如下声明来实现的,以确保应用程序被正确编译和链接

QT += uitools

QUiLoader类提供了构建用户界面的表单加载器对象。此用户界面可以从任何QIODevice(例如QFile对象)中检索,以获取存储在项目资源文件中的表单。 QUiLoader::load() 使用文件中包含的用户界面描述根据窗体小部件

QtUiTools模块类可以使用以下指令包括在内:

#include <QtUiTools>

调用QUiLoader::load()函数,如文本查找器示例中的代码所示:

static QWidget *loadUiFile(QWidget *parent)
{
    QFile file(":/forms/textfinder.ui");
    file.open(QIODevice::ReadOnly);

    QUiLoader loader;
    return loader.load(&file, parent);
}

在运行时使用QtUiTools构建用户界面的类中,我们可以使用QObject::findChild()在表单中定位对象。例如,在下面的代码中,我们根据一些组件的对象名和小部件类型来定位它们:

   ui_findButton = findChild<QPushButton*>("findButton");
    ui_textEdit = findChild<QTextEdit*>("textEdit");
    ui_lineEdit = findChild<QLineEdit*>("lineEdit");

运行时处理表单使开发人员可以自由地更改程序的用户界面,只需更改UI文件即可。这在定制程序以满足各种用户需求时非常有用,例如超大图标或支持辅助功能的不同颜色方案。

自动连接

为编译时间或者运行时间窗体定义的信号和槽可以手动或者自动设置,使用QMetaObject在信号和适当命名的槽之间进行连接的能力

通常,在QDialog中,如果我们想在接受用户输入的信息之前对其进行处理,我们需要将OK按钮的clicked()信号连接到对话框中的一个自定义槽中。我们将首先展示一个对话框的示例,其中插槽是手动连接的,然后将其与使用自动连接的对话框进行比较。

没有自动连接的对话

我们以与以前相同的方式定义对话框,但现在除了构造函数之外,还包括一个插槽:

class ImageDialog : public QDialog, private Ui::ImageDialog
{
    Q_OBJECT

public:
    ImageDialog(QWidget *parent = 0);

private slots:
    void checkValues();
};

checkValues()槽将用于验证用户提供的值。

在对话框的构造函数中,我们像以前一样设置小部件,并将Cancel按钮的clicked()信号连接到对话框的reject()槽。我们还禁用了两个按钮中的autoDefault属性,以确保对话框不会干扰行编辑处理返回键事件的方式:

ImageDialog::ImageDialog(QWidget *parent)
    : QDialog(parent)
{
    setupUi(this);
    okButton->setAutoDefault(false);
    cancelButton->setAutoDefault(false);
    ...
    connect(okButton, SIGNAL(clicked()), this, SLOT(checkValues()));
}

我们将OK按钮的clicked()信号连接到对话框的checkValues()槽,我们实现如下:

void ImageDialog::checkValues()
{
    if (nameLineEdit->text().isEmpty())
        (void) QMessageBox::information(this, tr("No Image Name"),
            tr("Please supply a name for the image."), QMessageBox::Cancel);
    else
        accept();
}

这个自定义槽只做了确保用户输入的数据有效所需的最低限度的工作—它只接受为图像指定名称时的输入。

带自用连接的小部件和对话

尽管在对话框中实现一个自定义槽并在构造函数中连接它很容易,但是我们可以使用QMetaObject的自动连接工具将OK按钮的clicked()信号连接到子类中的槽。uic会自动在对话框的setupUi()函数中生成代码来执行此操作,因此我们只需要声明并实现一个名称符合标准约定的插槽:

void on_<object name>_<signal name>(<signal parameters>);

使用此约定,我们可以定义并实现一个响应鼠标单击OK按钮的插槽:

class ImageDialog : public QDialog, private Ui::ImageDialog
{
    Q_OBJECT

public:
    ImageDialog(QWidget *parent = 0);

private slots:
    void on_okButton_clicked();
};

自动信号和插槽连接的另一个例子是文本查找器,它的on_findButton_clicked()插槽。

我们使用QMetaObject的系统来启用信号和插槽连接:

QMetaObject::connectSlotsByName(this);

这使我们能够实现插槽,如下所示:

void TextFinder::on_findButton_clicked()
{
    QString searchString = ui_lineEdit->text();
    QTextDocument *document = ui_textEdit->document();

    bool found = false;

    // undo previous change (if any)
    document->undo();

    if (searchString.isEmpty()) {
        QMessageBox::information(this, tr("Empty Search Field"),
                                 tr("The search field is empty. "
                                    "Please enter a word and click Find."));
    } else {
        QTextCursor highlightCursor(document);
        QTextCursor cursor(document);

        cursor.beginEditBlock();
    ...
        cursor.endEditBlock();

        if (found == false) {
            QMessageBox::information(this, tr("Word Not Found"),
                                     tr("Sorry, the word cannot be found."));
        }
    }
}

信号和插槽的自动连接既提供了标准命名约定,也提供了一个明确的界面,供小部件设计人员使用。通过提供实现给定界面的源代码,用户界面设计人员可以检查其设计是否实际工作,而无需自己编写代码。

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt怎么用Ui文件 第一步, 制作ui文件。 首先应该用Qt Designer绘制一个自己的界面,并存为myform.ui(这里的myform可以用自己喜欢的名字代替)。 在制作自己的界面文件时要注意以下几个要点: 1、要记住ui文件的名字,因为uic生成的代码会存在ui_myform.h里 2、要记住主窗体的object name, 因为ui文件提供的类名将以这个form的名字来命名 3、要特别注意你的form选择的基类要和你代码的窗体类兼容 4、要记得给每个后面需要访问到的控件起一个有意义并且好记的object name, 因为ui文件提供的控件将以这些object name来命名 清楚了以上几点,在代码使用你的ui文件就会变得非常简单。 第二步,将ui文件加入工程 这一步最简单,只需要修改pro文件,加入FORMS+=myform.ui qmake -project命令也可以识别后缀名为ui文件,并将之加入工程。 第三步,在代码引用ui文件 官方介绍的使用ui文件的方法有三种,一个是直接引用,二是单继承,三是多继承。 第一种方法其实很不实用,大家去看一下文档的例子就可以了;第二种和第三种没有本质的差别,可以并作一类,这里做重点介绍。 ui文件最终会被翻译成标准的C++代码,并存入一个.h文件,这个过程在调用make之后才进行,所以初始情况下你是看不到这个ui_myform.h文件的,只有经过了make过程该头文件才生成。不过没关系,没有这个文件我们照样能写出正确的代码。 单继承方式简单来说就是在代码首先要自定义一个子类(后文称为MyForm),该类要从form对应的窗体类(或其兼容的子类)派生;并用ui生成的类定义一个类里的成员变量(后文成文myui)。这样在MyForm的构造函数可以直接调用myui和myui的变量和函数,使用起来很方便。 举例说明, 比如这里有一个ui文件叫myform.uiui文件里定义的窗体名字为BigWidget,上面摆放了一个单行编辑控件叫lineeditName: //myform.h #include “ui_myform.h” class MyForm: public QWidget { Q_OBJECT public: MyForm(QWidget*parent) { myui.setupUi(this); } private: Ui::BigWidget myui; private: void my_function(); }; 上面这段简单的类的声明是前文所述前三点要点的最佳例证,请对照要点的文字描述和具体的代码体会其的含义。这里还有一点比较有意思的地方,就是ui文件提供的类被包含在了名为Ui的name space里,这样做的目的是将ui文件的命名空间与用户的代码分离,避免两者出现命名冲突的情况。相应的,我们写代码的时候也要注意在使用ui文件的类时要用“Ui::”的方式进行引用。 再来看cpp文件 //myform.cpp #include #include “myform.h” void my_function(void) { QMessageBox::information(this, “Name”, myui.lineeditName->text()); } 这里随便写了一个函数,为了说明如何在窗体类里调用ui文件定义的控件。这段代码非常简单,就不多作说明了。 有了单继承的基础,学习多继承是小菜一碟。来段代码看一下就明白了。 //myform.h #include “ui_myform.h” class MyForm: public QWidget, public Ui::BigWidget { Q_OBJECT public: MyForm(QWidget*parent) { setupUi(this); } private: void my_function(); }; //myform.cpp #include #include “myform.h” void my_function(void) { QMessageBox::information(this, “Name”, lineeditName->text()); } 是不是不用说明大家也能明白呢?多继承其实就是不仅从form需要的窗体类去派生,还要加上ui提供的类本身。这样带来的好处是你的窗体类继承了ui里的所有控件和方法,调用时就可以少写一些字。 单继承和多继承这两种方法没有好坏之分,大家可以根据自己的编程习惯取舍。 第四步,编译、验证在pro文件包含正确FORMS信息的情况下,运行qmake; make就可以编译工程了。 make时如果你认真看一下输出就会发现,make在最开始编译的时候就会自动调用uic去生成需要的代码。经过make之后ui_myform.h文件就生成了,建议大家去看一下这个文件的内容。
### 回答1: Qt是一款跨平台的C++应用开发框架,具有强大的UI控件库。QtUI控件可以使用C++语言编写,并支持多种操作系统如Windows、Linux、macOS等。 在QtUI控件使用Qt Designer工具进行设计和布局。Qt Designer提供了一个可视化的图形界面,可以通过拖拽和释放的方式快速创建和修改UI界面。通过容器控件如窗口、对话框和布局管理器,可以组合和排列UI控件,使其具有良好的布局效果。 QtUI控件库具有丰富的功能和样式,可以满足不同的需求。常见的UI控件包括按钮、标签、文本框、列表框、下拉框、复选框等。这些控件都可以在Qt Designer直接拖拽到界面,并通过属性编辑对其进行定制设置,如文字、颜色、大小等。 除了基础的UI控件,Qt还提供了一些特殊的控件,如进度条、滑动条、图形绘制、图表等,可以满足更复杂的UI需求。此外,Qt还支持用户自定义的UI控件,可以根据自己的需要进行扩展和定制。 在使用QtUI控件时,开发者需要编写对应的事件处理函数,通过连接信号和槽的方式响应用户的操作。通过信号和槽机制,UI控件可以与后台的业务逻辑进行交互,实现更复杂的功能。 总而言之,QtUI控件库提供了丰富的功能和样式,并且支持跨平台开发。开发者可以使用C++语言编写UI控件的代码,并通过Qt Designer可视化工具进行设计和布局,从而快速开发出美观、可用性强的应用程序。 ### 回答2: Qt是一款跨平台的应用程序开发框架,提供了丰富的UI控件供开发者使用。其UI控件C示例如下: ```c++ #include <QApplication> #include <QWidget> #include <QPushButton> int main(int argc, char *argv[]) { QApplication app(argc, argv); // 创建一个窗口 QWidget window; window.setWindowTitle("Qt UI控件示例"); // 创建一个按钮 QPushButton button("点击我", &window); button.setGeometry(50, 50, 100, 30); // 连接按钮的点击信号与槽函数 QObject::connect(&button, &QPushButton::clicked, [&]() { button.setText("已点击"); }); // 显示窗口 window.show(); // 运行应用程序 return app.exec(); } ``` 这个示例演示了一个简单的Qt程序,其包含一个窗口和一个按钮。窗口的标题设置为"Qt UI控件示例",按钮的文本设置为"点击我"。当按钮被点击时,按钮的文本会变为"已点击"。 在程序,首先需要创建一个QApplication对象来管理应用程序的生命周期。然后创建一个QWidget窗口,并设置窗口的标题。接着创建一个QPushButton按钮,并将它作为窗口的子控件。使用setGeometry函数可以设置按钮的位置和大小。 通过QObject::connect函数连接按钮的clicked信号与一个槽函数。在这个示例,槽函数使用了Lambda表达式,当按钮被点击时,它会将按钮的文本设置为"已点击"。 最后,调用窗口的show函数显示窗口,然后调用QApplication的exec函数运行应用程序。这样,程序就进入了事件循环,等待事件的发生和处理。 通过这个示例,可以简单了解如何使用QtUI控件来创建一个窗口和按钮,并监听按钮的点击事件。当然,Qt还提供了许多其他的UI控件和功能,开发者可以根据自己的需求进行灵活运用。 ### 回答3: Qt是一个跨平台的应用程序开发框架,通过它可以轻松构建图形用户界面(UI)。Qt提供了丰富的UI控件,可以用于创建各种交互式的窗口和界面。 在使用Qt编写UI界面时,可以使用Qt Designer来设计界面。Qt Designer是一个可视化界面设计工具,可以直接拖拽和放置各种UI控件,并进行属性设置。设计好界面后,Qt Designer会生成一个.ui文件,它包含了界面的布局和控件的属性。 在C++代码使用QtUI控件,首先需要将.ui文件转换为C++代码。Qt提供了一个uic工具,可以从.ui文件生成对应的C++代码。可以使用类似下面的命令进行转换: uic input.ui -o output.h 转换完成后,可以把生成的output.h文件包含到项目,并在代码通过调用控件的方法来实现功能。例如,可以通过QPushButton的clicked信号和相应的槽函数来处理按钮的点击事件;通过QLineEdit的textChanged信号和相应的槽函数来处理文本框内容的变化等等。 除了可以使用Qt Designer来设计界面外,也可以通过代码来创建和布局UI控件。Qt提供了各种UI控件的类,例如QPushButton、QLineEdit、QLabel等等。可以在代码对这些控件进行实例化,并设置它们的属性和布局关系。 最后需要注意的是,Qt提供了一套信号和槽机制用于处理控件之间的交互和通信。信号是一种特殊的函数,当特定的事件发生时被触发;槽是接收信号的函数。在UI控件,经常会使用信号和槽来实现各种功能。 综上所述,QtUI控件提供了丰富的功能和灵活的设计方式,可以用于开发各种跨平台的图形用户界面程序。只需要通过Qt Designer或者通过代码创建和布局UI控件,然后利用信号和槽机制实现界面交互即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值