PDA

View Full Version : Change Focus With Enter Key in TextEdit box



ad5xj
26th July 2007, 16:48
I am using text edit boxes to collect data to store in a SQLite database. In most Windows programs the enter key can be directed to change focus (as in VB). I have not found a way to change focus with the enter key in a text edit box. Trying to capture the key press event has not been particularly successful. There is very little documentation or examples to go by for this particular aspect. The goal is to make a cross platform app (Windows, Vista, Linux, Mac, etc) that works the same on all. I don't want the Windows conventions to dominate but this one is fairly common and expected.

marcel
26th July 2007, 16:49
Read the docs about event filters.
You could catch it if you install an event on the widget.

Regards

ad5xj
26th July 2007, 18:01
Thanks for the obvious. I did read the docs and I did set a filter. But I was never able to trap the enter key. There is nothing specific to this situation - that is why I posted this problem.

If there is something not-so-obvious I am missing please enlighten me.

marcel
26th July 2007, 18:15
First of all, it was not so obvious because you did not mention what method you used to intercept the key press.

Second of all, what key code were you looking for? Because there is a difference between Qt::Key_Enter( the numpad key) and Qt::Key_Return.

ad5xj
26th July 2007, 18:47
Marcel if you read my post it says "In most Windows programs the enter key can be directed to change focus". For windows users there is no difference in the "Return" key and the numeric keypad "Enter" key.

Also, I NOW know that the Qt:Key_Enter and Qt:Key_Return refer to two different hardware keys. I will change the code to look for both and see if it makes a difference.

ad5xj
26th July 2007, 18:55
I still get no response from my code looking for either key. Here is a snippet:


bool MainWindow::eventFilter(QObject *object, QEvent *event)
{
if (object == this && event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Enter)
{
// Special tab handling
qDebug("Enter Key Pressed...");
return true;
}
else if (keyEvent->key() == Qt::Key_Return)
{
// Special tab handling
qDebug("Enter Key Pressed...");
return true;
return false;
}
}
return false;
}

Is this not the correct method?

marcel
26th July 2007, 19:09
Marcel if you read my post it says "In most Windows programs the enter key can be directed to change focus". For windows users there is no difference in the "Return" key and the numeric keypad "Enter" key.
ok,ok.

I see you installed the main window as event filter for itself.
I have never seen that done, but I tend to believe it is incorrect. What is the point in doing that? Are you sure it is getting called? You might as well override keyPressEvent.

An event filter typically is a parent widget. Filtering events means catching them before they actually reach the "watched" object. This is not the case with your implementation because the event is already at the widget, since it coincides with the filter.

Regards

marcel
26th July 2007, 19:13
If you want to filter events for the main window, then subclass QApplication and override it's event filter. I think it should work.

Regards

ad5xj
26th July 2007, 19:15
So are you saying that the FilterObject is not the window? it is the ?what? the text box or is the text box a child widget of the filter - I'm cornfused.

marcel
26th July 2007, 19:19
bool QObject::eventFilter ( QObject * watched, QEvent (http://www.qtcentre.org/forum/qevent.html) * event ) [virtual]
Filters events if this object has been installed as an event filter for the watched object.
In your reimplementation of this function, if you want to filter the event out, i.e. stop it being handled further, return true; otherwise return false.
Example:
class MainWindow : public QMainWindow
{
public:
MainWindow();
protected:
bool eventFilter(QObject *obj, QEvent *ev);
private:
QTextEdit *textEdit;
};
MainWindow::MainWindow()
{
textEdit = new QTextEdit;
setCentralWidget(textEdit);
textEdit->installEventFilter(this);
}
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == textEdit) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
qDebug() << "Ate key press" << keyEvent->key();
return true;
} else {
return false;
}
} else {
// pass the event on to the parent class
return QMainWindow::eventFilter(obj, event);
}
}
Notice in the example above that unhandled events are passed to the base class's eventFilter() function, since the base class might have reimplemented eventFilter() for its own internal purposes.
Warning: If you delete the receiver object in this function, be sure to return true. Otherwise, Qt will forward the event to the deleted object and the program might crash.
See also installEventFilter (http://www.qtcentre.org/forum/qobject.html#installEventFilter)().



No, it is the window, but you just don't do it correctly?
From the code I conclude that you want to filter events for the Main Widnow. Is that so?
See the code bellow. It is an illustration on how event filters should be used.
There, the main window is the filter for one of its children, not for itself( that definitely can't work).

Regards

ad5xj
26th July 2007, 20:58
Ok, the missing piece you supplied was where to install the event filter. I changed my code and now the enter key fires the event filter. However, none of the widgets on the MainWindow show up. I even moved the installEventFilter() to the end of the constructor and still nothing shows on the window - as though the control with the focus was the only one on the form.

marcel
26th July 2007, 21:17
You probably don't let any other events pass either.
Could you post your new event filter?

Events that do not concern you should be ignored by the filter.

Regards

ad5xj
26th July 2007, 21:48
// in constructor
setCentralWidget(txtName);
txtName->installEventFilter(this);
//
////////// event filter /////////////
bool MainWindow::eventFilter(QObject *object, QEvent *event)
{
if (object == txtName && event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Enter)
{
// Special tab handling
qDebug("Enter Key Pressed...");
return true;
}
else if (keyEvent->key() == Qt::Key_Return)
{
// Special tab handling
qDebug("Enter Key Pressed...");
return true;
}
else
{
return QMainWindow::eventFilter(object, event);
}
}
else
{
return QMainWindow::eventFilter(object, event);
}
}
//

I will eventually add four other textedit controls to the statements for the same action.

marcel
26th July 2007, 21:58
The code seems OK.
You do this:


setCentralWidget(txtName);


What other widgets do you refer to?

This makes the text edit take over the entire client area in the window.

To add other widgets:


QWidget *w = new QWidget(this);
QHBoxLayout *l = new QHBoxLayout(w);
l->addWidget(some widget);
l->addWidget(some widget);
l->addWidget(some widget);
...
l->addWidget(txtEdit);
...
l->addWidget(some widget);
w->setLayout(l);
this->setCentralWidget(w);



This is just an example. You can use whatever layout you like.
The point is that in order to add multiple widgets in a main window client area, you need to have a container for them.

This is why you don't see any other widgets.

Regards

ad5xj
26th July 2007, 22:02
Ok I worked it out. I did not need to set the control as the central widget just installEventFilter(). When I changed the code it all worked. Thanks a million for your help.

marcel
26th July 2007, 22:04
You're welcome.