首页 > 其他分享 >PyQt:【重磅干货】实现一个自定义样式的窗口(比如去掉边框、改变标题位置、窗口按钮样式)

PyQt:【重磅干货】实现一个自定义样式的窗口(比如去掉边框、改变标题位置、窗口按钮样式)

时间:2024-03-31 23:32:41浏览次数:34  
标签:__ 标题栏 窗口 自定义 样式 self ._ 按钮 def

如果想突破PyQt自带窗口的样式限制,比如同时去掉窗口的边框、改变边框、改变标题位置、窗口控制按钮等等,那就需要实现一个自定义样式的窗口,本文教你如何实现

先来看看PyQt创建窗口的默认样式:

在这里插入图片描述

再看看一个自定义样式的窗口:

在这里插入图片描述

可以看到,这里示例的自定义窗口去掉了窗口的边框、改变了标题位置、标题栏颜色、窗口控制按钮的样式、去掉了最大化按钮

上完整代码(目前ai工具写不出来的!!):


#-*- coding:utf-8 -*-

from PyQt5.QtWidgets import QWidget, QLabel, QPushButton, QVBoxLayout
from PyQt5.QtCore import Qt, QPoint
from PyQt5.QtGui import QFont, QCursor

class QTitleLabel(QLabel):
  """
  新建标题栏标签类
  """
  def __init__(self, *args):
    super(QTitleLabel, self).__init__(*args)
    self.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
    self.setFixedHeight(30)

class QTitleButton(QPushButton):
  """
  新建标题栏按钮类
  """
  def __init__(self, *args):
    super(QTitleButton, self).__init__(*args)
    self.setFont(QFont("Webdings")) # 特殊字体以不借助图片实现最小化最大化和关闭按钮
    self.setFixedWidth(40)

