QT編寫窗口插件實(shí)現(xiàn)調(diào)用窗口的自適應(yīng)
前言
最近項(xiàng)目中遇到插件架構(gòu),將幾個(gè)功能模塊分別寫成了dll供主程序調(diào)用。本文主要在QT下實(shí)現(xiàn)這樣一個(gè)功能:
編寫一個(gè)dll,里面包含一個(gè)QDialog對話框作為主窗口。該dll提供四個(gè)接口,它們的作用分別是
1 打開主窗口
2 關(guān)閉主窗口
3 更新插件數(shù)據(jù)(暫不討論)
4 調(diào)用插件中的函數(shù)并獲取返回值(暫不討論)
然后由主程序調(diào)用dll,并將dll中的窗口嵌入自己的對話框中,并實(shí)現(xiàn)自適應(yīng)。
效果
編寫dll
1 創(chuàng)建一個(gè)Qt Library工程名為test,然后再插入一個(gè)QDialog名為testwidget。
此時(shí)工程中目錄有以下文件:
2 編輯ui,利用布局讓他能夠隨著窗口大小改變自適應(yīng)。注意對象查看器里布局變化,具體方法如下:
3 編寫接口
在test.h編寫接口函數(shù)定義,在test.cpp中實(shí)現(xiàn)。
其中全局變量g_pTestWidget是為了防止重復(fù)打開或者關(guān)閉。
代碼如下:
#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
#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; }
至此插件部分的任務(wù)完成了。
編寫主程序
主程序?yàn)橐粋€(gè)QWidget窗口,我們要將加載的QDialog窗口放進(jìn)Widget控件里,并使他相對于Widget實(shí)現(xiàn)自適應(yīng)。因此我們需要
子類化Widget控件(QWidget),重寫他的resizeEvent。
QResizingWidget繼承自QWidget:
#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
#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) { /* 發(fā)現(xiàn) 繼承自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如下:
也以同樣的布局方式設(shè)置自適應(yīng)。
下面編寫加載函數(shù),用QLibrary顯示加載dll,首先定義四個(gè)與dll中接口一致的函數(shù)指針。
代碼如下:
#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(); } }
至此主程序編寫完畢。
總結(jié)
如果主程序需要集成多個(gè)插件呢?那就要設(shè)計(jì)一個(gè)插件管理工具,下次再講。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
深入解析C++編程中基類與基類的繼承的相關(guān)知識(shí)
這篇文章主要介紹了C++編程中基類與基類的繼承的相關(guān)知識(shí),包括多個(gè)基類繼承與虛擬基類等重要知識(shí),需要的朋友可以參考下2016-01-01C++實(shí)現(xiàn)地鐵自動(dòng)售票系統(tǒng)程序設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)地鐵自動(dòng)售票系統(tǒng)程序設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03C++函數(shù)返回值為對象時(shí),構(gòu)造析構(gòu)函數(shù)的執(zhí)行細(xì)節(jié)
C++函數(shù)返回值為對象時(shí),構(gòu)造析構(gòu)函數(shù)的執(zhí)行細(xì)節(jié),需要的朋友,可以參考下2013-02-02C語言實(shí)現(xiàn)圖書管理系統(tǒng)課程設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)圖書管理系統(tǒng)課程設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07