Qt中的ui文件
Qt中的ui文件
简介
Qt中的UI文件是一种特殊的XML格式文件,用于描述应用程序的用户界面。这些文件可以使用Qt的可视化设计工具Qt Designer来创建和编辑。Qt Designer提供了直观的界面,允许用户通过拖放和配置界面元素来设计应用程序的图形用户界面(GUI)。
UI文件包含了界面上各种控件的信息,如按钮、文本框、下拉菜单等,以及它们的布局和属性设置。这些信息以XML格式存储,可以在Qt应用程序中通过Qt User Interface Compiler(uic)工具转换为C++代码,供应用程序使用。
在Qt应用程序中,UI文件通常与C++代码配合使用。开发者可以使用Qt Creator集成开发环境来创建和管理UI文件,并在C++代码中引用和操作这些文件。通过UI文件,开发者可以更加高效地设计和构建图形用户界面,提高应用程序的用户体验。
使用ui文件
默认的代码如下
//头文件 #ifndef WIDGET_H #define WIDGET_H #include <QWidget> QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); private: Ui::Widget *ui; }; #endif // WIDGET_H //源文件 #include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); } Widget::~Widget() { delete ui; } //ui文件 <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>Widget</class> <widget class="QWidget" name="Widget"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>800</width> <height>600</height> </rect> </property> <property name="windowTitle"> <string>Widget</string> </property> <widget class="QPushButton" name="pushButton"> <property name="geometry"> <rect> <x>370</x> <y>240</y> <width>75</width> <height>23</height> </rect> </property> <property name="text"> <string>PushButton</string> </property> </widget> </widget> <resources/> <connections/> </ui>
- 代码中首先声明了ui中的类,我们看着它的名字也是Widget,但其实它和现在的Widget类是不同的类
namespace Ui { class Widget; }
- 声明了ui指针指向ui中的类
private: Ui::Widget *ui;
- 包含由uic编译的ui_widget.h头文件,这个过程通常自动完成
#include "ui_widget.h"
- 在源文件中进行构造, 这里是使用了列表初始化相对于在构造函数中ui = new Ui::Widget;
Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget)
- 在构造函数中使用setupUi使得this指针指向的窗口成为承载ui中描述的布局和空间的对象
ui->setupUi(this);
到这里已经知道了如何显示ui的步骤
探秘ui文件内部
手动编译ui文件 使用 uic ./widget.ui -o ui_widget.h
/******************************************************************************** ** Form generated from reading UI file 'widget.ui' ** ** Created by: Qt User Interface Compiler version 6.4.3 ** ** WARNING! All changes made in this file will be lost when recompiling UI file! ********************************************************************************/ #ifndef UI_WIDGET_H #define UI_WIDGET_H #include <QtCore/QVariant> #include <QtWidgets/QApplication> #include <QtWidgets/QPushButton> #include <QtWidgets/QWidget> QT_BEGIN_NAMESPACE class Ui_Widget { public: QPushButton *pushButton; void setupUi(QWidget *Widget) { if (Widget->objectName().isEmpty()) Widget->setObjectName("Widget"); Widget->resize(800, 600); pushButton = new QPushButton(Widget); pushButton->setObjectName("pushButton"); pushButton->setGeometry(QRect(370, 240, 75, 23)); retranslateUi(Widget); QMetaObject::connectSlotsByName(Widget); } // setupUi void retranslateUi(QWidget *Widget) { Widget->setWindowTitle(QCoreApplication::translate("Widget", "Widget", nullptr)); pushButton->setText(QCoreApplication::translate("Widget", "PushButton", nullptr)); } // retranslateUi }; namespace Ui { class Widget: public Ui_Widget {}; } // namespace Ui QT_END_NAMESPACE #endif // UI_WIDGET_H
-
前几行的说明意思是让我们不要改动这个文件,它会在ui改变时候自动重新生成
-
setupUi
是 Qt 框架中自动生成的一个函数,通常出现在由 Qt Designer 创建的 UI 文件(.ui
文件)转换而来的 C++ 代码中。这个函数的主要作用是初始化用户界面(UI)。当你使用 Qt Designer 设计一个图形用户界面并保存为
.ui
文件后,Qt 的uic
工具会将这个.ui
文件转换为一个 C++ 类,这个类包含了一个setupUi
方法。这个方法负责根据.ui
文件中的设计,创建和配置界面上的所有控件(如按钮、文本框、列表等),并设置它们的属性(如位置、大小、字体等)。此外,
setupUi
还会自动处理信号和槽的连接。在 Qt 中,信号和槽是一种用于对象间通信的机制。一个对象的信号可以在某种事件发生时被触发,而槽则是对这个信号的响应。setupUi
会根据.ui
文件中的设置,自动将控件的信号连接到相应的槽函数上,从而实现了界面上的交互功能。在类的构造函数中,通常会调用
setupUi
方法来初始化界面。 -
retranslateUi
是一个Qt特有的方法,用于将UI控件中的文本从默认语言翻译为当前用户系统语言。这个方法通常在应用程序启动时调用,以确保所有UI控件的文本都是用用户的本地语言显示的。在Qt应用程序中,所有的文本字符串都应该定义在一个.ts
文件中。这个文件包含所有需要翻译的字符串及其对应的翻译。然后,使用Qt的linguist工具可以将.ts
文件翻译成目标语言的.qm
文件。应用程序启动时,Qt将加载与用户系统语言相对应的.qm
文件,并根据翻译文件中的内容更新UI控件中的文本。retranslateUi
方法的作用是将当前窗口(Widget
)及其子控件(如按钮)中的文本更新为翻译后的文本。在这个方法中,通过使用QCoreApplication::translate()
函数将默认文本字符串转换为翻译后的字符串,并将这些字符串赋值给相应的UI控件。这样,当应用程序运行时,如果用户的系统语言与应用程序使用的语言不同,那么应用程序就会显示翻译后的文本,从而提高用户体验。 -
使用namespace封装ui_Widget类为Widget类主要是为了保持一个统一的形式,但是它实质上是ui_Widget类
尝试使用自定义的ui文件
自定义一个myui的ui文件
首先我们要知道我们这个myui里面的类名,这里有一个坑,它一般并不是你的文件名对应的类名,我们到设计师或者用记事本改一下就好了,这里玩改成了MyUi的对象名.
1.在widget中先做前置声明,否则编译器不知道有这个类
namespace Ui{class MyUi;}
在Qt框架中,namespace Ui { class MyUi; }
是一个前向声明,它告诉编译器有一个名为 MyUi
的类定义在 Ui
命名空间中。这通常出现在由Qt的uic
工具自动生成的UI类文件中。这些文件通常是由Qt Designer工具创建的.ui
文件通过uic
工具转换而来的。
这里的 Ui::MyUi
类通常包含了在Qt Designer中定义的所有界面元素(如按钮、文本框等)的声明,以及布局和信号槽连接的设置。这个类通常不会被直接实例化,而是作为另一个类的成员被使用,这个类通常负责实现应用程序的逻辑。
2.声明指向Ui::MyUi的指针
Ui::MyUi * ui2;
3.包含uic自动转化过的ui_myui.h
这里有可能会报错,重新构建一下就好了,因为qmake,cmake并不是实时执行的
3.实例化ui2的对象
ui2 = new Ui::MyUi;
4.setupUi
ui2->setupUi(this);
逻辑和界面分离,使用逻辑类处理ui类中的数据
如果想在别的类中处理ui类的数据或者操纵ui里的控件,其实本质就是要明白对象之间的通信和类的封装
- 使用信号和槽
- 将this指针传递给别的类,如果想要操纵ui要将ui设置成公有的或者将将逻辑类变成ui类的友元
- 将ui的链接属性设置为外部的,这样可以跨文件访问
- 还有更多有待发掘
为什么要使用指针来指向UI中的类的对象
- 指针的理解:
- 指针是一个变量,它存储的是另一个变量的内存地址。通过指针,我们可以间接地访问和操作该内存地址中的数据。
- 在C++中,指针特别重要,因为它允许我们进行动态内存分配、函数参数传递、返回多个值等操作。
- 指针也提供了对内存的直接访问,这意味着使用指针时需要注意内存管理和安全性,以避免诸如内存泄漏、野指针等问题。
- 指针相当于一个门,在不暴露对象内部实现的前提下我们就可以操纵对象
- 指针的使用可以减少编译中的依赖,如果指向的对象改动,本文件也无需重新编译,因为指针实质上就是一个与位数机器字长相同的内存编号
2.使用指针来管理UI对象
在Qt中,UI通常是通过Qt Designer设计的,然后转换为.ui
文件。这个文件可以在运行时通过QUiLoader
类加载,或者通过uic
工具转换为C++代码。通常,这些由.ui
文件生成的类会包含大量的UI元素作为类的成员变量。
为了提高代码的灵活性和可重用性,Qt开发者经常将这些UI元素作为指针成员变量来管理。这样做的好处包括:
- 延迟初始化:UI元素可以在需要时才创建,而不是在对象构造时立即创建。
- 动态内存管理:允许动态地分配和释放UI元素的内存。
- 可替换性:可以更容易地替换UI元素,因为它们是通过指针引用的。
例如,一个典型的Qt窗口类可能包含指向按钮、文本框等UI元素的指针:
class MyWindow : public QMainWindow { Q_OBJECT public: MyWindow(QWidget *parent = nullptr); ~MyWindow(); private: QPushButton *myButton; QLineEdit *myLineEdit; // ... 其他UI元素 };
在这个例子中,myButton
和myLineEdit
是指向QPushButton
和QLineEdit
对象的指针,这些对象通常在MyWindow
的构造函数中创建,并在析构函数中删除。
3.PIMPL(Pointer to Implementation)设计模式
PIMPL,也称为Opaque Pointer或Cheshire Cat技术,是一种隐藏类的实现细节的设计模式。在Qt中,PIMPL模式通常用于减少编译依赖,隐藏实现细节,以及提高二进制兼容性。
使用PIMPL模式,类的实现细节被放在一个单独的实现类(通常称为Impl
)中,而公共接口类只包含一个指向实现类的私有指针。这样,当实现细节发生变化时,只要公共接口和指针类型保持不变,客户端代码就不需要重新编译。
在Qt中,PIMPL模式通常用于大型类或库,以减少编译时间和提高代码的稳定性。例如:
// MyWidget.h class MyWidgetImpl; // 前置声明 class MyWidget { public: MyWidget(); ~MyWidget(); void somePublicFunction(); private: MyWidgetImpl *d; // 指向实现的指针 }; // MyWidget.cpp #include "MyWidget.h" #include "MyWidgetImpl.h" // 包含实现类的定义 MyWidget::MyWidget() : d(new MyWidgetImpl) { // 初始化实现对象 } MyWidget::~MyWidget() { delete d; // 释放实现对象 } void MyWidget::somePublicFunction() { // 调用实现类的方法 d->someImplementationFunction(); }
在这个例子中,MyWidget
类只包含一个指向MyWidgetImpl
类的私有指针d
。所有MyWidget
的公共接口函数都通过d
指针来调用MyWidgetImpl
中的实现函数。这样,MyWidget
的客户端代码不需要知道或包含MyWidgetImpl
的定义,从而减少了编译依赖。
在Qt的UI编程中,PIMPL模式不常用于UI对象本身,因为UI对象通常是通过Qt Designer和.ui
文件直接生成的。然而,PIMPL模式可以用于封装复杂的业务逻辑或数据模型,这些逻辑或模型与UI对象交互,但不需要暴露给UI对象的使用者。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!