class QUnFrameWindow(QWidget):
  """
  无边框窗口类
  """
  def __init__(self):
    super(QUnFrameWindow, self).__init__(None, Qt.FramelessWindowHint) # 设置为顶级窗口,无边框
    self._padding = 5 # 设置边界宽度为5
    self.setGeometry(100, 100, 400, 300)
    self.initTitleLabel() # 安放标题栏标签
    self.setWindowTitle = self._setTitleText(self.setWindowTitle) # 用装饰器将设置WindowTitle名字函数共享到标题栏标签上
    self.setWindowTitle("自定义窗口")
    self.initLayout() # 设置框架布局
    self.setMinimumWidth(250)
    self.setMouseTracking(True) # 设置widget鼠标跟踪
    self.initDrag() # 设置鼠标跟踪判断默认值

  def initDrag(self):
    # 设置鼠标跟踪判断扳机默认值
    self._move_drag = False

  def initTitleLabel(self):
    # 安放标题栏标签
    self._TitleLabel = QTitleLabel(self)
    self._TitleLabel.setMouseTracking(True) # 设置标题栏标签鼠标跟踪(如不设,则标题栏内在widget上层,无法实现跟踪)
    self._TitleLabel.setIndent(150) # 设置标题栏文本缩进
    self._TitleLabel.move(0, 0) # 标题栏安放到左上角

  def initLayout(self):
    # 设置框架布局
    self._MainLayout = QVBoxLayout()
    self._MainLayout.setSpacing(0)
    self._MainLayout.addWidget(QLabel(), Qt.AlignLeft) # 顶一个QLabel在竖放框架第一行,以免正常内容挤占到标题范围里
    self._MainLayout.addStretch()
    self.setLayout(self._MainLayout)

  def addLayout(self, QLayout):
    # 给widget定义一个addLayout函数,以实现往竖放框架的正确内容区内嵌套Layout框架
    self._MainLayout.addLayout(QLayout)

  def _setTitleText(self, func):
    # 设置标题栏标签的装饰器函数
    def wrapper(*args):
      self._TitleLabel.setText(*args)
      return func(*args)
    return wrapper

  def setTitleAlignment(self, alignment):
    # 给widget定义一个setTitleAlignment函数,以实现标题栏标签的对齐方式设定
    self._TitleLabel.setAlignment(alignment | Qt.AlignVCenter)

  def setCloseButton(self, bool):
    # 给widget定义一个setCloseButton函数,为True时设置一个关闭按钮
    if bool == True:
      self._CloseButton = QTitleButton(b'\xef\x81\xb2'.decode("utf-8"), self)
      self._CloseButton.setObjectName("CloseButton") # 设置按钮的ObjectName以在qss样式表内定义不同的按钮样式
      self._CloseButton.setToolTip("关闭窗口")
      self._CloseButton.setMouseTracking(True) # 设置按钮鼠标跟踪(如不设,则按钮在widget上层,无法实现跟踪)
      self._CloseButton.setFixedHeight(self._TitleLabel.height()) # 设置按钮高度为标题栏高度
      self._CloseButton.clicked.connect(self.close) # 按钮信号连接到关闭窗口的槽函数

  def setMinMaxButtons(self, bool):
      # 给widget定义一个setMinMaxButtons函数,为True时设置最小化按钮
      if bool == True:
          self._MinimumButton = QTitleButton(b'\xef\x80\xb0'.decode("utf-8"), self)
          self._MinimumButton.setObjectName("MinMaxButton") # 设置按钮的ObjectName以在qss样式表内定义不同的按钮样式
          self._MinimumButton.setToolTip("最小化")
          self._MinimumButton.setMouseTracking(True) # 设置按钮鼠标跟踪(如不设,则按钮在widget上层,无法实现跟踪)
          self._MinimumButton.setFixedHeight(self._TitleLabel.height()) # 设置按钮高度为标题栏高度
          self._MinimumButton.clicked.connect(self.showMinimized) # 按钮信号连接到最小化窗口的槽函数

  def resizeEvent(self, QResizeEvent):
      # 自定义窗口调整大小事件
      self._TitleLabel.setFixedWidth(self.width()) # 将标题标签始终设为窗口宽度
      # 分别移动按钮到正确的位置
      try:
          self._CloseButton.move(self.width() - self._CloseButton.width(), 0)
      except:
          pass
      try:
          self._MinimumButton.move(self.width() - (self._CloseButton.width() + 1) * 2 + 1, 0)
      except:
          pass
  
  def mousePressEvent(self, event):
      # 重写鼠标点击的事件
      # 鼠标左键点击标题栏区域
      self._move_drag = True
      self.move_DragPosition = event.globalPos() - self.pos()
      event.accept()

  def mouseMoveEvent(self, QMouseEvent):
    # 鼠标手势
    self.setCursor(Qt.ArrowCursor)

    if Qt.LeftButton and self._move_drag:
      # 标题栏拖放窗口位置
      self.move(QMouseEvent.globalPos() - self.move_DragPosition)
      QMouseEvent.accept()

  def mouseReleaseEvent(self, QMouseEvent):
    # 鼠标释放后,各扳机复位
    self._move_drag = False

if __name__ == "__main__":
  from PyQt5.QtWidgets import QApplication
  import sys
  app = QApplication(sys.argv)
  app.setStyleSheet(open("./UnFrameStyle.qss").read())
  window = QUnFrameWindow()
  window.setCloseButton(True)
  window.setMinMaxButtons(True)
  window.show()
  sys.exit(app.exec_())

UnFrameStyle.qss文件中的代码:

/**********Title**********/
QTitleLabel{
    background-color: Gainsboro;
    font: 100 10pt;
}


/**********Button**********/
QTitleButton{
    background-color: rgba(255, 255, 255, 0);
    color: black;
    border: 0px;
    font: 100 10pt;
}
QTitleButton#MinMaxButton:hover{
    background-color: #D0D0D1;
    border: 0px;
    font: 100 10pt;
}
QTitleButton#CloseButton:hover{
    background-color: #D32424;
    color: white;
    border: 0px;
    font: 100 10pt;
}

有用点赞收藏加关注~

标签:__,标题栏,窗口,自定义,样式,self,._,按钮,def
From: https://blog.csdn.net/Mr_K_night/article/details/137081970

