I am developing embedded application for device with touch screen and need to handle separately single clicks and long presses on QTableView items. Single clicks should open editing dialog, long presses should only select item. The problem is that there is only 'pressed' signal in Qt, and I don't know what is the right way to handle long presses. Could anybody suggest how to do it?
Instead of using QTableView directly, subclass it and then implement the virtual functions: -
void mousePressEvent(QMouseEvent *)
void mouseReleaseEvent(QMouseEvent *)
You can then decide how you want to handle the events, creating a timer to see if a certain time has passed before the release event.
Install an event filter on the view's viewport() widget and process its mouse events. Use view->indexAt() to find out which item was clicked. See also Event Filters.
Related
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'd like to detect a click into a QPlainTextEdit widget. The ultimate goal is to launch a virtual keyboard widget. BTW, the QPlainTextEdit widget is described in a QT ui file and loaded by QUiLoader. I've tried installing an event handler for the QPlainTextEdit widget in order to catch QEvent::FocusIn events. Unfortunately this event is fired repeatedly, and not just once.
Note: I'm using QT 4.8.
Update
I've found a tutorial/example that shows how to launch a software input panel for a text input widget. Unfortunately, the input panel closes immediately after opening. Basically, the event QEvent::CloseSoftwareInputPanel is fired soon after QEvent::RequestSoftwareInputPanel.
If you want to detect just mouse press event, install event filter on the widget's viewport() widget. See QAbstractScrollArea docs for more details.
Usually FocusIn event must not happen repeatedly. May be you have called installEventFilter multiple times for one widget?
May be you still can use FocusIn event and ignore repeating events somehow.
The solution is to trigger a QEvent::RequestSoftwareInputPanel event (see also)
void InputPanel::saveFocusWidget(QWidget *oldFocus , QWidget *newFocus )
{
// check if newFocus is not null or top-level widget or previous widget
// check if newFocus is QPlainTextEdit
QEvent event( QEvent::RequestSoftwareInputPanel );
QApplication::sendEvent( newFocus , &event );
}
I've made my first qt window. Now I'd like to make my first dialog, using qt. I have just finished creating the dialog, which is basically made of a QDialogButtonBox, and now I'd like to connect it to the window. I have two beginner's questions:
How can I retrieve how the dialog was closed (ok pressed or cancel pressed) from the window.cpp, which creates a new dialog, and then calls dialog->show() ?
Where and how to destroy the dialog pointer ?
If you use dialog->show() then I assume it's non-modal dialog.
If you have created QDialogButtonBox and connected its signals with accept() and reject() slots of your dialog as documentation shows, then your dialog will emit finished(int) and additionally accepted() or rejected() signals by which you can determine how it was closed.
If you need more customized behavior, then you can reimplement closeEvent(QCloseEvent *event) or create your own singnals.
If you need to delete your dialog you can use setAttribute(Qt::WA_DeleteOnClose, true);, which will delete instance on close.
you can use one flag, and signal and slot.
when put OK flag=1 , and when put cancel then flag=-1; and then use signal.
in in the window.h write code how to handle that flags with 1 simple slot.
for destroying the pointer you can use signal and slot in your Dialog and tell when user push
Ok, or Cancel , or exit (up- right (red cross)) go to slot in call the Destructer of dialog
and also you that you better set parent of dialog to window.
First Question:
When you want to show the dialog,just construct it,using myDialog *d = new myDialog(this)(the this pointer will make sure that you havn't to delete the pointer you created 'cause Qt will handle this if you specified the dialog's parent). And use d->exec() if you need a modal dialog, or d->show() to make it non-modal;
Second Question:
Once your specified the dialog's parent object, all u need is just use it and leave alone the memory managent,Qt will do this for you. Also you can use d->setAttribute(Qt::WA_DeleteOnClose,true) to make it destroy itself when it is closed.
Remember to link the QDialogButtonBox to your dialog's actions.
I am writing a program in Qt that looks like this:
The main window is my class Window : QWidget, it has a QGridLayout containing four other widgets (Input_Menu : QWidget and Output_Menu : QWidget, and then two Canvas : QWidget)
I would like to trigger certain events when the user strikes a key. The problem is, the Window sometimes loses focus (it goes, say to Input_Menu, or maybe a button in Input_Menu...)
I have tried the following solutions, but they seem unsatisfactory (and dirty):
Give Window the focus whenever it loses it.
Tell each widget who could have the focus to trigger Window's KeyPressEvent function (or a clone of it) whenever it receives a keyboard event.
Ideally, I would like that if a widget receives an event (say a keyboard event) and doesn't know what to do with it, it should automatically call its parent's event handler. I would have hoped this to be a default feature of Qt but it doesn't look like it. On the other hand I am really confused about the whole focus thing, I don't really get what's going on. Can someone explain this to me: I have included a std::cout << "key pressed" << std::endl; in my Window::KeyPressEvent function. When I first run my program, it seems the focus is on the top QComboBox in Input_Menu: if I hit the Up/Down keys, I navigate in that box and no "key pressed" is showed in my console. If I hit most letters, nothing happens. But if I hit Left/Right keys, I do get a "key pressed" in my console!?
Thanks a lot in advance for your insights.
You can install an event filter on QApplication to filter the relevant QEvent::KeyPress events globally. From the Qt documentation:
It is also possible to filter all events for the entire application,
by installing an event filter on the QApplication or QCoreApplication
object. Such global event filters are called before the
object-specific filters. This is very powerful, but it also slows down
event delivery of every single event in the entire application; the
other techniques discussed should generally be used instead.
Besides the performance considerations, remember to check if your window currently has the focus before you filter the key event, or you might break popup dialogs or input into other windows.
Actually, I found that for keys that are modifiers (such as Shift, Control), Qt supports finding out whether they are pressed.
Eg : if(QApplication::keyboardModifiers() == Qt::ShiftModifier) ...
This is good enough.
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.