qt实现自定义标题栏的widget

实现思路:新建类MyWidget,继承Widget。

新建两个widget,titilewidget、centerwidget分别用于放置标题栏和其他内容。

在titlewidget里边添加图标、标题、最小化、最大化、关闭按钮

........

效果

MyWidget.h

#ifndef MYWIDGET_H
#define MYWIDGET_H
#pragma execution_character_set("UTF-8")
#include <QWidget>
#include <QIcon>
#include <QPushButton>
#include <QLabel>
#include <QMouseEvent>
#include <QLayout>
#include <QRect>
#include <QApplication>
#include <QDesktopWidget>
#include <QPalette>
#include <QStyle>
#include <QToolButton>


class MyWidget: public QWidget
{
    Q_OBJECT
private:
    QWidget *titleWidget;//标题栏Widget
    QToolButton *iconButton;//图标
    QPushButton *closeButton;//关闭按钮
    QPushButton *maxButton;//最大化按钮
    QPushButton *minButton;//最小化按钮
    QLabel *titleLabel;//标题label
    QRect winRect;//窗口位置
    bool m_ismaxed;//窗口是否最大化
    QPoint m_leftDownp;//左键按下的位置
    QPoint m_leftDownMapp;//左键按下时全局位置
    bool m_isleftClicked;//左键是否按下
    enum
    {
        Left,
        Right,
        Up,
        Bottom,
        LeftUp,
        RightUp,
        LeftBottom,
        RightBottom,
        Center
    };
    bool ApproximatelyEqual(const int a, const int b, int persion)
    {
        return abs(a-b) < persion ? true : false;
    }

protected:
    void mouseDoubleClickEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
    void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
    void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
    void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
    bool event(QEvent *event) Q_DECL_OVERRIDE;
    int GetMouseWidgetPos(QPoint p);//获取鼠标所在位置
    void setCursorShape(int CalPos);//设置鼠标样式

private:
    void InitializationWidget();//窗口初始化
    void ShowMaxSize();//窗口最大化
    void ShowNormalSize();//窗口非最大化

private slots:
    void WinNormalMaxChange();//窗口最大化最小化改变函数

public:
    QWidget *centerWidget;//中心widget,可操作空间
    MyWidget(QWidget *parent = nullptr);
    void SetWinTitle(QString title);//设置窗口标题
    void SetWinIcon(QIcon icon);//设置窗口图标
    void SetWinIcon(QImage img);
    void SetColor(uint r, uint g, uint b);//设置窗口颜色
};

#endif // MYWIDGET_H

MyWidget.cpp

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

MyWidget::MyWidget(QWidget *parent)
{
    setWindowFlags (Qt::FramelessWindowHint);
    this->resize(1200, 1000);
    m_ismaxed = 0;
    m_isleftClicked = 0;
    InitializationWidget();
    connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
    connect(minButton, SIGNAL(clicked()), this, SLOT(showMinimized()));
    connect(maxButton, SIGNAL(clicked()), this, SLOT(WinNormalMaxChange()));
    setAttribute(Qt::WA_Hover, true);
}


