现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

Qt实现无边框窗口自定义标题栏

2015-04-20 20:51 工业·编程 ⁄ 共 6346字 ⁄ 字号 暂无评论

本文实现了自定义标题栏的最小化,最大化(自适应任务栏),关闭,拉伸,拖曳。因为不想引入其他资源,所以按钮,背景都是系统提供的。

效果图:

直接上代码----

#include "widget.h"

#include <QApplication>

#include "CustomFrame.h"

int main(int argc, char *argv[])

{

    QApplication a(argc, argv);

    Widget *w = new Widget();

    CustomFrame frame(w, "CustomFrame");

    frame.show();

    return a.exec();

}

#pragma once

#include <QFrame>

class QToolButton;

class CustomFrame : public QFrame

{

    Q_OBJECT

public:

    explicit CustomFrame(QWidget *contentWidget, const QString &title);

public slots:

    void slotShowSmall();

    void slotShowMaxRestore();

protected:

    void mousePressEvent(QMouseEvent *);

    void mouseMoveEvent(QMouseEvent *);

    void mouseReleaseEvent(QMouseEvent *);

    bool nativeEvent(const QByteArray & eventType, void * message, long * result);

    void paintEvent(QPaintEvent *);

private:

    bool isMax_;

    bool isPress_;

    QPoint startPos_;

    QPoint clickPos_;

    QWidget *contentWidget_;

    QPixmap maxPixmap_;

    QPixmap restorePixmap_;

    QToolButton *maxButton_;

};

#include "CustomFrame.h"

#include <QtWidgets>

static const int TITLE_HEIGHT = 30;

static const int FRAME_BORDER = 2;

CustomFrame::CustomFrame(QWidget *contentWidget, const QString &title)

    : contentWidget_(contentWidget)

{

    this->setWindowFlags(Qt::FramelessWindowHint);

    this->setAttribute(Qt::WA_TranslucentBackground);

    this->setMouseTracking(true);

    isMax_ = false;

    isPress_ = false;

    QLabel *logoLabel = new QLabel();

    QPixmap logoPixmap = this->style()->standardPixmap(QStyle::SP_TitleBarMenuButton);

    logoLabel->setPixmap(logoPixmap);

    logoLabel->setFixedSize(16, 16);

    logoLabel->setScaledContents(true);

    QLabel *titleLabel = new QLabel();

    titleLabel->setText(title);

    QFont titleFont = titleLabel->font();

    titleFont.setBold(true);

    titleLabel->setFont(titleFont);

    titleLabel->setObjectName("whiteLabel");

    QToolButton *minButton = new QToolButton();

    QPixmap minPixmap = this->style()->standardPixmap(QStyle::SP_TitleBarMinButton);

    minButton->setIcon(minPixmap);

    connect(minButton, SIGNAL(clicked()), this, SLOT(slotShowSmall()));

    maxButton_ = new QToolButton();

    maxPixmap_ = this->style()->standardPixmap(QStyle::SP_TitleBarMaxButton);

    restorePixmap_ = this->style()->standardPixmap(QStyle::SP_TitleBarNormalButton);

    maxButton_->setIcon(maxPixmap_);

    connect(maxButton_, SIGNAL(clicked()), this, SLOT(slotShowMaxRestore()));

    QToolButton *closeButton = new QToolButton();

    QPixmap closePixmap = this->style()->standardPixmap(QStyle::SP_TitleBarCloseButton);

    closeButton->setIcon(closePixmap);

    connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));

    QHBoxLayout *titleLayout = new QHBoxLayout();

    titleLayout->addWidget(logoLabel);

    titleLayout->addWidget(titleLabel);

    titleLabel->setContentsMargins(5, 0, 0, 0);

    titleLayout->addStretch();

    titleLayout->addWidget(minButton, 0, Qt::AlignTop);

    titleLayout->addWidget(maxButton_, 0, Qt::AlignTop);

    titleLayout->addWidget(closeButton, 0, Qt::AlignTop);

    titleLayout->setSpacing(0);

    titleLayout->setContentsMargins(5, 0, 0, 0);

   

    QWidget *titleWidget = new QWidget();

    titleWidget->setLayout(titleLayout);

    titleWidget->installEventFilter(0);

    QVBoxLayout *mainLayout = new QVBoxLayout();

    mainLayout->addWidget(titleWidget);

    mainLayout->addWidget(contentWidget_);

    mainLayout->setSpacing(0);

    mainLayout->setMargin(5);

    this->setLayout(mainLayout);

}

