Qt学习:无边框界面的实现总结

无边框界面是每个桌面应用必备的功能。手机无边框就很好解决了,直接无边框就好了,默认是全屏的。但是桌面无边框会有很多问题,首先是不能拖动。

之前看过别人的无边框实现,大部分是做成整个界面按住哪里都能拖动,感觉这样不好。

另外看到大部分的代码都只实现了拖动,却没有实现标题栏。

还是自己做比较好。

1、无边框的实现代码

    // 无边框
    setWindowFlags(Qt::FramelessWindowHint|Qt::WindowMinimizeButtonHint);

2、做一个标题栏

    //QFrame * headFrame = new QFrame;
    MyQFrame * headFrame = new MyQFrame;

    connect(headFrame,SIGNAL(myQFramePress(QMouseEvent*)),this,SLOT(onMyQFramePress(QMouseEvent *)));
    connect(headFrame,SIGNAL(myQFrameRelease(QMouseEvent*)),this,SLOT(onMyQFrameRelease(QMouseEvent *)));

    // icon加载
    QPixmap pixmapIcon;
    pixmapIcon.load(":/img/headIcon.png");

    QLabel * labelHeadIcon = new QLabel;
    labelHeadIcon->setFixedSize(pixmapIcon.width(),pixmapIcon.height());
    labelHeadIcon->setPixmap(pixmapIcon);

    // 最小化按钮
    QPixmap pixmapMin;
    pixmapMin.load(":/img/miniBtn.png");

    QPushButton * minBtn = new QPushButton;
    minBtn->setFixedSize(pixmapMin.width(),pixmapMin.height());
    minBtn->setIcon(pixmapMin);
    minBtn->setIconSize(QSize(pixmapMin.width(),pixmapMin.height()));
    minBtn->setCursor(Qt::PointingHandCursor);
    minBtn->setStyleSheet("background-color: rgba(0, 0, 0, 0)");//此种方法完美实现按钮透明背景

    // 最大化按钮
    QPixmap pixmapFull;
    pixmapFull.load(":/img/fullBtn.png");

    QPushButton * fullBtn = new QPushButton;
    fullBtn->setFixedSize(pixmapFull.width(),pixmapFull.height());
    fullBtn->setIcon(pixmapFull);
    fullBtn->setIconSize(QSize(pixmapFull.width(),pixmapFull.height()));
    fullBtn->setCursor(Qt::PointingHandCursor);
    fullBtn->setStyleSheet("background-color: rgba(0, 0, 0, 0)");


    // 关闭按钮
    QPixmap pixmapClose;
    pixmapClose.load(":/img/closeBtn.png");

    QPushButton * closeBtn = new QPushButton;
    closeBtn->setFixedSize(pixmapClose.width(),pixmapClose.height());
    closeBtn->setIcon(pixmapClose);
    closeBtn->setIconSize(QSize(pixmapClose.width(),pixmapClose.height()));
    closeBtn->setCursor(Qt::PointingHandCursor);
    closeBtn->setStyleSheet("background-color: rgba(0, 0, 0, 0)");

    connect(minBtn,SIGNAL(clicked(bool)),SLOT(onMinBtnClick()));
    connect(fullBtn,SIGNAL(clicked(bool)),SLOT(onFullBtnClick()));
    connect(closeBtn,SIGNAL(clicked(bool)),SLOT(onCloseBtnClick()));

    // 创建一个layout:标题栏
    QHBoxLayout * headBoxLayout = new QHBoxLayout(headFrame);
    headBoxLayout->setMargin(0);// 设置边距为0
    headBoxLayout->addWidget(labelHeadIcon);// 添加左边的icon
    headBoxLayout->addStretch(1);// 添加弹簧
    headBoxLayout->addWidget(minBtn);
    headBoxLayout->addWidget(fullBtn);
    headBoxLayout->addWidget(closeBtn);

    headFrame->setAutoFillBackground(true);
    QColor color = QColor(37,37,118);
    QPalette p = headFrame->palette();
    p.setColor(QPalette::Window,color);
    headFrame->setPalette(p);
    headFrame->update();

注意,这个标题栏还要加入到主容器里:

    QVBoxLayout * mainLayout = new QVBoxLayout(this);
    mainLayout->setMargin(0);// 设置边距为0
    mainLayout->addWidget(headFrame);

3、标题栏使用的是自定义的QFrame

我们设计的目标是在标题栏按下鼠标左键则可以移动窗口,而非在任何地方都能移动窗口。而QFrame不能实现这个功能,我们需要一个自定义的QFrame。

鼠标监听功能自QWidget就有了,而QFrame是继承自QWidget的。

(1)但是他并非已经实现了,他的监听回调是虚函数,需要自己去实现;

