简述
模仿QQ登录界面。
主要涉及布局管理器、输入控件以及QSS样式的使用。
只实现了基本的外观,并不涉及到内部功能实现。
整个界面分为两大部分,上面的欢迎界面(upPanel)和下面的信息输入界面(downPanel)。每一个部分都用一个单独的类来实现。这两个类都继承自QWidget。
效果
核心代码
核心代码主要涉及以下几个方面的内容
- 实现无边框窗体
- 实现窗口的拖动
- 实现QQ工具栏
- 实现主功能区
无边框窗体
windows默认的工具栏和QQ不一样,为了方便我们实现自己的工具栏,我们要将它隐藏起来。
setWindowFlags(Qt::FramelessWindowHint);
窗口的拖动
默认情况下只有工具栏所在的矩形长条区域可以拖动控件,但是由于我们将该长条隐藏了,所以需要自己实现窗口拖动效果。
.h文件要添加的内容
protected:
void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
private:
bool isPressed;//鼠标按下标志(不分左右键)
QPoint startPosition;//鼠标按下的初始位置
.cpp文件要添加的内容
void UpPanel::mousePressEvent(QMouseEvent *e)
{
isPressed = true;
startPosition = event->globalPos();
QWidget::mousePressEvent(event);
}
void UpPanel::mouseMoveEvent(QMouseEvent *e)
{
if (isPressed)
{
QPoint movePoint = event->globalPos() - startPosition;
QPoint widgetPos = this->parentWidget()->pos();
startPosition = event->globalPos();
this->parentWidget()->move(widgetPos.x() + movePoint.x(), widgetPos.y() + movePoint.y());
}
QWidget::mouseMoveEvent(event);
}
void UpPanel::mouseReleaseEvent(QMouseEvent *)
{
isPressed = false;
QWidget::mouseReleaseEvent(event);
}
注意:这里设置的可拖动区域为上面板全局可拖动。
实现QQ工具栏
前面我们已经把默认的工具栏给隐藏了,下面需要自己实现工具栏,实现该工具栏的关键点在于如何通过Qt的布局管理器将两个按钮放到右上角。代码如下:
.h文件
#ifndef UPPANEL_H
#define UPPANEL_H
#include <QWidget>
#include <QLabel>
class QToolButton;
class QSpacerItem;
class UpPanel : public QWidget
{
Q_OBJECT
public:
explicit UpPanel(QWidget *parent = nullptr);
void loadStyleSheet(const QString &styleSheetFile);
virtual void paintEvent(QPaintEvent *event);
QToolButton *toolBtnClose;
QToolButton *toolBtnSmall;
QSpacerItem *verticalSpacer;
QSpacerItem *horizontalSpacer;
signals:
public slots:
};
#endif // UPPANEL_H
.cpp文件
#include "uppanel.h"
#include <QFile>
#include <QMessageBox>
#include <QPainter>
#include <QStyleOption>
#include <QSpacerItem>
#include <QToolButton>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QMovie>
#include <QLabel>
UpPanel::UpPanel(QWidget *parent) : QWidget(parent)
{
this->loadStyleSheet(":/up_panel.qss");
this->setContentsMargins(0, 0, 0, 0);
toolBtnClose = new QToolButton;
toolBtnClose->setObjectName(QString::fromUtf8("toolBtnClose"));
toolBtnSmall = new QToolButton;
toolBtnSmall->setObjectName(QString::fromUtf8("toolBtnSmall"));
horizontalSpacer = new QSpacerItem(619, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
verticalSpacer = new QSpacerItem(20, 241, QSizePolicy::Minimum, QSizePolicy::Expanding);
QHBoxLayout *toolBtnLayout = new QHBoxLayout;
toolBtnLayout->addWidget(toolBtnSmall);
toolBtnLayout->addWidget(toolBtnClose);
QGridLayout *gridLayout = new QGridLayout;
gridLayout->setSpacing(6);
gridLayout->setContentsMargins(0, 0, 0, 0);
gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
gridLayout->addItem(horizontalSpacer, 0, 0, 1, 1);
gridLayout->addLayout(toolBtnLayout, 0, 1, 1, 1);
gridLayout->addItem(verticalSpacer, 1, 1, 1, 1);
setLayout(gridLayout);
}
void UpPanel::loadStyleSheet(const QString &styleSheetFile)
{
QFile file(styleSheetFile);
file.open(QFile::ReadOnly);
if (file.isOpen())
{
QString styleSheet = this->styleSheet();
styleSheet += QLatin1String(file.readAll());//读取样式表文件
this->setStyleSheet(styleSheet);//把文件内容传参
file.close();
}
else
{
QMessageBox::information(this,"tip","cannot find qss file");
}
}
void UpPanel::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QStyleOption styleOpt;
styleOpt.init(this);
QPainter painter(this);
style()->drawPrimitive(QStyle::PE_Widget, &styleOpt, &painter, this);
}
窗口缩放
窗口缩放使用setWindowState来设置窗口状态。
void Widget::windowHide()
{
this->setWindowState(Qt::WindowMinimized);
}
实现主功能区
主功能区也就是信息输入区(downPanel),如下图所示:
通过观察,我们列出需要的控件如下
QLabel *qqHeadLabel;
QLabel *registerLabel;
QLabel *retrievePasswordLabel;
QLabel *addFriendsLabel;
QLabel *QRCodeLabel;
QComboBox *inputCountComboBox;
QLineEdit *passwordLineEdit;
QCheckBox *rememberPasswordBox;
QCheckBox *autoLoginBox;
QPushButton *logInPushButton;
QSpacerItem *verticalSpacer_0;
QSpacerItem *verticalSpacer_1;
QSpacerItem *horizontalSpacer_0;
QSpacerItem *horizontalSpacer_1;
QSpacerItem *horizontalSpacer_2;
控件设置以及布局如下
this->loadStyleSheet(":/down_panel.qss");
this->setObjectName("downPanel");
qqHeadLabel = new QLabel;
qqHeadLabel->setObjectName("qqHeadLabel");
registerLabel = new QLabel;
registerLabel->setObjectName("registerLabel");
registerLabel->setText("注册账号");
retrievePasswordLabel = new QLabel;
retrievePasswordLabel->setObjectName("retrievePasswordLabel");
retrievePasswordLabel->setText("找回密码");
addFriendsLabel = new QLabel;
addFriendsLabel->setObjectName("addFriendsLabel");
QRCodeLabel = new QLabel;
QRCodeLabel->setObjectName("QRCodeLabel");
inputCountComboBox = new QComboBox;
inputCountComboBox->setObjectName("inputCountComboBox");
inputCountComboBox->setEditable(true);
inputCountComboBox->addItem("1040283480");
inputCountComboBox->addItem("2839319053");
passwordLineEdit = new QLineEdit;
passwordLineEdit->setObjectName("passwordLineEdit");
passwordLineEdit->setEchoMode(QLineEdit::Password);
passwordLineEdit->setPlaceholderText("密码");
passwordLineEdit->addAction(QIcon(":/picture/keyboard.png"), QLineEdit::TrailingPosition);
rememberPasswordBox = new QCheckBox;
rememberPasswordBox->setObjectName("rememberPasswordBox");
rememberPasswordBox->setText("记住密码");
autoLoginBox = new QCheckBox;
autoLoginBox->setObjectName("autoLoginBox");
autoLoginBox->setText("自动登录");
logInPushButton = new QPushButton;
logInPushButton->setObjectName("logInPushButton");
logInPushButton->setText("登录");
QGridLayout *gridLayout_0 = new QGridLayout;
gridLayout_0->addWidget(qqHeadLabel, 0, 0, 3, 1);
gridLayout_0->addWidget(inputCountComboBox, 0, 1, 1, 2);
gridLayout_0->addWidget(passwordLineEdit, 1, 1, 1, 2);
gridLayout_0->addWidget(rememberPasswordBox, 2, 1, 1, 1);
gridLayout_0->addWidget(autoLoginBox, 2, 2, 1, 1);
gridLayout_0->addWidget(logInPushButton, 3, 1, 1, 2);
gridLayout_0->addWidget(registerLabel, 0, 3, 1, 1);
gridLayout_0->addWidget(retrievePasswordLabel, 1, 3, 1, 1);
QHBoxLayout *horizontalLayout = new QHBoxLayout;
horizontalLayout->addWidget(addFriendsLabel);
horizontalSpacer_0 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout->addItem(horizontalSpacer_0);
horizontalLayout->addWidget(QRCodeLabel);
QGridLayout *gridLayout_1 = new QGridLayout;
horizontalSpacer_1 = new QSpacerItem(189, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalSpacer_2 = new QSpacerItem(189, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
verticalSpacer_0 = new QSpacerItem(20, 31, QSizePolicy::Minimum, QSizePolicy::Expanding);
verticalSpacer_1 = new QSpacerItem(20, 32, QSizePolicy::Minimum, QSizePolicy::Expanding);
gridLayout_1->addItem(horizontalSpacer_1, 1, 0, 1, 1);
gridLayout_1->addItem(horizontalSpacer_2, 1, 2, 1, 1);
gridLayout_1->addItem(verticalSpacer_0, 0, 1, 1, 1);
gridLayout_1->addItem(verticalSpacer_0, 2, 1, 1, 1);
gridLayout_1->addLayout(gridLayout_0, 1, 1, 1, 1);
gridLayout_1->addLayout(horizontalLayout, 3, 0, 1, 3);
this->setLayout(gridLayout_1);
QSS样式
downPanel
QWidget#downPanel{
background-color: rgb(236, 236, 236);
}
QLabel#qqHeadLabel {
min-width:90px;
max-width:90px;
min-height:90px;
max-height:90px;
border-radius:45px;
border-image: url(:/picture/qqhead.png);
}
QLabel#addFriendsLabel {
min-width:20px;
max-width:20px;
min-height:20px;
max-height:20px;
border-image: url(:/picture/add_friends.png);
}
QLabel#QRCodeLabel {
min-width:20px;
max-width:20px;
min-height:20px;
max-height:20px;
border-image: url(:/picture/QRode.png);
}
QLabel#registerLabel {
color:rgb(0, 170, 255);
}
QLabel#retrievePasswordLabel {
color: rgb(0, 170, 255);
}
QCheckBox {
color: rgb(100, 100, 100);
}
QPushButton {
min-height:25px;
max-height:25px;
border-radius:3px;
background-color: rgb(0, 155, 232);
color:white;
}
QPushButton:hover {
min-height:25px;
max-height:25px;
border-radius:3px;
background-color: rgb(0, 155, 150);
color:white;
}
upPanel
QWidget {
image: url(:/picture/qq.png);
border-image: url(:/picture/title_background.gif)
}
QToolButton#toolBtnClose {
background:transparent;
border-image: url(:/picture/close.png);
image:none;
min-width:30px;
max-width:30px;
min-height:30px;
max-height:30px
}
QToolButton#toolBtnSmall {
background:transparent;
border-image: url(:/picture/mini.png);
image:none;
min-width:30px;
max-width:30px;
min-height:30px;
max-height:30px
}
QToolButton#toolBtnClose:hover {
background-color: rgba(0, 85, 255, 0.5);
}
QToolButton#toolBtnSmall:hover {
background-color: rgba(0, 85, 255, 0.5);
}
QSS使用注意事项:
- 如果一个类继承自QWidget,那么必须重新实现paintEvent,QSS样式才会有效果。
- 如果想要使用具体类选择器(#),那么必须通过setObjectName为具体的类设置objectname。
- 进行样式设计时请遵循方盒模型(Box Model)
- 掌握控件大小的设定方法(min-width;max-width;min-height;max-height)
引用
[1] Qt助手