Solved Shared Library + UI: Accessing the UI elements
-
I would like to develop a
shared library
that contains a window and UI elements.So, I created:
a) A Qtshared library
project calledmyLib
b) A plugin interface (abstract class) calledPlugin_API
c) Inherit the plugin interface in theMyLib
classHere is the
Plugin_API.h
#ifndef PLUGIN_API_H #define PLUGIN_API_H #include <QtPlugin> #include <QString> class Plugin_API : public QObject { Q_OBJECT public: virtual ~Plugin_API() = default; virtual void showUI(void) = 0; virtual void test(void) = 0; signals: void sendString(QString string); }; Q_DECLARE_INTERFACE(Plugin_API, "com.lamar.plugin") #endif // PLUGIN_API_H
Here is the
MyLib
Class definition:#ifndef MYLIB_H #define MYLIB_H #include <QObject> #include <QString> #include "myLib_global.h" #include "plugin_api.h" class MYLIB_EXPORT MyLib : public Plugin_API { Q_OBJECT Q_PLUGIN_METADATA(IID "com.lamar.plugin") Q_INTERFACES(Plugin_API) public: explicit MyLib(QObject* parent = nullptr); void test() override; void showUI() override; }; #endif // MYLIB_H
Finally, here is the
MyLib
implementation file:#include "mylib.h" MyLib::MyLib(QObject* parent) { } void MyLib::test() { } void MyLib::showUI() { }
Now, I would like to add a GUI window in this
MyLib
class. So, add a*.ui
file.
My question is: How can I add a*.ui
file to thisMyLib
class and be able to access all UI elements like this:void MyLib::showUI() { ui->show(); // Open the UI Window // Access to the UI elements: ui->myButton->setText("Test Button"); ui->myLabel->setText("Test Label"); }
Before I asked this question, I was creating a new
Qt Designer Form Class
and get 3 new files:my_ui_class.h
my_ui_class.cpp
my_ui_class.ui
After that, I was creating a
My_UI_Class
instance inside aMyLib
method, like:#include "my_ui_class.h" void MyLib::showUI() { My_UI_Class ui; ui.setModal(true); ui.exec(); }
The problem with this way is:
MyLib
doesn't have direct access to the UI elements and the UI events/signals likeon_btn_clicked()
.So, I think that should be a better way to add a UI to a
shared library
(in compile time).Could you help me?
Thank you,
-
@fem_dev
Hi
Ah.
Well you could just make its
Ui::My_UI_Class *ui;
public if you want to skip adding access functions to My_UI_Class. -
Hi
Im not sure i understand.
Dont mylib have access to the UI elements via
My_UI_Class ui; ?
Like normal when you create a Qt Designer Form Class ? -
@mrjj said in Shared Library + UI: Accessing the UI elements:
Dont mylib have access to the UI elements via
My_UI_Class ui; ?In this example below...I don't think so...
#include "my_ui_class.h" void MyLib::showUI() { My_UI_Class ui; // ITS NOT POSSIBLE TO DO THAT: ui.myLabel.setText("This is a test"); ui.setModal(true); ui.exec(); }
Is there a way do access
ui
elements inside thisMyLib
method above? -
@fem_dev
But then its not a normal UI struct thing ?
Can you show how its defined as it should be able to work 100% like
in a normal form. -
@mrjj said in Shared Library + UI: Accessing the UI elements:
But then its not a normal UI struct thing ?
Sorry, I believe I am not able to express myself well.
My point is this:
When I create a new project from ashared library
using the Qt Creator IDE, by default, that project does not create any*.ui
files associated with that library. I'm going to call this projectMyLib
.So, if it is desired that this
shared library
has a graphical interface (like a regular form, withbuttons
,labels
, ets ...) it is necessary to manually add a*.ui
file to this project.My question is: How should I proceed to add this
*.ui
file so that I can access all the graphic elements within the methods of the main class (MyLib
).Below is an example of how I would like to access graphics without having to create any intermediate objects (
QWidget
orQDialog
):void MyLib::someMethod() { ui->myLabel->setText("This is a test"); }
How the class MyLib can have a private member like:
Ui::MyLib *ui;
Did I get to express myself better? Is it possible?
-
@fem_dev said in Shared Library + UI: Accessing the UI elements:
it is necessary to manually add a *.ui file to this project.
No, it's not. You can simply use the wizard to add a ui class to your lib project.
Also I'm not sure why anybody else except the class should have access to the internal ui variable. -
Hi
No its not possible to directly add UI files to a LIB as its not a
QObject and cannot send signals etc
so it has to be via a QWidget
So just add
my_ui_class.h
my_ui_class.cpp
my_ui_class.ui
to the project and
use my_ui_class in the lib. -
@mrjj said in Shared Library + UI: Accessing the UI elements:
use my_ui_class in the lib.
Ok...I got the main idea.
@jsulm said in Shared Library + UI: Accessing the UI elements:
Also I'm not sure why anybody else except the class should have access to the internal ui variable.
Let me explain my doubt:
Suppose I do it again the previous way, that is, adding the above 3 files to the
MyLib
project using theQt Designer Form Class
:- my_ui_class.h
- my_ui_class.cpp
- my_ui_class.ui
So, I got this:
#include "my_ui_class.h" void MyLib::showUI() { My_UI_Class ui; ui.setModal(true); ui.exec(); }
When I click on any interface button, a
signal
is sent from the GUI to the UI class and it receives thatsignal
in aslot
calledon_btn_clicked()
.However, I would like to receive this
signal
within some method in theMyLib
class. This has many uses for me like:- Communicate the plugin UI with the
Main App
viaPlugin_API
interface - Allocate memory for the process to be done
- Open / close other components
etc...
How do I get the
on_btn_clicked ()
signal coming from the graphical interface to aMyLib
class slot? -
@fem_dev
Well you can try to make MyLib a QObject and see if that works.#include <QObject> class MYLIB_EXPORT Mylib : public QObject { Q_OBJECT public: Mylib(); };
Then it should be able to send and receive signals.
Im not sure if we get an issues with the event loop but try it and see.
-
@mrjj said in Shared Library + UI: Accessing the UI elements:
Well you can try to make MyLib a QObject and see if that works.
thank you...
Well, many large applications useshared libraries
that contain the GUI.
I would like to know what is the best or "canonical" way to create ashared library
+ GUI and how get the access of the GUI data inside of the "myLib".Is this way correct? Is this the
standard
way?// STEP 0: Create a `My_UI_Class` `private member` inside of `myLib` class class MYLIB_EXPORT MyLib : public Plugin_API { Q_OBJECT Q_PLUGIN_METADATA(IID "com.lamar.plugin") Q_INTERFACES(Plugin_API) ... private: My_UI_Class _my_ui; }
// STEP 1: From myLib call a `My_UI_Class` method to modify a UI parameter #include "my_ui_class.h" void MyLib::someMethod() { _my_ui->setX(100) }
// STEP 2: Now, inside the `My_UI_Class` method, I have acccess to the `ui` elements void My_UI_Class::setX(int x) { ui->mybtn->setText(x); }
In this example above, I have to do 2 steps to modify the UI element. Is this the correct / best way to do that?
Or there is a short-cut way to access and modify the UI elements direct frommyLib
methods? -
Hi
If Plugin_API inherits QObejct then yes it might work.The normal way is to expose QWidgets to the outside world and not have the actual lib
be sort of a Widget itself since its by nature not visual.
And yes, keep My_UI_Class _my_ui; private and provide access functions to the widgets
instead of allowing direct access as that creates a tight coupling with the users of the widgets
and internal structure. (which is unwanted)You never showed what you have inside My_UI_Class so i cant comment on
- Or there is a short-cut way to access and modify the UI elements direct from myLib methods?
-
@mrjj said in Shared Library + UI: Accessing the UI elements:
You never showed what you have inside My_UI_Class
It is just a regular
QDialog
class.
I add some buttons and labels using Qt Designer.#ifndef MY_UI_CLASS_H #define MY_UI_CLASS_H #include <QDialog> namespace Ui { class My_UI_Class; } class My_UI_Class : public QDialog { Q_OBJECT public: explicit My_UI_Class(QWidget *parent = nullptr); ~My_UI_Class(); private: Ui::My_UI_Class *ui; }; #endif // MY_UI_CLASS_H
#include "my_ui_class.h" #include "ui_my_ui_class.h" My_UI_Class::My_UI_Class(QWidget *parent) : QDialog(parent), ui(new Ui::My_UI_Class) { ui->setupUi(this); } My_UI_Class::~My_UI_Class() { delete ui; }
-
@fem_dev
Hi
Ah.
Well you could just make its
Ui::My_UI_Class *ui;
public if you want to skip adding access functions to My_UI_Class.