QT編寫窗口插件實現(xiàn)調(diào)用窗口的自適應(yīng)
前言
最近項目中遇到插件架構(gòu),將幾個功能模塊分別寫成了dll供主程序調(diào)用。本文主要在QT下實現(xiàn)這樣一個功能:
編寫一個dll,里面包含一個QDialog對話框作為主窗口。該dll提供四個接口,它們的作用分別是
1 打開主窗口
2 關(guān)閉主窗口
3 更新插件數(shù)據(jù)(暫不討論)
4 調(diào)用插件中的函數(shù)并獲取返回值(暫不討論)
然后由主程序調(diào)用dll,并將dll中的窗口嵌入自己的對話框中,并實現(xiàn)自適應(yīng)。
效果

編寫dll
1 創(chuàng)建一個Qt Library工程名為test,然后再插入一個QDialog名為testwidget。
此時工程中目錄有以下文件:

2 編輯ui,利用布局讓他能夠隨著窗口大小改變自適應(yīng)。注意對象查看器里布局變化,具體方法如下:

3 編寫接口
在test.h編寫接口函數(shù)定義,在test.cpp中實現(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ù)完成了。
編寫主程序
主程序為一個QWidget窗口,我們要將加載的QDialog窗口放進Widget控件里,并使他相對于Widget實現(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,首先定義四個與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é)
如果主程序需要集成多個插件呢?那就要設(shè)計一個插件管理工具,下次再講。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
json error: Use of overloaded operator [] is ambiguous錯誤的解決方
今天小編就為大家分享一篇關(guān)于json error: Use of overloaded operator [] is ambiguous錯誤的解決方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-04-04

