欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Qt自定义标题栏

程序员文章站 2022-07-13 23:14:20
...
#ifndef WINDOWHEADER_H
#define WINDOWHEADER_H
 
#include <QWidget>
#include <QLabel>
#include <QWidget>
#include <QToolButton>
#include <QHBoxLayout>
 
#include <QPoint>
#include <QString>
#include <QDebug>
 
// 自定义控件,可拖拽标题栏
class WindowHeader : public QWidget
{
    Q_OBJECT
public:
    // 构造函数
    WindowHeader(const char* name, 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 m_name; }
protected:
    // 重写鼠标事件
    void mouseMoveEvent(QMouseEvent *event);
    void mousePressEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
 
    virtual bool eventFilter(QObject *obj, QEvent *event);
    void paintEvent(QPaintEvent *event);
 
    // 将信号中转,不直接处理信号
signals:
    void ClickedClose();
    void ClickedMin();
    void ClickedMax();
    void ClickedMini();
    void ClickedSetting();
    void ClickedSkin();
 
private:
    // 应用名
    QString m_name;
    int m_height;
 
    // 关闭按钮
    QToolButton* m_toolbtnClose;
    // 最小化按钮
    QToolButton* m_toolbtnMin;
    // 最大化按钮
    QToolButton* m_toolbtnMax;
    // 迷你模式按钮
    QToolButton* m_toolbtnMini;
    // 软件配置按钮
    QToolButton* m_toolbtnSetting;
    // 皮肤设置按钮
    QToolButton* m_toolbtnSkin;
 
    // 呈现应用名称
    QLabel* m_lableAppName;
    // 呈现应用LOGO
    QLabel* m_lableAppLogo;
 
    // 鼠标上次移动开始时相对屏幕的位置
    QPoint m_pointStart;
    // 鼠标是否持续按下
    bool mbKeepPressed;
 
    // 父窗口的指针
    QWidget *m_widgetParent;
 
    // 最大化/还原
    void updateMaximize();
};
 
#endif // WINDOWHEADER_H
 

cpp文件

#include "WindowHeader.h"
#include <QEvent>
#include <QMouseEvent>
#include <QPixmap>
#include <QIcon>
#include <QPainter>
#include <QStyleOption>
 
WindowHeader::WindowHeader(const char* name, QWidget *parent)
    :QWidget(parent),
      m_name(name),
      m_height(48)
 
{
    // 父窗口指针赋值,并设置父窗口为透明的无边框模式,
    //以后所有的控件将在父窗口中布局,包括菜单栏,工具栏,状态栏以及设置个主窗口,
    m_widgetParent = parent;
    m_widgetParent->setAttribute(Qt::WA_TranslucentBackground);
    m_widgetParent->setWindowFlags(Qt::FramelessWindowHint | m_widgetParent->windowFlags());
 
    //监听父窗口事件,主要用于窗口大小变化
    m_widgetParent->installEventFilter(this);
 
    //设置大小属性,横向伸展,竖向固定
    this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    this->resize(m_widgetParent->width(), m_height);
 
    //绘制圆角需要设置这两个属性。
    this->setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明
    this->setWindowFlags(Qt::FramelessWindowHint);   //设置无边框窗口
 
    // 初始化按钮
    m_toolbtnClose = new QToolButton(this);
    m_toolbtnClose->setText("关闭");
    m_toolbtnMin = new QToolButton(this);
    m_toolbtnMin->setText("最小化");
    m_toolbtnMax = new QToolButton(this);
    m_toolbtnMax->setText("最大化");
    m_toolbtnMini = new QToolButton(this);
    m_toolbtnSetting = new QToolButton(this);
    m_toolbtnSkin = new QToolButton(this);
 
    // 初始化标签
    m_lableAppName = new QLabel(this);
    m_lableAppName->setText(m_name);
    m_lableAppLogo = new QLabel(this);
 
    // 初始化布局
    QHBoxLayout* mainLayout = new QHBoxLayout(this);
    mainLayout->setContentsMargins(0,0,0,0);
    mainLayout->setSpacing(2);
 
    // 设置布局
    mainLayout->addWidget(m_lableAppLogo);
    mainLayout->addWidget(m_lableAppName);
    // 设置“弹簧”,将呈现和按钮功能分开
    mainLayout->addStretch();
    mainLayout->addWidget(m_toolbtnSkin);
    mainLayout->addWidget(m_toolbtnSetting);
    mainLayout->addWidget(m_toolbtnMini);
    mainLayout->addWidget(m_toolbtnMin);
    mainLayout->addWidget(m_toolbtnMax);
    mainLayout->addWidget(m_toolbtnClose);
 
    // 将内部按钮信号全部发送出去,内部不做业务逻辑绑定
    connect(m_toolbtnClose,SIGNAL(clicked(bool)),SIGNAL(ClickedClose()));
    connect(m_toolbtnMax,SIGNAL(clicked(bool)),SIGNAL(ClickedMax()));
    connect(m_toolbtnMin,SIGNAL(clicked(bool)),SIGNAL(ClickedMin()));
    connect(m_toolbtnMini,SIGNAL(clicked(bool)),SIGNAL(ClickedMini()));
    connect(m_toolbtnSetting,SIGNAL(clicked(bool)),SIGNAL(ClickedSetting()));
    connect(m_toolbtnSkin,SIGNAL(clicked(bool)),SIGNAL(ClickedSkin()));
}
 
