PDA

View Full Version : Posting a QKeyEvent to a QLineEdit



cocheci
30th May 2006, 17:02
I am trying to post a QKeyEvent to a QLineEdit. The line edit seems to receive the event (I have tested this with an event filter), but the character is not displayed in the QLineEdit. Does anyone know why the QLineEdit does not display the character? Here is the code:

main.cpp


#include <QApplication>
#include "TestForm.h"

int main(int argc, char *argv[])
{

QApplication app(argc, argv);

TestForm form;
form.show();

return app.exec();
}


TestForm.h


#ifndef TEST_FORM_H
#define TEST_FORM_H

#include <QDialog>

class QLineEdit;

class TestForm : public QDialog
{
Q_OBJECT

public:
TestForm(QDialog* parent = 0);

public slots:
void postKeyEvent();

private:
QLineEdit* _line_edit;
};

#endif // TEST_FORM_H


TestForm.h


#include <QDialog>
#include <QFrame>
#include <QHBoxLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QSpacerItem>
#include <QVBoxLayout>
#include <QKeyEvent>
#include <QApplication>


#include "TestForm.h"


TestForm::TestForm(QDialog* parent)
: QDialog(parent)
{
QFrame* frame = new QFrame(this);
frame->setFrameShape(QFrame::StyledPanel);
frame->setFrameShadow(QFrame::Raised);

QHBoxLayout* hboxLayout_2 = new QHBoxLayout(frame);
hboxLayout_2->setSpacing(6);
hboxLayout_2->setMargin(0);

_line_edit = new QLineEdit(frame);

hboxLayout_2->addWidget(_line_edit);

QPushButton* button = new QPushButton(frame);
button->setText("Post key event");

hboxLayout_2->addWidget(button);

QObject::connect(button, SIGNAL(clicked()), this, SLOT(postKeyEvent()));


QHBoxLayout* hboxLayout = new QHBoxLayout();
hboxLayout->setSpacing(6);
hboxLayout->setMargin(0);

QSpacerItem* spacerItem = new QSpacerItem(131, 31, QSizePolicy::Expanding, QSizePolicy::Minimum);

hboxLayout->addItem(spacerItem);

QPushButton* okButton = new QPushButton(this);
okButton->setText("OK");

hboxLayout->addWidget(okButton);

QPushButton* cancelButton = new QPushButton(this);
cancelButton->setText("Cancel");

hboxLayout->addWidget(cancelButton);

QVBoxLayout *vboxLayout = new QVBoxLayout(this);
vboxLayout->setSpacing(6);
vboxLayout->setMargin(9);

vboxLayout->addWidget(frame);

vboxLayout->addLayout(hboxLayout);

// Connect the button clicked signals to the form slots
QObject::connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
QObject::connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));

}



void TestForm::postKeyEvent()
{

QApplication::postEvent(_line_edit,
new QKeyEvent(QEvent::KeyPress,
Qt::Key_A,
Qt::NoModifier));
}

jacek
30th May 2006, 17:08
What about this?
void TestForm::postKeyEvent()
{
QApplication::postEvent(_line_edit,
new QKeyEvent(QEvent::KeyPress,
Qt::Key_A,
Qt::NoModifier));
QApplication::postEvent(_line_edit,
new QKeyEvent(QEvent::KeyRelease,
Qt::Key_A,
Qt::NoModifier));
}

cocheci
30th May 2006, 17:15
I had tried that, and that doesn't work either. Additionally the QLineEdit reacts to the press event when the event is sent by the system (i.e. when you press the keyboard character key), it displays the character immediately, before the release event.

Thanks,
Cristian

jpn
31st May 2006, 09:10
QLineEdit uses QKeyEvent::text() for inserting text.


QApplication::postEvent(_line_edit,
new QKeyEvent(QEvent::KeyPress,
Qt::Key_A,
Qt::NoModifier,
"a")); // <-QKeyEvent::text

