Qt自定义标题栏并实现拖拽

来源:互联网 发布:笛卡尔积 sql 编辑:程序博客网 时间:2024/06/07 17:49

Qt自定义标题栏并实现拖拽

  很多时候,Qt自带的窗体边框不能满足我们的需求,或者我们觉得由于系统的主题影响导致界面太丑了,我们需要自行定义一个好看并和普通标题栏功能相同的控件去替代,以达到美化我们的程序界面的目的;本文简单的实现了该功能。
  下面是运行截图,由于图片选的比较丑,所以看起来不好看:
自定义标题栏
  实现了鼠标拖拽事件,没有为标题栏添加鼠标右键事件以及其他美化功能,可以自行添加。

拖拽实现详解:

  首先需要了解Qt的一些函数的意义:
  MouseEvent中的globalPos()函数返回的是相对屏幕的位置坐标,而pos()则是返回鼠标在当前控件(即捕获该鼠标事件的控件)中的位置;
  QWidget窗体的geometry().topLeft()则返回的是当前窗体的左上角在屏幕中的位置;

  其次让我们看图说话,理解下窗体移动:
窗体移动
  然后我们每次只要把上次的位置作为起始位置,就是一次次的拖拽了。

  最后,我们列出算式:
  startPos = event->globalPos();      // 鼠标的全局初始位置,按下时记住
  curWindowPos = geometry().topleft();  // 窗体的全局位置,移动时
  endPos = event->globalPos();      // 鼠标按下发生移动之后的位置,移动时
  move(curWindowPos+(startPos-endPos)); // 根据矢量移动方向是初始位置减去末位置,移动时
  startPos = endPos;     // 将初始位置记为上次末位置,然后执行直到释放拖拽,移动时

头文件


// WindowHeader.h#ifndef WINDOWHEADER_H#define WINDOWHEADER_H#include <QLabel>#include <QWidget>#include <QToolButton>#include <QHBoxLayout>#include <QPoint>#include <QString>// 自定义控件,可拖拽标题栏class WindowHeader : public QWidget{    Q_OBJECTpublic:    // 构造函数    WindowHeader(const char* appName, QWidget *parent);    // 设置关闭按钮icon    void SetCloseImage(const char* path);    // 设置最小化按钮icon    void SetMinImage(const char* path);    // 设置最大化按钮icon    void SetMaxImage(const char* path);    // 设置迷你模式按钮icon    void SetMiniImage(const char* path);    // 设置软件配置按钮icon    void SetSettingImage(const char* path);    // 设置皮肤按钮icon    void SetSkinImage(const char* path);    // 设置软件LOGO按钮icon    void SetAppLogo(const char* path,int w=20,int h=20);    // 获取软件名    QString GetAppName() { return msAppName; }protected:    // 重写鼠标事件    void mouseMoveEvent(QMouseEvent *event);    void mousePressEvent(QMouseEvent *event);    void mouseReleaseEvent(QMouseEvent *event);    // 将信号中转,不直接处理信号signals:    void ClickedClose();    void ClickedMin();    void ClickedMax();    void ClickedMini();    void ClickedSetting();    void ClickedSkin();private:    // 应用名    QString msAppName;    // 关闭按钮    QToolButton* mTlbtnClose;    // 最小化按钮    QToolButton* mTlbtnMin;    // 最大化按钮    QToolButton* mTlbtnMax;    // 迷你模式按钮    QToolButton* mTlbtnMini;    // 软件配置按钮    QToolButton* mTlbtnSetting;    // 皮肤设置按钮    QToolButton* mTlbtnSkin;    // 呈现应用名称    QLabel* mLblAppName;    // 呈现应用LOGO    QLabel* mLblAppLogo;    // 整体布局    QHBoxLayout* mLytMain;    // 鼠标上次移动开始时相对屏幕的位置    QPoint mPntStart;    // 鼠标是否持续按下    bool mbKeepPressed;    // 父窗口的指针    QWidget *mWidParent;};#endif // WINDOWHEADER_H

源文件


