I Have a Form with several LineEdits and other Elements and want to jump from one to the next by pressing the return key.
I find Return key instead of/additional to the tab key more user friendly.
I can probably do it if i use returnPressed() and setFocus() but i hope there is a better more elegant solution for this.
Is there a way to modify the built in tab order to also work with
return?
If not, what are the best ways to accomplish the above?
You're probably looking for the event handler. ( QEvent )
Example from the doc
bool MyWidget::event(QEvent *event)
{
if (event->type() == QEvent::KeyPress) {
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
if (ke->key() == Qt::Key_Tab) {
// special tab handling here
return true;
}
} else if (event->type() == MyCustomEventType) {
MyCustomEvent *myEvent = static_cast<MyCustomEvent *>(event);
// custom event handling here
return true;
}
return QWidget::event(event);
}
It's easily adjustable to any key.
For example if return is pressed simulate a tab key press event.
As mentioned, it is more efficient to override QWidget::keyPressEvent
Some code:
protected:
void keyPressEvent(QKeyEvent *event) override;
void MyWidget::keyPressEvent(QKeyEvent *event){
if(event->key()==Qt::Key_Return){
this->focusNextChild();
}
}
Related
Using the mouse events of QWidget it is possible to catch the user's interaction with the widget. However, Qt does not deliver only the resulting action (a click or a double click), but provides the whole sequence of events as it is. Thus, the action should be recognized manually and my question is: How? QMouseEvent::flags() doesn't help much, since the only flag Qt::MouseEventCreatedDoubleClick is never set, as reported here.
In other words, how to properly emit those two signals, defined in the header file of MyWidget (derived from QWidget):
void clicked();
void doubleClicked();
having those slots:
void MyWidget::mousePressEvent(QMouseEvent *event)
{
...
}
void MyWidget::mouseReleaseEvent(QMouseEvent *event)
{
...
}
void MyWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
...
}
By properly I mean that if the user double clicks MyWidget only MyWidget::doubleClicked should be emited instead of MyWidget::clicked followed by MyWidget::doubleClicked;
I met the same problem before. I think it is by design of Qt. This may not be a best solution, but what you can do is to create an event filter and 'wait' for a while:
bool m_bClicked = false;
bool eventFilter(QObject* object, QEvent* event)
{
if(event->type() == QEvent::MouseButtonPress)
{
// Wait for 400 milliseconds
m_bClicked = true;
QTimer::singleShot(400, this, SLOT(eventMousePressTimer()));
return true;
}
else if(event->type() == QEvent::MouseButtonDblClick)
{
// Double-clicked
m_bClicked = false;
return true;
}
return false;
}
void eventMousePressTimer()
{
if(m_bClicked)
{
// Single-clicked
}
}
This is my question. When I edit a cell in a QTableView, I would like that if I press TAB key, the current cell is updated, but the next cell isn't in edit mode.
I have try to create a eventFilter in a table, but it doesn't work. Neither if I create the eventFilter in the editor widget of the delegate.
This is my try of a eventFilter in the QTableView. My idea is that if the current cell is in the last column and row and the current row is not empty, I insert another row (this works fine) and if I am editing any cell, when I press TAB I can place on the next cell but without Edit Mode
This is a snippet of the code:
bool MiTabla::eventFilter(QObject *watched, QEvent *e)
{
if (e->type() == QEvent::KeyPress)
{
QModelIndex indice = this->currentIndex();
QKeyEvent *ke =static_cast<QKeyEvent*>(e);
switch (ke->key())
{
case (Qt::Key_Delete):
{
if (this->selectionModel()->isRowSelected(indice.row(),QModelIndex()))
{
//borrarLineas();
}
else
{
this->model()->setData(this->currentIndex(),"",Qt::EditRole);
}
break;
}
case (Qt::Key_Tab):
{
if (indice.row() == this->model()->rowCount(QModelIndex())-1
&& indice.column() == this->model()->columnCount(QModelIndex())-1
&& !NombreVacio())
{
this->model()->insertRow(this->model()->rowCount(QModelIndex()));
QModelIndex ind = this->model()->index(indice.row()+1,0);
this->setCurrentIndex(ind);
}
else //this doesn't work
{
QModelIndex ind = this->model()->index(indice.row(),indice.column()+1);
this->setCurrentIndex(ind);
}
break;
Thank you. I have solved it as you said.
I have reimplement the eventFilter() function in the delegate class (subclassed from QStyledItemDelegate) as below:
bool DelegadoNombre::eventFilter(QObject *obj, QEvent* event)
{
if (event->type()==QEvent::KeyPress)
{
QKeyEvent* key = static_cast<QKeyEvent*>(event);
if (key->key()==Qt::Key_Tab || key->key()==Qt::Key_Enter || key->key()==Qt::Key_Return)
{
QLineEdit *editor=qobject_cast<QLineEdit*>(obj);
emit commitData(editor);
emit closeEditor(editor, QStyledItemDelegate::NoHint);
}
else
{
return QObject::eventFilter(obj, event);
}
return false;
}
else
{
return QObject::eventFilter(obj, event);
}
return false;
}
This function says to editor of the delegate that if Tab Key is pressed it must commit the data and close the editor but no open the next editor in Edit Mode QStyledItemDelegate::NoHint.
Also, return false for allow to the table use this event
This is a bit of a beginners question but I don't find the solution.
I'm using an own object that inherits from QLineEdit and reiceves numbers as input (which works smoothly now).
Now I want to receive an event, when the user presses the Escape-button. This does not happen with the textChanged()-event. According to the documentation there is no special escape-event. So how else can this be done?
Thanks!
I had this same problem. I am solving it by implementing keyPressEvent in my QMainWindow.
void MainWindow::keyPressEvent(QKeyEvent *e)
{
if (e->key() == Qt::Key_Escape) {
QLineEdit *focus = qobject_cast<QLineEdit *>(focusWidget());
if (lineEditKeyEventSet.contains(focus)) {
focus->clear();
}
}
}
And setting up QSet<QLineEdit *> lineEditKeyEventSet to contain the QLineEdits that need this behavior.
void MainWindow::setupLineEditKeyEventList()
{
lineEditKeyEventSet.insert(ui->lineEdit_1);
lineEditKeyEventSet.insert(ui->lineEdit_2);
lineEditKeyEventSet.insert(ui->lineEdit_3);
}
You can either implement keyPressEvent :
void LineEdit::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Escape)
{
...
}
QLineEdit::keyPressEvent(event);
}
Or implement eventFilter :
bool LineEdit::eventFilter(QObject *obj, QEvent * event)
{
if((LineEdit *)obj == this && event->type()==QEvent::KeyPress && ((QKeyEvent*)event)->key() == Qt::Key_Escape )
{
...
}
return false;
}
When using the eventFilter approach, install the event filter in the constructor :
this->installEventFilter(this);
My task sounds simple: I want to programmatically press keyboard buttons in Qt/C++. So I want some lines of code that makes the GUI think some keyboard keys was pressed.
I do not want to use windows specific API if possible.
Can this be done? If so how/where should I get started?
The only reliable way to simulate/generate a user key event, is to use the QtTest module.
#include <QtTest>
#define QT_WIDGETS_LIB
#include <qtestkeyboard.h>
...
// For example:
QTest::keyClick(QApplication::focusWidget(), key, Qt::NoModifier);
// or even more low level:
qt_handleKeyEvent(widget->windowHandle(), QEvent::KeyPress, key, Qt::NoModifier);
qt_handleKeyEvent(widget->windowHandle(), QEvent::KeyRelease, key, Qt::NoModifier);
bool MyWidget::event(QEvent *event)
{
if (event->type() == QEvent::KeyPress) {
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
if (ke->key() == Qt::Key_Tab) {
// special tab handling here
return true;
}
} else if (event->type() == MyCustomEventType) {
MyCustomEvent *myEvent = static_cast<MyCustomEvent *>(event);
// custom event handling here
return true;
}
return QWidget::event(event);
}
This is a simple example from here. The main idea is that you have to send KeyPress event to your window object. Here is another good example.
How to detect which key was pressed by an user?
Tried to search web but couldn't find really anything interesting.
Thanks.
If you want to detect keypresses globally (useful for application shortcuts etc), you'll need to make one of your QObjects the eventFilter for the application, by first overloading QObject::eventFilter:
bool cKeyPressEater::eventFilter(QObject *Object, QEvent *Event)
{
if (Event->type() == QEvent::KeyPress)
{
QKeyEvent *KeyEvent = (QKeyEvent*)Event;
switch(KeyEvent->key())
{
case Qt::Key_F1:
//do something
break;
default:
break;
}
}
}
...and then installing that object as the eventFilter for your application:
QObject *KeyPressEater = GetYourEventFilterObject();
QCoreApplication::instance()->installEventFilter(KeyPressEater);
Otherwise, as #Mat says above, just overload QWidget::keyPressEvent. You'll need to setFocusPolicy and actually have focus in order to get the key presses.