void MyWidget::InitializationWidget()
{
    titleWidget = new QWidget();
    titleWidget->setStyleSheet("background-color:white;");
    titleWidget->resize(1200, 40);
    centerWidget = new QWidget();
    iconButton = new QToolButton();
    iconButton->setFixedSize(40, 40);
    iconButton->setToolButtonStyle(Qt::ToolButtonIconOnly);
    enum QStyle::StandardPixmap Icon = (enum QStyle::StandardPixmap) 0;
    iconButton->setIcon(QApplication::style()->standardIcon(Icon));
    iconButton->setStyleSheet("background:transparent");
    titleLabel = new QLabel("MyWidget");
    titleLabel->setStyleSheet("background:transparent;font-size:18px;border-width:0px");
    closeButton = new QPushButton("🗙");
    maxButton = new QPushButton("🗖");
    minButton = new QPushButton("⎯");
    closeButton->setFixedSize(60, 40);
    minButton->setFixedSize(60, 40);
    maxButton->setFixedSize(60, 40);
    minButton->setStyleSheet("QPushButton{border-style:none;background:transparent;font-size:20px;border-width:0px;text-align:center;}"
                             "QPushButton:hover{background-color:rgb(229, 229, 229);}");
    closeButton->setStyleSheet("QPushButton{border-style:none;background:transparent;font-size:20px;border-width:0px;text-align:center;}"
                               "QPushButton:hover{background-color:rgb(232, 17, 35);color:white;}");
    maxButton->setStyleSheet("QPushButton{border-style:none;background:transparent;font-size:20px;border-width:0px;text-align:center;}"
                             "QPushButton:hover{background-color:rgb(229, 229, 229);}");
    //标题widget里边加东西
    QSpacerItem *verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
    QHBoxLayout *hboxlayout = new QHBoxLayout();
    hboxlayout->addWidget(iconButton);
    hboxlayout->addWidget(titleLabel);
    hboxlayout->addItem(verticalSpacer);
    hboxlayout->addWidget(minButton);
    hboxlayout->addWidget(maxButton);
    hboxlayout->addWidget(closeButton);
    hboxlayout->setSpacing(0);
    hboxlayout->setContentsMargins(0,0,0,0);
    titleWidget->setLayout(hboxlayout);
    //设置标题widget与中心widget布局
    QVBoxLayout *vboxlayout = new QVBoxLayout();
    vboxlayout->addWidget(titleWidget, 1);
    vboxlayout->addWidget(centerWidget, 100);
    vboxlayout->setSpacing(0);
    vboxlayout->setContentsMargins(0,0,0,0);
    this->setLayout(vboxlayout);
}


void MyWidget::WinNormalMaxChange()
{
    if (m_ismaxed)
    {
        ShowNormalSize();
    }
    else
    {
        ShowMaxSize();
    }
}


void MyWidget::ShowMaxSize()
{
    winRect = this->geometry();
    QRect trect = QApplication::desktop()->screenGeometry();
    this->setGeometry(trect);
    maxButton->setText("🗗");
    m_ismaxed = 1;
}


void MyWidget::ShowNormalSize()
{
    this->setGeometry(winRect);
    maxButton->setText("🗖");
    m_ismaxed = 0;
}


void MyWidget::mousePressEvent(QMouseEvent *event)
{
    //左键拖动窗口移动、左键控制移动
    if (event->button() == Qt::LeftButton)
    {
        //为了拖动
        m_leftDownp = event->globalPos()-pos();
        //为了缩放
        m_leftDownMapp = event->globalPos();
        m_isleftClicked = 1;
    }
    QWidget::mousePressEvent(event);
}


void MyWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
    // 左键双击最大化
    if (event->button() == Qt::LeftButton && titleWidget->geometry().contains(this->mapFromGlobal(QCursor::pos())))
    {
        if (m_ismaxed)
        {
            ShowNormalSize();
        }
        else
        {
            ShowMaxSize();
        }
    }
    QWidget::mouseDoubleClickEvent(event);
}


void MyWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        m_isleftClicked = 0;
    }
}


void MyWidget::mouseMoveEvent(QMouseEvent *event)
{
    if (m_isleftClicked)
    {
        if (titleWidget->geometry().contains(this->mapFromGlobal(QCursor::pos())))
        {
            //执行移动
            this->move(event->globalPos() - m_leftDownp);
        }
        else
        {
            //执行缩放
            QPoint ptMoveSize = event->globalPos() - m_leftDownMapp;
            int CalPos = GetMouseWidgetPos(event->globalPos());
            QRect rect = geometry();
            switch(CalPos)
            {
            case LeftUp:
                rect.setTopLeft(winRect.topLeft()+ptMoveSize);
                break;
            case Up:
                rect.setTop(winRect.top()+ptMoveSize.y());
                break;
            case RightUp:
                rect.setTopRight(winRect.topRight()+ptMoveSize);
                break;
            case Left:
                rect.setLeft(winRect.left()+ptMoveSize.x());
                break;
            case Right:
                rect.setRight(winRect.right()+ptMoveSize.x());
                break;
            case LeftBottom:
                rect.setBottomLeft(winRect.bottomLeft()+ptMoveSize);
                break;
            case Bottom:
                rect.setBottom(winRect.bottom()+ptMoveSize.y());
                break;
            case RightBottom:
                rect.setBottomRight(winRect.bottomRight()+ptMoveSize);
                break;
            default:
                break;
            }
            setGeometry(rect);
        }
        if (!m_ismaxed)
            winRect = this->geometry();
    }
    QWidget::mouseMoveEvent(event);
}


