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

No cursor in QLineEdit after FocusIn event



  • Hi. I have a problem with QLineEdit.

    I need to call selectAll() after QLineEdit instance gets focus. So I made a custom class to use the appropriate event.

    The problem is, right after the overrided focusInEvent() is inserted into code, the cursor in this LineEdit stops working as it should, and the selection won't show (the one which should appear after selectAll() ). If I click LMB into LineEdit, nothing visibly changes, no cursor. The cursor appears after pressing arrow keys on keyboard, but it doesn't blink. If I click RMB into LineEdit, the selection appears, but the cursor works wrong still.

    If I check the cursor's position on focusInEvent, it says it's at the end of a value, as if everything is selected.

    I also tried calling a different method instead of selectAll(), namely clear(), and it works.

    So I'm wondering if I'm missing something that I should do, or this is potentially a bug.

    In this help article, it says that default focus event updates the widget:
    "[virtual protected] void QWidget::focusInEvent(QFocusEvent *event)
    ...
    The default implementation updates the widget (except for windows that do not specify a focusPolicy()).
    ..."
    But I tried calling update() for the LineEdit in different ways, and the problem persisted.

    QApplication::cursorFlashTime() is 400 , if it matters.

    Any help would be appreciated.

    I'm on Windows 7 64-bit
    Qt Creator 4.10, Qt 5.13.1 (MSVC 2017, 32 bit)


  • Lifetime Qt Champion

    Did you actually call the base class (QLineEdit::focusInEvent())? Please show us some code.



  • The code

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include "ui_mainwindow.h"
    
    #include <QMainWindow>
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private slots:
        void on_cmnd_tlk_file_open_triggered();
        void on_strings_table_itemSelectionChanged();
        void on_cur_str_number_field_returnPressed();
        void on_num_field_focus();  // slot to select all in LineEdit
    
    private:
        Ui::MainWindow *ui;
    
    };
    #endif // MAINWINDOW_H
    

    mainwindow.cpp

    #include "main.h"
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "tlk_functions.h"
    #include "number_input_field.h" //custom class
    
    #include <QSplitter>
    #include <QDebug>
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        QSplitter *window_splitter = new QSplitter(Qt::Vertical, nullptr);
        window_splitter->addWidget(ui->strings_table);
        window_splitter->addWidget(ui->text_field);
    
        QVBoxLayout *layout_tlk_tab = new QVBoxLayout(ui->tlk_tab);
        layout_tlk_tab->setMargin(0);
        layout_tlk_tab->addWidget(window_splitter);
    
        QRegExpValidator *numbers_filter = new QRegExpValidator(QRegExp("[0-9]*"), this);
        ui->cur_str_number_field->setValidator(numbers_filter);
    
        //connection of signal to slot
        connect(ui->cur_str_number_field, SIGNAL( num_field_got_focus() ), this, SLOT( on_num_field_focus() ));
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    
    void MainWindow::on_cmnd_tlk_file_open_triggered()
    {
        tlk_file_open(this, ui);
    }
    
    
    void MainWindow::on_strings_table_itemSelectionChanged()
    {
        tlk_string_selected(ui);
    }
    
    
    void MainWindow::on_cur_str_number_field_returnPressed()
    {
        tlk_number_input_finished(ui);
    }
    
    
    //slot to select all in LineEdit
    void MainWindow::on_num_field_focus()
    {
        qDebug() << "got focus";
        ui->cur_str_number_field->selectAll();
    }
    
    

    number_input_field.h (custom class)

    #ifndef NUMBER_INPUT_FIELD_H
    #define NUMBER_INPUT_FIELD_H
    
    #include <QLineEdit>
    
    class number_input_field : public QLineEdit
    {
        Q_OBJECT	//added to use signals and slots
    
    public:
        number_input_field(QWidget * = nullptr);
    
    signals:
        void num_field_got_focus(); //my custom signal
    
    protected:
        void focusInEvent(QFocusEvent *event) override;
    
    private:
    };
    
    #endif // NUMBER_INPUT_FIELD_H
    

    number_input_field.cpp (custom class)

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "number_input_field.h"
    
    #include <QWidget>
    #include <QFocusEvent>
    #include <QDebug>
    
    number_input_field::number_input_field(QWidget *)
    {
    }
    
    void number_input_field::focusInEvent(QFocusEvent *event)
    {
        emit num_field_got_focus();
        event->accept();
    }
    

    upd.: a link to an entire project.


  • Lifetime Qt Champion

    So, as I expected, you don't call the base class impl QLineEdit::focusInEvent() - how do you expect the QLineEdit can do anything then when it not receives the focus in event?



  • @Christian-Ehrlicher
    Could you explain where do I call it, i.o.w. what should I change?


  • Lifetime Qt Champion

    It's c++ basics - when you override a function you should/have to call the base class - otherwise the base class implementation will not get called: https://www.programiz.com/cpp-programming/function-overriding


  • Lifetime Qt Champion

    Hi
    Read the link @Christian-Ehrlicher gave you as its very good description and not
    technically hard to understand.

    And it goes for most overwrites you do with Widgets. You must call the base class also or something will often break.

    void number_input_field::focusInEvent(QFocusEvent *event)
    {
    QLineEdit::focusInEvent(event);// this call the base and give it the parameter also
    emit num_field_got_focus();
    event->accept();
    }

    Its a must know/understand c++ thing that you should take the time to study a bit in my opinion as its often needed :)



  • Thank you, problem solved.


  • Lifetime Qt Champion

    @rebus_x
    Super. Feel free to ask if any doubts about the call the base class thing as you will come across it everwhere in Qt.


Log in to reply