简体   繁体   English

如何在Qt中的插件和主应用程序之间通信?

[英]How to communicate between plugin and main application in Qt?

I need to let my drawing board application and its geometric figure plugins (draw rectangle, circle and so on) to communicate with each other: When .so file is loaded, main application will get a concrete factory to instance a figure class and a button (which will be loaded in main application to represent this figure). 我需要让我的绘图板应用程序及其几何图形插件(绘制矩形,圆形等)相互通信:加载.so文件时,主应用程序将获得一个具体的工厂来实例化一个图形类和一个按钮。 (将在主应用程序中加载以表示该图)。 When button is clicked, application can draw this figure. 单击按钮时,应用程序可以绘制该图。

I implement this stupidly: 我愚蠢地实现了这一点:

Main application has a QString to identity which figure client chooses. 主应用程序具有一个QString来标识客户端选择的图形对象。 I store a QString *point which point to this QString in factory and write code like this: 我在工厂中存储了一个QString *pointQString *point ,并编写如下代码:

QPushButton *CircleFactory::MyButton()
{
    QPushButton *drawCircleBut = new QPushButton;
    drawCircleBut->setIcon(QIcon(":/shape/circle"));
    connect(drawCircleBut, SIGNAL(clicked()), this, SLOT(changeShape()));
    return drawCircleBut;
}

void CircleFactory::changeShape()
{
    *point = ID_LABEL;
}

I believe that there must be better methods to solve this problem... Please give me some suggestions or advice. 我相信必须有更好的方法来解决此问题...请给我一些建议。

The simplest solution would be to leverage QObject's property system: 最简单的解决方案是利用QObject的属性系统:

QPushButton * CircleFactory::MyButton()
{
  QScopedPointer<QPushButton> button(new QPushButton);
  button->setIcon(QIcon(":/shape/circle"));
  button->setProperty("identity", ID_LABEL);
  return button->take();
}

Then, in whatever slot you connect to these buttons, you can easily check their identity; 然后,在连接到这些按钮的任何插槽中,您都可以轻松检查它们的身份;

void Foo::buttonClicked() {
  qDebug() << "clicked on:" << sender()->property("identity");
}

That way you avoid the need for global variables. 这样,您就不需要全局变量。

I question the need for the button to identify itself in such a way. 我质疑按钮是否需要以这种方式标识自己。 What I worry about is that you're using the button's identity to then somehow refer back to the circle object or the right plugin. 我担心的是您正在使用按钮的标识,然后以某种方式返回到圆形对象或正确的插件。

Instead, the circle factory should offer a button that is already connected to a proper slot. 相反,圈子工厂应该提供一个已经连接到正确插槽的按钮。 If that's not possible, you'll have to explain further the design and intended function of your "drawing board application". 如果不可能,那么您将不得不进一步解释“绘图板应用程序”的设计和预期功能。 As you might imagine, it's far from obvious how such an application should work - what's obvious to you is not obvious to anyone else. 您可能会想像到,这样的应用程序应该如何工作还很遥远-对您而言显而易见的对其他人而言并不明显。

Another solution would be to extend your geometric figure plugin interface so that only plugins know how their shape is called and how it looks like if it is represented as an QIcon . 另一个解决方案是扩展几何图形插件界面,以便只有插件知道如何调用其形状以及如果将其表示为QIcon则看起来如何。 The appication itself won't know anything about circles or rectangles. 该应用程序本身对圆形或矩形一无所知。

#include <QString>

class GeometricPluginInterface
{
public:
   GeometricPluginInterface() {}
   virtual ~GeometricPluginInterface() {}

   virtual QString name() const = 0;
   virtual QIcon icon() const = 0;

};

On startup of your application you can store all your loaded plugins in a QList (eg QList<GeometricPluginInterface*> m_plugins; ). 在启动应用程序时,您可以将所有已加载的插件存储在QList (例如QList<GeometricPluginInterface*> m_plugins; )。 If you fill your UI with the buttons, you can iterate over the list and create a QPushButton for every plugin with the icon you get from the plugin itself. 如果用按钮填充UI,则可以遍历列表,并使用从插件本身获取的图标为每个插件创建QPushButton You can connect the clicked signal of the button to a slot via a lambda (since C++11) like in the code. 您可以像代码中那样通过lambda(自C ++ 11起)将按钮的clicked信号连接到插槽。

foreach (GeometricPluginInterface *plugin, m_plugins) {
   QPushButton *button = new QPushButton;
   button->setIcon(plugin->icon());
   connect(button, &QPushButton::clicked,
           [this, plugin] {
      geometryButtonClicked(plugin->name());
   });
   ui->buttonLayout->addWidget(button);
}

void GeometricPluginInterface::geometryButtonClicked(const QString &geometryName)
{
   qDebug() << "Geometry clicked: " << geometryName;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM