Qt5 自定义 Widget 控件 LED(插件)


Warning: Undefined variable $v in E:\home\LocalUser\424681\www\blog\wordpress\wp-content\plugins\wp-content-index\wp-content-index.php on line 357

Warning: Undefined variable $v in E:\home\LocalUser\424681\www\blog\wordpress\wp-content\plugins\wp-content-index\wp-content-index.php on line 357
目录 Content
[hide]

本文将系统介绍如何编写一个LED控件,并集成到 Designer 和 Creator 中。由最初翻译一篇博文开始。

以 qt-opensource-windows-x86-5.12.2 为例,Qt 安装目录在 c:\Qt\Qt5.12.2\5.12.2\msvc2015_64\ ,即采用 MSVC 2015 64位的编译器和链接库。

一、翻译:集成一个自定义部件到Qt Designer 中

这篇文章对于入门作用很大,介绍了如何实现一个 LED 类,以及如何实现 Designer Plungin 类。但是,没有介绍如何如何使用编译出来的共享库。原文一下跳跃到了在 Designer 中拖放和设置控件。

二、集成自定义控件并使用的步骤

本文做一些补充,先对 pro 文件做一些修改和解释:

greaterThan(QT_MAJOR_VERSION, 4) {
    QT += widgets designer
}

lessThan(QT_MAJOR_VERSION, 5) {
    CONFIG += designer 
}

CONFIG += plugin

TEMPLATE = lib
TARGET = $$qtLibraryTarget($$TARGET)
target.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS += target

INCLUDEPATH += .

# Input
HEADERS += LED.h       \
           LEDPlugin.h
SOURCES += LED.cpp     \
           LEDPlugin.cpp

RESOURCES += \
    icon.qrc

$$qtLibraryTarget($$TARGET) 的解释:

  • $$TARGET:返回 TARGET 变量的值,如果没有赋值,则默认为 Pro 文件的前缀名称,例如 led-designer-plugin。
  • $$qtLibraryTarget :返回相应编译版本的dll,如Release版本 led-designer-plugin 或者 Debug版本 led-designer-plugind
  • RESOURCE:将控件指定一个icon图标文件。原文是默认的Qt图标。
    QIcon LEDPlugin::
    icon() const
    {
        return QIcon(":/icon/led.png");
    }

1、在 Qt Designer 中使用 LED 控件

将编译生成的 led-designer-plugin.dll 拷贝到相应位数版本的 desinger 目录下。

例如:生成的版本是 Qt_5_12_2_MSVC2015_64bit,则把 led-designer-plugin.dll  拷贝到C:\Qt\Qt5.12.2\5.12.2\msvc2015_64\plugins\designer,然后打开相应版本的 Desiginer ,例如 Designer 5.12.2 (MSVC 2015 64-bit) 即可以在Designer的 Widget Box 里看到 ICS Custom Widgets 分组下的 LED 控件,并可以进行拖放和设置操作,更改设置,可以看到更改结果。

总结:dll 文件作为 Designer 的一个插件,所以编译版本要与 Desinger 一致。要想在 Designer 中使用,需要拷贝到 Qt 安装目录下的 plugins\designer 目录下。

问题:无法在 Qt Creator 中的 Desingn 视图(注意,不是 Desinger )中看到 LED 控件。

2、在 Qt Creator 的 Design 视图中使用 LED 控件

此处非常重要,对于理解 Creator 的插件系统,必须要清楚相互关联。

在 Qt creator 中使用,必然作为 Qt Creator 的插件,位数版本要与 Creator 一致。打开 Creator ,在菜单Help -> About Qt Creator 里,可找到编译版本,例如: Based on Qt 5.12.2 (MSVC 2015, 32 bit),这就说明 Qt Creator 是 32 位的 MSVC2015编译的。

捋顺了版本关系,那么位置就好办了,编译好 32 位的 led-designer-plugin.dll 拷贝到 C:\Qt\Qt5.12.2\Tools\QtCreator\bin\plugins\designer 目录下,即可可在Designer的 Widget Box 里看到 ICS Custom Widgets 分组下的 LED 控件,并可以进行拖放和设置操作,更改设置,可以看到更改结果。

总结:dll 文件作为 Creator 的一个插件,编译版本需要与 Creator 一致。要想在 Design 视图中使用,需要把拷贝到  C:\Qt\Qt5.12.2\Tools\QtCreator\bin\plugins\designer 目录下。

问题:编译报错  “error: dependent ‘LED.h’ does not exist.”

3、INCLUDEPATH 指定头文件位置

前面无论在 Designer 或者 Design 中,.ui文件编译成源文件,都用找 LED.h ,那么需要在 .Pro 文件中指定头文件位置。

 INCLUDEPATH += "C:\Users\LT\Desktop\led-designer-plugin\SRC"

这下,不会报找不到 “LED.h” 了。但是,会产生一堆 link 错误:“error: LNK2019: unresolved external symbol “__declspec(dllimport) public: __cdecl LED::LED(class QWidget *)” ,是找不到 lib 文件了。

4、LIBS 指定库文件位置

应该告诉Qt,lib文件的位置,需要在 .Pro 文件中指定位置。

LIBS += -L"C:\Users\LT\Desktop\led-designer-plugin\build-led-designer-plugin-Desktop_Qt_5_12_2_MSVC2015_64bit-Release\release"
LIBS += -lled-designer-plugin

这样,编译构建成功。但是,运行报错:

The program has unexpectedly finished.

这种情况一般是没找到 dll文件,将相应位数版本的dll文件和exe放在一起,运行,又报错了

QWidget: Must construct a QApplication before a QWidget

这种情况是 debug 版本,调用了 release版本的 lib ,更换 debug 版本

LIBS += -L"C:\Users\LT\Desktop\led-designer-plugin\build-led-designer-plugin-Desktop_Qt_5_12_2_MSVC2015_64bit-Debug\debug"
LIBS += -lled-designer-plugind

重新 build,可以运行了!

总结:要指定头文件位置,以及release和debug版本的库文件。

5、将控件相关文件放在一个统一的地方

前面,*.h *.lib *.dll 都分散在不同的地方,但我希望将其放在一个统一的地方。

  • 将64位的 led-designer-plugin.dll 和 led-designer-plugind.dll 文件拷贝到 c:\Qt\Qt5.12.2\5.12.2\msvc2015_64\bin\ 文件夹下,以便 QtCraetor 环境中能找到 dll 文件。
  • 将 led-designer-plugin.lib 和 led-designer-plugind.lib拷贝到 c:\Qt\Qt5.12.2\5.12.2\msvc2015_64\lib 路径下。
  • 将 led.h 放入到一个空文件夹 LED 中,再将此文件夹拷贝到 c:\Qt\Qt5.12.2\5.12.2\msvc2015_64\include\  路径下。

文件的具体结构也可参照 opencv 预编译的msvc版本进行组织。

使用时,在 Pro 文件中配置

win32{
    INCLUDEPATH += $$(QTDIR)/include/LED/
    LIBS += -L$$(QTDIR)/lib/

    CONFIG(debug,debug|release) {
        LIBS += -lled-designer-plugind
    } else {
        LIBS += -lled-designer-plugin
    }
}

或者保存为 pri文件,如c:/Qt/LT.pri,包含在调用pro文件中。

include("c:/Qt/LT.pri")

6、其他事项

问题1:使用 windeployqt 并不会自动拷贝自定义控件的dll。如何让其自动拷贝?

问题2:将QWidget 控件组合为自己的控件。

三、其他经验的汇总

其他网友的经验也很有用,汇总一些:

延伸阅读

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.