I am just starting out with QT. I have read through some tutorials, and I think I have an understanding of signals and slots. I am writing a GUI that has various buttons that change the state of my main program. So for example in a drawing app, you would pick different drawing tools (using various buttons).
What is the best way to go about this? My first thought was to try to connect the clicked signal of the PushButton to some function that sets a current_tool variable. I did some searching and couldn't find a way to connect a QObject signal to a regular function.
This leads me to believe that there is probably a different approach. One where I create a new QObject (my own extension that is) that has various GUI properties. I would then define my slots here for the various buttons.
What is the best way to do this in QT. I am new and do not know of the preferred practice.
Any info would be useful,
thanks
You can define these "normal functions" as slots. Slots are just normal functions that can also be called by signals:
class ToolSelector : public QObject {
Q_OBJECT
public:
Tool *selected;
public slots:
void selectBrush();
void selectPen();
void selectFill();
};
ToolSelector::selectBrush() {
delete selected;
selected = new Brush();
}
ToolSelector::selectPen() {
// ...
}
// ...
toolsel = new ToolSelector();
brushButton = new QPushButton();
connect(brushButton, SIGNAL(clicked()), toolsel, SLOT(selectBrush()));
Inherit from the class that uic generates, creating, say, a MyAppWindow class. Provide extra METHODs in that class, as well as a Document or Drawing object. Connect these methods to the signals you're interested in, and them alter a member variable that contains the drawing state.
Related
My question is how to do proper object/resource management when working with Qt plugins. Default RAII does not seem to work well with Qt.
In our application we work with modules (Qt plugins) that are dynamically loaded at runtime. When loaded plugins can initialize themselves and as part of this initialization phase they can add their own widgets to the application.
- to the toolbar
- to a side panel
- etc.
Widgets that are added to the main windows have their ownership also transferred.
This all works fine, but now that our application grows more complicated we also need to pay attention to the shutdown phase. Simply unloading the modules will get us into all kinds of trouble. Objects that aren't there or types that are unloaded while their objects are still alive.
To have a reliable shutdown it seems that the only proper way to go is to do reverse initialization. This also means that every module that adds widgets to the mainwindow must remove them as well. Already trying to do this with the first widgets got me into trouble.
Module A registers widget W with the MainWindow. Preferably I would want to return a scoped object removing and deleting the widget when going out of scope. However already it seems that given widget W you cannot remove it simply from the toolbar as it works with actions (and removing the action does not delete the widget! See example below).
Concluding, it seems to me Qt is made in such a way that it gets ownership of everything and you have to rely on Qt to delete it. This does not work well with modules. I'm looking for a solution/best practice here.
Edit:
I added an example where a module adds a custom widget to the toolbar of the MainWindow. My goal is that the module is in charge of when the widget is deleted, for the reasons stated before. The example is to make the question more concrete. It represents the generic problem - ownership of qt objects - that use this pattern in combination with plugins.
example:
executable.cpp
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0) {
ui->setupUi(this);
LoadPlugin();
}
void LoadPlugin() {
m_plugin = new QPluginLoader("module.dll");
m_plugin->load();
IModule* moduleInstance = qobject_cast<IModule*>(m_plugin->instance());
moduleInstance->Initialize(this);
}
void AddToolbarSection(QWidget* widget) {
/** ownership is transferred here to Qt */
mainToolBar->insertWidget(pWidget);
}
void RemoveToolbarSection(){
/** How to get the widget deleted? */
}
/** this is called before the destructor */
void UnloadPlugin() {
moduleInstance->Shutdown();
m_plugin->unload();
}
~MainWindow() {
/** deletion of toolbar sections must already been done here
as the modules are already unloaded. Otherwise access violations occur
because specific type information is not accessible anymore.
*/
}
private:
Ui::MainWindow *ui;
QPluginLoader* m_plugin;
IModule* m_moduleInstance;
};
module.cpp
class EXPORT_MODULE IModule : public QObject
{
Q_OBJECT
Q_PLUGIN_METADATA(IID IModuleIID)
Q_INTERFACES(IModule)
public:
IModule() {
}
void Initialize(QMainWindow* window) {
/** QMyToolbarSectionWidget is a custom widget defined in this module (module.dll)
it has a specific destructor and triggers all kinds application
specific cleanup */
m_toolbarSection = new QMyToolbarSectionWidget();
window->AddToolbarSection(m_toolbarSection);
}
void Shutdown() {
window->RemoveToolbarSection(m_toolbarSection);
}
private:
QWidget* m_toolbarSection;
};
That's a bit difficult to answer since it depends on your architecture.
In general Qt's idea of cleanup is tied to the parent pointer. i.e
QObject *root;
QObject *leaf = new QObject();
leaf->setParent(root);
root->deleteLater();
QPluginLoader will even cleanup your root component on unload, so in theory, any tree below your plugin is cleared. Simply make sure that everything you return from your root is a QObject parented to your root. If it's not a QObject, wrap it in QObject.
class MyExtension : public QWidget {
QAction *myAction;
MyExtension() : QWidget() {
myAction = new QAction(this);
}
QAction *getAction() {
return myAction
}
}
from your question i understand you might also be working like this:
class MyExtension : public QObject {
MyWindow * myWindow;
QAction * myAction;
MyExtension() : QObject() {
myWindow = new MyWindow(this);
myAction = new QAction(this);
}
void addToMainThing(TheMainThing *tmt) {
tmt->addWidget(myAction);
}
}
same thing. simply always make sure your QObject is parented to something that is parented to your plugin root.
Cross posting this question on the Qt forum got me the following answer.
Even though Qt takes ownership of QWidgets/QObjects that are added to the Ui, it is still possible to delete them from the client side. Qts resource management system is built in such a way that it will know when a QObject gets deleted and it will handle this deletion by updating the UI as well as removing internal references to it. See the link for more details.
I am creating a QSystemTrayIcon traymenu. Its contextmenu has several actions which I need to identify.
public slots:
void s_showNote();
void Traymenu::createMainContextMenu(){
...
std::string noteTitle = m_noteList[i]->getTitle();
QString menuEntryName = QString::fromStdString(noteTitle);
QAction *openNote = m_mainContextMenu.addAction(menuEntryName);
QObject::connect(openNote,SIGNAL(triggered() ),this,SLOT(s_showNote()) );
QVariant noteID;
noteID.setValue(m_noteList[i]->getID());
openNote->setData(noteID);
The error is
QObject::connect: No such slot QSystemTrayIcon::s_showNote()
All of the code above is a part of my class definition that inherits from QSystemTrayIcon. How can I call the SLOT?
You seem to have at least two issues ongoing:
Use Q_OBJECT for QObject derived classes.
You will need to re-run qmake correspondingly.
As for the first point, please use C++11 and at least Qt 5.2 in the future because in cases like this, you will get a static compiler time error which comes handy for avoiding these tedious issues.
i have an multithreaded qt application. when i am doing some processes in mainwindow.cpp, at the same time, i want to update mainwindow.ui from other thread.
i have mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include "mainwindow.h"
class mythread : public QThread
{
public:
void run();
mythread( MainWindow* ana );
MainWindow* ana;
private:
};
#endif // MYTHREAD_H
mythread.cpp
mythread::mythread(MainWindow* a)
{
cout << "thread created" << endl;
ana = a;
}
void mythread::run()
{
QPixmap i1 (":/notes/pic/4mdodiyez.jpg");
QLabel *label = new QLabel();
label->setPixmap(i1);
ana->ui->horizontalLayout_4->addWidget(label);
}
but the problem is that, i cannot reach the ana->ui->horizontalLayout_4->addWidget(label);
how can i do that?
but the problem is that, i cannot reach the
ana->ui->horizontalLayout_4->addWidget(label);
Put your UI modifications in a slot in your main window, and connect a thread signal to that slot, chances are it will work. I think only the main thread has access to the UI in Qt. Thus if you want GUI functionality, it must be there, and can be only signaled from other threads.
OK, here is a simple example. BTW, your scenario doesn't really require to extend QThread - so you are better off not doing it, unless you really have to. That is why in this example I will use a normal QThread with a QObject based worker instead, but the concept is the same if you subclass QThread:
The main UI:
class MainUI : public QWidget
{
Q_OBJECT
public:
explicit MainUI(QWidget *parent = 0): QWidget(parent) {
layout = new QHBoxLayout(this);
setLayout(layout);
QThread *thread = new QThread(this);
GUIUpdater *updater = new GUIUpdater();
updater->moveToThread(thread);
connect(updater, SIGNAL(requestNewLabel(QString)), this, SLOT(createLabel(QString)));
connect(thread, SIGNAL(destroyed()), updater, SLOT(deleteLater()));
updater->newLabel("h:/test.png");
}
public slots:
void createLabel(const QString &imgSource) {
QPixmap i1(imgSource);
QLabel *label = new QLabel(this);
label->setPixmap(i1);
layout->addWidget(label);
}
private:
QHBoxLayout *layout;
};
... and the worker object:
class GUIUpdater : public QObject {
Q_OBJECT
public:
explicit GUIUpdater(QObject *parent = 0) : QObject(parent) {}
void newLabel(const QString &image) { emit requestNewLabel(image); }
signals:
void requestNewLabel(const QString &);
};
The worker object is created and moved to another thread, then connected to the slot that creates the labels, then its newLabel method is invoked, which is just a wrapper to emit the requestNewLabel signal and pass the path to the image. The signal is then passed from the worker object/thread to the main UI slot along with the image path parameter and a new label is added to the layout.
Since the worker object is created without parent in order to be able to move it to another thread, we also connect the thread destroyed signal to the worker deleteLater() slot.
First and foremost, "you're doing it wrong". Normally you want to create a class derived from a QObject and move that class to a new thread object instead of deriving your class from a Qthread
Now to get onto the specifics of your question, you're not able to directly modify the ui elements of your main GUI thread from a separate thread. You have to connect a signal from your 2nd thread to a slot in your main thread. You can pass any data that you need through this signal/slot connection but you're unable to directly modify the ui element (which in all honestly you probably do not want to if you intend to keep the frontend of your app separate from the backend). Checkout Qt's signal and slot documentation for a whole lot more information
how can i do that?
You've already got the answers to what you should be doing, but not a why, so I'm going to add a why.
The reason you don't modify GUI elements from another thread is because GUI elements are usually not thread-safe. This means that if both your main GUI thread and your worker thread update the UI, you cannot be certain of the order of what happened when.
For reading data generally this can sometimes be fine (e.g. checking a condition) but generally you do not want this to be case. For writing data, this is almost always the source of very, very stressful bugs which occur "at random".
Another answer has remarked on good design principles - not only does constraining your GUI logic to one thread and firing signals to talk to it get rid of your race condition issues, but it also forces you to compartmentalize your code nicely. Presentation logic (the display bit) and data processing logic can then be cleanly separated out, which makes maintaining the two much easier.
At this stage you might think: heck, this threads business is farrrrrr too much work! I'll just avoid that. To see why this is a bad idea, implement a file copy program in a single thread with a simple progress bar telling you how far along the copy is. Run it on a large file. On Windows, after a while, the application will "go white" (or on XP I think it goes gray) and will be "not responding". This is very literally what is happening.
GUI applications internally mostly work on the variation of "one big loop" processing and dispatching messages. Windows, for example, measures response time to those messages. If a message takes too long to get a response, Windows then decides it is dead, and takes over. This is documented in GetMessage().
So whilst it may seem like quite a bit of work, Signals/Slots (an event-driven model) is basically the way to go - another way to think of this is that it is totally acceptable for your threads to generate "events" for the UI too - such as progress updates and the like.
I'm fairly new in QT. Taking below fairly simply explain from qt docs :
class CalculatorForm : public QWidget
{
Q_OBJECT
public:
CalculatorForm(QWidget *parent = 0);
private slots:
void on_inputSpinBox1_valueChanged(int value); //why is that slots are private?
private:
Ui::CalculatorForm ui;
};
and implementation of constructor
CalculatorForm::CalculatorForm(QWidget *parent)
: QWidget(parent) {
ui.setupUi(this); // <-- Question below
}
Q: I was wondering why do we pass this pointer to setupUi function?, what does it do ?
So that the dialog will have the caller as parent, so that eg when the parent is closed the dialog can be closed automatically. Generally all gui elements have a pointer to their parent.
private slots:
void on_inputSpinBox1_valueChanged(int value); //why is that slots are private?
These are auto generated slots which exactly match the naming of the gui elments in QtDesigner. They are only meant to do the direct hookup to those gui elements and so should be dealt with in this class. If these signals were extended to other classes then any change in the gui would require changing a lot of other code which doesn't need to know details of the gui.
In the handler slot for the specific gui element you can then emit another more general signal to the rest of the app.
The only widget that setupUi doesn't create is the widget at the top of the hierarchy in the ui file, and as the Ui::CalculatorForm class instance doesn't know the widget it has to fill, it (this) has to be passed explicitly to the class at some point.
this or any other widget you would pass to it, is used as the parent to all other subwidgets. For example, you could fill a widget without inheritance like this:
QWidget *widget = new QWidget;
Ui::CalculatorForm *ui = new Ui::CalculatorForm;
ui->setupUi(widget);
widget->show();
But really, it would be easier to understand if you read the content of the uic generated file (probably named ui_calculatorform.h).
setupUi creates the instances of widgets (QLabel, QTextEdit and so on). The [user interface compiler] (http://qt-project.org/doc/qt-4.8/uic.html) gets information for you from the .UI form and generates widget-creation code in the generated moc source files.
The manual way of creating widgets without using the Qt Designer or a UI file would be like so:
QWidget* pWidget = new QWidget(this);
I think it is to add the caller widget to the layout of this UI.
This widget will be the toplevel widget.
Martin Beckett answer might be correct as well, as what he described is a common behavior in Qt (cf the 'parent' argument in most of widget's derived class constructor)
Note that you have alternative ways how designer can auto-generate code.
In this case you have a separate 'UI' class for this code which is not QObject so it also is not a QWidget.
Auto generated code needs information about parent widget and to make auto-conections of slots and signals so this is why you have to pass this.
This pater is less intrusive then other pasterns (that is why it is default). You can also try alternative patters (check Qt Creator Designer options), but I recommend you to see what is generated by designer tools in default settings.
I'm wondering how to access parent class in my Qt application.
Lets say my project has following structure:
mainWindow: MainWindow
tabWidget: QTabWidget
tab1: MySubClass1
tab2: MySubClass2
tabWidget: QTabWidget
xtab1: MySubSubClass1
xtab2: MySubSubClass2
It is a little simplified.
What I want to do is to access mainWindows object from one of xtab2 slot functions.
(1) What would be the best method ?
I tried to pass the pointer to mainWindow along the tree but I get runtime errors.
(2) Should I include mainwindow.h in xtab.h file or should I do it in xtab.cpp file ?
Thanks for help :)
If you really need the mainwindow, passing the MainWindow pointer is the best way to do it. A static method has the drawback that it will stop working with more than one mainwindow.
I would suggest to avoid accessing the mainwindow from the contained widgets though and use signals instead. E.g.:
class MainWindow {
public:
explicit MainWindow( QWidget* parent=0 ) {
tab = new TabWidget;
...
MySubSubClass1* ssw1 = new MySubSubClass;
connect( ssw1, SIGNAL(textChanged(QString)), this, SLOT(page1TextChanged(QString));
tab->addWidget( ssw1 );
}
private Q_SLOTS:
void page1TextChanged( const QString& ) {
//do something...
}
};
MySubSubClass1 then emits textChanged(), addresseeChanged() (e.g. in Addressbook), or whatever level of abstraction or detail makes sense on the higher level. That way MySubSubClass is generic and doesn't have to know about MainWindow at all. It can be reused in any other context. If MySubSubClass itself contains other widgets, it can again connect to their signals.
You could create a static method and object inside MainWindow that would return mainwindow object.
Something like this:
private:
static MainWindow* _windowInstance
public:
static MainWindow* windowInstance()
{
return _windowInstance;
}
This seems to be the simples solution in most cases. Now you just have to include mainwindow.h whenever you need to access this object.
And don't forget to initialize _windowInstance in the contructor, like this;
_windowInstance = this;
By parent class, I assume you mean parent widget?
If you want to find the top level widget, QWidget::window() will point you to it. Use dynamic_cast or qobject_cast to turn it into your MainWindow object.
If you want to go up some arbitrary level, use paerntWidget().
There are a variety of different solutions to this problem, the one you chose as the answer is in terms of object orientation and encapsulation one of the worse ones. Some thoughts
Encapsulation: if you find yourself having to provide access accross a large distance in relation (down a long chain of containers or subclasses) you might want to look at the functionality that you are trying to distribute. I might be that it should be encapsulated in a class by itself that can passed around easier than where it is currently located (the main window in your case).
Abstraction: Unless it is actually functionality of QMainWindow that you need to access don't pass a pointer to your MainWindow class, create an interface for the functionality that you need, have your MainWindow implement that interface and pass around and object of the interface type instead of your MainWindow type.
Signals and Slots: As Frank noted, implement the appropriate functionality using Qt's signalling mechanism, this makes the connection between the caller and callee into a dynamic one, again separating it from the actual MainWindow class
QApplication: If you absolutely have to have global information restrict the entry point, you already have one singleton the QApplication object, make it the maintainer of all the other objects that need to be globally accessible, derive your own QApplication class and maintain global references in there. Your QApplication class can then create or destroy the needed global objects.
With more information about what you need to do with the MainWindow instance or what needs to be communicated you will also get better answers
QWidget* parent = this ;
while (parent -> parentWidget()) parent = parent -> parentWidget() ;