0
点赞
收藏
分享

微信扫一扫

Qt之自定义QLineEdit


一.效果

要实现类似QQ登录界面的账号和密码输入框大概有三种方法
1.使用QLineEdit的addAction方法

QAction *passwordAction = new QAction(this);
passwordAction ->setIcon(QIcon(":/icons/Password.png"));
m_passwordLineEdit->addAction(passwordAction, QLineEdit::LeadingPosition);

QAction *keyboardAction = m_passwordLineEdit->addAction(QIcon(":/icons/KeyBoard.png"), QLineEdit::TrailingPosition);

connect(keyboardAction, &QAction::triggered, this, [=]{
qDebug()<<"clicked the keyboard";
});

但是这种方法无法完全实现QQ的效果,一是因为icon无法紧贴QLineEdit的左右两边,二是因为QLineEdit设置占位字符,当鼠标点击QLineEdit获取焦点时,占位符还是显示的,而QQ登录窗口中LineEdit有焦点时,占位字符是不显示。使用这种方法,并用stylesheet去掉编辑框的左上右边框,效果如下图所示:

Qt之自定义QLineEdit_自定义

还有就是上述icon是没有点击效果的,可以给action设置按钮,代码如下:

QToolButton *button = new QToolButton;
button ->setCursor(Qt::ArrowCursor);//如果不设置鼠标样式,鼠标移动到按钮上依旧显示为编辑框的鼠标样式.
QWidgetAction *action = new QWidgetAction(ui->lineEdit);
action->setDefaultWidget(pBtn);
ui->lineEdit->addAction(action, QLineEdit::TrailingPosition);

2.使用多个控件组装实现
首先要子类化QLineEdit,解决占位符问题。根据focusInEvent和focusOutEvent事件判断焦点是否在输入框中,同时重写setPlaceholderText方法,把最开始设置的占位字符保存下来,然后焦点进入的时候,如果输入框中没有字符就把占位字符清空,如果本身就有内容字符,则占位字符不显示。
然后在QLineEdit的左右各加一个QPushButton,再把三者布局到一个QWidget上,最后用stylesheet设置QWidget下边框的颜色,这样能做到和QQ一毛一样。
但是这样做也有一个缺点,它和原来的QLineEdit已经大不一样了,只能用来做QQ。而且既然子类化了QLineEdit,当然可以直接在QLineEdit里添加QPushButton,这就是本文推荐的方法3
3.子类化QLineEdit
这样做的好处是显而易见的,假设子类名为QHLineEdit,那么在UI上拖一个QLineEdit,只需将该QLineEidt提升为QHLineEdit,非常方便。而且当不做QQ时,QHLineEdit可以和普通的QLineEdit一样使用。效果如下:
这是QQ的

Qt之自定义QLineEdit_QLineEdit_02


这是我的 

Qt之自定义QLineEdit_Qt_03

二.实现

QQ登录输入框左边的icon是不能点击的,但是当输入框获取焦点的时候,该icon会变色。右边的输入框有鼠标hover效果和点击效果。所以这里可以用个取巧的做法,在给QLineEdit添加按钮的时候,如果传入两张图片,则该按钮不能点击,但可以变色;如果传入三张图片(normal、hover和press),则该按钮可以点击。源码如下:

 QHLineEdit.h

#ifndef QHLINEEDIT_H
#define QHLINEEDIT_H

#include <QLineEdit>
#include <QAction>
#include <QPushButton>
#include <QMouseEvent>

class QHLineEdit : public QLineEdit
{
Q_OBJECT

public:
QHLineEdit(QWidget *parent=nullptr);
~QHLineEdit();

void setPlaceholderText(const QString &text);
QPushButton *addButton(const QList<QIcon> &icons, ActionPosition position);

enum FocusStatus
{
FocusIn,
FocusOut
};

protected:
bool eventFilter(QObject *obj, QEvent *event) override;
void focusInEvent(QFocusEvent *event) override;
void focusOutEvent(QFocusEvent *event) override;

private:
QString m_placeHolderText;
QPushButton *m_leadingButton;
QPushButton *m_trailingButton;
// 只有当icons等于三个的时候才支持pushButton的hover和点击.
// 当icons等于两个的时候支持lineEdit获取焦点时切换图标.
QList<QIcon> m_leadingIcons;
QList<QIcon> m_trailingIcons;

signals:
void focusStatusChanged(int status);
};

