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

2024-04-26 09:18

本文主要是介绍Qt 无边框窗口自定义标题栏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

实现了自定义标题栏的最小化,最大化(自适应任务栏),关闭,拉伸,拖曳。

因为不想引入其他资源,所以按钮,背景都是系统提供的。

效果图:



直接上代码。

用法:

#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);
}


这篇关于Qt 无边框窗口自定义标题栏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/937181

相关文章

使用Sentinel自定义返回和实现区分来源方式

《使用Sentinel自定义返回和实现区分来源方式》:本文主要介绍使用Sentinel自定义返回和实现区分来源方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Sentinel自定义返回和实现区分来源1. 自定义错误返回2. 实现区分来源总结Sentinel自定

如何自定义Nginx JSON日志格式配置

《如何自定义NginxJSON日志格式配置》Nginx作为最流行的Web服务器之一,其灵活的日志配置能力允许我们根据需求定制日志格式,本文将详细介绍如何配置Nginx以JSON格式记录访问日志,这种... 目录前言为什么选择jsON格式日志?配置步骤详解1. 安装Nginx服务2. 自定义JSON日志格式各

Android自定义Scrollbar的两种实现方式

《Android自定义Scrollbar的两种实现方式》本文介绍两种实现自定义滚动条的方法,分别通过ItemDecoration方案和独立View方案实现滚动条定制化,文章通过代码示例讲解的非常详细,... 目录方案一:ItemDecoration实现(推荐用于RecyclerView)实现原理完整代码实现

基于Spring实现自定义错误信息返回详解

《基于Spring实现自定义错误信息返回详解》这篇文章主要为大家详细介绍了如何基于Spring实现自定义错误信息返回效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录背景目标实现产出背景Spring 提供了 @RestConChina编程trollerAdvice 用来实现 HTT

Qt 中 isHidden 和 isVisible 的区别与使用小结

《Qt中isHidden和isVisible的区别与使用小结》Qt中的isHidden()和isVisible()方法都用于查询组件显示或隐藏状态,然而,它们有很大的区别,了解它们对于正确操... 目录1. 基础概念2. 区别清见3. 实际案例4. 注意事项5. 总结1. 基础概念Qt 中的 isHidd

SpringSecurity 认证、注销、权限控制功能(注销、记住密码、自定义登入页)

《SpringSecurity认证、注销、权限控制功能(注销、记住密码、自定义登入页)》SpringSecurity是一个强大的Java框架,用于保护应用程序的安全性,它提供了一套全面的安全解决方案... 目录简介认识Spring Security“认证”(Authentication)“授权” (Auth

QT移植到RK3568开发板的方法步骤

《QT移植到RK3568开发板的方法步骤》本文主要介绍了QT移植到RK3568开发板的方法步骤,文中通过图文示例介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录前言一、获取SDK1. 安装依赖2. 获取SDK资源包3. SDK工程目录介绍4. 获取补丁包二

Qt把文件夹从A移动到B的实现示例

《Qt把文件夹从A移动到B的实现示例》本文主要介绍了Qt把文件夹从A移动到B的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录如何移动一个文件? 如何移动文件夹(包含里面的全部内容):如何删除文件夹:QT 文件复制,移动(

SpringBoot自定义注解如何解决公共字段填充问题

《SpringBoot自定义注解如何解决公共字段填充问题》本文介绍了在系统开发中,如何使用AOP切面编程实现公共字段自动填充的功能,从而简化代码,通过自定义注解和切面类,可以统一处理创建时间和修改时间... 目录1.1 问题分析1.2 实现思路1.3 代码开发1.3.1 步骤一1.3.2 步骤二1.3.3

dubbo3 filter(过滤器)如何自定义过滤器

《dubbo3filter(过滤器)如何自定义过滤器》dubbo3filter(过滤器)类似于javaweb中的filter和springmvc中的intercaptor,用于在请求发送前或到达前进... 目录dubbo3 filter(过滤器)简介dubbo 过滤器运行时机自定义 filter第一种 @A