(2)我们想统一在主页面处理这些回调,而非在组件的类里面单独处理这些回调,那么,我们还需要给他添加信号,然后在主页面添加槽,完成信号的触发及调用。

myqframe.h:

#ifndef MYQFRAME_H
#define MYQFRAME_H

#include <QFrame>


class MyQFrame : public QFrame
{
    Q_OBJECT
public:
    explicit MyQFrame();
    ~MyQFrame();
protected:
    void mousePressEvent(QMouseEvent *e);
    void mouseMoveEvent(QMouseEvent *e);
    void mouseReleaseEvent(QMouseEvent *e);
    void mouseDoubleClickEvent(QMouseEvent *e);

signals:
    void myQFramePress(QMouseEvent *e);// 注意,信号只需注册,并在cpp里调用,无需实现
    void myQFrameRelease(QMouseEvent *e);
};

#endif // MYQFRAME_H

myqframe.cpp:

#include "myqframe.h"
#include <QDebug>

MyQFrame::MyQFrame()
{
    this->setMouseTracking(true);// 此属性没有设为true则不会监听到mouseMove
}
MyQFrame::~MyQFrame()
{

}
void MyQFrame::mousePressEvent(QMouseEvent *e)
{
    // 此事件只在此地触发,没必要让父窗口捕捉到,因此也就不需要抛出QFrame::mousePressEvent
    myQFramePress(e);
}
void MyQFrame::mouseMoveEvent(QMouseEvent *e)
{
    // 注意:在此抛出QFrame::mouseMoveEvent(e);则在父窗口可以接收到mouseMoveEvent事件,否则接收不到
    // 另外,必须设置this->setMouseTracking(true);否则不能触发此回调函数
    QFrame::mouseMoveEvent(e);
}
void MyQFrame::mouseReleaseEvent(QMouseEvent *e)
{
    myQFrameRelease(e);
}
void MyQFrame::mouseDoubleClickEvent(QMouseEvent *e)
{
//    qDebug()<<"doubleclick!";
}

4、主窗口代码

dialog.h:

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPoint>
#include <QMouseEvent>
#include <QKeyEvent>

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;
    initUI();
    bool IsPressed;
    QPoint startPoint;
private slots:
    void onMyQFramePress(QMouseEvent *e);
    void onMyQFrameRelease(QMouseEvent *e);
    void onMinBtnClick();
    void onFullBtnClick();
    void onCloseBtnClick();
protected:
    void mouseMoveEvent(QMouseEvent * e);
    void keyPressEvent(QKeyEvent *);
};

#endif // DIALOG_H

dialog.cpp:

#include "dialog.h"
#include "ui_dialog.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLabel>
#include <QDebug>
#include <QPushButton>
#include <myqframe.h>
#include <QPoint>
#include <QCursor>

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    resize(QSize(800,600));

    initUI();
    IsPressed = false;
}

