QT QLineEdit失去焦点事件问题与解决

本文介绍如何获得QLineEdit的失去焦点事件和获得焦点的输入框也会触发失去焦点事件的问题!

目录

一、QLineEdit获得失去焦点事件

1.自定义类继承自QLineEdit

2.重写 focusOutEvent

3.使用

二、失去焦点事件问题

1.问题描述

2.问题解决

三、源码分享

lineeditfocus.h

lineeditfocus.cpp

widget.cpp


一、QLineEdit获得失去焦点事件

1.自定义类继承自QLineEdit

class LineEditFocus : public QLineEdit {
    Q_OBJECT
public:
    explicit LineEditFocus(QWidget *parent = nullptr) { }
    ~LineEditFocus() override { }
}

2.重写 focusOutEvent

protected:
    // 焦点离开
    void focusOutEvent(QFocusEvent *event) override { }
    // 获得焦点
    void focusInEvent(QFocusEvent *event) override { }

当获得焦点时,focusInEvent方法会被触发;当失去焦点时,focusOutEvent方法会被触发;

然后就可以在方法内部做一些我们的需求处理,例如可以通过信号与槽通知主程序等;

3.使用

直接使用我们自定义的类,创建LineEditFocus对象即可;

如果使用的是ui布局中的部件,那么可以将部件提升为我们自定义的LineEditFocus即可;

二、失去焦点事件问题

1.问题描述

如果有多个输入框部件,且当前输入框部件失去焦点,且另一个获得焦点的部件不是输入框时,那么是没有问题的!

如果当前输入框失去焦点,且另一个获得焦点的部件也是输入框,那么这样就会出现问题;

会优先触发另一个输入框的失去焦点事件,然后才会触发当前输入框的失去焦点事件,最后再触发另一个输入框的获得焦点事件!!!

案例:

(1).继续在自定义类中添加信号 ;可以根据个人需求传输参数值,例如可以将当前输入框的文本传送;

signals:
    void signalLoseFocus(int index);

(2).然后在失去焦点方法中,触发此信号

void LineEditFocus::focusOutEvent(QFocusEvent *event)
{
    static int index = 1;
    emit signalLoseFocus(index++);
    QLineEdit::focusOutEvent(event);
}

(3).最后在主窗体中使用即可(ui部件,提升即可)

void Widget::init()
{
    LineEditFocus *le1 = new LineEditFocus(this);
    LineEditFocus *le2 = new LineEditFocus(this);
    LineEditFocus *le3 = new LineEditFocus(this);

    QList<LineEditFocus *> list;
    list << le1 << le2 << le3;

    foreach (LineEditFocus *lef, list) {
        lef->setFixedSize(350, 50);
        connect(lef, &LineEditFocus::signalLoseFocus, this, &Widget::onLeaveFocus);
    }


    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->addWidget(le1);
    layout->addWidget(le2);
    layout->addWidget(le3);
    this->setLayout(layout);
}

(4).在槽函数中将接收到的index,通过messagebox提示出来

void Widget::onLeaveFocus(int index)
{
    QMessageBox::information(this, "提示", QString("输入框焦点离开:%1").arg(index));
}

(5).运行效果

可以看出,确实是有问题的!

2.问题解决

具体是什么原因导致出现这样的问题,我也没搞明白;

但是办法总比困难多,我们转换一下思路去解决他;

(1).增加变量用于标志是否获取到了焦点

private:
    // 焦点获得标志
    bool m_focus;

(2).焦点获得,获得焦点时,m_focus赋值true

void LineEditFocus::focusInEvent(QFocusEvent *event)
{
    m_focus = true;    // 标志当前编辑框已经获得焦点
    QLineEdit::focusInEvent(event);
}

(3).失去焦点,通过m_focus变量辅助配合判断

void LineEditFocus::focusOutEvent(QFocusEvent *event)
{
    if (m_focus && event->lostFocus()) {    // event->lostFocus(): type() == FocusOut
        m_focus = false;    // 焦点失去
        emit signalLoseFocus(m_index);
    }

    QLineEdit::focusOutEvent(event);
}

通过上面的测试可知,当从第一个输入框点击第二个输入框时,优先触发第二个输入框的失去焦点事件,此时,第二个输入框是还没有获得焦点的,即m_focus变量值为false,信号就没法触发;

紧接着第一个输入框的失去焦点事件触发,因为先前已经获得了焦点,即m_focus变量值为true,所以第一个输入框的失去焦点事件可以正常发射信号;

最后才会触发第二个输入框的获得焦点事件。

(3).运行测试

问题完美解决!

三、源码分享

lineeditfocus.h

#ifndef LINEEDIT_FOCUS_H
#define LINEEDIT_FOCUS_H

#include <QLineEdit>

class LineEditFocus : public QLineEdit {
    Q_OBJECT
public:
    explicit LineEditFocus(QWidget *parent = nullptr);
    ~LineEditFocus() override;

    void SetIndex(int index);
    int GetIndex() const;


signals:
    void signalLoseFocus(int index);
    void signalInFocus(int index);

protected:
    // 焦点离开
    void focusOutEvent(QFocusEvent *event) override;
    // 获得焦点
    void focusInEvent(QFocusEvent *event) override;

private:
    // 记录标志
    int m_index;

    // 焦点获得标志
    bool m_focus;
};

#endif // LINEEDIT_FOCUS_H

lineeditfocus.cpp

#include "lineeditfocus.h"

#include <QFocusEvent>

LineEditFocus::LineEditFocus(QWidget *parent) : QLineEdit(parent)
{
    m_index = 0;
    m_focus = false;
}

LineEditFocus::~LineEditFocus()
{

}

void LineEditFocus::SetIndex(int index)
{
    m_index = index;
}

void LineEditFocus::focusOutEvent(QFocusEvent *event)
{
    if (m_focus && event->lostFocus()) {    // event->lostFocus() --> return type() == FocusOut;
        m_focus = false;    // 焦点失去
        emit signalLoseFocus(m_index);
    }

    QLineEdit::focusOutEvent(event);
}

void LineEditFocus::focusInEvent(QFocusEvent *event)
{
    m_focus = true; // 焦点获得
    QLineEdit::focusInEvent(event);
}

widget.cpp

#include "widget.h"
#include "ui_widget.h"

#include "lineeditfocus.h"

#include <QMessageBox>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    init();
}

Widget::~Widget()
{
    delete ui;
}

void Widget::init()
{
    LineEditFocus *le1 = new LineEditFocus(this);
//    le1->setFixedSize(350, 50);
//    le1->SetIndex(1);
    LineEditFocus *le2 = new LineEditFocus(this);
//    le2->setFixedSize(350, 50);
//    le2->SetIndex(2);
    LineEditFocus *le3 = new LineEditFocus(this);
//    le3->setFixedSize(350, 50);
//    le3->SetIndex(3);


    QList<LineEditFocus *> list;
    list << le1 << le2 << le3;

    int index = 1;
    foreach (LineEditFocus *lef, list) {
        lef->setFixedSize(350, 50);
        lef->SetIndex(index++);
        connect(lef, &LineEditFocus::signalLoseFocus, this, &Widget::onLeaveFocus);
    }


    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->addWidget(le1);
    layout->addWidget(le2);
    layout->addWidget(le3);
    this->setLayout(layout);


}


void Widget::onLeaveFocus(int index)
{
    QMessageBox::information(this, "提示", QString("输入框焦点离开:%1").arg(index));
}

完!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cpp_learners

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值