码迷,mamicode.com
首页 > 其他好文 > 详细

Qt 自定义标题栏

时间:2019-07-16 16:41:59      阅读:107      评论:0      收藏:0      [点我收藏+]

标签:file   表示   ifd   sed   区域   皮肤   tom   nal   efi   

1 头文件

#ifndef TITLEBAR_H
#define TITLEBAR_H

#include <QLabel>
#include <QPushButton>
#include "ui_TitleBar.h"

class  TitleBar : public QWidget
{
    Q_OBJECT

public:
    explicit TitleBar(QWidget *parent = nullptr);
    ~TitleBar();
    void setMiniBtnIcon(const QIcon& icon);
    void setMaxiBtnIcon(const QIcon& icon);
    void setCloseBtnIcon(const QIcon& icon);
protected:
    //鼠标双击事件
    virtual void mouseDoubleClickEvent(QMouseEvent *event);
    //鼠标按下事件
    virtual void mousePressEvent(QMouseEvent *event);
    //鼠标释放事件
    virtual void mouseReleaseEvent(QMouseEvent *event);
    //鼠标移动事件
    virtual void mouseMoveEvent(QMouseEvent *event);
    //设置界面标题与图标
    virtual bool eventFilter(QObject *obj, QEvent *event);

private slots:

    //进行最小化、最大化/还原、关闭操作
    void onClicked();
private:

    //最大化/还原
    void updateMaximize();

private:
    Ui::TitleBar ui;
    QPoint pos;        //鼠标当前点击坐标
    bool mouse_press; //鼠标按下 
};

#endif // TitleBar_H

2 cpp文件

#include <QLabel>
#include <QPushButton>
#include <QHBoxLayout>
#include <QEvent>
#include <QMouseEvent>
#include <QApplication>
#include "TitleBar.h"

//调用WIN API
#ifdef Q_OS_WIN
#include <qt_windows.h>
#endif

