把Qt的界面文件(.ui文件)生成源文件(.h或.cpp)封装成链接库

本文介绍如何使用Qt设计器创建界面,并将其转换为.dll和.lib文件,通过具体步骤演示了.ui文件的编译和集成过程,适用于需要将Qt界面作为库使用的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

在用Qt做开发时,为了方便快速,一般都使用Qt设计师界面类来做界面相关的布局,这个类在当前工程中是没有.cpp或.h文件的,但主类又有引入了这个头文件,点开转到定义或声明时,是打不开的,如下图:
在这里插入图片描述
如果要把整个项目导成dll和lib,就按当前的文件导出,是会报找不到ui_XXX类的路径的。那什么样才能把设计好的.ui界面导成dll和lib呢,看了好多种办法,有真接是用手写代码的方式去而已界面,这样的工作量有点。下面我演示下我觉得可行办法,虽然有些笨,但起码可以调用。

解决方法

1.新建一个工程,包含.ui文件,然后打开.ui文件拖入想要的控件,保存,编译.ui文件。
在这里插入图片描述
2.打开当前工程,找到目录下的.ui文件,复制下来,新建一个目录把它放进去。
在这里插入图片描述
3.然后去qt安路径下找到uic.exe文件,也把它复制到刚刚放.ui文件的目录下,此时当前目录只有两个文件。
在这里插入图片描述
在这里插入图片描述
4.按住窗口加R件,输入cmd,进入控件台界面,运行uic xxx.ui -o xxx.h或者uic xxx.ui -o xxx.cpp,在当前目录下就多了一个.h或者.cpp文件,这两个文件只要一个就可以了。
在这里插入图片描述
5.新建一个工程,选择类库。
在这里插入图片描述
6.把刚才生成的.h文件导入到当前工程,然后打开刚刚生成的源码,我们可以看到整个类的所有属性和成员函数。
.ui文件生成的.h文件

