QT自定义窗口标题栏实现拖动双击放大缩小

    去掉Qt窗口的标题边框,重新定义标题栏,可以在标题栏上实现更多的功能,能满足更多的开发需求,可以实现标题栏的拖动,双击,自定义放大缩小。

     本文引用自:http://www.devbean.net/2011/10/custom-qt-titlebar/,感谢原作者,本文对其进行了重新整理,并且修改了一些小问题。

    运行界面如下:


    详细代码如下:

#include <QWidget>
#include <QToolButton>
#include <QPixmap>

class XMainWindowTitle : public QWidget
{
    Q_OBJECT
public:
    XMainWindowTitle(QWidget *parent);

public slots:
    void showSmall();

    void showMaxRestore();

protected:
    void mousePressEvent(QMouseEvent *e);
    void mouseMoveEvent(QMouseEvent *e);
    void mouseDoubleClickEvent(QMouseEvent *e);

private:
    QToolButton *minimize;
    QToolButton *maximize;
    QToolButton *close;
    QPixmap restorePix, maxPix;
    bool maxNormal;
    QPoint startPos;
    QPoint clickPos;
};
#include "XMainWindowTitle.h"
#include <QHBoxLayout>
#include <QMouseEvent>
#include <QStyle>
#include <QLabel>

XMainWindowTitle::XMainWindowTitle(QWidget *parent)
{
    // 不继承父组件的背景色
    setAutoFillBackground(true);
    // 使用 Highlight 作为背景色
    setBackgroundRole(QPalette::Highlight);

    minimize = new QToolButton(this);
    maximize = new QToolButton(this);
    close= new QToolButton(this);

    QPixmap pix = style()->standardPixmap(QStyle::SP_TitleBarCloseButton);
    close->setIcon(pix);
    close->setToolTip("close");
    close->setStyleSheet("QToolButton:hover{background-color:rgb(219,75,75);}");

    maxPix = style()->standardPixmap(QStyle::SP_TitleBarMaxButton);
    maximize->setIcon(maxPix);
    maximize->setToolTip("restore");

    pix = style()->standardPixmap(QStyle::SP_TitleBarMinButton);
    minimize->setIcon(pix);
    minimize->setToolTip("minsize");

    restorePix = style()->standardPixmap(QStyle::SP_TitleBarNormalButton);

    minimize->setMinimumSize(30,25);
    close->setMinimumSize(30,25);
    maximize->setMinimumSize(30,25);

    QLabel *label = new QLabel(this);
    label->setText("Window Title");
    parent->setWindowTitle("Window Title");

    QHBoxLayout *hbox = new QHBoxLayout(this);

    hbox->addWidget(label);
    hbox->addWidget(minimize);
    hbox->addWidget(maximize);
    hbox->addWidget(close);

    hbox->insertStretch(1, 500);
    hbox->setSpacing(0);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    maxNormal = false;

    connect(close, SIGNAL( clicked() ), parent, SLOT(close() ) );
    connect(minimize, SIGNAL( clicked() ), this, SLOT(showSmall() ) );
    connect(maximize, SIGNAL( clicked() ), this, SLOT(showMaxRestore() ) );
}

void XMainWindowTitle::showSmall()
{
    parentWidget()->showMinimized();
}

void XMainWindowTitle::showMaxRestore()
{
    if (maxNormal) {
        parentWidget()->showNormal();
        maxNormal = !maxNormal;
        maximize->setIcon(maxPix);
    } else {
        parentWidget()->showMaximized();
        maxNormal = !maxNormal;
        maximize->setIcon(restorePix);
    }
}

void XMainWindowTitle::mousePressEvent(QMouseEvent *e)
{
    startPos = e->globalPos();
    clickPos = mapToParent(e->pos());
}
void XMainWindowTitle::mouseMoveEvent(QMouseEvent *e)
{
    if (maxNormal)
        return;
    parentWidget()->move(e->globalPos() - clickPos);
}

void XMainWindowTitle::mouseDoubleClickEvent(QMouseEvent *e)
{
    if(e->button() == Qt::LeftButton)
    {
        showMaxRestore();
    }
}

#include "XMainWindowTitle.h"
#include <QFrame>

class XMainWindow : public QFrame
{
public:

    XMainWindow();

    // 通过 getter 允许外界访问 frame 的 content 区域
    // 其它子组件应该添加到这里
    QWidget *contentWidget() const ;

    XMainWindowTitle *mainWindowTitle() const ;

protected:
    void mousePressEvent(QMouseEvent *e);

    void mouseMoveEvent(QMouseEvent *e);

    void mouseReleaseEvent(QMouseEvent *e);

private:
    XMainWindowTitle *titleBar;
    QWidget *content;
    QPoint oldPos;
    bool mouseDown;
    bool left, right, bottom;
};
#include "XMainWindow.h"
#include <QVBoxLayout>
#include <QMouseEvent>
#include <QDebug>

XMainWindow::XMainWindow()
{
    mouseDown = false;
    setFrameShape(Panel);

    setWindowFlags(Qt::FramelessWindowHint);
    setMouseTracking(true);

    titleBar = new XMainWindowTitle(this);
    titleBar->setCursor(Qt::ArrowCursor);

    content = new QWidget(this);

    content->setMouseTracking(true);
    QVBoxLayout *vbox = new QVBoxLayout(this);
    vbox->addWidget(titleBar);
    vbox->setContentsMargins(0,0,0,0);
    vbox->setSpacing(0);

    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(content);
    layout->setContentsMargins(5,5,5,5);
    layout->setSpacing(0);
    vbox->addLayout(layout);
}

QWidget *XMainWindow::contentWidget() const { return content; }

XMainWindowTitle *XMainWindow::mainWindowTitle() const { return titleBar; }

void XMainWindow::mousePressEvent(QMouseEvent *e)
{
    oldPos = e->pos();
    mouseDown = e->button() == Qt::LeftButton;
}

void XMainWindow::mouseMoveEvent(QMouseEvent *e)
{
    int x = e->x();
    int y = e->y();

    if (mouseDown) {
        int dx = x - oldPos.x();
        int dy = y - oldPos.y();

        QRect g = geometry();

        if (left)
            g.setLeft(g.left() + dx);
        if (right)
            g.setRight(g.right() + dx);
        if (bottom)
            g.setBottom(g.bottom() + dy);

        setGeometry(g);

        oldPos = QPoint(!left ? e->x() : oldPos.x(), e->y());
    } else {
        QRect r = rect();
        left = qAbs(x - r.left()) <= 5;
        right = qAbs(x - r.right()) <= 5;
        bottom = qAbs(y - r.bottom()) <= 5;
        bool hor = left | right;

        if (hor && bottom) {
            if (left)
                setCursor(Qt::SizeBDiagCursor);
            else
                setCursor(Qt::SizeFDiagCursor);
        } else if (hor) {
            setCursor(Qt::SizeHorCursor);
        } else if (bottom) {
            setCursor(Qt::SizeVerCursor);
        } else {
            setCursor(Qt::ArrowCursor);
        }
    }
}

void XMainWindow::mouseReleaseEvent(QMouseEvent *e)
{
    mouseDown = false;
}




  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值