PDA

View Full Version : Windows 7 tablet--how to get virtual keyboard for text entry?



davethomaspilot
2nd March 2013, 12:09
I'm just now deploying my Qt application on a Windows 7 tablet. I expected the virtual keyboard to come up whenever I touched something like an entry box, but nothing happens.

Is there something easy I can do to get the virtual keyboard (or numeric keypad) to come up, or do I need to do my own widgets for this that are only used for specific platforms (that don't have physical keyboards).

Thanks,

Dave Thomas

wysota
2nd March 2013, 12:45
You need a working input context plugin. I don't know if Qt provides one for Win7 tablets. If not, either search the net or implement your own.

davethomaspilot
2nd March 2013, 22:40
No clue what a "working input context plugin" is, but I like learning new things. If it's a big deal, I can just do my own widget that comes up when the entry boxes (or equivalent) are clicked.

Thanks!

Dave Thomas

wysota
2nd March 2013, 23:32
See QInputContext and QInputContextPlugin.

davethomaspilot
8th March 2013, 15:09
I used this example:

http://qt-project.org/doc/qt-4.8/tools-inputpanel.html

Thanks!

Dave Thomas

Added after 56 minutes:

That works (http://qt-project.org/doc/qt-4.8/tools-inputpanel.html) except I can only add digits, not replace or delete them.

So, I'm trying to add a "clear" or "delete" button. I replaced the "*" button in Qt Designer with one labelled "Clear" and added a dynamic "buttonValue" with value "C". So a signal gets emitted from "MyInputPanel" with a parameter of 'C' when that button is touched

The slot in MyInputPanelContext receives the signal with the QChar 'C'. KeyPress and KeyRelease events are generated for the other buttons and sent using QApplicaiton::sendEvent. I'm not aware of an event that will always map to something that will clear the contents of a spinbox, for example.

So, I'm thinking I'd add a dynamic cast of the widget in focus to each of the widget types for which my application will need the clear function. The call the clear() method after the first dynamic cast that succeeds.

I'm thinking this might not be the "smart way" to do it but I think it will work. Is there a better way?

Thanks,

I used this example:

http://qt-project.org/doc/qt-4.8/tools-inputpanel.html

Thanks!

Dave Thomas

Added after 56 minutes:

That works (http://qt-project.org/doc/qt-4.8/tools-inputpanel.html) except I can only add digits, not replace or delete them.

So, I'm trying to add a "clear" or "delete" button. I replaced the "*" button in Qt Designer with one labelled "Clear" and added a dynamic "buttonValue" with value "C". So a signal gets emitted from "MyInputPanel" with a parameter of 'C' when that button is touched

The slot in MyInputPanelContext receives the signal with the QChar 'C'. KeyPress and KeyRelease events are generated for the other buttons and sent using QApplicaiton::sendEvent. I'm not aware of an event that will always map to something that will clear the contents of a spinbox, for example.

So, I'm thinking I'd add a dynamic cast of the widget in focus to each of the widget types for which my application will need the clear function. The call the clear() method after the first dynamic cast that succeeds.

I'm thinking this might not be the "smart way" to do it but I think it will work. Is there a better way?

Thanks,

I used this example:

http://qt-project.org/doc/qt-4.8/tools-inputpanel.html

Thanks!

Dave Thomas

Added after 56 minutes:

That works (http://qt-project.org/doc/qt-4.8/tools-inputpanel.html) except I can only add digits, not replace or delete them.

So, I'm trying to add a "clear" or "delete" button. I replaced the "*" button in Qt Designer with one labelled "Clear" and added a dynamic "buttonValue" with value "C". So a signal gets emitted from "MyInputPanel" with a parameter of 'C' when that button is touched

The slot in MyInputPanelContext receives the signal with the QChar 'C'. KeyPress and KeyRelease events are generated for the other buttons and sent using QApplicaiton::sendEvent. I'm not aware of an event that will always map to something that will clear the contents of a spinbox, for example.

So, I'm thinking I'd add a dynamic cast of the widget in focus to each of the widget types for which my application will need the clear function. The call the clear() method after the first dynamic cast that succeeds.

I'm thinking this might not be the "smart way" to do it but I think it will work. Is there a better way?

Thanks,

Added after 49 minutes:

Not elegant, but this works:



void MyInputPanelContext::sendCharacter(QChar character)
{
QPointer<QWidget> w = focusWidget();

if (!w)
return;

if (character == 'C')
{

QKeyEvent delPress(QEvent::KeyPress, Qt::Key_Delete,Qt::NoModifier, QString(character));
QKeyEvent delRelease(QEvent::KeyRelease, Qt::Key_Delete,Qt::NoModifier, QString());


QApplication::sendEvent(w, &delPress);
QApplication::sendEvent(w, &delRelease);
return;
}

QKeyEvent keyPress(QEvent::KeyPress, character.unicode(), Qt::NoModifier, QString(character));
QApplication::sendEvent(w, &keyPress);

if (!w)
return;

QKeyEvent keyRelease(QEvent::KeyPress, character.unicode(), Qt::NoModifier, QString());
QApplication::sendEvent(w, &keyRelease);
}

wysota
8th March 2013, 20:45
Basing your solutions on tutorials or examples that have simple usecases in mind often yields bad results -- like in this case.

Why are you trying to "extend" sendCharacter() when in your case it is not true that every keypress yields a new QChar element that should be added to the input? A trivial solution is to connect the "delete" key to a separate slot (or whatever else piece of code you have) that will generate a proper event and send it to the focus widget.


connect(myDeleteButton, SIGNAL(clicked()), myContext, SLOT(sendDelete()));

// ...

void MyInputPanelContext::sendDelete() {
if(!focusWidget()) return;
QKeyEvent delPress(QEvent::KeyPress, Qt::Key_Delete, Qt::NoModifier);
QApplication::sendEvent(focusWidget(), &delPress);
QKeyEvent delRelease(QEvent::KeyRelease, Qt::Key_Delete, Qt::NoModifier);
QApplication::sendEvent(focusWidget(), &delRelease);
}

davethomaspilot
8th March 2013, 23:24
Yes, I like that better.

Thanks!

Dave Thomas

Added after 52 minutes:

Except it doesn't work. focusWidget() is returning zero in the sendDelete() method. Yet, it correctly returns a pointer to the spinBox widget when any other button is pushed in the sample code's "sendchCharacter" . I do have the focusPolicy for the delete button set to "NoFocus".

That doesn't make sense. From the Qt docs:

QWidget * QApplication::focusWidget () [static]
Returns the application widget that has the keyboard input focus, or 0 if no widget in this application has the focus.


Why would the keyboard focus be changing?

wysota
8th March 2013, 23:53
Maybe you forgot to set your button's focus policy in the input panel to NoFocus and it steals focus from whatever had focus before or something like that.

davethomaspilot
9th March 2013, 00:03
No, I did have the focusPolicy to NoFocus for the new button.

I had the send_delete a member function of MyInputPanel when the focusWidget() call was returning null. When I instead made it a member function of MyInputPanelContext (which required making the keypad ui form a public member of MyInput so I could do the connection int the MyInputPanelContext constructor), it works fine.

Don't understand that at all--but not sure I care now that it's working.