// 设置应用LOGO
void WindowHeader::SetAppLogo(const char *path,int w,int h)
{
    QPixmap newPix = QPixmap(path).scaled(w,h,Qt::KeepAspectRatio);;
    m_lableAppLogo->setPixmap(newPix);
}
 
void WindowHeader::SetSkinImage(const char *path)
{
    QIcon icon(path);
    m_toolbtnSkin->setIcon(icon);
}
 
void WindowHeader::SetSettingImage(const char *path)
{
    QIcon icon(path);
    m_toolbtnSetting->setIcon(icon);
}
 
void WindowHeader::SetMiniImage(const char *path)
{
    QIcon icon(path);
    m_toolbtnMini->setIcon(icon);
}
 
void WindowHeader::SetMaxImage(const char *path)
{
    QIcon icon(path);
    m_toolbtnMax->setIcon(icon);
}
 
void WindowHeader::SetMinImage(const char *path)
{
    QIcon icon(path);
    m_toolbtnMin->setIcon(icon);
}
 
void WindowHeader::SetCloseImage(const char *path)
{
    QIcon icon(path);
    m_toolbtnClose->setIcon(icon);
}
 
// 重写mouseMoveEvent
void WindowHeader::mouseMoveEvent(QMouseEvent *event)
{
    // 持续按住才做对应事件
    if (mbKeepPressed)
    {
        // 将父窗体移动到父窗体之前的位置加上鼠标移动的位置event->globalPos()- m_pointStart
        m_widgetParent->move(m_widgetParent->geometry().topLeft() + event->globalPos()- m_pointStart);
        // 将鼠标在屏幕中的位置替换为新的位置
        m_pointStart = event->globalPos();
    }
}
 
// 重写mousePressEvent
void WindowHeader::mousePressEvent(QMouseEvent *event)
{
    // 鼠标左键按下事件
    if (event->button() == Qt::LeftButton)
    {
        // 记录鼠标状态
        mbKeepPressed = true;
        // 记录鼠标在屏幕中的位置
        m_pointStart = event->globalPos();
    }
}
 
// 重写mouseReleaseEvent
void WindowHeader::mouseReleaseEvent(QMouseEvent *event)
{
    // 鼠标左键释放
    if (event->button() == Qt::LeftButton)
    {
        // 记录鼠标状态
        mbKeepPressed = false;
    }
}
 
void WindowHeader::updateMaximize()
{
    QWidget *pWindow = this->window();
    if (pWindow->isTopLevel())
    {
        bool bMaximize = pWindow->isMaximized();
        if (bMaximize)
        {
            m_toolbtnMax->setToolTip("还原");
            m_toolbtnMax->setText("还原");
//            m_toolbtnMax->setProperty("maximizeProperty", "restore");
        }
        else
        {
//            m_toolbtnMax->setProperty("maximizeProperty", "maximize");
            m_toolbtnMax->setToolTip("最大化");
            m_toolbtnMax->setText("最大化");
        }
    }
}
 
