Search code examples
c++qtfocusqtableviewqtvirtualkeyboard

QtVirtualKeyboard focus problem when editing a cell in a QTableView


I have been battling for the last couple of days to include the QtVirtualKeyboard into my QWidget based app that is running on a Raspberry Pi with a 7" touch screen display.

Here's what I've done so far :

Installed the plugin :

sudo apt-get install -y qtvirtualkeyboard-plugin
sudo apt-get install -y qml-module-qtquick-controls2
sudo apt-get install -y qtdeclarative5-dev
sudo apt-get install qml-module-qt-labs-folderlistmodel

Added the QT_IM_MODULE environment variable and set that to qtvirtualkeyboard

Added QT += quickwidgets to my .pro

Created a QQuickWidget to place my virtual keyboard.

.h

private:
    QQuickWidget *m_quickWidget;

.cpp

// In constructor
QUrl source(QML_FILE_PATH + "virtualkeyboard.qml");
m_quickWidget->setSource(source);
m_quickWidget->setAttribute(Qt::WA_AcceptTouchEvents);
ui->verticalLayout->addWidget(m_quickWidget);

And finally my virtualkeyboard.qml file

import QtQuick 2.7
import QtQuick.VirtualKeyboard 2.1

Rectangle {
    id: window
    width: 600
    height: 0

    InputPanel {
        id: inputPanel
        width: window.width

        states: State {
            name: "visible"
            when: inputPanel.active
            PropertyChanges {
                target: window
                height: inputPanel.height
            }
        }
        transitions: Transition {
            from: ""
            to: "visible"
            reversible: true
            ParallelAnimation {
                NumberAnimation {
                    properties: "y"
                    duration: 250
                    easing.type: Easing.InOutQuad
                }
            }
        }
    }
}

So up to now, visually everything is looking pretty good. When I open my app, the keyboard widget is not visible (window height: 0 in qml), and when I double-click a cell in my QTableView (which has flags Qt::ItemIsEnabled | Qt::ItemIsEditable), the keyboard widget shows up at the bottom of my vertical layout at the right position and size.

And now to my problems :

  • The main problem I have is when I double-click on my editable cell, my keyboard widget shows up and my cell seems to still have focus (blinking cursor is visible in the clicked cell). Up to now all is working well. But when I click a button on the virtual keyboard, the editable cell loses focus, the keyboard widget closes, and I get this error in my application console : InputContext::sendKeyClick(): no focus to send key click - QGuiApplication::focusWindow() is: QWidgetWindow(0x1e68250, name="ConfigWindow") where ConfigWindow is the name of the base widget in my Designer form.

  • Another smaller yet seemingly unsolvable issue I have is that the keyboard only opens up when I double-click a cell in my QTableView. This is a weird one because i set the editTriggers to CurrentChanged in my designer. I know that works because if I single click my cell, the cursor starts blinking and if I use my physical keyboard which is connected to my raspberry, I can edit the text. (Of course, the physical keyboard is only available during the development of my app and won't be available in the finished product).

I hope I have been clear enough, but will gladly provide more details if required.

Any help on either of these issues would be greatly appreciated.

Cheers.

EDIT: Some useful links I have come across:

Qt Virtual Keyboard in QQuickWidget

Resize qtvirtualkeyboard according to QObject

Qt Virtual Keyboard


Solution

  • Ok, so after another few days of all out war with the virtual keyboard, I have finally achieved the desired result.

    After finding this gem of a guide, it turns out that because the widget containing my QTableView and QtVirtualKeyboard was a QDialog that was being displayed using the exec() method, it meant that the window properties wouldn't allow the keyboard to modify my data. And while the solution proposed in the guide didn't resolve my problem, making my widget inherit QWidget did set me off along the path to getting it all working properly.

    I say this because once I changed my QDialog into a QWidget, I then had a console output error saying unknown:0 input method is not set every time I pressed a key.

    The solution to this was to remove the Qt:Dialog flag from my setWindowFlags() method. And maybe most importantly, set the focus policy of my QQuickWidget to NoFocus like so:

    // In constructor
    QUrl source(QML_FILE_PATH + "virtualkeyboard.qml");
    m_quickWidget->setSource(source);
    m_quickWidget->setAttribute(Qt::WA_AcceptTouchEvents);
    m_quickWidget->setFocusPolicy(Qt::NoFocus);
    ui->verticalLayout->addWidget(m_quickWidget);
    

    Hallelujah!! My QtVirtualKeyboard finally sends the clicked keys to my editable cell.

    Finally, to open the keyboard with a single click on a cell in my table, I'm sure there is a better solution than this, but i connected a slot to my QTableView's pressed signal and manually set the visibility of the input method:

    void ConfigWindow::on_tableView_pressed(const QModelIndex &index)
    {
        if ((index.column() == 0) || (index.column() == 1))
        {
            QApplication::inputMethod()->show();
        }
    }
    

    Hope this helps anyone having the same trouble as me with this powerful yet painfully under-documented plugin.