Writing window plug-in for QT and realizing the self-adaptation of call window

Keywords: Qt

Catalog

Preface

Effect

Writing dll

Write main program

summary

Preface

Recently, the plug-in architecture was encountered in the project, and several functional modules were written into dll for calling by the main program. This paper mainly implements such a function under the QT:

Write a dll, which contains a QDialog dialog box as the main window. The DLL provides four interfaces, each of which serves as

1 Open the main window

2 Close the main window

3 Update plug-in data (not discussed yet)

4 Call the function in the plug-in and get the return value (not discussed yet)

 

Then the main program calls the dll and embeds the window in the dll into its own dialog box to realize self-adaptation.

Effect

 

Writing dll

1. Create a Qt Library project named test and insert a QDialog named test widget.

At this time, the project directory has the following files:

2 Edit the ui and use the layout to enable him to adapt with the size of the window. Pay attention to the layout changes in the object viewer. The specific methods are as follows:

3 Writing Interface

The interface function definition is written in test.h and implemented in test.cpp.

The global variable g_pTestWidget is designed to prevent repeated opening or closing.

The code is as follows:

#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;
}

So far, the task of the plug-in part has been completed.

Write main program

The main program is a QWidget window. We need to put the loaded QDialog window into the Widget control and make it adaptive to the Widget. So we need

Subclass the Widget control (QWidget) to override its resizeEvent.

QResizingWidget inherits from 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)
{
	/*
	It was found that the custom class inherited from QWidget was invalid using setStyleSheet.
	If Q_OBJECT is deleted from the header file, setStyleSheet takes effect.
	But signal and slot can't be used without OBJECT.
	Finally, we find a solution to overload the paintEvent method, which inherits from the QWidget's custom class.
	And add the following code:
	*/
    QStyleOption opt;
    opt.init(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
	QWidget::paintEvent(sEvent);
}

The main program QWidget is as follows:

Self-adaptation is also set in the same layout.

Next, we write the load function and use QLibrary to display the load dll. First, we define four function pointers that are consistent with the interface in the dll.

The code is as follows:

#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();
	}
}

So far, the main program has been written.

summary

What if the main program needs to integrate multiple plug-ins? Then we need to design a plug-in management tool, which we will talk about next time.

Posted by reversenorm on Thu, 09 May 2019 22:16:39 -0700