/********************************************************************************
** Form generated from reading UI file 'QtGuiDllDemo.ui'
**
** Created by: Qt User Interface Compiler version 5.7.1
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/

#ifndef QTGUIDLLDEMO_H
#define QTGUIDLLDEMO_H

#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenu>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QToolBar>
#include <QtWidgets/QWidget>

QT_BEGIN_NAMESPACE

class Ui_QtGuiDllDemoClass
{
public:
    QAction *actionOpen;
    QWidget *centralWidget;
    QPushButton *pushButton;
    QPushButton *pushButton_2;
    QMenuBar *menuBar;
    QMenu *menu;
    QToolBar *mainToolBar;
    QStatusBar *statusBar;

    void setupUi(QMainWindow *QtGuiDllDemoClass)
    {
        if (QtGuiDllDemoClass->objectName().isEmpty())
            QtGuiDllDemoClass->setObjectName(QStringLiteral("QtGuiDllDemoClass"));
        QtGuiDllDemoClass->resize(1046, 786);
        actionOpen = new QAction(QtGuiDllDemoClass);
        actionOpen->setObjectName(QStringLiteral("actionOpen"));
        centralWidget = new QWidget(QtGuiDllDemoClass);
        centralWidget->setObjectName(QStringLiteral("centralWidget"));
        pushButton = new QPushButton(centralWidget);
        pushButton->setObjectName(QStringLiteral("pushButton"));
        pushButton->setGeometry(QRect(330, 210, 231, 111));
        pushButton_2 = new QPushButton(centralWidget);
        pushButton_2->setObjectName(QStringLiteral("pushButton_2"));
        pushButton_2->setGeometry(QRect(400, 430, 231, 81));
        QtGuiDllDemoClass->setCentralWidget(centralWidget);
        menuBar = new QMenuBar(QtGuiDllDemoClass);
        menuBar->setObjectName(QStringLiteral("menuBar"));
        menuBar->setGeometry(QRect(0, 0, 1046, 23));
        menu = new QMenu(menuBar);
        menu->setObjectName(QStringLiteral("menu"));
        QtGuiDllDemoClass->setMenuBar(menuBar);
        mainToolBar = new QToolBar(QtGuiDllDemoClass);
        mainToolBar->setObjectName(QStringLiteral("mainToolBar"));
        QtGuiDllDemoClass->addToolBar(Qt::TopToolBarArea, mainToolBar);
        statusBar = new QStatusBar(QtGuiDllDemoClass);
        statusBar->setObjectName(QStringLiteral("statusBar"));
        QtGuiDllDemoClass->setStatusBar(statusBar);

        menuBar->addAction(menu->menuAction());
        menu->addAction(actionOpen);

        retranslateUi(QtGuiDllDemoClass);

        QMetaObject::connectSlotsByName(QtGuiDllDemoClass);
    } // setupUi

    void retranslateUi(QMainWindow *QtGuiDllDemoClass)
    {
        QtGuiDllDemoClass->setWindowTitle(QApplication::translate("QtGuiDllDemoClass", "QtGuiDllDemo", Q_NULLPTR));
        actionOpen->setText(QApplication::translate("QtGuiDllDemoClass", "open", Q_NULLPTR));
        pushButton->setText(QApplication::translate("QtGuiDllDemoClass", "\346\216\247\344\273\266", Q_NULLPTR));
        pushButton_2->setText(QApplication::translate("QtGuiDllDemoClass", "\347\225\214\351\235\242", Q_NULLPTR));
        menu->setTitle(QApplication::translate("QtGuiDllDemoClass", "\346\226\207\344\273\266", Q_NULLPTR));
    } // retranslateUi

};

namespace Ui {
    class QtGuiDllDemoClass: public Ui_QtGuiDllDemoClass {};
} // namespace Ui

QT_END_NAMESPACE
#endif // QTGUIDLLDEMO_H

7.按qt给的格式把.h更改之后加到当前类的下面。
在当前工程的类加了ui类的.h文件

#pragma once

#include "guidlltest_global.h"
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenu>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QToolBar>
#include <QtWidgets/QWidget>

class GUIDLLTEST_EXPORT GuiDllTest
{
public:
	GuiDllTest();
};

QT_BEGIN_NAMESPACE

class GUIDLLTEST_EXPORT Ui_QtGuiDllDemoClass
{
public:
	QAction *actionOpen;
	QWidget *centralWidget;
	QPushButton *pushButton;
	QPushButton *pushButton_2;
	QMenuBar *menuBar;
	QMenu *menu;
	QToolBar *mainToolBar;
	QStatusBar *statusBar;

	void setupUi(QMainWindow *QtGuiDllDemoClass);

	void retranslateUi(QMainWindow *QtGuiDllDemoClass);

};

namespace Ui {
	class QtGuiDllDemoClass : public Ui_QtGuiDllDemoClass {};
} // namespace Ui

QT_END_NAMESPACE

加了ui类的.cpp文件

#include "GuiDllTest.h"

GuiDllTest::GuiDllTest()
{
}

void Ui_QtGuiDllDemoClass::setupUi(QMainWindow *QtGuiDllDemoClass)
{
	if (QtGuiDllDemoClass->objectName().isEmpty())
		QtGuiDllDemoClass->setObjectName(QStringLiteral("QtGuiDllDemoClass"));
	QtGuiDllDemoClass->resize(1046, 786);
	actionOpen = new QAction(QtGuiDllDemoClass);
	actionOpen->setObjectName(QStringLiteral("actionOpen"));
	centralWidget = new QWidget(QtGuiDllDemoClass);
	centralWidget->setObjectName(QStringLiteral("centralWidget"));
	pushButton = new QPushButton(centralWidget);
	pushButton->setObjectName(QStringLiteral("pushButton"));
	pushButton->setGeometry(QRect(330, 210, 231, 111));
	pushButton_2 = new QPushButton(centralWidget);
	pushButton_2->setObjectName(QStringLiteral("pushButton_2"));
	pushButton_2->setGeometry(QRect(400, 430, 231, 81));
	QtGuiDllDemoClass->setCentralWidget(centralWidget);
	menuBar = new QMenuBar(QtGuiDllDemoClass);
	menuBar->setObjectName(QStringLiteral("menuBar"));
	menuBar->setGeometry(QRect(0, 0, 1046, 23));
	menu = new QMenu(menuBar);
	menu->setObjectName(QStringLiteral("menu"));
	QtGuiDllDemoClass->setMenuBar(menuBar);
	mainToolBar = new QToolBar(QtGuiDllDemoClass);
	mainToolBar->setObjectName(QStringLiteral("mainToolBar"));
	QtGuiDllDemoClass->addToolBar(Qt::TopToolBarArea, mainToolBar);
	statusBar = new QStatusBar(QtGuiDllDemoClass);
	statusBar->setObjectName(QStringLiteral("statusBar"));
	QtGuiDllDemoClass->setStatusBar(statusBar);

	menuBar->addAction(menu->menuAction());
	menu->addAction(actionOpen);

	retranslateUi(QtGuiDllDemoClass);

	QMetaObject::connectSlotsByName(QtGuiDllDemoClass);
} // setupUi

void Ui_QtGuiDllDemoClass::retranslateUi(QMainWindow *QtGuiDllDemoClass)
{
	QtGuiDllDemoClass->setWindowTitle(QApplication::translate("QtGuiDllDemoClass", "QtGuiDllDemo", Q_NULLPTR));
	actionOpen->setText(QApplication::translate("QtGuiDllDemoClass", "open", Q_NULLPTR));
	pushButton->setText(QApplication::translate("QtGuiDllDemoClass", "\346\216\247\344\273\266", Q_NULLPTR));
	pushButton_2->setText(QApplication::translate("QtGuiDllDemoClass", "\347\225\214\351\235\242", Q_NULLPTR));
	menu->setTitle(QApplication::translate("QtGuiDllDemoClass", "\346\226\207\344\273\266", Q_NULLPTR));
} // retranslateUi

8.重新生成解决方案,就在当前目录下生成一个dll文件和lib文件,按正常类调用就可以了。
在这里插入图片描述

<think>好的,我现在需要帮用户在Windows下的QT环境中创建一个hello world的.so库,并构建一个使用这个库的完整项目,目标架构是arm64-v8a。首先,我得理清楚整个流程,确保每个步骤都正确,特别是跨平台编译到ARM架构的部分。 首先,用户提到的是生成.so库,但通常Windows下动态库是.dll文件,而.so是Linux/Unix系统的。不过,可能用户是想在Windows环境下交叉编译生成适用于Android ARM64的.so库?者用户可能混淆了库的扩展名。需要明确目标平台。由于用户提到了arm64-v8a,这通常是Android的架构,所以推测用户是想在Windows下使用Qt进行Android开发,生成ARM64的.so库,并在另一个Android项目中调用它。 接下来,我需要考虑Qt对Android的支持。Qt Creator需要配置Android SDK、NDK工具链。用户需要确保安装了这些组件,并且在Qt Creator中设置了正确的套件(Kit)。 步骤可能包括: 1. 创建动态库项目,配置为Android ARM64-v8a。 2. 编写hello world函数,并正确导出符号(可能需要使用类似之前的导出宏,比如Q_DECL_EXPORT)。 3. 构建库,生成.so文件。 4. 创建应用程序项目,同样配置为Android ARM64-v8a。 5. 链接到之前生成.so库,并调用函数。 6. 处理库的部署路径问题,确保应用在设备上能找到库。 需要注意的是,在Windows下编译Android ARM的.so库,需要使用正确的工具链。Qt Creator中需要选择Android ARM64-v8a的套件。同时,动态库的导出符号在Android中可能需要不同的处理,者默认导出,但为了跨平台兼容,可能还是需要使用导出宏。 另外,在构建应用项目时,需要在.pro文件CMakeLists.txt中添加库的引用,包含头文件,并指定库的路径。在部署到Android设备时,可能需要将.so文件放在正确的目录(如jniLibs/arm64-v8a)。 可能的难点包括: - 正确配置Qt Creator的Android环境。 - 确保导出符号的正确性,避免运行时找不到函数。 - 处理库的依赖部署路径。 需要检查用户是否已经正确设置Android开发环境,如果没有,可能需要指导他们安装必要的组件。此外,确保示例代码中的函数正确导出,并且在应用项目中正确引用。 最后,可能需要提供一个完整的示例,包括库应用的代码,以及构建步骤,确保用户能够一步步操作,避免遗漏关键配置。</think>### **Windows+Qt下构建ARM64动态库及调用示例** #### **1. 环境准备** - **Qt版本**:5.15+ Qt6,需支持Android开发 - **工具链**: - Android NDK r21+(建议使用Qt预装版本) - JDK 8+ - Android SDK(API级别≥21) - **Qt Creator配置**: 1. 进入`Tools > Options > Devices > Android` 2. 设置SDK、NDK、JDK路径 3. 创建`Android ARM64-v8a`编译套件 --- ### **2. 创建动态库项目** #### **步骤1:新建Qt动态库项目** 1. **模板选择**:`Library > C++ Library` 2. **类型**:`Shared Library` 3. **名称**:`HelloLib` 4. **套件选择**:`Android ARM64-v8a` #### **步骤2:添加导出宏** 修改`hellolib_global.h`: ```cpp #pragma once #include <QtCore/qglobal.h> #if defined(HELLOLIB_LIBRARY) # define HELLOLIB_EXPORT Q_DECL_EXPORT #else # define HELLOLIB_EXPORT Q_DECL_IMPORT #endif ``` #### **步骤3:实现函数** 修改`hello.h`: ```cpp #include "hellolib_global.h" extern "C" HELLOLIB_EXPORT void hello(); // 强制C符号命名 ``` 修改`hello.cpp`: ```cpp #include <QDebug> #include "hello.h" void hello() { qDebug() << "Hello from ARM64!"; } ``` #### **步骤4:编译生成.so** - 构建后生成文件路径: ``` build-*Android_ARM64_v8a-*/android-arm64-v8a/libHelloLib.so ``` --- ### **3. 创建应用程序项目** #### **步骤1:新建Qt Widgets应用** 1. **模板选择**:`Application > Qt Widgets App` 2. **名称**:`HelloApp` 3. **套件选择**:`Android ARM64-v8a` #### **步骤2:添加库文件** 1. **目录结构**: ``` HelloApp/ ├── android/ │ └── libs/ │ └── arm64-v8a/ │ └── libHelloLib.so └── ... ``` 2. **修改.pro文件**: ```qmake android { ANDROID_EXTRA_LIBS += $$PWD/android/libs/arm64-v8a/libHelloLib.so } ``` #### **步骤3:调用库函数** 修改`mainwindow.cpp`: ```cpp #include "mainwindow.h" #include "hello.h" // 头文件需手动复制到项目目录 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { hello(); // 调用动态库函数 } ``` --- ### **4. 部署配置** #### **关键配置项** 1. **AndroidManifest.xml**: ```xml <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33"/> <uses-feature android:glEsVersion="0x00030000" android:required="true"/> ``` 2. **构建配置**: ```qmake QT += core widgets CONFIG += c++17 ``` --- ### **5. 完整CMake方案(Qt6推荐)** #### **动态库CMakeLists.txt**: ```cmake cmake_minimum_required(VERSION 3.16) project(HelloLib LANGUAGES CXX) set(CMAKE_AUTOMOC ON) find_package(Qt6 COMPONENTS Core REQUIRED) add_library(HelloLib SHARED hello.cpp hellolib_global.h ) target_link_libraries(HelloLib PRIVATE Qt6::Core) set_target_properties(HelloLib PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/android/libs/arm64-v8a" ) ``` #### **应用程序CMakeLists.txt**: ```cmake cmake_minimum_required(VERSION 3.16) project(HelloApp LANGUAGES CXX) set(CMAKE_AUTOMOC ON) find_package(Qt6 COMPONENTS Widgets REQUIRED) add_executable(HelloApp main.cpp mainwindow.cpp ) target_link_libraries(HelloApp PRIVATE Qt6::Widgets ${CMAKE_CURRENT_SOURCE_DIR}/../HelloLib/android/libs/arm64-v8a/libHelloLib.so ) ``` --- ### **6. 验证流程** | 步骤 | 操作 | 预期结果 | |------|------|----------| | 1 | 连接Android设备(需开启开发者模式) | 设备被Qt Creator识别 | | 2 | 编译并部署库APP | 生成APK文件并自动安装 | | 3 | 运行APP | 设备输出"Hello from ARM64!"日志 | **日志查看**: ```bash adb logcat -s "qml:*" # 查看Qt日志 ``` --- ### **常见问题处理** #### **问题1:找不到动态库** **解决方案**: ```qmake # 在应用程序的.pro文件中添加 LIBS += -L$$PWD/android/libs/arm64-v8a -lHelloLib ``` #### **问题2:ABI不兼容** **错误提示**: `java.lang.UnsatisfiedLinkError: dlopen failed: "has bad ELF magic"` **解决方法**: 确认编译套件部署目标的ABI一致(必须同为arm64-v8a)。 #### **问题3:Qt版本兼容性** 若使用Qt6,需在`CMakeLists.txt`中指定: ```cmake find_package(Qt6 COMPONENTS Core Gui Widgets REQUIRED) ``` --- 通过以上步骤,即可在Windows+Qt环境下完ARM64架构动态库的构建与调用。重点注意工具链匹配符号导出规则,建议优先使用CMake构建系统以获得更好的跨平台支持。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知来者逆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值