I am trying to reimplement or modify a tab code in a gui application. They are currently using Qt signal and slots system to handle addition and removal of tabs from the tab bar (For example if a tab was being drag from one tab widget to another, the old tab widget will signal the new tab widget that a new tab is coming). I was thinking rather than using that, I could simplify things using a thread safe singleton class. Then when ever a tab is moved, the widget just call on the singleton rather than emitting a signal.
Thanks
Signals and Slots.
Without even starting why the singleton would be bad, the way the data is updated inside Qt would be messed up by the singleton approach.
Don't do that. You are working within an environment and should use the mechanism the framework provides. What about if the UI in the future will have multiple windows and maybe multiple instances?
If possible you should always try to use the way from the framework you are using. This will also help in the future for the maintenance (upgrades, new hires, etc.)
You want to use a singleton, which will accept messages and dispatch them back ? (note: if you use a garden variety object instead of a singleton, you're essentially implementing an Observer pattern).
Then you are reinventing signals and slots, which use a global state internally. Instead of putting work in reinventing some difficult piece of code, why don't you use the already existing signals and slots ?
Related
I am new to QT. As far as I can see, there are two ways to connect signals and slots with each other. One way would be using the connect method. When e.g. wanting to put a method ButtonReleased() to the slot that is triggered after the released() signal of a pushButton with name pushButton, one could write:
connect(ui->pushButton, SIGNAL(released()), this, SLOT(ButtonPressed()));
However, as far as I see, one could also define a method with name on_pushButton_released() to achieve the same connection. Is there any difference between both methods and if so, which one is preferred?
Thanks in advance!
There are indeed two main ways to connect signals to slots.
The first one, using the connect method allows to connect any signal to any slot (or signal) as long as the function signatures match. This is the main way to connect signals in Qt.
The second way are member methods that are called on_ObjectName_SignalName(). These are automatically connected by Qt, if a UI element called ObjectName exists and has a signal called SignalName. This is specifically meant for the use case of having some Widget with a separate .ui file, which contains these elements that you want to connect to. As such, this mechanism does not work if you create UI elements "by hand" in your C++ code.
As you can see, the second mechanism has very specific requirements that need to be satisfied to work, although these are not uncommon. So if you have satisfied these conditions I see no Problem in doing it this way, but others may disagree and this is largely personal preference.
Also note: The syntax in your question is the old syntax from Qt4. If you are using Qt5 and newer, it is highly advised to use the new syntax.
You can read more about signals and slots on the Qt Documentation.
Since creating widgets takes a lot of time, I try to create widgets in different threads and add them to the main layout, but that fails. When creating widgets and then adding them sequentially, the program works normally. Notifications I received: "QObject::setParent: Cannot set parent, new parent is in a different thread"
Is there a way to do it?
No, there is no way to do it.
Qt GUI classes including QWidget must be used only from the main thread.
Quoting Qt documentation:
Although QObject is reentrant, the GUI classes, notably QWidget and
all its subclasses, are not reentrant. They can only be used from the
main thread. As noted earlier, QCoreApplication::exec() must also be
called from that thread.
This is enforced in Qt code by a Q_ASSERT_X when you construct a QWidget:
Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget",
"Widgets must be created in the GUI thread.");
So, even if you would find some work around to make it work, you would not have any guarantee that your code will work in a reproducible way and that any Qt update will not break your code.
Regarding your specific problem, creating widgets should not be time consuming. I can think of 2 reasons why it would be time consuming:
Your widgets are doing heavy computation when you create them. Then you shoul put the computation, and only the computation, in another thread.
You are creating a lot of widgets in one shot. The you can deffer the creation using the event loop. Basically, you create some widgets then post an event or set a timer that will create some more widget, etc. until you meet some stop conditions.
Typical situation: you have an application, that save and load preferences
(save and load handled by class Config).
Imagine there's such a preference for fonts of some GUI elements.
So we have
struct Font;
struct Config {
const Font& getFontForSpecificGUIElement() const;
//save to disk if Font changed
void setFontForSpecificGUIElement(Font);
};
Whenever the font is changed I need to inform all instances of class SpecificGUIElement of that change.
How can achieve such notification functionality?
To keep Config simple I want to decouple that functionality. Besides, there will many properties like this (30-50 of them).
So in general I want:
Not require implementing virtual interfaces
I don't need thread safety
Convenient registration of event handlers
I need notification for new subscribed receivers, with last recent
notification if were any (I mean, as in my example Font changed, and when new GUI elements subscribe on such event, they receive, event automatically triggered for them, and they receive last variant of Font)
Convenient registration of event type (I mean in item above
we create some kind of value cache, so it should be simple add new one)
I suppose this is common enough requirements, so may be there already solution,
in popular C++ libraries, like boost ?
Update:
Why Qt not suitable for me. I see two approaches
with Qt, QEvent subsystem. But because of it is impossible
send event to unknown listeners it is no go. Why not signal/slots, first you need inherit QObject, second to implement (4), I have to create MessageBus class to cache last values, and adding new events starts require to much work:
add data field, add new signal, add function(X) to emit new signal, because of signal actually protected functions,
plus in (X) i need compare last value with new one.
Yes, this alsready exists in e.g.:
Boost Signals2
http://www.boost.org/doc/libs/1_59_0/doc/html/signals2.html
There are many samples that should get you going.
Signals2 does offer thread safety, but I guess that doesn't harm.
Alternatively,
Qt
Qt does have a signals/slots implementation, as do many other UI frameworks:
http://doc.qt.io/qt-4.8/signalsandslots.html
I'm trying to create a signal and slot in Qt4 and I am fairly new to Qt. From what I understand in Qt5 it is just created automatically and this is not the case in Qt4 it seems. I'm trying to create a an action when the user clicks on an option in the menu bar at the to of the UI.= I see that there is a Signal/Slot editor at the bottom of the screen with options "Sender", "Signal", "Receiver", and "Slot". I'm not entirely sure how to use this function. Any help is appreciated.
Basically you need to connect your signal and slot
connect(ui->button1, SIGNAL(clicked()), this, SLOT(yourSlot()));
and in this link there is good example about signals and slot: signals and slots in qt.
You seem to have misunderstood.
The difference in Qt 5 is that it offers new syntax to make the connections.
The connection is "automatic" when you don't specify the connection type, i.e. direct, queued, etc, the default is automatic, which makes Qt check the object's thread ownership and select the appropriate connection type.
Connections must either be explicitly made in code, or be made using the UI editor, and while the latter may save you some typing in some cases, in general most of the connections you end up making are explicit in code, so you better learn how to do it, because the UI editor can help you only in a few corner cases. I haven't really used the UI editor for connections, and have tried it once or twice years ago, but the limitation I think is that you can only make connections between UI elements and signals and slots of the widget.
Consider that signal and slot connections are not merely a UI thing, it is a core principle in Qt and UI is just one of its many uses.
QMenu can be created by using popup() or exec(). The former creates it asynchrously while the latter blocks. But this isn't useful when you're using a QMenuBar (AFAIK).
My question is, is it possible to tell QMenuBar to only popup asynchrous/modeless QMenus? I'm not sure the terms are correct, but all I want is a Menu that won't block the rest of the application when users click on it.
The workaround you're looking for is to move your objects that can't live with such "abuse" to a separate QThread. If you have a clean interface using signals and slots, this is trivial. Just use moveToThread() and you're done. You don't need to worry about anything else.