I need to detect when the user release the finger from the screen.
I'm doing an application with SwipeView, but when the finger remove from the screen I need to detect the minimum slide also.
There is a method for this ? Or maybe if I detect when the finger leave the screen on the ApplicatioWindow.
Thanks.
In the very beginning of my QML learning I had a similar problem: I wanted to detect mouse events without interfering with the rest of the application.
It might not be the right solution, maybe it is very bad style or hacky but it works, and might help you.
The idea is to build a C++ item that I use somewhere as parent node to all nodes I want to spy on their mouse events. In this Item I hook in the childMouseEventFilter by reimplementing it as follows:
bool MouseEventListener::childMouseEventFilter(QQuickItem *item, QEvent *event)
{
emit mouseEventHappend();
event->ignore(); // Don't know if that is right. I think I should not have it here.
return QQuickItem::childMouseEventFilter(item, event);
}
In this solution I don't check what kind of mouse event I got, but you might, and emit different signals depending on it.
If used on a touch device, there will be two events you might be interested in:
QTouchEvent
QMouseEvent
Check the QEvent.type() to handle them appropriately. The interesting types are:
QEvent::MouseButtonPress
QEvent::MouseButtonRelease
QEvent::MouseMove
QEvent::TouchBegin
QEvent::TouchCancel
QEvent::TouchEnd
QEvent::TouchUpdate
More: http://doc.qt.io/qt-5/qevent.html#Type-enum
Especially the touch events offer nice information about the start of the gesture and the last leg of the finger movement, that might be of interest to you.
I guess that the best method for your application is to use a ListView with horizontal orientation and delegate is a "page" and now you can detect
ListView is inherited from Flickable and you can detect the mouse event now.
http://doc.qt.io/qt-5/qml-qtquick-listview.html
Related
By default, QDialog windows have a question mark pushbutton in the upper-right corner. When I press it, the mouse cursor is changed to the 'Forbidden' cursor, and nothing else seems to happen.
While there is lots of information generated from those who want to remove the question mark (at least three SO threads are devoted to the topic), the documentation for QDialog doesn't have anything about how to actually use it.
How do I get my application to display information when the question mark is clicked? E.g., how do I get the clicked signal from the button? Better yet, where is this button documented?
The other answers were a bit misleading for me, focusing only on catching the question mark event, but not explaining the normal usage.
When this button is clicked and WhatsThisMode is triggered, the elements of the dialog are supposed to give info about themselves. And if mouse hovers over an element that supports this info then the pointer will become a pointing arrow with a question mark (on Windows at least), with a tooltip message displayed on mouse click.
Here's how to achieve it in PySide:
someWidget.setWhatsThis("Help on widget")
QWhatsThis documentation for PySide and Qt5 is also available.
It is not a button documented by Qt. You can detect this by catching events and checking event type:
http://qt-project.org/doc/qt-5/qevent.html#Type-enum
There are different types as QEvent::EnterWhatsThisMode QEvent::WhatsThisClicked and so on. I achieved something similar to what are you looking for using event filter in mainwindow.
if(event->type() == QEvent::EnterWhatsThisMode)
qDebug() << "click";
I saw "click" when I clicked on ? button.
Based on Chernobyl's answer, this is how I did it in Python (PySide):
def event(self, event):
if event.type() == QtCore.QEvent.EnterWhatsThisMode:
print "click"
return True
return QtGui.QDialog.event(self, event)
That is, you reimplement event when app enters 'WhatsThisMode'. Otherwise, pass along control back to the base class.
It almost works. The only wrinkle is that the mouse cursor is still turned into the 'Forbidden' shape. Based on another post, I got rid of that by adding:
QtGui.QWhatsThis.leaveWhatsThisMode()
As the line right before the print command in the previous.
I'm creating an app with a history like in a web browser: back and forward buttons with a popup menu which is showed on press and hold. The DelayedPopup mode was created exactly for my scenario and it kind of works.
The problem is that the delay used to detect a hold is too short. While I have no trouble with back-forward buttons in, say, Google Chrome, in my app popup menus are popping up regulary when I intend just a simple click.
I suppose setting the delay to a larger value will solve the issue but I can't find a way to do this. The doc says
The default delay is 600 ms; you can adjust it with setPopupDelay()
but it's clearly wrong or outdated info because there is no setPopupDelay in sight.
Any suggestions?
Upd: Though increased delay considerably helped the popup menu still gets shown from time to time. I think there is a bug in Qt.
setPopupDelay was used by Qt 3. Now you have to create your own style by subclassing QStyle or one of its subclasses, and re-implementing the QStyle::styleHint method.
int MyStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const
{
if (hint == QStyle::SH_ToolButton_PopupDelay)
return 1200;
return QStyle::styleHint(hint, option, widget, returnData);
}
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.
I am learning Qt and am trying to paint a simple display for my program with QPainter.
I draw static elements (frames etc.) once and only update dynamic elements afterwards.
Everything works fine, except for when the window loses focus. As soon as that happens, the whole area is cleared (dynamic elements keeps being painted as before).
Is it possible to prevent this behaviour? If not, how do I determine if the window have lost focus?
When your widget is uncovered, the paintEvent member will be called. The event passed in has a region() member that tells you what part of the widget should be redrawn. You can use that to redraw the static parts if/when necessary.
While I did not find why the screen was repainted, the focus can be triggered by using
eventFilter(QObject *, QEvent *event) {
if (event->type() == QEvent::ActivationChange){}
}
and paint function can be called from here. Although a slight delay must be added, as the trigger usually fires before the window looses focus (hence still clearing the repaint).
I want an app's main window to ignore mouse and keyboard events, passing them to applications underneath it in the window manager Z-order.
I see how to make child widgets ignore keyboard or mouse events, but how about the main window?
I'm trying to make a desktop widget that always sits just over the background and is totally invisible to keyboard and mouse events. (Pass through)
Qt::X11BypassWindowManagerHint gets me keyboard pass through (although sadly X11 specific, but fine for now), so how about mouse events?
Is there a OS-agnostic way to be transparent to keyboard events?
EDIT:
The key word here is transparency.
I don't want to EAT mouse and keyboard events, I want the window manager to know I don't want them at all. Those events should be directed to whatever application is under me in the zorder.
For example, I want to be able to click on desktop icons that are covered by my widget and interact with them as if the widget was not there.
I found the following solution (tested on Linux, also works on Windows according to #TheSHEEEP):
setWindowFlags(windowFlags() | Qt::WindowTransparentForInput);
It has been added in more recent qt release (i did not find when)
see http://doc.qt.io/qt-5/qt.html
On Windows you can set WS_EX_TRANSPARENT
To do this in Qt use the following code:
Include the header,
#if _WIN32
#include <windows.h>
#endif
and put the following code into the constructor.
#if _WIN32
HWND hwnd = (HWND) winId();
LONG styles = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, styles | WS_EX_TRANSPARENT);
#endif
Maybe what you want is
widget->setAttribute(Qt::WA_TransparentForMouseEvents)
? That's what QRubberBand uses to let it's parent handle the mouse events. As for keyboard events, a QWidget doesn't get any keyboard events unless it has set itself a focusPolicy().
setFocusPolicy( Qt::NoFocus );
should therefore take care of the keyboard events.
Use Qt's event filters: they will allow your application to eat whichever events you specify (i.e. keyboard and mouse events) but still process other events such as paint events.
bool FilterObject::eventFilter(QObject* object, QEvent* event)
{
QKeyEvent* pKeyEvent = qobject_cast<QKeyEvent*>(event);
QMouseEvent* pMouseEvent = qobject_cast<QMouseEvent*>(event);
if (pKeyEvent || pMouseEvent)
{
// eat all keyboard and mouse events
return true;
}
return FilterObjectParent::eventFilter(object, event);
}
Maybe I'm missing something here, but have you tried subclassing the QMainWindow class and overriding the QWidget::event() method to always return false? If you need to handle some events, you could add that intelligence here as well.
This technique should allow you to inspect the events coming in to the application and ignore them if desired without having to eat them using an event filter.
If this doesn't work you could attempt to redirect the events to the desktop by calling QCoreApplication::notify() and passing the event to the desktop widget obtained by calling QApplication::desktop(). I have no idea if this would work, but it seemed like it might be worth giving a try.
I think that overriding is supposed to work:
bool YourMainWindow::event( QEvent *event )
{
event ->accept();
return true;
}
that's some of what the QWidget class documentation says about event() member function:
This function returns true if the
event was recognized, otherwise it
returns false. If the recognized event
was accepted (see QEvent::accepted),
any further processing such as event
propagation to the parent widget
stops.