Qt 自定义标题栏

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文件见上传文件

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

时间: 2024-10-08 02:15:45

Qt 自定义标题栏的相关文章

qt自定义标题栏

1)创建一个标题的界面类,重新实现鼠标移动点击等事件 2)设置主界面无边框,创建一个垂直布局管理器,插入标题界面,在标题界面和主界面之间添加一个分割器 setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); QtGuiDetailTitle *title = new QtGuiDetailTitle(this); ui.verticalLayout->setContentsMargins(8, 8, 8, 8);//

paip.提升用户体验---c++ qt自定义窗体(1)---标题栏的绘制

源地址:http://blog.csdn.net/attilax/article/details/12343625 paip.提升用户体验---c++ qt自定义窗体(1)---标题栏的绘制 效果图: 作者Attilax ,  EMAIL:[email protected] 来源:attilax的专栏地址:http://blog.csdn.net/attilax 第一步:去掉系统默认标题栏 1 第2步:添加自定义标题栏以及最小化,最大化.关闭按钮...还有左边的窗体小图标.. 2 第3步:添加标

QT自定义精美换肤界面

陆陆续续用QT开发过很多项目,也用QT写过不少私活项目,也写过N个工具,一直梦寐以求能像VC一样可以很方便的有个自定义的界面,QSS的强大让我看到了很好的希望,辗转百度谷歌无数次,一直搜索QT相关的换肤文章,绝大部分的是一些简单的按钮文本样式,要做到整体换肤程度几乎不行,QTCN论坛里的奋斗的孩子写了个模仿360安全卫士系列,让我既惊喜有遗憾,惊喜的是能够用QT实现一个这么完整的360安全卫士界面,确实不错,也支持多种换肤,遗憾的是我下载过的是VC版本的,对于一直执着于用Qt Creator 来

android 自定义标题栏

今天来看一下如何通过组合多个控件实现自定义标题栏 众所周知,标题栏是应用中必不可少的控件,为了避免多次重写,将其封装起来,供每个布局调用即可. 这里我们采用经典的左中右布局,也可以根据项目需要自行调整,比如在右侧再加一个控件,或者将标题偏左都可以 注:其中应用到了上一篇文章中的ButtonM控件,大家可以先简单了解一下. 还是先来看一下效果图:    图一 初始状态                                         图二 按下了右侧的搜索按钮 下面来看代码实现,共四

WPF 自定义标题栏

自定义标题栏效果如上,代码示例 <Grid> <Grid.Resources> <Style TargetType="RadioButton"> <Setter Property="Margin" Value="0.5,2"></Setter> <Setter Property="Template"> <Setter.Value> <Co

【Win 10开发】自定义标题栏

UWP 现在已经可以自定义标题栏了,毕竟看灰色时间长了也会厌烦,开发者们还是希望能够将自己的UI做的更加漂亮,更加与众不同.那么废话不多说,我们开始吧! 首先要了解ApplicationViewTitleBar这个类.其中提供了以下属性: MSDN参考地址:ApplicationViewTitleBar class 首先,我们写一个TitleBarChanged方法,在里面先获取到当前窗口的实例. 1 ApplicationView view = ApplicationView.GetForCu

Qt自定义菜单项

经常会看到一些菜单的部分项是由几个按钮组成的,如酷狗.QQ.360都有类似菜单,对于常规的菜单项,图标 + 文字 实现一个事件,很容易完成,那么怎么自定义菜单项呢? Qt提供了支持,就是利用QWidget + QWidgetAction来完成.QWidgetAction继承自QAction,无法通过继承来实现一个界面,但它提供了setDefaultWidget来绑定一个界面,使用起来就更加方便了. 下面实现一个没有Action的菜单,并通过按钮显示出来: void UserMenu::Creat

安卓学习随笔 -- 自定义标题栏

在安卓中不喜欢系统默认的标题栏,那么如何让自定义一个自己的标题栏呢. 自定义后的标题栏如下: 首先这里需要定义一个自定义的标题栏布局 title.xml文件 (里边需要两个图片这个很简单) <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fi

android自定义标题栏,背景颜色填充满

设置标题栏背景 1> 准备背景图片: background_pix.png 注:用背景图片比用颜色好处,可以让背景看起来有凹凸感. 2> drawable文件夹下放xml文件 bitmap_repeat.xml <?xml version="1.0" encoding="utf-8"?> <bitmap xmlns:android="http://schemas.android.com/apk/res/android"