#endif // QHLINEEDIT_H

QHLineEdit.cpp

#include "QHLineEdit.h"

#include <QHBoxLayout>
#include <QDebug>

QHLineEdit::QHLineEdit(QWidget *parent)
: QLineEdit(parent)
{
m_leadingButton = new QPushButton(this);
m_leadingButton->installEventFilter(this);
m_leadingButton->setStyleSheet("background-color:transparent");
m_leadingButton->setFixedSize(0,0);
connect(m_leadingButton,&QPushButton::pressed,this,[=]{
if(m_leadingIcons.length()==3)
{
m_leadingButton->setIcon(m_leadingIcons.at(2));
}
});

connect(m_leadingButton,&QPushButton::released,this,[=]{
if(m_leadingIcons.length()==3)
{
m_leadingButton->setIcon(m_leadingIcons.at(1));
}
});

m_trailingButton = new QPushButton(this);
m_trailingButton->installEventFilter(this);
m_trailingButton->setStyleSheet("background-color:transparent");
m_trailingButton->setFixedSize(0,0);
connect(m_trailingButton,&QPushButton::pressed,this,[=]{
if(m_trailingIcons.length()==3)
{
m_trailingButton->setIcon(m_trailingIcons.at(2));
}
});
connect(m_trailingButton,&QPushButton::released,this,[=]{
if(m_trailingIcons.length()==3)
{
m_trailingButton->setIcon(m_trailingIcons.at(1));
}
});

QHBoxLayout *hLayout = new QHBoxLayout();
hLayout->addWidget(m_leadingButton);
hLayout->addStretch();
hLayout->addWidget(m_trailingButton);
hLayout->setMargin(0);
setLayout(hLayout);
}

QHLineEdit::~QHLineEdit()
{

}

void QHLineEdit::setPlaceholderText(const QString &text)
{
m_placeHolderText = text;
QLineEdit::setPlaceholderText(text);
}

QPushButton *QHLineEdit::addButton(const QList<QIcon> &icons, ActionPosition position)
{
if(icons.length()==0 || icons.length()>3)
{
return nullptr;
}

if(position==QLineEdit::LeadingPosition)
{
m_leadingIcons.clear();
m_leadingIcons = icons;
m_leadingButton->setFixedSize(this->height()/2,this->height());
m_leadingButton->setIcon(icons.at(0));
m_leadingButton->setIconSize(QSize(m_leadingButton->width(),m_leadingButton->width()));
setTextMargins(m_leadingButton->width()+6, 0, m_trailingButton->width(), 0);

return m_leadingButton;
}
else if(position==QLineEdit::TrailingPosition)
{
m_trailingIcons.clear();
m_trailingIcons = icons;
m_trailingButton->setFixedSize(this->height()/2,this->height());
m_trailingButton->setIcon(icons.at(0));
m_trailingButton->setIconSize(QSize(m_trailingButton->width(),m_trailingButton->width()));
setTextMargins(m_leadingButton->width()+6, 0, m_trailingButton->width(), 0);

return m_trailingButton;
}

return nullptr;
}

bool QHLineEdit::eventFilter(QObject *obj, QEvent *event)
{
if (obj == (QObject*)m_leadingButton || obj == (QObject*)m_trailingButton)
{
if (event->type() == QEvent::Enter)
{
setCursor(Qt::ArrowCursor);

if(obj == (QObject*)m_leadingButton)
{
if(m_leadingIcons.length()==3)
{
m_leadingButton->setIcon(m_leadingIcons.at(1));
}
}
else
{
if(m_trailingIcons.length()==3)
{
m_trailingButton->setIcon(m_trailingIcons.at(1));
}
}
}
else if(event->type() == QEvent::Leave)
{
setCursor(Qt::IBeamCursor);

if(obj == (QObject*)m_leadingButton)
{
if(m_leadingIcons.length()==3)
{
m_leadingButton->setIcon(m_leadingIcons.at(0));
}
}
else
{
if(m_trailingIcons.length()==3)
{
m_trailingButton->setIcon(m_trailingIcons.at(0));
}
}
}

return false;
}

return QLineEdit::eventFilter(obj, event);
}