bool MyWidget::event(QEvent *event)
{
    //更改鼠标样式
    if (event->type() == QEvent::HoverEnter || event->type() == QEvent::HoverLeave || event->type() == QEvent::HoverMove)
    {
        QHoverEvent* pHoverEvent = static_cast<QHoverEvent*>(event);
        QPoint cursorPos = mapToGlobal(pHoverEvent->pos());
        if(!m_isleftClicked)
        {
            int CalPos = GetMouseWidgetPos(cursorPos);
            setCursorShape(CalPos);
        }
    }
    return QWidget::event(event);
}


int MyWidget::GetMouseWidgetPos(QPoint p)
{
    QRect rect = geometry();
    int minx = rect.x();
    int miny = rect.y();
    int maxy = rect.y()+rect.height();
    int maxx = rect.x()+rect.width();
    int x = p.x();
    int y = p.y();
    int persion = 5;
    if (ApproximatelyEqual(x, minx, persion) && ApproximatelyEqual(y, miny, persion))
        return LeftUp;
    else if (ApproximatelyEqual(x, minx, persion))
        return Left;
    else if (ApproximatelyEqual(y, miny, persion))
        return Up;
    else if (ApproximatelyEqual(x, maxx, persion) && ApproximatelyEqual(y, maxy, persion))
        return RightBottom;
    else if (ApproximatelyEqual(x, maxx, persion))
        return Right;
    else if (ApproximatelyEqual(y, maxy, persion))
        return Bottom;
    else if (ApproximatelyEqual(x, minx, persion) && ApproximatelyEqual(y, maxy, persion))
        return LeftBottom;
    else if (ApproximatelyEqual(x, maxx, persion) && ApproximatelyEqual(y, miny, persion))
        return RightUp;
    else
        return Center;
}


void MyWidget::setCursorShape(int CalPos)
{
    Qt::CursorShape cursor;
    switch(CalPos)
    {
    case LeftUp:
    case RightBottom:
        cursor = Qt::SizeFDiagCursor;
        break;
    case RightUp:
    case LeftBottom:
        cursor = Qt::SizeBDiagCursor;
        break;
    case Up:
    case Bottom:
        cursor = Qt::SizeVerCursor;
        break;
    case Left:
    case Right:
        cursor = Qt::SizeHorCursor;
        break;
    default:
        cursor = Qt::ArrowCursor;
        break;
    }
    setCursor(cursor);
}


void MyWidget::SetWinTitle(QString title)
{
    titleLabel->setText(title);
}


void MyWidget::SetWinIcon(QIcon icon)
{
    iconButton->setIcon(icon);
}


void MyWidget::SetWinIcon(QImage img)
{
    QPixmap pmap = QPixmap::fromImage(img);
    QIcon icon(pmap.scaled(iconButton->width(), iconButton->height()));
    iconButton->setIcon(icon);
}


void MyWidget::SetColor(uint r, uint g, uint b)
{
    QString str = "background-color:rgb(" +  QString::number(r) + "," + QString::number(g) + "," + QString::number(b) + ");";
    titleWidget->setStyleSheet(str);
}

调用——main.cpp

#include "MyWidget.h"
#include <QApplication>




