In my application, I have one tableview of items, and a side-panel "preview":ing the latest selected item.
I want clicking on an item to change the selection, and double-clicking to cause a "run"-action to be performed. More specifically, I want the "run"-action (including key-navigation and pressing enter) to be bound to the "activation" of the item in the table-row.
My problem is; single-clicks does not only change the selection, but fires the "activated" signal on the item. I would like to tweak it such that:
Navigation Keys, Single Mouse Click: Selection-change, update preview-panel
Enter Key, Double Mouse Click: Activate/run/open action triggered.
Is there a nice clean way to do it, or are overriding the onclick/doubleclick events my best option? Or is there some other tabular list-widget better suiting my needs?
I would connect the slot for the preview action to the currentChanged() signal of the table view's selectionModel(). This covers single clicks and key navigation.
Then there's two options for the double clicks and Enter key presses:
Subclass your tableview, override doubleClickEvent() and keyPressEvent() and fire your custom signal in there, with maybe the model index or something else as an argument. Then just connect your run method to your own signal as you have full control over when it is fired.
If you don't want to subclass, you can use the installEventFilter() mechanism.
Either I'm getting your approach wrong or I'm too tired, but if you want to trigger a run event you should avoid the activated signal completely. Set the signal slot mechanism so that your double click and Enter key press event trigger your run() function, and then the single click/nav buttons should trigger the 'activated' slot which will return your index in the tableview.
I'm pretty certain Qt wants you to be explicit about which signal points to which slot or it'll ignore it or point to a default.
Related
In my QTreeWidget,
When I single click -> Single click Action has to be performed
When I double click -> double click action has to be performed (it is ok to perform single click action along with it).
But what happens is every time, double click is performed apart from the double click action, two times single click's slot is called.
I don't think this is a desirable behaviour of QTreeWidget in any case.
Can anyone suggest me how to workaround this, hopefully in a short, simple and clean way.
Depending on what you do in case itemClicked is received, you might want to use currentItemChanged as a workaround instead. This might even be helpful for keyboard users. But this really depends on what you want to do after receiving itemClicked.
Suppose I've a Qt app based on QWidget, in which I'd like to obtain a "feedback" everytime I press a QPushButton, I rotate a QDial, I press a mouse button. My question is: how can I set a slot that informs me everytime something happened inside my app built for a touchscreen, in which I need to know when user does something on it.
MousePressEvent partially solves my problem; so when user touches the screen, MousePressEvent warns me about it. Problem is related to widgets as QPushButtons or QDials.
At the moment, I've already arranged my widgets with a lot of subwidgets; number of pushbutton is about 300. How can obtain triggering signal when one of them is pressed without re-edit every single button?
You can use an "event filter" that is installed on QApplication instance. This filter will receive all the events in your application, afterwards you can check event type and object type to pick the events you are interested in. See my answer to another question here for details.
My team is developing an UI for an apparatus with touch screen and we would like it to emit a sound (from a buzzer) each time the user correctly presses a button (so using the release event). Notice that I don't want to play the sound after each click on the interface, but only when the click is over a button.
We use many types of button, sometimes QPushButton and most of the times customized buttons derived from QAbstractButton. In most cases these buttons get an objectName.
So I supposed in order to do that, I would have to catch the MouseButtonRelease event and since I'm already working with a subclass of QApplication to handle excetions, I decided to do this in the notify function.
I tried, then, some methods to recognized when the MouseButtonRelease was related to a button but none of them were successfull. The best one, verifying the receiver's objectName was still not good enought not only because not all buttons had an objectName (which, of course, can be handled), but specially because not always the event was caught for buttons with names set. In other words, sometimes I would click in a button and it recognizes the event and sometimes I would click in the same button and the event is not recognized.
I did some research and another method I found was to set an event filter in the MainWindow, but not all widgets have the MainWindow as their parent which means I would have to Ctrl+c / Ctrl+V the same code time after time when I obviously want something more localized (i.e. in only one spot).
So why it happens that the notify not always handles the events? And how could I do this? Any suggestions are appreciated specially one that is less heavier then handling the events globally.
As info, the other two ways I tried to catch the events with similar or even worst results inside notify were with receiver->inherits("...") and qobject_cast< QAbstractButton* >(receiver).
I have an issue with associating a keypress to a QAction. I'm mapping Enter to an action like this:
myAction->setShortcut(Qt::Key_Return);
The problem is that the QAction is also triggered when I type a value in a QSpinBox and then press Enter. I was expecting the spinbox to consume the event (so it's not caught by the mainwindow) but it's not working like that.
I've seen that I can add a context to my shortcut, I tried all values but this does not solve my issue.
#Matthew It is indeed rejecting the event:
case Qt::Key_Enter:
case Qt::Key_Return:
d->edit->d_func()->control->clearUndo();
d->interpret(d->keyboardTracking ? AlwaysEmit : EmitIfChanged);
selectAll();
event->ignore();
emit editingFinished();
return;
I find this behavior quite strange.
From my knowledge the QSpinBox default behavior does wait until you press return to accept the value. Technically the value is set/accepted as soon as you change it.
If you're looking to change that behaviour, i.e. when you hit return on your QSpinBox you the value is actually set/accepted, then you will most likely have to handle the associated key press event yourself on the QSpinBox and mark it as accepted (i.e. event->accepted() ).
Otherwise, this sounds like it is working as originally designed although not as you want.
I have exactly the same problem, only in PyQt and with QLineEdit
It may be that QActions are always considered menu actions, or global, and have a higher priority than Widget Default keys.
My "solution" was to create a global list of my actions with important keys (Return, Tab, Backspace etc.) as shortcuts.
Then I hook into QLineEdit focusInEvent and focusOutEvent. Each time the event happens I loop over the actions-list and deactivate them all on focusIn and activate them again on focusOut. Then I give the event to the original focus event handlers.
I really hope there is a better solution.
I have a button named 'Start', and when it's clicked, a lengthy operation starts and I want it to change to a button named 'Stop'. The behavior when you click it obviously changes as well. What is the best way to implement this - by changing the button's text and reconnecting the 'clicked()' signal to a different slot, or by having two buttons and then hiding 'Start' and showing 'Stop'.
Both of your options work. A simple third alternative is to change the button text (changing the icon would be a good idea too), and saving the "state" (playing/not playing) somewhere. In your connected slot, just do the Right Thing depending on current state. (That way you don't have to reconnect anything).
Another option is to use the push button with setCheckable(true) set. This way the button acts more like a toggle-button (stays depressed when first clicked, raises back with second click), and combining that with your dynamic text/icon change.
If you use this, you should use the toggled(bool) signal rather than the clicked() one. The slot argument tells you whether the button is "active" or not. (This can also be queried with isChecked().)