Dialog::initUI()
{
    // 无边框
    setWindowFlags(Qt::FramelessWindowHint|Qt::WindowMinimizeButtonHint);

    // ______________________________设置标题栏_________________________________
    // QFrame做背景
    //QFrame * headFrame = new QFrame;
    MyQFrame * headFrame = new MyQFrame;

    connect(headFrame,SIGNAL(myQFramePress(QMouseEvent*)),this,SLOT(onMyQFramePress(QMouseEvent *)));
    connect(headFrame,SIGNAL(myQFrameRelease(QMouseEvent*)),this,SLOT(onMyQFrameRelease(QMouseEvent *)));

    // icon加载
    QPixmap pixmapIcon;
    pixmapIcon.load(":/img/headIcon.png");

    QLabel * labelHeadIcon = new QLabel;
    labelHeadIcon->setFixedSize(pixmapIcon.width(),pixmapIcon.height());
    labelHeadIcon->setPixmap(pixmapIcon);

    // 最小化按钮
    QPixmap pixmapMin;
    pixmapMin.load(":/img/miniBtn.png");

    QPushButton * minBtn = new QPushButton;
    minBtn->setFixedSize(pixmapMin.width(),pixmapMin.height());
    minBtn->setIcon(pixmapMin);
    minBtn->setIconSize(QSize(pixmapMin.width(),pixmapMin.height()));
    minBtn->setCursor(Qt::PointingHandCursor);
    minBtn->setStyleSheet("background-color: rgba(0, 0, 0, 0)");//此种方法完美实现按钮透明背景

    // 最大化按钮
    QPixmap pixmapFull;
    pixmapFull.load(":/img/fullBtn.png");

    QPushButton * fullBtn = new QPushButton;
    fullBtn->setFixedSize(pixmapFull.width(),pixmapFull.height());
    fullBtn->setIcon(pixmapFull);
    fullBtn->setIconSize(QSize(pixmapFull.width(),pixmapFull.height()));
    fullBtn->setCursor(Qt::PointingHandCursor);
    fullBtn->setStyleSheet("background-color: rgba(0, 0, 0, 0)");


    // 关闭按钮
    QPixmap pixmapClose;
    pixmapClose.load(":/img/closeBtn.png");

    QPushButton * closeBtn = new QPushButton;
    closeBtn->setFixedSize(pixmapClose.width(),pixmapClose.height());
    closeBtn->setIcon(pixmapClose);
    closeBtn->setIconSize(QSize(pixmapClose.width(),pixmapClose.height()));
    closeBtn->setCursor(Qt::PointingHandCursor);
    closeBtn->setStyleSheet("background-color: rgba(0, 0, 0, 0)");

    connect(minBtn,SIGNAL(clicked(bool)),SLOT(onMinBtnClick()));
    connect(fullBtn,SIGNAL(clicked(bool)),SLOT(onFullBtnClick()));
    connect(closeBtn,SIGNAL(clicked(bool)),SLOT(onCloseBtnClick()));

    // 创建一个layout:标题栏
    QHBoxLayout * headBoxLayout = new QHBoxLayout(headFrame);
    headBoxLayout->setMargin(0);// 设置边距为0
    headBoxLayout->addWidget(labelHeadIcon);// 添加左边的icon
    headBoxLayout->addStretch(1);// 添加弹簧
    headBoxLayout->addWidget(minBtn);
    headBoxLayout->addWidget(fullBtn);
    headBoxLayout->addWidget(closeBtn);

    headFrame->setAutoFillBackground(true);
    QColor color = QColor(37,37,118);
    QPalette p = headFrame->palette();
    p.setColor(QPalette::Window,color);
    headFrame->setPalette(p);
    headFrame->update();

    // _____________________________关于本机_____________________________________
    // 关于本机按钮
    QPixmap pixmapAbout;
    pixmapAbout.load(":/img/about.png");

    QPushButton * aboutBtn = new QPushButton;
    aboutBtn->setFixedSize(pixmapAbout.width(),pixmapAbout.height());
    aboutBtn->setIcon(pixmapAbout);
    aboutBtn->setIconSize(QSize(pixmapAbout.width(),pixmapAbout.height()));
    aboutBtn->setCursor(Qt::PointingHandCursor);
    aboutBtn->setStyleSheet("background-color: rgba(0, 0, 0, 0)");

    // 创建一个layout:关于本机
    QFrame * aboutFrame = new QFrame;

    QHBoxLayout * aboutBoxLayout = new QHBoxLayout(aboutFrame);
    aboutBoxLayout->setMargin(0);
    aboutBoxLayout->addStretch(8);
    aboutBoxLayout->addWidget(aboutBtn);
    aboutBoxLayout->addStretch(1);

    // ____________________________程序功能模块按钮_____________________________
    QPixmap pixmapRunBtn;
    pixmapRunBtn.load(":/img/runBtnWithTitle.png");

    QPixmap pixmapReportBtn;
    pixmapReportBtn.load(":/img/reportBtnWithTitle.png");

    QPixmap pixmapClearBtn;
    pixmapClearBtn.load(":/img/clearBtnWithTitle.png");

    QPixmap pixmapDevelopBtn;
    pixmapDevelopBtn.load(":/img/developBtnWithTitle.png");

    QPushButton * runBtn = new QPushButton;
    runBtn->setFixedSize(pixmapRunBtn.width(),pixmapRunBtn.height());
    runBtn->setIcon(pixmapRunBtn);
    runBtn->setIconSize(QSize(pixmapRunBtn.width(),pixmapRunBtn.height()));
    runBtn->setCursor(Qt::PointingHandCursor);
    runBtn->setStyleSheet("background-color: rgba(0, 0, 0, 0)");

    QPushButton * reportBtn = new QPushButton;
    reportBtn->setFixedSize(pixmapReportBtn.width(),pixmapReportBtn.height());
    reportBtn->setIcon(pixmapReportBtn);
    reportBtn->setIconSize(QSize(pixmapReportBtn.width(),pixmapReportBtn.height()));
    reportBtn->setCursor(Qt::PointingHandCursor);
    reportBtn->setStyleSheet("background-color: rgba(0, 0, 0, 0)");

    QPushButton * clearBtn = new QPushButton;
    clearBtn->setFixedSize(pixmapClearBtn.width(),pixmapClearBtn.height());
    clearBtn->setIcon(pixmapClearBtn);
    clearBtn->setIconSize(QSize(pixmapClearBtn.width(),pixmapClearBtn.height()));
    clearBtn->setCursor(Qt::PointingHandCursor);
    clearBtn->setStyleSheet("background-color: rgba(0, 0, 0, 0)");

    QPushButton * developBtn = new QPushButton;
    developBtn->setFixedSize(pixmapDevelopBtn.width(),pixmapDevelopBtn.height());
    developBtn->setIcon(pixmapDevelopBtn);
    developBtn->setIconSize(QSize(pixmapDevelopBtn.width(),pixmapDevelopBtn.height()));
    developBtn->setCursor(Qt::PointingHandCursor);
    developBtn->setStyleSheet("background-color: rgba(0, 0, 0, 0)");


    QFrame * funcFrame = new QFrame;

    QHBoxLayout * funcBoxLayout = new QHBoxLayout(funcFrame);
    funcBoxLayout->setMargin(0);
    funcBoxLayout->addStretch(3);
    funcBoxLayout->addWidget(runBtn);
    funcBoxLayout->addStretch(2);
    funcBoxLayout->addWidget(reportBtn);
    funcBoxLayout->addStretch(2);
    funcBoxLayout->addWidget(clearBtn);
    funcBoxLayout->addStretch(2);
    funcBoxLayout->addWidget(developBtn);
    funcBoxLayout->addStretch(3);

    //____________________________公司logo___________________________

    QPixmap pixmapLogo;
    pixmapLogo.load(":/img/ze.jpg");

    QLabel * labelLogo = new QLabel;
    labelLogo->setFixedSize(pixmapLogo.width(),pixmapLogo.height());
    labelLogo->setPixmap(pixmapLogo);

    QFrame * logoFrame = new QFrame;

    QHBoxLayout * logoBoxLayout = new QHBoxLayout(logoFrame);
    logoBoxLayout->setMargin(0);
    logoBoxLayout->addStretch(100);
    logoBoxLayout->addWidget(labelLogo);
    logoBoxLayout->addStretch(1);

    // __________________________底部状态显示及版权声明_____________________

    QLabel * labelStatus = new QLabel;
    QFont fontStatus;
    fontStatus.setPointSize(12);
    labelStatus->setFont(fontStatus);

    labelStatus->setText("2018/03/06 10:16:30 通讯成功");

    QLabel * labelCopyRight = new QLabel;
    QFont fontCopyRight;
    fontCopyRight.setPointSize(12);
    fontCopyRight.setFamily("Microsoft YaHei");
    fontCopyRight.setBold(true);
    labelCopyRight->setFont(fontCopyRight);
    labelCopyRight->setText("Copyright(c) 科技股份有限公司.ALL RIGHT RESERVED");

    QFrame * bottomFrame = new QFrame;

    QHBoxLayout * bottomBoxLayout = new QHBoxLayout(bottomFrame);
    bottomBoxLayout->setMargin(0);
    bottomBoxLayout->addStretch(1);
    bottomBoxLayout->addWidget(labelStatus);
    bottomBoxLayout->addStretch(4);
    bottomBoxLayout->addWidget(labelCopyRight);
    bottomBoxLayout->addStretch(1);


    // _____________________________主容器______________________________
    QVBoxLayout * mainLayout = new QVBoxLayout(this);
    mainLayout->setMargin(0);// 设置边距为0
    mainLayout->addWidget(headFrame);
    mainLayout->addStretch(5);
    mainLayout->addWidget(aboutFrame);
    mainLayout->addStretch(25);
    mainLayout->addWidget(funcFrame);
    mainLayout->addStretch(30);
    mainLayout->addWidget(logoFrame);
    mainLayout->addWidget(bottomFrame);
    mainLayout->addStretch(1);

}