相关文章

  • 一招关掉所有广告弹窗(包括360安全卫士弹出的全部广告窗口)
    一招关掉所有广告弹窗(包括360安全卫士弹出的全部广告窗口)前言怎么确定电脑资源被占用开启“任务管理器”查找占用资源程序关闭资源占用程序弹窗多怎么永久关掉安装“360安全卫士”关完了,还有?如何关闭360安全卫士的广告弹窗360安全卫士设置关掉功能定制广告关掉弹窗设置......
  • 八股文——TCP四大机制!小白也能懂!(重传机制、滑动窗口、流量控制、拥塞控制)
    引言TCP巨复杂!同时在八股计算机网络中也经常被问到,必须会!这篇文章将让小白有个大体框架,知道怎么个事,面试中可以有话说,也能让佬更加巩固知识点。TCP是一个可靠的传输协议,为了保证它的可靠性,出现七七八八的机制,它可能有数据的破坏、丢包、重复以及分片顺序混乱等问题,TCP通过序......
  • Tomcat启动失败,窗口一闪而过问题解决
    在启动Tomcat时窗口一闪而过,解决方法:在Tomcat安装目录\bin下启动cmd,或在C盘启动后跳转到Tomcat安装目录\bin,输入startup.bat(一定要先做这步,确保具体问题,再根据具体问题百度,不然又是配置JRE,又是配置Tomcat环境变量,最后做了无用功),如果显示如下:先确保java环境变量没问题,我的java......
  • web前端之页面逐渐呈现代码功能、对象数据如何获取下一个值、创建元素并添加id与类名
    MENU前言style(全部代码)JavaScript(核心代码)html(基本代码)前言1、效果演示以视频为准,暂未录视频(敬请期待);2、私信或微信可获取完整代码(WX:MJ682517)style(全部代码)*{margin:0;padding:0;box-sizing:border-box;}::-webkit-scrol......
  • 9.折磨了一周的springboot样式跳转
    大致是这样的springboot一个项目将头部和侧部公共部分都提取出来但是一点击员工怎么侧边样式一直失败我看F12报错说的什么cavas渲染加上了还是错啊因为我是侧边栏的问题我的Controller跳转肯定没错这个真是让我难受了一周多因为还差增删改查就设计完毕了这个坑一......
  • Flink中的时间和窗口
    前言:    在批处理统计中,我们可以等一批数据都到齐后统一处理。但是在实时处理统计中,我们是来一条数据处理一条数据,那么我们怎么统计最近一段时间内的数据呢?引入“窗口”。    所谓的“窗口”,一般就是划定的一段时间范围,也就是“时间窗”;对在这个范围内的数据......
  • 政安晨:【Keras机器学习实践要点】(十)—— 自定义保存和序列化
    目录导言涵盖的APISetup状态保存自定义构建和编译保存自定义结论政安晨的个人主页:政安晨欢迎 ......
  • 「21」一个方法,让你实现多人异地自定义直播连麦
    「21」开源复刻实现模拟多人异地连麦直播场景如何利用OBS和腾讯会议软件搭配使用,模拟APP直播端的双人连麦画面效果,多用于需要电脑直播,并且需要和嘉宾远程连麦直播时使用,最终实现的效果,如下图示:直播后台效果为什么要用这种方法呢?主要有两方面:一是,连麦需要主持人做串场(主持......
  • Open CASCADE学习|自定义圆柱螺旋线
    由《OpenCASCADEBRepFormat》中可知,圆柱面的参数方程为:通过控制圆柱面的参数空间[u,v]便可以得到任意圆柱螺旋线。本例先根据参数生成圆柱面上的点,再把点拟合成空间曲线,从而得到螺旋线。#include<Geom_CylindricalSurface.hxx>#include<gp_Ax3.hxx>#include<GeomAP......
  • 【BlossomRPC】如何自定义一个RPC协议?
    文章目录如何设计一个RPC协议?RPC项目配置中心项目网关项目如何设计一个RPC协议?在上面的需求描述中我们知道,RPC非常重要的一环,就是自己制定符合自己需求的通信协议,这里,我简单的列出了我的协议。publicclassRpcHeaderimplementsSerializable{//publicst......