简体   繁体   中英

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). When button is clicked, application can draw this figure.

I implement this stupidly:

Main application has a QString to identity which figure client chooses. I store a QString *point which point to this QString in factory and write code like this:

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:

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 . 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; ). 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. You can connect the clicked signal of the button to a slot via a lambda (since C++11) like in the code.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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