bool WindowHeader::eventFilter(QObject *obj, QEvent *event)
{
    if(obj == m_widgetParent)
    {
        if(event->type() == QEvent::WindowTitleChange)
        {
            m_name = m_widgetParent->windowTitle();
            m_lableAppName->setText(m_name);
            return true;
        }
        else if(event->type() == QEvent::WindowIconChange)
        {
            QIcon icon = m_widgetParent->windowIcon();
            m_lableAppLogo->setPixmap(icon.pixmap(m_lableAppLogo->size()));
            return true;
        }
        else if(event->type() == QEvent::WindowStateChange || event->type() == QEvent::Resize)
        {
            this->resize(m_widgetParent->width(), m_height);
            updateMaximize();
            return true;
        }
    }
 
    return QWidget::eventFilter(obj, event);
}
 
 
void WindowHeader::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);  // 反锯齿;
    painter.setBrush(QBrush(Qt::red));
    painter.setPen(Qt::transparent);
    QRect rect = this->rect();
    painter.drawRoundedRect(rect, 10, 10);//绘制圆角矩形
 
    //覆盖上面绘制圆角矩形的左下角和右下角
    QRect rect2(QPoint(rect.left(), rect.center().y()), rect.bottomRight());
    painter.drawRect(rect2);
 
//    painter.fillRect(this->rect(), QColor(255, 0, 0, 80));  //QColor最后一个参数80代表背景的透明度
 
    QWidget::paintEvent(event);
}
使用:
#ifndef WIDGET_H
#define WIDGET_H
 
#include <QWidget>
#include "windowheader.h"
#include <QVBoxLayout>
#include <QMenuBar>
#include <QToolBar>
 
class Widget : public QWidget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = 0);
 
    void setMenuBar(QMenuBar* menuBar);
    void setCentralWidget(QWidget *widget);
 
protected:
    virtual void paintEvent(QPaintEvent *event);
 
private:
    WindowHeader* m_titleBar;
    QMenuBar* m_menuBar;
 
    QWidget* m_centralWidget;
    QVBoxLayout* m_mainLayout;
 
 
signals:
 
public slots:
};
 
#endif // WIDGET_H
#include "widget.h"
#include <QPainter>
#include <QDebug>
#include <QPushButton>
 
Widget::Widget(QWidget *parent) :
    QWidget(parent)
{
 
 
    m_titleBar = new WindowHeader(this->windowTitle().toStdString().c_str(), this);
    connect(m_titleBar, SIGNAL(ClickedClose()),
            this, SLOT(close()));
    connect(m_titleBar, SIGNAL(ClickedMin()),
            this, SLOT(showMinimized()));
    connect(m_titleBar, SIGNAL(ClickedMax()),
            this, SLOT(showMaximized()));
 
    this->setWindowTitle("自定义窗口");
    this->setWindowIcon(QIcon(":reboot.ico"));
 
    m_menuBar = new QMenuBar(this);
    QMenu* menu = new QMenu("文件(&F)", this);
    m_menuBar->addMenu(menu);
    menu->addAction("打开");
 
    m_centralWidget = new QWidget(this);
    m_centralWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    m_mainLayout = new QVBoxLayout;
    m_mainLayout->setContentsMargins(2, 0, 2, 0);
//    qDebug() << m_titleBar->height();
    m_mainLayout->addSpacing(m_titleBar->height());
    m_mainLayout->addWidget(m_menuBar);
    m_mainLayout->addWidget(m_centralWidget);
//    m_mainLayout->addStretch();
    this->setLayout(m_mainLayout);
}
 
void Widget::setCentralWidget(QWidget* widget)
{
    if(widget == NULL)
        return;
 
    m_mainLayout->replaceWidget(m_centralWidget, widget);
    delete m_centralWidget;
    m_centralWidget = widget;
    m_centralWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
 
//    m_centralWidget->show();
}
 
void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);  // 反锯齿;
    QPen pen;
    pen.setStyle(Qt::SolidLine);
    pen.setWidth(1);
    pen.setColor(Qt::red);
    painter.setPen(pen);
 
    //从标题栏左下角开始画
    QRect rect = m_titleBar->rect();
    QRect rect2(rect.bottomLeft(), this->rect().bottomRight()/* - QPoint(2, 0)*/);
    painter.drawRect(rect2);
 
    painter.fillRect(rect2, QColor(255, 0, 0, 30));  //QColor最后一个参数80代表背景的透明度
 
    QWidget::paintEvent(event);
}
 
主程序调用:
Widget* w = new Widget;
    w->setWindowTitle("标题栏");
    w->resize(400, 300);
    w->show();
    QWidget* w2 = new QWidget;
    w->setCentralWidget(w2);
    QPushButton* btn = new QPushButton("OK", w2);
    QVBoxLayout* layout = new QVBoxLayout;
    layout->setContentsMargins(0, 0, 0, 0);
    layout->addWidget(btn);
    layout->addStretch();
    w2->setLayout(layout);