在前面的文章里为大家展示了用Qt实现的QQ登录界面以及QQ窗口的右键菜单控件,(Qt 实现 QQ 9.0版 自定义菜单控件、以及Qt 实现 QQ 9.0 新版登录窗口),有兴趣的小伙伴可以看下相关的文章,今天就把QQ登录界面的输入框单独拿出来分享一下。
单独看QQ的输入框其实也就是一个LineEdit,但是其实不是那么简单,用Qt要实现一样的效果需要加一些样式,贴图,布局等,还有一点就是重写QLineEdit基类。
为什么要重写QLineEdit呢,因为QLineEdit设置占位字符,当鼠标点击,焦点进入LineEdit时(如下图),占位符还是显示的。而QQ的登录窗口中LineEdit有焦点时,占位字符是不显示的。
Qt文档中也给了详细的介绍,请看红色矩形框中文字叙述。
正常情况下,即使QLineEdit有焦点时也会显示占位字符,但是输入框中文字设置为居中显示,那么输入框有焦点时,占位字符不会显示。
将输入框中文字设置为居中显示之后(见下方代码),当焦点进入输入框时,占位字符就不显示了,但是这不是我们想要的效果。实际上我们是要文字居左显示,所以这里要重写QLineEdit,自己控制占位字符的显示。
整体思路即根据focusInEvent和focusOutEvent事件判断焦点是否在输入框中,同时重写setPlaceholderText方法,把最开始设置的占位字符保存下来,然后焦点进入的时候如果输入框中没有字符 就把占位字符清空,如果本身就有内容字符,占位字符是不显示的。
然后在焦点离开输入框时,判断当前输入框是否有内容字符,如果没有则恢复之前保存的占位字符。
// 鼠标是否点击进行编辑;
void signalIsMouseIn(bool isFocusIn);
class MyLineEdit : public QLineEdit
{
Q_OBJECT
public:
MyLineEdit(QWidget* parent = NULL)
: QLineEdit(parent)
{
}
void setPlaceholderText(const QString &text)
{
m_placeHolderText = text;
__super::setPlaceholderText(text);
}
private:
void focusInEvent(QFocusEvent *event)
{
if (this->text().isEmpty())
{
__super::setPlaceholderText("");
}
emit signalIsMouseIn(true);
return __super::focusInEvent(event);
}
void focusOutEvent(QFocusEvent *event)
{
if (this->text().isEmpty())
{
this->setPlaceholderText(m_placeHolderText);
}
emit signalIsMouseIn(false);
return __super::focusOutEvent(event);
}
signals:
// 鼠标是否点击进行编辑;
void signalIsMouseIn(bool isFocusIn);
private:
QString m_placeHolderText;
};
因为QLineEdit不提供焦点进出的信号,所有这里添加了一个信号,在focusInEvent和focusOutEvent事件中进行触发,
这里为什么要添加这个信号呢?因为QQ的输入框前面的图标在有焦点的时候会变成蓝色,没有焦点的时候会变成灰色,所以这里需要这个信号来通知进行变换图标。可以见下方代码中此信号的用处。
class QQLineEditWidget : public QWidget
{
Q_OBJECT
public:
QQLineEditWidget(QWidget *parent = Q_NULLPTR);
private:
void initWidget();
private:
void paintEvent(QPaintEvent *event);
};
#include "QQLineEdit.h"
#include
#include
#include
#pragma execution_character_set("utf-8")
QQLineEditWidget::QQLineEditWidget(QWidget *parent)
: QWidget(parent)
{
initWidget();
this->setFixedSize(QSize(430, 330));
this->setAttribute(Qt::WA_TranslucentBackground);
this->setWindowFlag(Qt::FramelessWindowHint);
// 设置阴影边框;
auto shadowEffect = new QGraphicsDropShadowEffect(this);
shadowEffect->setOffset(0, 0);
shadowEffect->setColor(Qt::black);
shadowEffect->setBlurRadius(10);
this->setGraphicsEffect(shadowEffect);
}
void QQLineEditWidget::initWidget()
{
// 设置两个输入框前后的图标及按钮;
QLabel* m_labelQQ = new QLabel;
m_labelQQ->setFixedSize(QSize(14, 20));
m_labelQQ->setPixmap(QIcon(":/Resources/LoginWindow/QQ_Focus.png").pixmap(m_labelQQ->size()));
QLabel* m_labelLocker = new QLabel;
m_labelLocker->setFixedSize(QSize(12, 14));
m_labelLocker->setPixmap(QIcon(":/Resources/LoginWindow/Locker_Normal.png").pixmap(m_labelLocker->size()));
QPushButton* m_pButtonPullDown = new QPushButton;
m_pButtonPullDown->setCursor(Qt::ArrowCursor);
m_pButtonPullDown->setFixedSize(QSize(16, 16));
m_pButtonPullDown->setStyleSheet("QPushButton{border-image:url(:/Resources/LoginWindow/PullDownButton_Normal.png);}\
QPushButton:hover{border-image:url(:/Resources/LoginWindow/PullDownButton_Hover.png);}");
QPushButton* m_pButtonKeyborad = new QPushButton;
m_pButtonKeyborad->setCursor(Qt::PointingHandCursor);
m_pButtonKeyborad->setFixedSize(QSize(16, 16));
m_pButtonKeyborad->setStyleSheet("QPushButton{border-image:url(:/Resources/LoginWindow/keyboard.png) 0 80 0 0;}\
QPushButton:hover{border-image:url(:/Resources/LoginWindow/keyboard.png) 0 40 0 40;}\
QPushButton:pressed{border-image:url(:/Resources/LoginWindow/keyboard.png) 0 0 0 80;}");
MyLineEdit* lineEditAccount = new MyLineEdit;
lineEditAccount->setPlaceholderText("QQ号码/手机/邮箱");
lineEditAccount->setTextMargins(20, 0, 20, 0);
lineEditAccount->setFixedSize(QSize(235, 28));
// 这里通过signalIsMouseIn信号进行图标切换;
connect(lineEditAccount, &MyLineEdit::signalIsMouseIn, this, [=](bool isMouseIn) {
if (isMouseIn)
{
m_labelQQ->setPixmap(QIcon(":/Resources/LoginWindow/QQ_Focus.png").pixmap(m_labelQQ->size()));
}
else
{
m_labelQQ->setPixmap(QIcon(":/Resources/LoginWindow/QQ_Normal.png").pixmap(m_labelQQ->size()));
}
});
QHBoxLayout* hAccountLayout = new QHBoxLayout(lineEditAccount);
hAccountLayout->addWidget(m_labelQQ);
hAccountLayout->addStretch();
hAccountLayout->addWidget(m_pButtonPullDown);
hAccountLayout->setMargin(0);
MyLineEdit* lineEditPassed = new MyLineEdit;
// 测试setPlaceholderText在是否有焦点的时候显示占位字符;
// lineEditPassed->setAlignment(Qt::AlignCenter);
lineEditPassed->setPlaceholderText("密码");
lineEditPassed->setTextMargins(20, 0, 20, 0);
lineEditPassed->setFixedSize(QSize(235, 28));
connect(lineEditPassed, &MyLineEdit::signalIsMouseIn, this, [=](bool isMouseIn) {
if (isMouseIn)
{
m_labelLocker->setPixmap(QIcon(":/Resources/LoginWindow/Locker_Focus.png").pixmap(m_labelLocker->size()));
}
else
{
m_labelLocker->setPixmap(QIcon(":/Resources/LoginWindow/Locker_Normal.png").pixmap(m_labelLocker->size()));
}
});
this->setStyleSheet("*{font-family:Microsoft YaHei;font-size:12px;}\
QLineEdit{font-size:13px;background:transparent;border:none;border-bottom:1px solid rgb(229, 229, 229);}\
QLineEdit:hover{border-bottom:1px solid rgb(193,193, 193);}\
QLineEdit:focus{border-bottom:1px solid rgb(18, 183, 245);}");
QHBoxLayout* hPswLayout = new QHBoxLayout(lineEditPassed);
hPswLayout->addWidget(m_labelLocker);
hPswLayout->addStretch();
hPswLayout->addWidget(m_pButtonKeyborad);
hPswLayout->setMargin(0);
QVBoxLayout* vBoxLayout = new QVBoxLayout();
vBoxLayout->addStretch();
vBoxLayout->addWidget(lineEditAccount);
vBoxLayout->addWidget(lineEditPassed);
vBoxLayout->addStretch();
vBoxLayout->setSpacing(10);
vBoxLayout->setMargin(0);
QHBoxLayout* hMainLayout = new QHBoxLayout(this);
hMainLayout->addStretch();
hMainLayout->addLayout(vBoxLayout);
hMainLayout->addStretch();
hMainLayout->setMargin(10);
}
void QQLineEditWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(Qt::NoPen);
painter.setBrush(Qt::white);
painter.drawRoundedRect(this->rect().adjusted(10, 10, -10, -10), 3, 3);
}