本文介绍了一个基于Qt框架的动态下划线单行文本框控件DynamicUnderlineLineEdit的实现。该控件继承自QLineEdit,通过重写paintEvent、focusInEvent和focusOutEvent等方法,实现了以下功能:1)获取焦点时下划线从左向右动态延伸;2)失去焦点时下划线从右向左动态收缩;3)可自定义下划线颜色、宽度和动画速度;4)支持设置文字颜色和占位符颜色。控件使用QTimer控制动画效果,通过画笔设置实现不同状态下的下划线渲染,具有抗锯齿和透明背景等特性。
#ifndef DynamicUnderlineLineEdit_H
#define DynamicUnderlineLineEdit_H
#include <QWidget>
#include <QLineEdit>
#include <QPainter>
#include <QPaintEvent>
#include <QFocusEvent>
#include <QTimer>
#include <QColor>
#include <QPointF>
#include <QPalette>
//动态下划线单行文本框:Dynamic Underline LineEdit
class DynamicUnderlineLineEdit : public QLineEdit
{
Q_OBJECT
public:
explicit DynamicUnderlineLineEdit(QWidget *parent = nullptr);
explicit DynamicUnderlineLineEdit(const QString &text, QWidget *parent = nullptr);
void setLinePen( const QPen &focusInPen,
const QPen &focusOutPen = QPen(QBrush(QColor(66,66,66)),2)); // 设置线条的绘制画笔,参数:获取焦点的绘制画笔,失去焦点的绘制画笔
void setTextColor(const QColor &textColor); // 设置输入文字颜色
void setPlaceholderTextColor(const QColor &placeholderText); // 设置预设背景文字颜色
void setLineSpeed(int speed); // 设置线条填速度,越小越快,最小为1,实际使用可根据文本框的长度不同设置不同的速度以达到最佳观感
private:
int right_coordinate{-1}; // 线条右侧坐标
QTimer *timer;
QPen inactive_pen;// 未获得焦点时线条的绘制画笔
QPen active_pen; // 获得焦点时线条的绘制画笔
void initializeMemberVariable();
private slots:
void inFocus(); // 获得焦点
void outFocus(); // 失去焦点
protected:
virtual void paintEvent(QPaintEvent *event) override;
virtual void focusInEvent(QFocusEvent *event) override; // 获取焦点事件
virtual void focusOutEvent(QFocusEvent *event) override; // 失去焦点事件
};
#endif // DynamicUnderlineLineEdit_H
#include "DynamicUnderlineLineEdit.h"
DynamicUnderlineLineEdit::DynamicUnderlineLineEdit(QWidget *parent)
: QLineEdit{parent},
timer{new QTimer(this)}
{
initializeMemberVariable();
}
DynamicUnderlineLineEdit::DynamicUnderlineLineEdit(const QString &text, QWidget *parent)
: QLineEdit::QLineEdit(text,parent)
{
initializeMemberVariable();
}
void DynamicUnderlineLineEdit::setLinePen( const QPen &focusInPen,const QPen &focusOutPen)
{
inactive_pen = focusOutPen;
active_pen = focusInPen;
}
void DynamicUnderlineLineEdit::setTextColor(const QColor &textColor)
{
const_cast<QPalette &>(palette()).setColor(QPalette::ColorRole::Text, textColor);
}
void DynamicUnderlineLineEdit::setPlaceholderTextColor(const QColor &placeholderText)
{
const_cast<QPalette &>(palette()).setColor(QPalette::ColorRole::PlaceholderText, placeholderText);
}
void DynamicUnderlineLineEdit::setLineSpeed(int speed)
{
timer->setInterval(speed);
}
void DynamicUnderlineLineEdit::initializeMemberVariable()
{
setFocusPolicy(Qt::ClickFocus);
timer->setInterval(12);
connect(timer, &QTimer::timeout, this, &DynamicUnderlineLineEdit::inFocus);
setAttribute(Qt::WA_TranslucentBackground);//背景透明
setFrame(false);//无边框
setTextMargins(10, 0, 0, 0);//设置文本左边距10像素
inactive_pen.setColor(qRgb(66, 66, 66));
inactive_pen.setWidth(2);
active_pen.setColor(qRgb(0, 123, 255));
active_pen.setWidth(2);
}
void DynamicUnderlineLineEdit::inFocus()
{
right_coordinate += 10;
if (right_coordinate > width())
timer->stop();
update();
}
void DynamicUnderlineLineEdit::outFocus()
{
right_coordinate -= 10;
if (right_coordinate < 0)
timer->stop();
update();
}
void DynamicUnderlineLineEdit::paintEvent(QPaintEvent *event)
{
QLineEdit::paintEvent(event);
QPainter painter = QPainter(this);
painter.setRenderHint(QPainter::RenderHint::Antialiasing); // 抗锯齿
painter.setPen(inactive_pen); // 设置画笔颜色和线条样式
painter.drawLine(0, height() - inactive_pen.width(),width(), height() - inactive_pen.width()); // 在底部画未选中时的线条
painter.setPen(active_pen);
painter.drawLine(-2, height() - active_pen.width(),right_coordinate, height() - active_pen.width()); // 在底部画选中时的线条
}
void DynamicUnderlineLineEdit::focusInEvent(QFocusEvent *event)
{
QLineEdit::focusInEvent(event);
timer->disconnect();
connect(timer, &QTimer::timeout, this, &DynamicUnderlineLineEdit::inFocus);
timer->start();
}
void DynamicUnderlineLineEdit::focusOutEvent(QFocusEvent *event)
{
QLineEdit::focusOutEvent(event);
timer->disconnect();
connect(timer, &QTimer::timeout, this, &DynamicUnderlineLineEdit::outFocus);
timer->start();
}