Qt · 密码输入框检测并显示大写锁定键已打开

3 篇文章 0 订阅

先上效果图

在这里插入图片描述

代码实现

带小三角的悬浮提示窗口

// tiplabel.h
#ifndef TIPLABEL_H
#define TIPLABEL_H

/*************************************
 * \brief 带有小三角的tip label
 * \author NiceBlueChai
 *************************************/
#include <QLabel>

//Triangle tip label
// TODO: 添加属性支持样式表设置样式
// TODO: 支持通过enum选择上下左右四个方向的小三角
class TipLabel : public QLabel
{
    Q_OBJECT
public:
     TipLabel(const QString& text, QWidget *parent = nullptr);

    bool eventFilter(QObject*,QEvent*) override;
    QSize sizeHint() const override;

    void updatePos(const QPoint& pos);
    using CallBackType = std::function<QPoint ()>;
    void setCallBack( CallBackType updatePosCallBack);
    void setTopWindow(QWidget* w);

protected:
    void paintEvent(QPaintEvent*) override;

private:
    CallBackType updatePosCallBack;
    QWidget* top_widget{nullptr};
};

#endif // TIPLABEL_H
// tiplabel.cpp
#include "tiplabel.h"
#include <QApplication>
#include <QMouseEvent>
#include <QPainter>
#include <QPolygon>

namespace {
const int kTriangleHeight = 8;
const int kTriangleWidth = 20;
const int kTriangleLeftMargin = 30;
}

TipLabel::TipLabel(const QString &text, QWidget *parent)
    :QLabel(parent, Qt::ToolTip | Qt::FramelessWindowHint | Qt::BypassGraphicsProxyWidget)
{
    setText(text);
    setAttribute(Qt::WA_TranslucentBackground, true);
    setAttribute(Qt::WA_TransparentForMouseEvents, true);
    qApp->installEventFilter(this);
}

bool TipLabel::eventFilter(QObject *o, QEvent *e)
{
    if(o == parent()){
    switch(e->type()){
    case QEvent::WindowDeactivate:
        hide();
    default:
        break;
    }
    }
    if(top_widget  && this->updatePosCallBack && o == top_widget){
        if(e->type() == QEvent::Move) {
            updatePos(updatePosCallBack());
        }
    }
    return false;
}

QSize TipLabel::sizeHint() const
{
    return QSize(120, 34);
}

void TipLabel::updatePos(const QPoint &pos)
{
    move(pos- QPoint(kTriangleLeftMargin + kTriangleWidth/2, 0));
}

void TipLabel::setCallBack(CallBackType updatePosCallBack)
{
    this->updatePosCallBack = updatePosCallBack;
}

void TipLabel::setTopWindow(QWidget *w)
{
    top_widget = w;
}

void TipLabel::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QPolygon polygon_triangle, polygon;
    polygon_triangle << QPoint(kTriangleLeftMargin, kTriangleHeight)
                     << QPoint(kTriangleLeftMargin + kTriangleWidth/2, 0)
                     << QPoint(kTriangleWidth + kTriangleLeftMargin, kTriangleHeight)<<
        QPoint(width() - 1, kTriangleHeight)
        << QPoint(width() -1, height() -1)
        << QPoint(1, height() -1)
        << QPoint(1, kTriangleHeight) <<QPoint(kTriangleLeftMargin, kTriangleHeight);

    QRectF text_rect = rect().adjusted(0, kTriangleHeight, -1, -1);
    painter.fillRect(rect(), Qt::transparent);
    painter.save();
    painter.setPen(Qt::NoPen);
    painter.setBrush(Qt::white);
    painter.drawPolygon(polygon_triangle);
    painter.drawRoundedRect(text_rect, 6.0, 5.0);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setPen(Qt::gray);
    painter.setBrush(Qt::NoBrush);
    painter.drawPolyline(polygon_triangle);
    painter.restore();

    QTextOption opt;
    opt.setAlignment(Qt::AlignCenter);
    painter.drawText(text_rect, text(), opt);
}
使用上面小窗口在Lineedit获得焦点时显示大写锁定已打开
// tiplabel-lineedit.h
#ifndef TIPLABELLINEEDIT_H
#define TIPLABELLINEEDIT_H

#include <QLineEdit>

class TipLabel;
class TipLabelLineedit : public QLineEdit
{
    Q_OBJECT
public:
    explicit TipLabelLineedit(QWidget *parent = nullptr);
    void setTopWindow(QWidget* w);
    void setTipVisible(bool v);
    virtual QPoint tipPos();

    // QWidget interface
protected:
    void resizeEvent(QResizeEvent *event) override;
    void focusInEvent(QFocusEvent* event) override;
    void focusOutEvent(QFocusEvent* event) override;
    void keyEvent(QKeyEvent* event) override;

private:
    TipLabel* label;
    bool tip_visible{false};
};

#endif // TIPLABELLINEEDIT_H
#include "tiplabel-lineedit.h"
#include "../IMLabel/tiplabel.h"
#include <QResizeEvent>
#include "gui-util.h"
using namespace IMUtils;

TipLabelLineedit::TipLabelLineedit(QWidget *parent)
    : QLineEdit{parent}, label(new TipLabel("大写锁定已打开", this))
{
    auto calback = [this]()->QPoint{
        return tipPos();
    };
    label->setCallBack(calback);
}

void TipLabelLineedit::setTopWindow(QWidget *w)
{
    label->setTopWindow(w);
}

void TipLabelLineedit::setTipVisible(bool v)
{
    tip_visible = v;
}

QPoint TipLabelLineedit::tipPos()
{
    auto pos = mapToGlobal(QPoint(10, size().height()/2));
    return pos;
}

void TipLabelLineedit::resizeEvent(QResizeEvent *event)
{
    auto pos = mapToGlobal(QPoint(6, event->size().height()/2));
    label->updatePos(pos);

    QLineEdit::resizeEvent(event);
}

void TipLabelLineedit::focusInEvent(QFocusEvent *event)
{
    if(tip_visible && getCapsLockToggled()){
        label->showNormal();
    }
    QLineEdit::focusInEvent(event);
}

void TipLabelLineedit::focusOutEvent(QFocusEvent *event)
{
    label->hide();
    QLineEdit::focusOutEvent(event);
}

void TipLabelLineedit::keyPressEvent(QKeyEvent *event)
{
    if(tip_visible && getCapsLockToggled()){
        label->showNormal();
    }else {
        label->hide();
    }
    QLineEdit::keyPressEvent(event);
}

参考链接

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值