// WindowHeader.cpp#include "WindowHeader.h"#include <QMouseEvent>#include <QPixmap>#include <QIcon>WindowHeader::WindowHeader(const char* appName,QWidget *parent)    :QWidget(parent),msAppName(appName){    // 父窗口指针赋值,并设置父窗口为无边框模式    mWidParent = parent;    mWidParent->setWindowFlags(Qt::FramelessWindowHint | mWidParent->windowFlags());    // 初始化按钮    mTlbtnClose = new QToolButton(this);    mTlbtnMin = new QToolButton(this);    mTlbtnMax = new QToolButton(this);    mTlbtnMini = new QToolButton(this);    mTlbtnSetting = new QToolButton(this);    mTlbtnSkin = new QToolButton(this);    // 初始化标签    mLblAppName = new QLabel(this);    mLblAppName->setText(msAppName);    mLblAppLogo = new QLabel(this);    // 初始化布局    mLytMain = new QHBoxLayout(this);    mLytMain->setContentsMargins(2,2,2,2);    mLytMain->setSpacing(2);    // 设置布局    mLytMain->addWidget(mLblAppLogo);    mLytMain->addWidget(mLblAppName);    // 设置“弹簧”,将呈现和按钮功能分开    mLytMain->addStretch();    mLytMain->addWidget(mTlbtnSkin);    mLytMain->addWidget(mTlbtnSetting);    mLytMain->addWidget(mTlbtnMini);    mLytMain->addWidget(mTlbtnMin);    mLytMain->addWidget(mTlbtnMax);    mLytMain->addWidget(mTlbtnClose);    // 将内部按钮信号全部发送出去,内部不做业务逻辑绑定    connect(mTlbtnClose,SIGNAL(clicked(bool)),SIGNAL(ClickedClose()));    connect(mTlbtnMax,SIGNAL(clicked(bool)),SIGNAL(ClickedMax()));    connect(mTlbtnMin,SIGNAL(clicked(bool)),SIGNAL(ClickedMin()));    connect(mTlbtnMini,SIGNAL(clicked(bool)),SIGNAL(ClickedMini()));    connect(mTlbtnSetting,SIGNAL(clicked(bool)),SIGNAL(ClickedSetting()));    connect(mTlbtnSkin,SIGNAL(clicked(bool)),SIGNAL(ClickedSkin()));}// 设置应用LOGOvoid WindowHeader::SetAppLogo(const char *path,int w,int h){    QPixmap newPix = QPixmap(path).scaled(w,h,Qt::KeepAspectRatio);    mLblAppLogo->setPixmap(newPix);}void WindowHeader::SetSkinImage(const char *path){    QIcon icon(path);    mTlbtnSkin->setIcon(icon);}void WindowHeader::SetSettingImage(const char *path){    QIcon icon(path);    mTlbtnSetting->setIcon(icon);}void WindowHeader::SetMiniImage(const char *path){    QIcon icon(path);    mTlbtnMini->setIcon(icon);}void WindowHeader::SetMaxImage(const char *path){    QIcon icon(path);    mTlbtnMax->setIcon(icon);}void WindowHeader::SetMinImage(const char *path){    QIcon icon(path);    mTlbtnMin->setIcon(icon);}void WindowHeader::SetCloseImage(const char *path){    QIcon icon(path);    mTlbtnClose->setIcon(icon);}// 重写mouseMoveEventvoid WindowHeader::mouseMoveEvent(QMouseEvent *event){    // 持续按住才做对应事件    if (mbKeepPressed)    {        // 将父窗体移动到父窗体之前的位置加上鼠标移动的位置【event->globalPos()- mPntStart】        mWidParent->move(mWidParent->geometry().topLeft() + event->globalPos()- mPntStart);        // 将鼠标在屏幕中的位置替换为新的位置        mPntStart = event->globalPos();    }}// 重写mousePressEventvoid WindowHeader::mousePressEvent(QMouseEvent *event){    // 鼠标左键按下事件    if (event->button() == Qt::LeftButton)    {        // 记录鼠标状态        mbKeepPressed = true;        // 记录鼠标在屏幕中的位置        mPntStart = event->globalPos();    }}// 重写mouseReleaseEventvoid WindowHeader::mouseReleaseEvent(QMouseEvent *event){    // 鼠标左键释放    if (event->button() == Qt::LeftButton)    {        // 记录鼠标状态        mbKeepPressed = false;    }}

原文出处:http://blog.csdn.net/motou263514/article/details/78090483

原创粉丝点击