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 );
}
Related
What is the difference between hide,close and show of pushbutton or any widget in terms of memory?
Which is better if I don't want to use widget again?
First as said #Hayt, read the documentation.
For the actual answer:
hide() is the same as setVisible(false).
show() is the same as setVisible(true).
close() attempts to close the widget by triggering a QCloseEvent, if the event is accepted the result is:
The same as calling hide() if Qt::WA_DeleteOnClose attribute is not set on the widget which is the default.
The same as calling deleteLater() if Qt::WA_DeleteOnClose is set.
In term of memory, any of the 3 will not change anything (except for close() if you have set Qt::WA_DeleteOnClose). If you do not want to use the widget ever, the best is to delete it:
delete pointerToMyWidget;
or
pointerToMyWidget->deleteLater();
The second form is generally safer as the 1st one can be dangerous depending on where your write it. (e.g you delete it in a slot called by a signal emitted by the widget you delete).
According to Qt, you can read this :
CLOSE :
Closes this widget. Returns true if the widget was closed; otherwise
returns false.
First it sends the widget a QCloseEvent. The widget is hidden if it
accepts the close event. If it ignores the event, nothing happens. The
default implementation of QWidget::closeEvent() accepts the close
event.
If the widget has the Qt::WA_DeleteOnClose flag, the widget is also
deleted. A close events is delivered to the widget no matter if the
widget is visible or not.
The QApplication::lastWindowClosed() signal is emitted when the last
visible primary window (i.e. window with no parent) with the
Qt::WA_QuitOnClose attribute set is closed. By default this attribute
is set for all widgets except transient windows such as splash
screens, tool windows, and popup menus.
.
HIDE : Hides the widget. This function is equivalent to
setVisible(false).
Note: If you are working with QDialog or its subclasses and you invoke
the show() function after this function, the dialog will be displayed
in its original position.
.
SHOW : Shows the widget and its child widgets. This function is
equivalent to setVisible(true).
If you don't need to use your widget, call close(). You can manage the event to destroy your widget.
hide() only hides. It's only graphical, you can't see your widget but you don't destroy it.
But I think that the name fo the function are enough explicit to understand!
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.
In visual studio, when designing a windows form, I can easily add an OnClick event handler for a button by double clicking on it. Is it possible to do the same in QtCreator? How should I handle the Click event of a button? Is manually writing the required code from scratch the only option?
In the designer,
add Push Button to the form
right click the Push Button
select "Go to slot..."
select "clicked()" signal
done
The terms are different from .NET, so in this case we are talking about signals and slots, and the signal emitted when QPushButton is clicked is called clicked() instead of OnClick.
Reading the Qt's documentation about signals and slots is recommended.
In header file:
private slots:
void exit_app();
in xyz.cpp:
connect(ui.button_name, SIGNAL(clicked()), this, SLOT(exit_app()));
define the exit_app() func that SLOT calls.
void QtTest2::exit_app()
{
QApplication::exit();
}
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.
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.