Make QLineEdit detect Tab Key Press event? - qt

I couldn't find anything in the docs. I found one solution that uses PyQt or something, but I'd rather not have to use that. Also, it would be pretty nice if there was a signal for it, but it doesn't look like there is.

1.When you install an event filter as Sam suggested (m_lineEdit->installEventFilter(this);) you need to handle QEvent::KeyPress and check the key to be equal Qt::Key_Tab:
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == m_lineEdit) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Tab)
{
//do what you need;
return true;
}
}
// pass the event on to the parent class
return QMainWindow::eventFilter(obj, event);
}
2.Another way to do that is to create a new class inherited from QLineEdit and reimplement keyPressEvent:
void LineEdit::keyPressEvent(QKeyEvent* event)
{
if (keyEvent->key() == Qt::Key_Tab)
{
emit tabPressed();
return;
}
QLineEdit::keyPressEvent(event);
}

You should be able to use QObject::installEventFilter(QObject*) to intercept the key press event. There's an example here: http://qt-project.org/doc/qt-4.8/qobject.html#installEventFilter .

Related

QQuickPaintedItem mouseReleaseEvent gets only called after doubleclick

I've derived a class from QQuickPaintedItem in which I want to handle the mousePressEvent and the mouseReleasEvent (and also the mouseMoveEvent but that is not my prolem now).
The mousePressEvent gets called properly everytime the left mouse button is pressed. But the mouseReleaseEvent gets only called after a double click. What I expected is to get the event everytime the button is released. How can I change this?
This is what I do:
MyView::MyView(QQuickItem *parent):
QQuickPaintedItem(parent)
{
setAcceptedMouseButtons(Qt::LeftButton);
}
void MyView::mousePressEvent(QMouseEvent *evt)
{
//gets called after every single mouse click
qDebug("mousePressEvent");
if(evt->button() == Qt::LeftButton)
{
//do something...
evt->accept();
}
else
{
evt->ignore();
}
QQuickPaintedItem::mousePressEvent(evt);
}
void MyView::mouseReleaseEvent(QMouseEvent *evt)
{
//gets only called when releasing the mouse button after a double click
qDebug("mouseReleaseEvent");
if(evt->button() == Qt::LeftButton)
{
//do something...
evt->accept();
}
else
{
evt->ignore();
}
QQuickPaintedItem::mouseReleaseEvent(evt);
}
So I finally found the solution!
Calling the base class implementation is a bad idea since the base class simply calls ignore() on the event. Here is the base class implementation:
void QWindow::mousePressEvent(QMouseEvent *ev)
{
ev->ignore();
}
void QWindow::mouseReleaseEvent(QMouseEvent *ev)
{
ev->ignore();
}
So this is how it works:
MyView::MyView(QQuickItem *parent):
QQuickPaintedItem(parent)
{
setAcceptedMouseButtons(Qt::LeftButton);
}
void MyView::mousePressEvent(QMouseEvent *evt)
{
//gets called after every single mouse click
qDebug("mousePressEvent");
if(evt->button() == Qt::LeftButton)
{
//do something...
evt->accept();
}
else
{
evt->ignore();
}
//DON'T DO THIS:
//QQuickPaintedItem::mousePressEvent(evt);
}
void MyView::mouseReleaseEvent(QMouseEvent *evt)
{
//now gets called with every mouse release since we don't call the base class any more
qDebug("mouseReleaseEvent");
if(evt->button() == Qt::LeftButton)
{
//do something...
evt->accept();
}
else
{
evt->ignore();
}
//DON'T DO THIS:
//QQuickPaintedItem::mouseReleaseEvent(evt);
}

Qt: QMouseEvent - How to get widget

I am using QMouseEvent and QKeyEvents in my program. I programmatically make various widgets (QDockWidgets and QCustomPlots).
I would like to use a single click and keypress handler function. However, I am struggling to get the widget that is actually being clicked, so that I can do certain stuff within that widget.
Is there a way to return from a ClickEvent the name of the widget that was clicked?
You can implement eventFilter in your mainWindow and listen for events from widgets there :
bool MainWindow::eventFilter(QObject * obj, QEvent * event)
{
if((myWidget *)obj == widget1 && event->type()==QEvent::KeyPress)
{
int pressedKey = ((QKeyEvent*)event)->key();
...
}
else if((myWidget *)obj == widget2 && event->type()==QEvent::MouseButtonRelease)
{
if(((QMouseEvent*)event)->button() == Qt::LeftButton)
{
...
}
}
return false;
}
Also do not forget to install event filters for your widgets in the mainWindow constructor :
widget1->installEventFilter(this);
widget2->installEventFilter(this);

How to make a Qt dialog read-only?