TitleBar::TitleBar(QWidget *parent)
    : QWidget(parent) {
    ui.setupUi(this);
    mouse_press = false;
    //setFixedHeight(30);
    // 设置窗口背景透明;
    //setAttribute(Qt::WA_TranslucentBackground);
    //给按钮设置静态tooltip,当鼠标移上去时显示tooltip
    ui.btnMinimize->setToolTip(tr("Minimize"));
    ui.btnMaximize->setToolTip(tr("Maximize"));
    ui.btnClose->setToolTip(tr("Close"));

    QPalette pal(palette());
    pal.setColor(QPalette::Background, QColor(150, 150, 150));
    setAutoFillBackground(true);
    setPalette(pal);

    connect(ui.btnMinimize, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
    connect(ui.btnMaximize, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
    connect(ui.btnClose, SIGNAL(clicked(bool)), this, SLOT(onClicked()));

    //隐藏更换皮肤按钮
    ui.btnSkin->setVisible(false);

    setAttribute(Qt::WA_StyledBackground);


}

TitleBar::~TitleBar() {

}
//双击标题栏进行界面的最大化/还原
void TitleBar::mouseDoubleClickEvent(QMouseEvent *event) {
    Q_UNUSED(event);

    emit ui.btnMaximize->clicked();
}

void TitleBar::mousePressEvent(QMouseEvent *event) {
    if (event->button() == Qt::LeftButton) {
        mouse_press = true;

        pos = event->globalPos();
    }
    event->ignore();
}

void TitleBar::mouseMoveEvent(QMouseEvent *event) {
    //若鼠标左键被按下
    if (mouse_press) {
        QPoint move_pos = event->globalPos()-pos;   //鼠标现在位置-原来位置
        //移动主窗体
        window()->move(window()->pos() + move_pos);//窗口位置+鼠标移动距离
        pos = event->globalPos();                 //更新位置
    }
    event->ignore();
}

void TitleBar::mouseReleaseEvent(QMouseEvent *event) {
    //设置鼠标为未被按下
    mouse_press = false;
    event->ignore();
}
//使用事件过滤器监听标题栏所在的窗体,所以当窗体标题、图标等信息发生改变时,标题栏也应该随之改变
bool TitleBar::eventFilter(QObject *obj, QEvent *event) {
    switch (event->type()) {         //判断发生事件的类型
    case QEvent::WindowTitleChange: { //窗口标题改变事件
        QWidget *pWidget = qobject_cast<QWidget *>
                           (obj); //获得发生事件的窗口对象
        if (pWidget) {
            //窗体标题改变,则标题栏标题也随之改变
            ui.labelTitle->setText(pWidget->windowTitle());
            return true;
        }
    }
    break;

    case QEvent::WindowIconChange: { //窗口图标改变事件
        QWidget *pWidget = qobject_cast<QWidget *>(obj);
        if (pWidget) {
            //窗体图标改变,则标题栏图标也随之改变
            QIcon icon = pWidget->windowIcon();
//            ui.labelIcon->setPixmap(icon.pixmap(ui.labelIcon->size()));
            return true;
        }
    }
    break;

    case QEvent::Resize:
        updateMaximize(); //最大化/还原
        return true;

    default:
        return QWidget::eventFilter(obj, event);
    }

    return QWidget::eventFilter(obj, event);
}
//进行最小化、最大化/还原、关闭操作
void TitleBar::onClicked() {
    QPushButton *pButton = qobject_cast<QPushButton *>(sender());

    QWidget *pWindow = this->window(); //获得标题栏所在的窗口

    if (pWindow->isTopLevel()) {
        if (pButton == ui.btnMinimize) {
            pWindow->showMinimized(); //窗口最小化显示
        } else if (pButton == ui.btnMaximize) {
            pWindow->isMaximized() ? pWindow->showNormal() :
            pWindow->showMaximized();  //窗口最大化/还原显示
        } else if (pButton == ui.btnClose) {
            pWindow->close();       //窗口关闭
        }
    }
}

//最大化/还原
void TitleBar::updateMaximize() {
    QWidget *pWindow = this->window();           //获得标题栏所在的窗口

    if (pWindow->isTopLevel()) {
        bool bMaximize =
            pWindow->isMaximized(); //判断窗口是不是最大化状态,是则返回true,否则返回false
        if (bMaximize) {
            //目前窗口是最大化状态,则最大化/还原的toolTip设置为"Restore"
            ui.btnMaximize->setToolTip(tr("Restore"));
            //设置按钮的属性名为"maximizeProperty"
            ui.btnMaximize->setProperty("maximizeProperty", "restore");
        } else {
            //目前窗口是还原状态,则最大化/还原的toolTip设置为"Maximize"
            ui.btnMaximize->setToolTip(tr("Maximize"));
            //设置按钮的属性名为"maximizeProperty"
            ui.btnMaximize->setProperty("maximizeProperty", "maximize");
        }

        ui.btnMaximize->setStyle(QApplication::style());
    }
}


void TitleBar::setMiniBtnIcon(const QIcon& icon) {
    ui.btnMinimize->setIcon(icon.pixmap(ui.btnMinimize->size()));
}

void TitleBar::setMaxiBtnIcon(const QIcon& icon) {
    ui.btnMaximize->setIcon(icon.pixmap(ui.btnMaximize->size()));
}

void TitleBar::setCloseBtnIcon(const QIcon& icon) {
    ui.btnClose->setIcon(icon.pixmap(ui.btnClose->size()));
}

3 使用说明

自定义标题栏使用说明(包含TitleBar.h,TitleBar.cpp,TitleBar.ui三个文件):
1主窗体类中添加头文件:
//调用WIN API需要用到的头文件 [实现缩放]
#ifdef Q_OS_WIN
#include <qt_windows.h>
#include <Windowsx.h>
#endif

2主窗体类中
   添加成员变量:
 int m_nBorderWidth;//表示鼠标位于边框缩放范围的宽度
   添加成员函数:
//nativeEvent主要用于进程间通信-消息传递,使用这种方式后来实现窗体的缩放 
bool xxx::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
    Q_UNUSED(eventType)

        MSG *param = static_cast<MSG *>(message);

    switch (param->message)
    {
    case WM_NCHITTEST:
    {
        int nX = GET_X_LPARAM(param->lParam) - this->geometry().x();
        int nY = GET_Y_LPARAM(param->lParam) - this->geometry().y();

        // 如果鼠标位于子控件上,则不进行处理
        if (childAt(nX, nY) != nullptr)
            return QWidget::nativeEvent(eventType, message, result);

        *result = HTCAPTION;

        // 鼠标区域位于窗体边框,进行缩放
        if ((nX > 0) && (nX < m_nBorderWidth))
            *result = HTLEFT;

        if ((nX > this->width() - m_nBorderWidth) && (nX < this->width()))
            *result = HTRIGHT;

        if ((nY > 0) && (nY < m_nBorderWidth))
            *result = HTTOP;

        if ((nY > this->height() - m_nBorderWidth) && (nY < this->height()))
            *result = HTBOTTOM;

        if ((nX > 0) && (nX < m_nBorderWidth) && (nY > 0)
            && (nY < m_nBorderWidth))
            *result = HTTOPLEFT;

        if ((nX > this->width() - m_nBorderWidth) && (nX < this->width())
            && (nY > 0) && (nY < m_nBorderWidth))
            *result = HTTOPRIGHT;

        if ((nX > 0) && (nX < m_nBorderWidth)
            && (nY > this->height() - m_nBorderWidth) && (nY < this->height()))
            *result = HTBOTTOMLEFT;

        if ((nX > this->width() - m_nBorderWidth) && (nX < this->width())
            && (nY > this->height() - m_nBorderWidth) && (nY < this->height()))
            *result = HTBOTTOMRIGHT;

        return true;
    }
    }

    return QWidget::nativeEvent(eventType, message, result);
}

3 在widget中应用自定义标题栏
(1)在需要添加自定义标题栏的widget的ui文件中,拖动一个widget加入到当前widget布局的最上方,然后提升控件类为TitleBar
(2)主窗体类的构造函数中添加如下代码:

//Qt::FramelessWindowHint设置窗口标志为无边框,而Qt::WindowStaysOnTopHint使窗口位于所有界面之上
setWindowFlags(Qt::FramelessWindowHint);
//ui中提升控件
installEventFilter(ui.widget);//ui.widget 为布局中提升的自定义标题控件
 //设置标题栏标题 图标 按钮图标,可在ui文件中直接修改,也可在代码中修改
setWindowTitle("Custom Window");
setWindowIcon(QIcon(""));
ui.widget->setMiniBtnIcon(QIcon(""));
ui.widget->setMaxiBtnIcon(QIcon(""));
ui.widget->setCloseBtnIcon(QIcon(""));
m_nBorderWidth= 5;

4 在mainwindow中应用自定义标题栏
(1)新建一个widget,拖动一个子widget到当前widget布局的最上放,提升控件为TitleBar
(2) 在当前widget的类中添加头文件,成员变量和成员函数,同上
(3)在当前widget的构造函数中添加如下代码
//Qt::FramelessWindowHint设置窗口标志为无边框,而Qt::WindowStaysOnTopHint使窗口位于所有界面之上
setWindowFlags(Qt::FramelessWindowHint);
//ui中提升控件
installEventFilter(ui.widget);//ui.widget 为布局中提升的自定义标题控件
 //设置标题栏标题 图标 按钮图标,可在ui文件中直接修改,也可在代码中修改
/*
setWindowTitle("Custom Window");
setWindowIcon(QIcon(""));
ui.widget->setMiniBtnIcon(QIcon(""));
ui.widget->setMaxiBtnIcon(QIcon(""));
ui.widget->setCloseBtnIcon(QIcon(""));
*/
m_nBorderWidth= 5;

//MainWindow为需要添加自定义标题栏的主界面类
MainWindow *maindow = new MainWindow(this);
maindow->setWindowFlags(Qt::FramelessWindowHint);

/*
QVBoxLayout *vlayout = new QVBoxLayout;
vlayout->addWidget(ui.titlebar_widget_);
QString path = QStringLiteral(":/png/最小化.png");
QIcon minicon(path);
ui.titlebar_widget_->setMiniBtnIcon(minicon);
path = QStringLiteral(":/png/窗口.png");
QIcon maxicon(path);
ui.titlebar_widget_->setMaxiBtnIcon(maxicon);
path = QStringLiteral(":/png/关  闭.png");
QIcon closeicon(path);
ui.titlebar_widget_->setCloseBtnIcon(closeicon);

QString filestyle =
    QStringLiteral("background-image: url(:/png/标题栏-背景.png);");
ui.titlebar_widget_->setStyleSheet(filestyle);
*/

QVBoxLayout *vlayout = new QVBoxLayout;
vlayout->addWidget(ui.titlebar_widget_);
vlayout->addWidget(maindow);
//设置布局距离上下左右的距离,根据需要设置,也可在ui中修改
vlayout->setContentsMargins(2,1,2,1);
setLayout(vlayout);

(4)在显示主界面的时候,在main函数中将MainWindow类换为新加的widget,即可显示自定义标题栏

 4 ui文件见上传文件

Qt 自定义标题栏

标签:file   表示   ifd   sed   区域   皮肤   tom   nal   efi   

原文地址:https://www.cnblogs.com/LuckCoder/p/11195704.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!