簡述
模仿QQ登錄界面。
主要涉及佈局管理器、輸入控件以及QSS樣式的使用。
只實現了基本的外觀,並不涉及到內部功能實現。
整個界面分爲兩大部分,上面的歡迎界面(upPanel)和下面的信息輸入界面(downPanel)。每一個部分都用一個單獨的類來實現。這兩個類都繼承自QWidget。
效果
核心代碼
核心代碼主要涉及以下幾個方面的內容
- 實現無邊框窗體
- 實現窗口的拖動
- 實現QQ工具欄
- 實現主功能區
無邊框窗體
windows默認的工具欄和QQ不一樣,爲了方便我們實現自己的工具欄,我們要將它隱藏起來。
setWindowFlags(Qt::FramelessWindowHint);
窗口的拖動
默認情況下只有工具欄所在的矩形長條區域可以拖動控件,但是由於我們將該長條隱藏了,所以需要自己實現窗口拖動效果,主要依據的是重寫鼠標事件函數。
.h文件要添加的內容
public: //設置鼠標按下可移動窗口的區域,在子窗口中必須設置該區域
void setAreaMovable(const QRect rt);
protected:
void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
private:
Ui::Widget *ui;
QRect m_areaMovable;//可移動窗口的區域,鼠標只有在該區域按下才能移動窗口
bool m_bPressed;//鼠標按下標誌(不分左右鍵)
QPoint m_ptPress;//鼠標按下的初始位置
.cpp文件要添加的內容
void Widget::mousePressEvent(QMouseEvent *e)
{
//鼠標左鍵
if(e->button() == Qt::LeftButton)
{
m_ptPress = e->pos();
qDebug() << pos() << e->pos() << m_ptPress;
m_bPressed = m_areaMovable.contains(m_ptPress);
}
}
void Widget::mouseMoveEvent(QMouseEvent *e)
{
if(m_bPressed)
{
qDebug() << pos() << e->pos() << m_ptPress;
move(pos() + e->pos() - m_ptPress);
}
}
void Widget::mouseReleaseEvent(QMouseEvent *)
{
m_bPressed = false;
}
//設置鼠標按下的區域
void Widget::setAreaMovable(const QRect rt)
{
if(m_areaMovable != rt)
{
m_areaMovable = rt;
}
}
並在主窗口構造函數中加入下面的語句
m_areaMovable = geometry();
m_bPressed = false;
注意:這裏設置的可拖動區域爲全局,如果想要實現僅某個區域可拖動,需要調用setAreaMovable來設定可拖動區域。
實現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助手