If I want to make a connection in Qt as follows:
QObject::connect(quitButton, SIGNAL(clicked()), &myapp, SLOT(quit());
What does &myapp refer to here? Why should it be used?
Thanks.
In this case what you get is that whenever the quitButton sends the signal clicked it will be sent to the slot quit in myapp. If the names mean what I think this is probably a button to, well..., quit your app.
Notice there are different versions of connect. It's hard to get the context from a single line of code, but anyway you might wanna check qApp which already represents your application.
EDIT: From another post from you I noticed you asked a trivial question about pointers. So if this is more about what the &character means, it takes the address of your object. This is pure C++ (nothing specific to Qt).
What does &myapp refer to here? Why should it be used?
This is the object that will handle the signal (The & takes the objects address (ie. the underlying code uses pointers).
QObject::connect(quitButton, SIGNAL(clicked()), &myapp, SLOT(quit());
Translation:
When the signal clicked is activated on the object quitButton
Call the slot quit on the object myapp.
What this means:
A signal is just a method that is called by the object when certain internal state changes. In this case the object will call signal when the user interfaced element is clicked on by the mouse.
The signal method will then call all (slot) methods that have been registered. So in this case when you click on the button signal() is called this in turn will call the quit() method on the object 'myapp`.
Given the way QT examples are normally done. myapp is an application object and the quit() method will cause the main thread to exit from the call to exec().
Related
I would like to understand a simple piece of code I came across. It is a connection between an object of the interface and two signals.
The code is:
connect( ui->checkbox_legEnabled,
SIGNAL( stateChanged( int ) ), SIGNAL( edited() ) );
What is the meaning of this line of code?
Thanks,
Sara
With Qt signals and slots, you can directly connect one signal to another signal (or non-signal member function), without having a slot in between. See connection function invoked here is this overload of QObject::connect.
This line of code hence means, whenever the object ui->checkbox_legEnabled (presumably some kind of QCheckbox) emits the stateChanged signal (that has an int parameter passed along), directly emit another signal (or ordinary member function) edited (without parameters).
Short answer is you can connect a signal to another signal and that means that the second signal will also emit whenever the first signal is emitted, read more about signals and slots in the documentation here, also check out the new way to call connect (with function pointers)
Now in your case what it does it's basically allows you to keep the ui private, but in the same time forward the signals you want to the outside of your object, by allowing other objects to connect to the signal(s) you provide in the interface.
Incomplete usage example (based on your code, i named the class that contains your code MyWidget): the main-window (or whoever) that has access to your widget can be notified whenever something changes inside, by connecting to the edited signal:
void MainWindow::createMyWidget()
{
m_myWidget = new MyWidget(this);
connect(m_myWidget, &MyWidget::edited, this, &MainWindow::myWidgetWasEdited));
}
This way whenever something changes inside MyWidget the MainWindow can be notified about the edit and it can take the necessary actions inside the myWidgetWasEdited slot.
This can be expanded, if needed, to provide an signal for each particular "edit" instead of a single generic edited signal (but this depends on your needs).
I am new to Qt. I have worker thread that is an std::thread. The worker thread function continuously fetches some some data in a loop. The size of the data is frequently updated on a Text element on a QML UI. I have a listener callback which is nothing but an std::function and it gets called from the thread's function. It sends me callbacks based on which I updated the Text element on QML. I update it using signal slot mechanism.
Following is the QML : Text element:
Text {
id: mytext
objectName: "mytextobject"
function slotUpdateData(someValue){
mytext = someValue
}
}
SignalUpdateData is connected with slotUpdateData which resides on QML side. Every time I get the data event callback from the std::thread, I emit SignalUpdateData which updates the QML Text element on UI.
void CallBackReceivedFromWorkerThread(float someValue) {
emit SignalUpdateData(someValue)
}
Following is how I have connected this C++ signal with the QML slot
QObject::connect(this, SIGNAL(SignalUpdateData(QVariant)), myTextItemQObject, SLOT(slotUpdateData(QVariant)));
And all of this works fine. No crashes, lock-ups, nothing.
As per my understanding, since the worker thread's function is triggering the callback, the execution control is on the worker thread when the callback is received. So when doing emit SignalUpdateData(someValue), we'er still on the worker thread. And as far as I know from my previous experience in android & java, we cannot update the UI from anywhere outside the main thread of the application.
So, How is this working ? Is emit SignalUpdateData(someValue) putting the call into the main UI thread's event loop ? Is Qt still making the UI change on main thread in spite of me calling for it from a worker thread ? If my approach is fine, then does it have performance implications ? What is the best recommendation to do this ?
I want to be very sure about this & not just lucky about making this to work. Should I use a Qt::Connection_enum as well for best approach ?
You're leveraging Qt the way it was meant to be! And you've run into it accidentally: that's a sign of a decent design - it "just works". Hooray for you, hooray for Qt :)
It's working because Qt has been designed specifically to make it work, and you're using the default automatic connection whose raison d'être is to help you out in this specific case. So you happen to be doing everything right: change nothing!
When you emit a signal, Qt acquires relevant source and destination object mutexes, and compares the receiving object's thread() to QThread::currentThread(). If they are identical, the slot/functor is called immediately: it happens in the body of the signal, so the slot is called before the signal returns. This is safe as the target object is used from its thread(), where it's safe.
If target->thread() != QThread::currentThread(), then a QMetaCallEvent is queued to the target object. The event contains the (equivalent of) slot method pointer and a copy of any parameters passed by the slot. The QObject::event implementation handles the event and executes the call. The target object thread's event loop is on the call stack, since its job is to deliver the queued events to the object.
The above is, in a nutshell the meaning of a Qt::AutoConnection. If you're using Qt::QueuedConnection, the 2nd case applies no matter what the threads are. If you're using Qt::DirectConnection, the 1st case applies no matter what.
My guess is that >95% of the uses of a non-automatic connection type in Qt-related questions on SO are unnecessary and stem from lack of understanding and resorting to what amounts to magic incantations.
I know how to call a signal from inside the class where the signal is located: by using emit. But what if I want to call it externally, from the parent object?
The reason why I want to do is is because a given QPushButton is connected to a slot which picks the button that called it by using sender(). Now I want the same functionallity of that slot to be called but not after a manual click in the button, but from within the code itself. Normally I would just programatically call for the slot, but because of the usage of sender(), that way is invalid: calling the slot directly will not give it the id of the button.
So how could I "externally" ask for the object for it to emit one of its signals? That is, how can I make my QPushButton emit its clicked() signal from within the code, not by clicking the button with the mouse?
You cannot emit signal directly from the parent object.
Only the class that defines a signal and its subclasses can emit the signal. (http://qt-project.org/doc/qt-4.8/signalsandslots.html#signals)
You can define a method in your QPushButton emitClicked() where you emit the signal. Then you call emitClicked() on instance of your QPushButton from the code.
The Qt headers contain this interesting line (in qobjectdefs.h):
#define emit
Which means that presence or absence of the emit keyword has no effect on the code, it's only there to make it more obvious to the human reader that you are emitting a signal. That is to say:
emit clicked();
is exactly the same (as far as the C++ compiler is concerned) as
clicked();
Given that, if you want your button to emit its clicked() signal, it's just a matter of doing this:
myButton->clicked();
(although if you wanted to be clever about it, this would work equally well):
emit myButton->clicked();
Seems that Qt Test module is just for this case.
Check out this tutorial on simulating GUI events.
Basically you use QTest::mouseClick and pass pointer to your push button.
I'm working on a tool, on the main window of the tool there are few Qt widgets added on it.
When we used to RMB click on the Qt widget, a context menu pops up (and via eventFilter few functions have been called) to do the required work- say, doTask() slot gets called up with the receiver object.
Now I have to add a banner menu on the window, which has to copy all the features of RMB context menu.
Since this banner menu is not of Qt, but written in some internal functions (say, LISP) I have problems in calling that slot function - doTask(), as I don't know what is the receiver object.
How can I communicate with a Qt widget through some external command/language?
Please add comment if anything is not clear in this.
Can you not expose a simple C style method from a QT aware object that acts as a proxy for the slot calls. ie Your banner calls method, method then calls appropriate slots?
Your basic problem is just knowing the receiver object. Once you do, you can call its slot directly (doesn't need to go through a signal).
The menu knows this, because it keeps a pointer to the receiver object. Your own banner menu must do the same. "It doesn't know the receiver object" must therefore be fixed.
I am developing Qt application (Qt version 4.7.3) on SBC6000x board.
I have a MessageBox class derived from QDialog. I have made this class singleton.
Whenever a messagebox is to be show I am using .exec method to show it.
There are few places where I need to show messageboxes one after another.
So, to show new messagebox, I have to close previous one and show new one.
e.g. When Messagebox is open and at same time I receive an error from background I have to close the messagebox which is currently shown and show the one with error.
To closes previous dialog I have exposed CloseDlg method from messagebox class and trying to close it.
Inside this CloseDlg I am emitting finished signal.
void CMsgBox::CloseDlg()
{
if (NULL != CMsgBox::m_msgBox)
{
if(CMsgBox::m_msgBox->isVisible())
{
emit CMsgBox::m_msgBox->finished(0);
//QApplication::processEvents();
}
}
}
and calling it as
CMsgBox::CloseDlg();
My show method is :-
int CMsgBox::showMsgBox(Icon icon, const QString &textMsg, const QString &okBtnText)
{
if (CMsgBox::m_msgBox == NULL)
{
CMsgBox::m_msgBox = new CMsgBox();
}
CMsgBox::m_msgBox->setText(textMsg);
CMsgBox::m_msgBox->setIcon(icon);
CMsgBox::m_msgBox->setOkBtnText(okBtnText);
CMsgBox::m_msgBox->exec();
return CMsgBox::m_msgBox->m_btnPressed; //return, unblock the call
}
Again when I call showMsgBox,it is showing me following warning.
QDialog::exec: Recursive call detected
Problem is, it doesn’t return from previous exec call (unless we return, as commented above //).
I tried same with close(), accept(), reject() methods instead of finished() event but nothing worked.
What is the way to return from previous exe call and achieve above scenario? Any help is welcome.
What you have here looks like a race condition. A modal QDialog runs its own event loop, so your application behaves like a multithreaded application and you need to take care of concurrency and race conditions.
When you receive a second in your main event loop, you call CMsgBox::CloseDlg() and CMsgBox::showMsgBox() in quick succession. However, CloseDlg() tells the dialog's event loop to return, but CloseDlg() actually returns before the dialog's event loop is done cleaning up, and showMsgBox() attempts to call exec() on a dialog which hasn't finished exiting yet.
What you need to do is, when you call CMsgBox::CloseDlg(), connect to the finished(int) signal, and only when you receive the finished(int) can you safely exec() the dialog again.
NOTE: When connecting to the finished(int) signal, make sure to use a Qt::QueuedConnection instead of a Qt::DirectConnection which is the default.
So, you need modeless dialog box. As explained in their documentation :
Modeless dialogs are displayed using show(), which returns control to the caller immediately.
Therefore, instead of showing the box with exec(), show it with show().
Alternative to show() method suggested in another answer is, use QDialog::open(). It will return, but will still give you modal dialog, so the rest of the GUI will be disabled until you close it.