我是靠谱客的博主 可靠龙猫,这篇文章主要介绍QT编写窗口插件实现调用窗口的自适应,现在分享给大家,希望可以做个参考。

前言

最近项目中遇到插件架构,将几个功能模块分别写成了dll供主程序调用。本文主要在QT下实现这样一个功能:

编写一个dll,里面包含一个QDialog对话框作为主窗口。该dll提供四个接口,它们的作用分别是

1 打开主窗口

2 关闭主窗口

3 更新插件数据(暂不讨论)

4 调用插件中的函数并获取返回值(暂不讨论)

然后由主程序调用dll,并将dll中的窗口嵌入自己的对话框中,并实现自适应。

效果 

编写dll

 1  创建一个Qt Library工程名为test,然后再插入一个QDialog名为testwidget。

此时工程中目录有以下文件:

2 编辑ui,利用布局让他能够随着窗口大小改变自适应。注意对象查看器里布局变化,具体方法如下:

3 编写接口

在test.h编写接口函数定义,在test.cpp中实现。

其中全局变量g_pTestWidget是为了防止重复打开或者关闭。

代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#ifndef TEST_H #define TEST_H #include "test_global.h" #include "testwidget.h" class TEST_EXPORT test { public: test(); ~test(); private: }; #ifdef __cplusplus extern "C" { // we need to export the C interface #endif void TEST_EXPORT PluginStart(void *lParentWidget); void TEST_EXPORT PluginClose(bool bCompleteClose); void TEST_EXPORT PluginUpdate(void *upDate); TEST_EXPORT const char* PluginFunction(const char* input); #ifdef __cplusplus } #endif #endif // TEST_H
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include "test.h" testWidget *g_pTestWidget = NULL; test::test() { } test::~test() { } void TEST_EXPORT PluginStart(void *lParentWidget) { if (NULL == g_pTestWidget) { g_pTestWidget = new testWidget(); } if (NULL != lParentWidget) { g_pTestWidget->setParent((QDialog *)lParentWidget); g_pTestWidget->raise(); g_pTestWidget->setGeometry(0, 0, ((QDialog *)lParentWidget)->width(), ((QDialog *)lParentWidget)->height()); } g_pTestWidget->show(); } void TEST_EXPORT PluginClose(bool bCompleteClose) { if (g_pTestWidget != NULL) { if (bCompleteClose) { g_pTestWidget->hide(); } else { g_pTestWidget->close(); delete g_pTestWidget; g_pTestWidget = NULL; } } } void TEST_EXPORT PluginUpdate(void *upDate) { } TEST_EXPORT const char* PluginFunction(const char* input) { return input; }

至此插件部分的任务完成了。

编写主程序

主程序为一个QWidget窗口,我们要将加载的QDialog窗口放进Widget控件里,并使他相对于Widget实现自适应。因此我们需要

子类化Widget控件(QWidget),重写他的resizeEvent。

QResizingWidget继承自QWidget:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef QRESIZINGWIDGET_H #define QRESIZINGWIDGET_H #pragma once #include <QWidget> class QResizingWidget : public QWidget { Q_OBJECT public: explicit QResizingWidget(QWidget *parent = 0); virtual ~QResizingWidget(); protected: virtual void paintEvent(QPaintEvent *sEvent); virtual void resizeEvent(QResizeEvent* sEvent); }; #endif
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include "qresizingwidget.h" #include <QResizeEvent> #include <QStyleOption> #include <QPainter> QResizingWidget::QResizingWidget(QWidget *parent /*= 0*/) : QWidget(parent) { } QResizingWidget::~QResizingWidget() { } void QResizingWidget::resizeEvent(QResizeEvent* sEvent) { QWidget::resizeEvent(sEvent); foreach(auto itr, children()) { if (itr->isWidgetType()) { itr->setProperty("geometry", QRectF(0, 0, geometry().width(), geometry().height())); } } } void QResizingWidget::paintEvent(QPaintEvent *sEvent) { /* 发现 继承自QWidget的自定义类 ,使用setStyleSheet无效, 如果删除头文件中的 Q_OBJECT,setStyleSheet生效, 但不用OBJECT 就无法所使用signal and slot, 最后找到解决办法,继承自QWidget的自定义类中,重载 paintEvent方法, 并加入如下代码: */ QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); QWidget::paintEvent(sEvent); }

主程序QWidget如下:

也以同样的布局方式设置自适应。

下面编写加载函数,用QLibrary显示加载dll,首先定义四个与dll中接口一致的函数指针。

代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include "testdll.h" #include <QLibrary> #include <QDebug> typedef void (*fun_start)(void *lparentWidget); typedef void (*fun_close)(bool bCompleteClose); typedef void (*fun_update)(const char *upDate); typedef const char* (*fun_callback)(void *input); fun_start g_Start = NULL; fun_close g_End = NULL; QLibrary myDll; testDll::testDll(QWidget *parent) : QWidget(parent) { ui.setupUi(this); connect(ui.load, SIGNAL(clicked()), this, SLOT(load())); connect(ui.unload, SIGNAL(clicked()), this, SLOT(unload())); } testDll::~testDll() { } void testDll::load() { myDll.setFileName("test.dll"); if (myDll.load()) { if (!myDll.isLoaded()) { qDebug() << "load error!"; } else { g_Start = (fun_start)myDll.resolve("PluginStart"); qDebug() << g_Start; qDebug() << "load success!"; g_Start(ui.widget); } } } void testDll::unload() { if (myDll.isLoaded()) { g_End = (fun_close)myDll.resolve("PluginClose"); g_End(false); myDll.unload(); } }

至此主程序编写完毕。

总结

如果主程序需要集成多个插件呢?那就要设计一个插件管理工具,下次再讲。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持靠谱客。

最后

以上就是可靠龙猫最近收集整理的关于QT编写窗口插件实现调用窗口的自适应的全部内容,更多相关QT编写窗口插件实现调用窗口内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(115)

评论列表共有 0 条评论

立即
投稿
返回
顶部