int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    MyWidget w;
    w.SetWinTitle("test");
    QImage img("D:/Postgraduate/something/QCoomapTest/QCoomapTest/gui-icon.png");
    w.SetWinIcon(img);
    w.SetColor(18, 55, 107);
    w.show();
    return a.exec();
}

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以通过以下步骤自定义Qt主窗口的标题栏: 1. 在Qt设计器中,将窗口的标题栏设置为无(TitleBar->NoTitle)。 2. 在窗口中添加一个QWidget作为自定义标题栏。 3. 在自定义标题栏中添加需要的控件,比如QPushButton、QLabel等。 4. 重写窗口的鼠标事件,实现拖动窗口的功能。为此,您需要在窗口中实现mousePressEvent、mouseMoveEvent和mouseReleaseEvent三个事件函数。 5. 在mousePressEvent中,记录鼠标点击位置,用于计算窗口的移动距离。 6. 在mouseMoveEvent中,计算鼠标移动距离,并根据距离移动窗口。 7. 在mouseReleaseEvent中,清除记录的鼠标点击位置。 8. 最后,将自定义标题栏添加到窗口中,调整位置和大小即可。 下面是一个示例代码,可以帮助您更好地理解如何实现自定义标题栏: ```cpp #include <QtGui> #include <QtWidgets> class CustomTitleBar : public QWidget { public: CustomTitleBar(QWidget* parent = nullptr) : QWidget(parent) { setFixedHeight(30); QLabel* titleLabel = new QLabel("Custom Title Bar"); QPushButton* minimizeButton = new QPushButton("-"); QPushButton* maximizeButton = new QPushButton("□"); QPushButton* closeButton = new QPushButton("X"); QHBoxLayout* layout = new QHBoxLayout(this); layout->addWidget(titleLabel); layout->addStretch(); layout->addWidget(minimizeButton); layout->addWidget(maximizeButton); layout->addWidget(closeButton); connect(minimizeButton, &QPushButton::clicked, parent, &QWidget::showMinimized); connect(maximizeButton, &QPushButton::clicked, parent, &QWidget::showMaximized); connect(closeButton, &QPushButton::clicked, parent, &QWidget::close); } }; class MainWindow : public QMainWindow { public: MainWindow(QWidget* parent = nullptr) : QMainWindow(parent) { setWindowTitle("Custom Title Bar"); CustomTitleBar* titleBar = new CustomTitleBar(this); setMenuWidget(titleBar); QVBoxLayout* layout = new QVBoxLayout; QLabel* label = new QLabel("Hello, World!"); layout->addWidget(label); QWidget* centralWidget = new QWidget; centralWidget->setLayout(layout); setCentralWidget(centralWidget); } protected: void mousePressEvent(QMouseEvent* event) override { if (event->button() == Qt::LeftButton) { m_dragPosition = event->globalPos() - frameGeometry().topLeft(); event->accept(); } } void mouseMoveEvent(QMouseEvent* event) override { if (event->buttons() & Qt::LeftButton) { move(event->globalPos() - m_dragPosition); event->accept(); } } void mouseReleaseEvent(QMouseEvent* event) override { if (event->button() == Qt::LeftButton) { m_dragPosition = QPoint(); event->accept(); } } private: QPoint m_dragPosition; }; int main(int argc, char* argv[]) { QApplication app(argc, argv); MainWindow window; window.show(); return app.exec(); } ``` 在这个示例中,我们首先实现了一个CustomTitleBar类,该类继承自QWidget,用于创建自定义标题栏。在CustomTitleBar中,我们添加了一个QLabel和三个QPushButton,分别用于显示标题、最小化窗口、最大化/还原窗口和关闭窗口。我们通过QHBoxLayout将这些控件添加到CustomTitleBar中,并使用connect函数将这些按钮的点击事件连接到MainWindow的相应函数。 在MainWindow中,我们创建了一个CustomTitleBar对象,并使用setMenuWidget函数将其设置为菜单栏。然后,我们创建了一个QVBoxLayout,并向其中添加一个QLabel。最后,我们将QVBoxLayout设置为中心部件,并通过setCentralWidget函数将其添加到MainWindow中。 对于拖动窗口的实现,我们重写了MainWindow的mousePressEvent、mouseMoveEvent和mouseReleaseEvent三个函数。在mousePressEvent中,我们记录了鼠标点击位置,用于计算窗口的移动距离。在mouseMoveEvent中,我们计算了鼠标移动距离,并根据距离移动窗口。在mouseReleaseEvent中,我们清除了记录的鼠标点击位置。 最后,我们创建了一个QApplication对象,并显示了MainWindow。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值