void Dialog::mouseMoveEvent(QMouseEvent *e)
{
    if(IsPressed)
    {
        // 原理:移动相对位置
        // QCursor::pos()鼠标位置
        // startPoint起始位置
        // move设置的是QWidget左上角的坐标
        QPoint windowPos(QCursor::pos()-startPoint);
        move(windowPos);
    }
}

void Dialog::onMyQFramePress(QMouseEvent *e)
{
    IsPressed = true;
    startPoint = e->pos();
}
void Dialog::onMyQFrameRelease(QMouseEvent *e)
{
    IsPressed = false;
}
void Dialog::onMinBtnClick()
{
    this->showMinimized();
}
void Dialog::onFullBtnClick()
{
    if(this->isFullScreen())
    {
        this->setWindowFlags(Qt::SubWindow);
        this->showNormal();
    }else
    {
        this->setWindowFlags(Qt::Window);
        this->showFullScreen();
    }
}
void Dialog::onCloseBtnClick()
{
    QApplication::exit();
}
void Dialog::keyPressEvent(QKeyEvent * keyset)
{
    if(keyset->key()==Qt::Key_Escape)
    {
        if(this->isFullScreen())
        {
            this->setWindowFlags(Qt::SubWindow);
            this->showNormal();
        }
    }
}

Dialog::~Dialog()
{
    delete ui;
}




猜你喜欢

转载自blog.csdn.net/wzj0808/article/details/79459242
今日推荐