Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Own keyboard doesn't work well on raspberry.



  • Hi, I wrote simply screen keyboard which shows when QTextEdit has focus. In window where I want to input chars i have loop:

    void LoginScreen::loop()
    {
        while(this->isVisible())
        {
            if(ui->login->hasFocus())
            {
                keyboard->activate(ui->login, ui->loginButton);
                keyboard->show();
                keyboard->activateWindow();
                keyboard->raise();
            }
            else if(ui->password->hasFocus())
            {
                keyboard->activate(ui->password, ui->loginButton);
                keyboard->show();
                keyboard->activateWindow();
                keyboard->raise();
            }
            qApp->processEvents();
        }
    }
    

    To close keyboard when user clicks somewhere else i wrote:

    void LoginScreen::mousePressEvent(QMouseEvent *event)
    {
        ui->label->setFocus();
        keyboard->hide();
    }
    

    Keyboard class (singleton):

    Keyboard* Keyboard::instance = nullptr;
    
    Keyboard::Keyboard(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::Keyboard)
    {
        ui->setupUi(this);
        setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
        ile++;
    }
    
    Keyboard::~Keyboard()
    {
        delete ui;
        ile--;
    }
    
    Keyboard* Keyboard::getKeyboard()
    {
        if(!instance)
        {
            instance = new Keyboard();
        }
        return instance;
    }
    
    void Keyboard::activate(QLineEdit *toEdit, QPushButton *toClick)
    {
        this->toClick = toClick;
        this->toEdit = toEdit;
        if(toEdit->echoMode() == 2)
        {
            this->type = 0;
            on_SWITCH_clicked();
        }
        else if(toEdit->text().size()==0)
        {
            this->type = 2;
            on_SWITCH_clicked();
        }
        else if(toEdit->text().size() > 0)
        {
            this->type = 0;
            on_SWITCH_clicked();
        }
    }
    
    void Keyboard::on_Q_clicked()
    {
        toEdit->insert(ui->Q->text());
        if(toEdit->text().size()==1)
        {
            this->type = 0;
            on_SWITCH_clicked();
        }
    }
    
    etc...
    

    So, when i click login lineEdit my keyboard shows and everythink works good. When i click background keybords hides and shows when i click some of lineEdit. But, when I have focused login lineEdit, and then I click password lineEdit it sometimes change focus after one click, sometimes i have to click again. Before i added Qt::WindowStaysOnTopHint on keyboard window everytime i had to click twice to change focused lineEdit. I don't have any idea why it's happening on Raspberry Pi 3B with Raspbian, on windows 10 everythink works perfect even without Qt::WindowStaysOnTopHint. BTW, is there any way to keep Cursor on lineEdit when i shows my keyboard? Now I change background in styleSheet from white to grey to see where am i writing.

    qtvirtualkeyboard is not an option.


  • Moderators

    @Dankal you my dear friend are a maniac by implementing your keyboard this way one core is running on full blast all the time when the keyboard is visible.

    No wonder the pi stumbles with this.

    Whats that loop supposed to do anyway?



  • @J-Hilk Because QLineEdit has no "clicked()" slot, I came up with a replacement for searching if this field has focus, in summary it's a replacement for clicked() to bring up the keyboard when user wants to enter text :)

    Pi does not look like it has a problem with this loop, as I mentioned the combination QLineEdit -> background -> QLineEdit works fine every time, I thought it was a matter of window settings, because the window manager in Windows and Linux I guessing is different


  • Moderators

    @Dankal overwrite the https://doc.qt.io/qt-5/qwidget.html#focusInEvent and https://doc.qt.io/qt-5/qwidget.html#focusOutEvent (its the base class) and show /hide your keyboard according to this


    if this doesn't work quite right, it's been a while since I made this myself, than overwrite the QEvent function itself, that one is definitely called


    #ifndef MYLINEEDIT_H
    #define MYLINEEDIT_H
    
    #include <QLineEdit>
    #include <QEvent>
    #include <QDebug>
    
    class MyLineEdit : public QLineEdit
    {
        Q_OBJECT
    public:
        explicit MyLineEdit(QWidget *parent = nullptr) : QLineEdit(parent)
        {
            connect(this, &MyLineEdit::focusInSignal, this, []()->void{qDebug() << "Focus in event";});
            connect(this, &MyLineEdit::focusOutSignal, this, []()->void{qDebug() << "Focus out event";});
        }
    
    signals:
        void focusInSignal();
        void focusOutSignal();
    
    protected:
        virtual bool event(QEvent *event) override {
            if (event->type() == QEvent::FocusIn)
                emit focusInSignal();
            if(event->type() == QEvent::FocusOut)
                emit focusOutSignal();
            return  QLineEdit::event(event);
        }
    
    };
    
    #endif // MYLINEEDIT_H
    
    


  • @J-Hilk Thank you so much, I had no idea it could be done that way. What I did:

        ui->login->installEventFilter(this);
        ui->password->installEventFilter(this);
    
    ...
    
    bool LoginScreen::eventFilter(QObject *obj, QEvent *event)
    {
        if( obj == ui->login && event->type() == QEvent::FocusIn)
        {
            ui->login->setStyleSheet("color: rgb(0, 0, 0);background-color: rgb(200, 200, 200);font: 75 30pt \"Tahoma\";border-style: solid;border-width:4px;border-radius:30px;");
            ui->password->setStyleSheet("color: rgb(0, 0, 0);background-color: rgb(255, 255, 255);font: 75 30pt \"Tahoma\";border-style: solid;border-width:4px;border-radius:30px;");
            keyboard->activate(ui->login, ui->loginButton);
            keyboard->show();
            keyboard->activateWindow();
            return false;
        }
        else if( obj == ui->password && event->type() == QEvent::FocusIn)
        {
            ui->password->setStyleSheet("color: rgb(0, 0, 0);background-color: rgb(200, 200, 200);font: 75 30pt \"Tahoma\";border-style: solid;border-width:4px;border-radius:30px;");
            ui->login->setStyleSheet("color: rgb(0, 0, 0);background-color: rgb(255, 255, 255);font: 75 30pt \"Tahoma\";border-style: solid;border-width:4px;border-radius:30px;");
            keyboard->activate(ui->password, ui->loginButton);
            keyboard->show();
            keyboard->activateWindow();
            return false;
        }
    }
    

    Now it works as it should, thank you again :)



  • @Dankal said in Own keyboard doesn't work well on raspberry.:

    Now it works as it should

    great, please don't forget to mark your post as solved!


Log in to reply