I'm using a QSlider (v4.6) for input as well as to provide feedback to the user. For the feedback I will be calling the setValue method. I'm trying to find a signal that will fire only if the user modified the value. The valueChanged signal fires when the user changed the value as well as when I call setValue. sliderMoved only fires when the user drags the slider (not when using the keyboard). I checked the API docs and can't seem to find anything. Am I missing something? This seems something that would be common. If there is no other signal, how would you recommend that I simulate this functionality? Should I set a flag before calling setValue, disconnect and reconnect the signal every time I call setValue...?
Good question, I checked the API and also couldn't find a signal that would be triggered only if value was modified by user. The workaround you proposed may be the only option, just keep in mind that you don't have to disconnect / connect all signals, just use QObject::blockSignals method:
slider->blockSignals(true);
slider->setValue(x);
slider->blockSignals(false);
Hope that helps.
Related
I have a combo which is disabled, but adding an element to it will emit the currentIndexChanged(int) signal.
I expected signals to be naturally turned off when a widget is disabled, but it's not the case. I know there is blockSignals(bool), but if there are many widgets whose signals must be "blocked when disabled", blockSignals would require a Boolean state for each widget.
How can I disable the signals sent by a widget when it is disabled (and not alter its blockSignals state)?
EDIT
To clarify: since this is a widget, user cannot interact with it when it's disabled, but some signals are emitted when altering the widget programmatically. In my case there are two interesting signals:
currentIndexChanged(int) and activated(int)
The problem in my code is that I sometimes alter the combo programmatically AND I wish it to emit a signal, and sometimes it's the user that alters the combo by interacting. That's why I am using currentIndexChanged and not activated.
In both cases, anyway, I don't want the signals to be emitted when widget is disabled.
The QComboBox signals are user interaction based from end user point of view if you only have a QComboBox and nothing else as your question seems to imply.
I simply cannot reproduce the issue. I have just made a short program where I cannot get any of the QComboBox signals emitted since I cannot simply interact with the widget.
Edit: It might be a good idea to upate your question with more context for the casual readers, but based on further clarification in comments, yes, programatically it might be the case, but then signals might be useful to process programmatically, too, with corresponding slots, so it is not a major improvement if Qt blocks them automatically.
Luckily, the feature you wish to have is already available:
bool QObject::blockSignals(bool block)
If block is true, signals emitted by this object are blocked (i.e., emitting a signal will not invoke anything connected to it). If block is false, no such blocking will occur.
The return value is the previous value of signalsBlocked().
Note that the destroyed() signal will be emitted even if the signals for this object have been blocked.
If you want to do it for many widgets, create a simple function that you call instead of myWidget->setDisabled(true);:
inline bool disableAndBlockSignals(QWidget *widget)
{
widget->setDisabled(true);
return widget->blockSignals(true);
}
If you want to disable only some of them, say, currentIndexChanged, you can use disconnect manually then.
You can disconnect signals with the QObject::disconnect(); when you want to block them and then reconnecting them when you want to unblock them.
In your case, the signals are the sole source of state information carried on to other objects. If you disable them, the other objects won't ever get any notification that the state was changed. This can cause bugs in the objects that depend on being informed of your widget's state.
There are at least two solutions:
Don't change the widget's state. You can certainly defer the update of the widget's contents until after it gets reenabled.
Create a proxy that monitors the originating widget's state, and queues up the signals (with compression) until the widget gets reenabled.
Due to those workarounds, your design may require a rework. Perhaps it'd be better if you could cope with signals from those disabled widgets. You should also evaluate whether disabling a widget doesn't break the user experience. What if the user wants to see the contents of a widget, but doesn't mean to change the current setting? A disabled widget in such a case is going too far. You can make you own, perhaps subclassed, widget, acting so that the control is not disabled, but the current element stays fixed. This could even be a separate object, applicable to any control - through judicious leverage of the user property.
I am writing a simple GUI, in which I have a ComboBoxText. I write a log message when ever the user clicks on the ComboBoxText.
I have tried almost all the button release and popup signals but no results. The only thing which works is signal_changed() but I don't not need that. Please help me, below is my sample code :
myCombo->signal_button_release_event().connect(sigc::mem_fun(this,&ComboBoxText::ComboInput),false);
and here is the call back function:
bool ComboBoxText::ComboInput(GdkEventButton *pEvt) {
// Here do the desired stuffs !!
return false; }
Use GTK+ property popup-shown. Not sure about Gtkmm syntax, probably property_popup_shown().get_value().
If you need a signal to listen to, connect to popdown or notify::popup-shown (the latter is invoked when property value changes; again, I'm not sure about Gtkmm syntax).
The idea here was to fire an event when the ComboBoxText is clicked. After some readings I figured it out that the ComboBoxText does not fire any on_click event as such.
One could mask a key press event (which by the way gets fired) and call the signal handler. This might not be handy for people who specifically looking for a on_click event but for those who are working with a keyboard or touch screen device. Here is a small chunk of code :`
mCombo.add_events(Gdk::KEY_PRESS_MASK);
mCombo.signal_event().connect(sigc::mem_fun(this,&ClassName::Handler),false);
cheers :)
I am trying to create one event handler for button clicks and connect that to multiple buttons (creating a simple calculator where pressing each number adds its text to the lineEdit).
In C# we would use the sender object which was passed as a parameter and then cast it back to Button and get its Text or other needed property and go on.
I am new to Qt, Do we have such a thing or a similar approach in Qt? Since I couldn't get it out of the signal/slot method of Qt.
On the QObject / QWidget that receives the signal, call this->sender() (QObject::sender()), and cast it with dynamic_cast<MyWidgetType*>(...)
You can find some good examples here for linking back to the issuer of an event.
http://doc.qt.digia.com/qq/qq10-signalmapper.html
They give you different examples for
The sender() Approach (like Jamin Grey's approach below)
The Subclass Approach
The Signal Mapper Approach
I am writing a qt program and have the following requirement.
When 30 sec passed without any click, lock the screen. If someone clicks again after these 30 secs, redirect him to a login screen.
I have read the qt doc about event and I believe that I need either method 1 or 2 to process mouse event.
1.Installing an event filter on qApp
An event filter on qApp monitors all events sent to all objects in the application.
2.Reimplementing QApplication::notify().
Qt's event loop and sendEvent() call this function to dispatch events. By reimplementing it, you get to see events before anybody else.
They also seems powerful to me, but I don't understand their difference.
Which one suits my requirement? Thank You.
You can basically achieve the same thing with either solution except for the fact that QApplication::notify (or its override) will be called before any event filter that may be on your application.
As the first approach does not require subclassing QApplication, it usually is the preferred one.The only reason to override QApplication::notify in your case would be if you needed to override it due to other reasons anyway, e.g. because you need to do anything related to your own custom events.
But looking at your requirements I would personally go for the following solution:
Install an event filter on qApp
Create a timer with a 30 seconds interval
Connect the timer to the lock screen method
Have your event filter reset the timer every time a mouse press is detected.
Dependent on your application you might also want to look for KeyPress events and maybe MouseMove events as well.
I'm New to QT. I understand that you can force a display refresh, but I've pulled all my hair out trying to figure out how. Here is what I'm specifically trying to do.
I press a button (onClick signal event), which runs code that changes an image (QLabel) on the display, waits for input, and then proceeds by changing a new image (different QLabel). I've tried everything and the display doesn't refresh until the onclick signal event code is complete. Right now, I'm not waiting for user input, I'm using usleep(~500 ms) for testing purposes.
From what I read, QT is event driven meaning that I'm basically creating a bunch of events, that get put in a que, and executed when the (onClick signal event) returns to the (main loop)/(event handler). I don't want to wait until the function is complete, it's going to make programming extremely painful if I have to accomplish this routine entirely based on events.
How can I force the QLabel pixmap to refresh. I've tried everything. Below is all the code I have tried in my onClick signal event handler. (upButton is the name of the QLabel which is a pixmap)
update();
repaint();
ui->upButton->setUpdatesEnabled(TRUE);
update();
repaint();
QPaintEvent paintevent(ui->upButton->childrenRegion());
QPaintEvent * test = &paintevent;
paintEvent(test);
this->changeEvent(test);
ui->upButton->update();
ui->upButton->repaint();
ui->upButton->repaint(ui->upButton->childrenRegion());
repaint();
QApplication::sendPostedEvents();
this->parentWidget()->update();
usleep(100000);
As you can see, I'm just shooting in the dark at this point. I've tried to look at sample code and do all my homework, but I'm lost. Appreciate any help, advice, and or sample code.
I was using sleep to emulate a brief amount of time the computer was waiting for something to happen.
As I stated in my question, I didn't want to use events because it's a whole lot of unnecessary work to accomplish something extremely simply.
Also, the 'event' that needs to take place for the program to continue, is a USB event. Since I'm using an HID class device, there is no way to set an event to happen without a wait loop. USB HID classes don't permit setting interrupts, the OS claims the device.
I managed to get the above to work. I walked through the debugger and noticed the display would refresh before the sleep function. Running the program independently, I got random results with the display refreshing 1% of the time. I got rid of the sleep function, and added some other code in it's place to emulate a delay, and it was fine.
Just for everyone's knowledge, this is possible, it's not forbidden, and it's easy to do with the following:
qApp->processEvents();
qApp is a global external variable in the QApplication header.
Because this USB event is making my flow tricky, I stumbled upon the QWaitCondition Class. I was going to start a process waiting for the USB event. I would wait until the process releases the wait condition for my routine to continue.
But if anyone thinks this is a bad idea, please, speak out. I really do appreciate your feedback PiedPiper and Hostile Fork.
Thank you.
I noticed sometimes when you have multiple layered widgets, or widgets inside of widgets it helps to call their repaint() events.
For example
this->repaint();
this->parentWidget()->repaint();
this->parentWidget()->parentWidget()->repaint();
This is far easier then pushing out any processing to another Thread, or creating additional event handlers.
You shouldn't be waiting for input in your event handler. You need to rethink the logic of your program to use events the way they were intended. All the update() and repaint() calls in your code are unnecessary if you return to the event loop.
If i understood correctly, you have a slot and in this slot, you update the image shown in a QLabel. But you want this change to be displayed before the slot finishes.
If that is the case, issue an update() event, and call qApp->processEvents(). This method processes events that are waiting in the event queue and then returns, therefore this may be what you are after.
PS: an update() may not be necessary at all, i am not sure.