How to make a QT dialog read-only? Any general way to implement it easily? For example
(1) set all its containing widgets disable. (how to implement it?)
(2) Intercept edit events like key pressed, mouse pressed but how not to intercept the one to close the dialog?
I think this feature should be very helpful.
Disabling the widgets can be done similar to the following:
void myDialog::disableWidgets()
{
QList<QWidget *> widgets = this->findChildren<QWidget *>();
foreach(QWidget* widget, widgets)
{
widget->setEnabled(false);
}
}
To intercept events, QDialog includes the function installEventFilter(QObject*).
This allows you to use a separate object to receive all events passed to the dialog. You can then choose to handle the event in the object, or pass it on to the dialog itself by calling the base class QObject::eventFilter
class MyEventHandler : public QObject
{
Q_OBJECT
protected:
bool MyEventHandler::eventFilter(QObject *obj, QEvent *event)
{
// handle key press events
if (event->type() == QEvent::KeyPress)
{
// Do something
// ...
return true; // event handled by the class
}
else
{ // ignore this event and pass it to the dialog as usual
return QObject::eventFilter(obj, event);
}
}
return false;
};
QDialog* dlg = new QDialog;
MyEventHandler evtHandler = new MyEventHandler;
dlg->installEventFilter(evtHandler);
Read-only is a strange term to apply to a dialog. Disabling all widgets as above does the trick. If you only wanted to make the input part of a QInputDialog read-only (while leaving scrollbars, buttons, etc. enabled), you could adapt that code as below:
QInputDialog dialog(this);
dialog.setOptions(QInputDialog::UsePlainTextEditForTextInput);
dialog.setWindowTitle("Title");
dialog.setLabelText("Label");
dialog.setTextValue("1\n2\n3\n");
QList<QWidget *> widgets = dialog.findChildren<QWidget *>();
foreach(QWidget* widget, widgets) {
if (strcmp(widget->metaObject()->className(),"QPlainTextEdit")==0) {
QPlainTextEdit *t = static_cast<QPlainTextEdit*>(widget);
t->setReadOnly(true);
}
}
dialog.exec();

auto select first proposition of QCompleter in PopupCompletion mode

I didn't manage to select the first item of the completer when the popup is displayed in PopupCompletion mode.
My current code that doesnt work:
completer->setCompletionPrefix(text);
QItemSelectionModel* sm = new QItemSelectionModel(completer->completionModel());
sm->select(completer->completionModel()->index(0,0), QItemSelectionModel::Select);
completer->popup()->setSelectionModel(sm);
Any suggestions?
I would try changing the order of the last 2 lines:
completer->popup()->setSelectionModel(sm);
sm->select(completer->completionModel()->index(0,0), QItemSelectionModel::Select);
Probably the change of the selection for the popup (its a view) ocurs when selectionChanged() is emited.
So you have to set first the selection model, then do the select.
void QItemSelectionModel::select ( const QModelIndex & index,
QItemSelectionModel::SelectionFlags command ) [virtual slot]
Selects the model item index using the specified command, and emits
selectionChanged().
BTW, u dont have to create a new selection model, just ask the popup for it (Againt, its a view):
completer->popup()->selectionModel();
http://qt-project.org/doc/qt-5.0/qtwidgets/qabstractitemview.html#selectionModel
I don't know if this is what you wanted, but in my case I wanted to be able to press enter and auto-select the first item in the pop-up list (as it does with UnfilteredPopupCompletion).
What worked for me was:
class AutoSelectFirstFilter : public QObject
{
Q_OBJECT
protected:
virtual bool eventFilter(QObject *obj, QEvent *event) override
{
if (event->type() == QEvent::KeyPress)
{
if(static_cast<QKeyEvent *>(event)->key() == Qt::Key_Return)
{
QAbstractItemView* l = static_cast<QAbstractItemView*>(obj);
QModelIndex i = l->model()->index(0,0);
if(i.isValid())
l->selectionModel()->select(i, QItemSelectionModel::Select);
}
}
return false;
}
};
and than:
AutoSelectFirstFilter tmp;
completer->popup()->installEventFilter(&tmp);
PS: Don't forget to re-run qmake.

Respond to application-wide "hotkey" in Qt

I've got a simple Qt app, and I just want to respond to the F12 key, regardless of which widget has focus.
Is there some easy signal or something I can hook in to?
I want to use the F12 key to toggle the main window fullscreen on/off.
I haven't tried, but here is what I would do :
Create a QShortcut and make sure its context (with setContext()) is Qt::ApplicationShortcut.
shortcut = new QShortcut(QKeySequence(Qt::Key_F12), parent);
shortcut->setContext(Qt::ApplicationShortcut);
Then you just need to connect a slot to the QShortcut::activated() signal.
If you have a "central widget" which all of the other widgets are children of, then you can simply set that as the widget argument for QShortcut.
(Python, qt5)
self.centralwidget = QtWidgets.QWidget(MainWindow)
QtWidgets.QShortcut(QtGui.QKeySequence("F12"), self.centralwidget, self.goFullScreen)
I added this as an answer because the shortcut context flag: Qt.ApplicationShortcut did not work for me.
Setting the shortcut context to Qt::ApplicationShortcut has a serious flaw. It will not work in modal dialogs. So if you want a trully real pan-application-wide shortcut, then you need to override application's notify() method. The alternative is to install event filter for the application object but that I suspect would be slower and requires slightly more code. With notify() it is very simple:
class MyApplication : public QApplication
{
// TODO: constructor etc.
protected:
bool MyApplication::notify(QObject *receiver, QEvent *event) override
{
if (event->type() == QEvent::KeyPress)
{
auto keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_F12 && keyEvent->modifiers() == Qt::NoModifiers)
{
// TODO: do what you need to do
return true;
}
}
return QApplication::notify(receiver, event);
}
}

Resources