当前位置:   article > 正文

Python运用PySide6/PyQt居然可以制作如此好看的界面——““创意解析””_pyside6炫酷界面

pyside6炫酷界面

PyThon运用PySide6/PyQt居然可以制作如此好看的界面——““创意解析””

导语:

你将获取以下知识:

  • 相关控件:

    QWidget
    QLineEidt
    QTableWidget
    QLabel
    QPushButton
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • Qss美化

  • 多线程与信号

界面风格:

圆角,简约,暗夜模式

主界面分析:

请添加图片描述

  1. 窗口标题栏被替换
  2. 内容区由搜索框和快捷栏组成

窗口界面详解:

1.首先 (标题栏):

先将默认的标题栏去掉

        self.setWindowFlags(Qt.WindowType.Window | Qt.WindowType.FramelessWindowHint) # 设置无边框
        self.setAttribute(Qt.WA_TranslucentBackground) # 设置窗口背景透明
  • 1
  • 2

其次通过Qss实现圆角需要paintEvent的支持

def paintEvent(self, event):
    opt = QStyleOption()
    opt.initFrom(self)
    p = QPainter(self)
    self.style().drawPrimitive(QStyle.PrimitiveElement.PE_Widget,opt,p,self)

    super().paintEvent(event)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

接着我们开始重实现标题栏
右边由:QLabel构成 左边由:QPushButton构成

值得留意的是Qss背景不支持?

self.setAttribute(Qt.WA_StyledBackground, True)  # 支持qss设置背景
  • 1

重实现 标题栏拖拽窗口移动

def mousePressEvent(self, event):
    super().mousePressEvent(event)
    if event.button() == Qt.MouseButton.LeftButton:
        self._press = True
        self.mouseStartPos = event.globalPos()	# 获取点击屏幕坐标
        self.windowTopLeftPos = self.mapToGlobal(self.frameGeometry().topLeft()) # 获取窗口左上角屏幕坐标

def mouseMoveEvent(self, event):
    super().mouseMoveEvent(event)
    if self._press:
        distance = event.globalPos() - self.mouseStartPos # 计算移动距离
        self.window().move(distance + self.windowTopLeftPos) # 移动窗口

def mouseReleaseEvent(self, event):
    super().mouseReleaseEvent(event)
    if self._press:
        self._press = False
        
# 注意坐标系应相当于屏幕坐标系
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
2.其次 (搜索框):

主要是对QLineEidt的样式设置和PaintEvent的重写

def paintEvent(self, event):
    super().paintEvent(event)

    painter = QPainter(self)

    img = QPixmap('./img/find.png').scaled(34,34,Qt.AspectRatioMode.IgnoreAspectRatio, Qt.TransformationMode.SmoothTransformation)
    painter.drawPixmap(
        600-25-18,2, img)
    
# Qss
QLineEdit{
        color: white;
        padding-left: 12px;
        padding-right: 40px;
        border: 2px solid gray;
        border-radius: 20px;
        background-color: #282c35;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

至于QLineEdit的搜索按钮点击事件,通过重写mousePressEvent实现,详解源代码

3.最后 (快捷栏):

它由QTableWidet构成,单元格由两个QLabel构成

值得注意点是:QTableWidget设置样式(stylesheet)后,单元格行高列宽会失效,解决方法如下:

self.horizontalHeader().setDefaultSectionSize(int)
self.verticalHeader().setDefaultSectionSize(int)
  • 1
  • 2

标题和图标,通过爬虫获取

from PIL import Image
from urllib.parse import urlsplit
import requests as rq

def getIcon(url:str):
   # 知识点:网址通常开放 主机名 + “/favicon.ico” 为图标api
   parser_url = urlsplit(url)
   netloc = parser_url.netloc	# 获取主机名
   icon_url = parser_url.scheme + '://' + netloc + "/favicon.ico"
   savePath = f'./img/{netloc.replace(".","_")}.ico'
   if not os.path.exists(savePath):
       img = Image.open(BytesIO(rq.get(icon_url,headers=HEADERS,verify=False).content))
       if img.width < 64 or img.height < 64:
           img = img.resize((64,64))
       img.save(savePath,sizes=[(64,64)])
   return netloc.replace(".","_")

# 获取标题部分详见源代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

由于爬虫会阻塞主线程,所以使用多线程加载是个好方法

from threading import Thread

currentThreading = Thread(target=self.cellInit,
                                     args=(row,index,DEFAULTURLS[key],key,))
currentThreading.start()

class shortcutsBar(QTableWidget):
   addCell = Signal(int,int,str,str)
   def __init__(self, parent=None):
       super().__init__(parent)
       self.bind()
       self.initSetup()
	
   def bind(self):
       self.addCell.connect(self.setCellEvent)
	
   def initSetup(self):
       # 详解源代码
       .......
       
		DEFAULTURLS ={'SteamWorkShop': 'https://steamcommunity.com/', 'Watt Toolkit': 'https://steampp.net/'}
       for index,key in enumerate(DEFAULTURLS.keys()):
           row = 0
           if index > 5:
               index -= 5
               row = 1

           currentThreading = Thread(target=self.cellInit,
                                     args=(row,index,DEFAULTURLS[key],key,))
           currentThreading.start()
   
   def cellInit(self,row:int,col:int,url:str,text:str):
       img = getIcon(url)
       self.addCell.emit(row,col,img,text)

   @Slot(int,int,str,str)
   def setCellEvent(self,row:int,col:int,img:str,text:str):
       cell = QWidget()
       cellLayout = QVBoxLayout(cell)
       cellText = QLabel(text)
       cellText.setFont(QFont('微软雅黑',12))
       cellText.setStyleSheet('color: #ffffff')

       cellIcon = iconLabel(f'./img/{img}.ico',text)

       cellLayout.addWidget(cellIcon,alignment=Qt.AlignmentFlag.AlignCenter)
       cellLayout.addWidget(cellText,alignment=Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignBottom)

       self.setCellWidget(row,col,cell)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

这里采用原生多线程 + Signal 的原因是:在多线程中操作任何UI容易造成软件崩溃
如果是连续往UI添加东西要给界面留绘制时间 (sleep)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/652008
推荐阅读
相关标签
  

闽ICP备14008679号