wysota
31st May 2006, 09:15
Can't you simply use QLineEdit::setText() or QLineEdit::insert()?

cocheci
31st May 2006, 16:39
Can't you simply use QLineEdit::setText() or QLineEdit::insert()?

I could have, but I was just wondering why the posting of the key press event does not work.
My next question is why posting a QMousePress event to the QLineEdit doesn't do the same thing as it does when run interactively (i.e. set the keyboard focus on the QLineEdit).

Thanks,
Cristian

wysota
31st May 2006, 18:41
Because it is QFocusEvent's responsibility.

jpn
31st May 2006, 18:43
It's the OS which is responsible for sending appropriate events. There are separate mouse and focus in/out events. A single mouse event doesn't cause all other appropriate events to be sent (compared to the situation what happens upon a mouse click).

QWidget offers methods for setting focus and QLineEdit (or QTextCursor) offers methods for setting cursor position. Don't try to re-invent a wheel.. ;)

cocheci
2nd June 2006, 20:14
It's the OS which is responsible for sending appropriate events. There are separate mouse and focus in/out events. A single mouse event doesn't cause all other appropriate events to be sent (compared to the situation what happens upon a mouse click).

QWidget offers methods for setting focus and QLineEdit (or QTextCursor) offers methods for setting cursor position. Don't try to re-invent a wheel.. ;)


Because it is QFocusEvent's responsibility.


But ... here's what I'm trying to achieve: I am trying to write automatic unit tests for my widgets by "simulating" the user interaction with the widget. E.g. for a left mouse press I am sending a MousePress event to the widget. Are you saying that's not enough? Are you saying that I cannot automate the simulation of the user interaction with the widget?

jacek
2nd June 2006, 20:16
Are you saying that I cannot automate the simulation of the user interaction with the widget?
You can, but you have to send all events that normally would be sent to that widget. You could use event filter to record all events and then just replay them.

cocheci
2nd June 2006, 21:48
You can, but you have to send all events that normally would be sent to that widget. You could use event filter to record all events and then just replay them.

I tried that, but it didn't quite work as in interactive mode. The LineEdit receives 4 events when the user clicks on it:

Enter
FocusIn
MousePress
MouseRelease

When I send these four events to the line edit, the bliking cursor is displayed (in the LineEdit), but the LineEdit never receives the keyboard focus. I even sent a FocusOut event to the widget that is supposed to lose focus, but the LineEdit still didn't gain focus.

Thanks,
Cristian

jpn
2nd June 2006, 23:56
Looks like it might be impossible to handle it this way. Still if you send a focus event and the widget even receives it, QApplication won't be tricked. Although the widget prepares itself as if it had been focused (like QLineEdit's cursor starts blinking etc.), the next (real) key press event still goes to a widget which the qApp believes that has focus. QApplication updates it's focus widget (QApplicationPrivate::setFocusWidget()) only when a focus event comes from the underlying system, window manager, or focus is set manually by calling QWidget::setFocus().

jacek
3rd June 2006, 00:15
Maybe you could use QtTest module? It has some methods for sending key events.

cocheci
5th June 2006, 14:49
Maybe you could use QtTest module? It has some methods for sending key events.

Thanks Jacek, it looks like this might work, I'll definitely try it. Here's the first phrase from the "Simulating GUI Event" chapter:

QTestLib features some mechanisms to test graphical user interfaces. Instead of simulating native window system events, QTestLib sends internal Qt events. That means there are no side-effects on the machine the tests are running on.

If this works, I'll let you know.

Cristian

cocheci
5th June 2006, 15:54
Thanks Jacek, it looks like this might work, I'll definitely try it. Here's the first phrase from the "Simulating GUI Event" chapter:

QTestLib features some mechanisms to test graphical user interfaces. Instead of simulating native window system events, QTestLib sends internal Qt events. That means there are no side-effects on the machine the tests are running on.

If this works, I'll let you know.

Cristian

This worked, thank you all!!

Cristian