void CustomFrame::slotShowSmall()

{

    this->showMinimized();

}

void CustomFrame::slotShowMaxRestore()

{

    if (isMax_) {

        this->showNormal();

        maxButton_->setIcon(maxPixmap_);

    } else {

        this->showMaximized();

        maxButton_->setIcon(restorePixmap_);

    }

    isMax_ = !isMax_;

}

void CustomFrame::mousePressEvent(QMouseEvent *e)

{

    startPos_ = e->globalPos();

    clickPos_ = e->pos();

    if (e->button() == Qt::LeftButton) {

        if (e->type() == QEvent::MouseButtonPress) {

            isPress_ = true;

        } else if (e->type() == QEvent::MouseButtonDblClick && e->pos().y() <= TITLE_HEIGHT) {

            this->slotShowMaxRestore();

        }

    }

}

void CustomFrame::mouseMoveEvent(QMouseEvent *e)

{

    if (isMax_ || !isPress_) {

        return;

    }

    this->move(e->globalPos() - clickPos_);

}

void CustomFrame::mouseReleaseEvent(QMouseEvent *)

{

    isPress_ = false;

}

bool CustomFrame::nativeEvent(const QByteArray & eventType, void * message, long * result)

{

    Q_UNUSED(eventType);

    const int HIT_BORDER = 5;

    const MSG *msg=static_cast<MSG*>(message);

    if(msg->message == WM_NCHITTEST) {

        int xPos = ((int)(short)LOWORD(msg->lParam)) - this->frameGeometry().x();

        int yPos = ((int)(short)HIWORD(msg->lParam)) - this->frameGeometry().y();

        if(this->childAt(xPos,yPos) == 0) {

            *result = HTCAPTION;

        } else {

            return false;

        }

        if(xPos > 0 && xPos < HIT_BORDER) {

            *result = HTLEFT;

        }

        if(xPos > (this->width() - HIT_BORDER) && xPos < (this->width() - 0)) {

            *result = HTRIGHT;

        }

        if(yPos > 0 && yPos < HIT_BORDER) {

            *result = HTTOP;

        }

        if(yPos > (this->height() - HIT_BORDER) && yPos < (this->height() - 0)) {

            *result = HTBOTTOM;

        }

        if(xPos > 0 && xPos < HIT_BORDER && yPos > 0 && yPos < HIT_BORDER) {

            *result = HTTOPLEFT;

        }

        if(xPos > (this->width() - HIT_BORDER) && xPos < (this->width() - 0) && yPos > 0 && yPos < HIT_BORDER) {

            *result = HTTOPRIGHT;

        }

        if(xPos > 0 && xPos < HIT_BORDER && yPos > (this->height() - HIT_BORDER) && yPos < (this->height() - 0)) {

            *result = HTBOTTOMLEFT;

        }

        if(xPos > (this->width() - HIT_BORDER) && xPos < (this->width() - 0) && yPos > (this->height() - HIT_BORDER) && yPos < (this->height() - 0)) {

            *result = HTBOTTOMRIGHT;

        }

        return true;

    }

    return false;

}

void CustomFrame::paintEvent(QPaintEvent *e)

{

    int border = FRAME_BORDER;

    if (this->isMaximized()) {

        border = 0;

    }

    QPainter painter(this);

    QPainterPath painterPath;

    painterPath.setFillRule(Qt::WindingFill);

    painterPath.addRect(border, border, this->width()-2*border, this->height()-2*border);

    painter.setRenderHint(QPainter::Antialiasing, true);

    painter.fillPath(painterPath, QBrush(Qt::white));

    QColor color(200, 200, 200);

    for (int i=0; i<border; i++) {

        color.setAlpha((i+1)*30);

        painter.setPen(color);

        painter.drawRect(border-i, border-i, this->width()-(border-i)*2, this->height()-(border-i)*2);

    }

    painter.setPen(Qt::NoPen);

    painter.setBrush(Qt::white);

    // 这里可以在资源中指定一张标题背景图片

    //painter.drawPixmap(QRect(border, border, this->width()-2*border, this->height()-2*border), QPixmap(DEFAULT_SKIN));

    painter.drawRect(QRect(border, TITLE_HEIGHT, this->width()-2*border, this->height()-TITLE_HEIGHT-border));

    QFrame::paintEvent(e);

}

给我留言

留言无头像?