自学内容网 自学内容网

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));
}

完!


原文地址:https://blog.csdn.net/cpp_learner/article/details/143776448

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!