void QHLineEdit::focusInEvent(QFocusEvent *event)
{
if (this->text().isEmpty())
{
QLineEdit::setPlaceholderText("");
}

if(m_leadingIcons.length()==2)
{
m_leadingButton->setIcon(m_leadingIcons.at(1));
}
else if(m_trailingIcons.length()==2)
{
m_trailingButton->setIcon(m_trailingIcons.at(1));
}

emit focusStatusChanged(FocusIn);

QLineEdit::focusInEvent(event);
}

void QHLineEdit::focusOutEvent(QFocusEvent *event)
{
if (this->text().isEmpty())
{
this->setPlaceholderText(m_placeHolderText);
}

if(m_leadingIcons.length()==2)
{
m_leadingButton->setIcon(m_leadingIcons.at(0));
}
else if(m_trailingIcons.length()==2)
{
m_trailingButton->setIcon(m_trailingIcons.at(0));
}

emit focusStatusChanged(FocusOut);

QLineEdit::focusOutEvent(event);
}

使用方法:

    QList<QIcon> icons;
icons.append(QIcon(":/icons/Phone.png"));
icons.append(QIcon(":/icons/PhoneHover.png"));
ui->userNameLineEdit->addButton(icons,QLineEdit::LeadingPosition);
connect(ui->userNameLineEdit,&QHLineEdit::focusStatusChanged,this,[=](int status){
if(status==QHLineEdit::FocusIn)
{
ui->userNameLineEdit->setStyleSheet("background-color: transparent;"
"border-style:solid;"
"border-width:1px;"
"border-top-color: transparent;"
"border-right-color: transparent;"
"border-left-color: transparent;"
"border-bottom-color: rgb(99, 188, 255);");
}
else if(status==QHLineEdit::FocusOut)
{
ui->userNameLineEdit->setStyleSheet("background-color: transparent;"
"border-style:solid;"
"border-width:1px;"
"border-top-color: transparent;"
"border-right-color: transparent;"
"border-left-color: transparent;"
"border-bottom-color: rgb(129, 129, 129);");
}
});

icons.clear();
icons.append(QIcon(":/icons/DownArrow.png"));
icons.append(QIcon(":/icons/DownArrowHover.png"));
icons.append(QIcon(":/icons/DownArrow.png"));
QPushButton *downArrowButton = ui->userNameLineEdit->addButton(icons,QLineEdit::TrailingPosition);
connect(downArrowButton,&QPushButton::clicked,this,[=]{

});

icons.clear();
icons.append(QIcon(":/icons/Password.png"));
icons.append(QIcon(":/icons/PasswordHover.png"));
ui->passwordLineEdit->addButton(icons,QLineEdit::LeadingPosition);
connect(ui->passwordLineEdit,&QHLineEdit::focusStatusChanged,this,[=](int status){
if(status==QHLineEdit::FocusIn)
{
ui->passwordLineEdit->setStyleSheet("background-color: transparent;"
"border-style:solid;"
"border-width:1px;"
"border-top-color: transparent;"
"border-right-color: transparent;"
"border-left-color: transparent;"
"border-bottom-color: rgb(99, 188, 255);");
}
else if(status==QHLineEdit::FocusOut)
{
ui->passwordLineEdit->setStyleSheet("background-color: transparent;"
"border-style:solid;"
"border-width:1px;"
"border-top-color: transparent;"
"border-right-color: transparent;"
"border-left-color: transparent;"
"border-bottom-color: rgb(129, 129, 129);");
}
});

icons.clear();
icons.append(QIcon(":/icons/Keyboard.png"));
icons.append(QIcon(":/icons/KeyboardHover.png"));
icons.append(QIcon(":/icons/Keyboard.png"));
QPushButton *keyboardButton = ui->passwordLineEdit->addButton(icons,QLineEdit::TrailingPosition);
connect(keyboardButton,&QPushButton::clicked,this,[=]{

});

举报

相关推荐

0 条评论