无边框界面是每个桌面应用必备的功能。手机无边框就很好解决了,直接无边框就好了,默认是全屏的。但是桌面无边框会有很多问题,首先是不能拖动。
之前看过别人的无边框实现,大部分是做成整个界面按住哪里都能拖动,感觉这样不好。
另外看到大部分的代码都只实现了拖动,却没有实现标题栏。
还是自己做比较好。
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; }