Pyside6 QWidget 控件之父(2)

三、Pyside6事件机制简要版

为了便于后面的学习,事件在这里绕不开。但是,由于刚开始学习,过于深入反而会造成焦虑。所以,将事件机制简化进行说明。

1.事件的概念

事件就是程序在运行过程中接收到的需要处理的命令,比如鼠标点击一个按钮,按下键盘按键等等。在Pyside中,事件被封装成一个个对象,全部的Pyside事件都继承自抽象类QEvent,用于描述程序内部或者外部的动作,任意的QObject对象都具有处理事件的能力。

常见的事件类型如下:

键盘事件 :按键的按下和松开

鼠标事件:鼠标移动,按下和松开

拖放事件:用鼠标进行拖放

滚轮事件:鼠标滚轮滚动

绘屏事件:重绘窗口部分部件

定时事件:定时器到时

焦点事件:键盘焦点移动

进入和离开事件:鼠标进入widget内或移出

移动事件:widget位置移动

大小改变事件:widget大小改变

显示和隐藏事件:widget显示或隐藏

窗口事件:窗口是否为当前窗口

2.事件的产生

PySide6事件的产生分为两种,一种是用户交互时操作系统产生,如鼠标事件、键盘事件等;另一种是程序自己产生,如计时器事件或用户自定义事件。

操作系统的事件,即通过操作系统获取的事件,如鼠标按下事件,鼠标双击 事件,键盘按下事件等。这些事件操作系统通常会针对设备的操作设置监听函数,当用户做出相应操作(点击鼠标、按下键盘),监听函数将发出事件消息。事件消息被存放在操作系统的消息队列中,通过操作系统调度,消息队列中的事件消息会分发给相应的事件产生者(应用程序或操作系统本身)。

Pyside应用程序内部也有消息队列的机制,原理同操作系统。而这个消息队列同时存储操作系统分发来的事件消息和应用程序本身产生的事件消息。应用程序将这些消息包装成包含接收者和事件类型的对象QEvent发送给QApplication。QApplication在根据接收者和事件类型发送给控件的具体方法予以执行。

上面就是Pyside的事件机制简要介绍。下面,我们通过具体例子再进行学习。

3.鼠标事件和键盘事件的API

1).鼠标事件QMouseEvent的API

构造函数不介绍,仅QEvent.Type就需要说明很多。下面的方法也是常用的一些,并列出。但同时,由于QMouseEvent继承自QSingPointEvent,所以将其合并罗列。

API函数

参数说明

返回值

功能作用

button(self)NoneQt.QMouseButton返回导致事件发生的鼠标按钮
buttons(self)NoneQt.QMouseButton返回事件生成时的鼠标按键状态。

clone(self)

None

QMouseEvent

创建一个鼠标事件的副本

globalPosition(self)NoneQPointF返回鼠标事件中的点在屏幕或虚拟桌面中的位置
position(self)NoneQPointF返回鼠标事件中该点相对于窗口或场景的位置。

flags(self)

None

Qt.MouseEventFlag

返回鼠标事件标志

globalPos(self)None

QPoint

同globalPosition()

globalX(self)Noneint获取globalPosition()的x坐标
globalY(self)Noneint获取globalPosition()的y坐标
localPos(self)None

QPoint

同position()
x(self)Noneint获取globalPosition()的y坐标
y(self)Noneint获取globalPosition()的y坐标

首先看下面的鼠标图片:

当我们要对事件进行操作时,首先我们要知道对于鼠标对象来说,事件的产生着是谁,是左键、右键、还是中键或者是其他键。只有获取了具体键位,我们才能够进行具体的内容的编写。比如一个按钮,左键被点击,我们让他打印一句话;右键被点击,我们则会让它弹出一个右键菜单。而上述API中的button()方法就是获取鼠标具体的键位,与之对应的Qt.MouseButton是一个枚举类:

枚举类

枚举常量

枚举值

功能描述

Qt.MouseButton

NoButton

控件不接受任何鼠标按键的操作

AllButton

控件接受所有鼠标按键的操作

LeftButton

对应鼠标左键

RightButton对应鼠标右键
MiddleButton对用中键(大多数是滚轮)
XButton1后退键
BackButton后退键
ExtraButton1功能键1(非滚轮)
XButton2前进键
ForwardButton前进键
TaskButton特殊功能键

ExtraButton2

~

ExtraButton24

功能键2~功能键24(非滚轮)

我们常用鼠标也就是左键、右键、滚轮(中键)、前进键和后退键。多功能键的鼠标通常适用于游戏鼠标。

buttons()方法则是多键位的一个组合值,通常用“|”操作符进行连接。比如,我们要在一个文档页面中拖动一幅图片大范围移动位置需要左键+滚轮一起操作。

其他关于坐标的方法,都是关于当前鼠标点击位置坐标获取的方法。global是相对于屏幕的,local是相对于控件的。这里需要说明的是,由于历史版本的原因,红色字体部分不推荐使用,未来可能会被去除。

最后,还要说一下, 控件针对按键的不同操作状态提供了不同的方法:

单击:mousePressEvent()和mouseResleaseEvent(),即按下和抬起

双击:mouseDoubleClickEvent()

滚轮滚动:WheelEvent()

example:

# -*- codeing:uft-8 -*-
from PySide6.QtWidgets import QApplication,QWidget
from PySide6.QtCore import Qt
import sys
class testWindow(QWidget):

    def __init__(self):
        super(testWindow, self).__init__()
        self.resize(800, 800)
        self.setWindowTitle("事件的示例")

    def mousePressEvent(self, e):
        # 调用父对象的事件方法。我们并不知道Pyside内部对此鼠标事件是如何处理的
        # 所以调用其父对象方法自动处理。处理完,我们再实现自己需要的功能
        # 所有的事件方法的重写,推荐这种方式,除非你确实知道其内部如何处理
        super(testWindow, self).mousePressEvent(e)
        if e.button() == Qt.MouseButton.LeftButton:
            print("鼠标左键被按下了")

        elif e.button() == Qt.MouseButton.RightButton:
            print("鼠标右键被按下了")

        elif e.button() == Qt.MouseButton.MiddleButton:
            print("鼠标滚轮被按下了")

    def wheelEvent(self, event):
        super(testWindow, self).wheelEvent(event)
        print("滚轮滚动了")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = testWindow()
    win.show()
    sys.exit(app.exec())

2).键盘事件QKeyEvent的API

键盘事件,也就是用户通过键盘按下按键和释放按键的动作所产生的事件。与鼠标事件类似,编程人员需要获取被按下的键具体是哪一个,才能针对性的设计。所以,对应键盘上的每一个键,Pyside都进行了记录,通过枚举值存放在内部。

控件针对按键的操作提供了按下和释放两个方法:

keyPressEvent()和keyReleaseEvent()

API函数

参数说明

返回值

功能作用

clone(self)

None

QKeyEvent

创建一个键盘事件的副本

count(self)Noneint返回此事件中涉及的键的数目。如果text()不为空,这只是字符串的长度。
isAutoRepeat(self)

None

bool

返回按键是否设置自动重复
key(self)Noneint返回按下或释放的键的代码。
keyCombination(self)NoneQKeyCombination返回键盘修饰符与键组合
modifiers(self)NoneQt.KeyboardModifier返回修饰符
text(self)NonestrReturns the Unicode text that this key generated.

对于上述方法中的几个返回值进行大致介绍:Qt.KeyboardModifier是内置的修饰符的一个枚举类,它主要标识的是ctrl、shift、alt、command(苹果键盘)等用于组合的键。枚举常量如下:

枚举类

枚举常量

枚举值

功能描述

Qt.KeyboardModifier

NoModifier

没有按下修饰符按键

ShiftModifier

按下Shift键

ControlModifier

按下control键

AltModifier

按下alt键

MetaModifier

按下meta键

KeypadModifier

按下一个小键盘中的按键

而QKeyCombination暂时可以理解为专为ctrl+x等组合键设置的类,具体再后面快捷键章节学习。

key()的返回值是Qt.key这个键位枚举类的枚举值,通常我们使用其枚举常量,更直观。只列举部分其枚举值,不全部列出,具体在快捷键章节学习。

另外,

枚举类

枚举常量

枚举值

功能描述

Qt.Key

Key_Escape

Escape(退出)键

Key_Tab

Tab(制表符)键

Key_Backspace

Backspace(后撤)键

Key_Enter

Enter(确定)键

Key_Shift

Shift键

Key_Control

Ctrl键

Key_Alt

Alt键

Key_Space

Space(空格)键

Key_0

数字0键

Key_1

数字1键

Key_2

数字2键

Key_3

数字3键

Key_4

数字4键

Key_5

数字5键

Key_6

数字6键

Key_7

数字7键

Key_8

数字8键

Key_9

数字9键

Key_A

字母A键

Key_B

字母B键

Key_C

字母C键

Key_D

字母D键

Key_E

字母E键

Key_F

字母F键

Key_G

字母G键

Key_H

字母H键

Key_I

字母I键

Key_G

字母G键

Key_K

字母K键

Key_L

字母L键

Key_M

字母M键

Key_N

字母N键

Key_O

字母O键

Key_P

字母P键

Key_Q

字母Q键

Key_R

字母R键

Key_S

字母S键

Key_T

字母T键

Key_U

字母U键

Key_V

字母V键

Key_W

字母W键

Key_X

字母X键

Key_Y

字母Y键

Key_Z

字母Z键

具体的使用请看下面的例子:

example:

# -*- codeing:uft-8 -*-
from PySide6.QtWidgets import QApplication,QWidget
from PySide6.QtGui import QKeyEvent
from PySide6.QtCore import Qt
import sys
class testWindow(QWidget):

    def __init__(self):
        super(testWindow, self).__init__()
        self.resize(800, 800)
        self.setWindowTitle("键盘事件的示例")

    def keyPressEvent(self, event):
        super(testWindow, self).keyReleaseEvent(event)
        
        # 如果点击esc键,关闭窗口
        if event.key() == Qt.Key.Key_Escape:
            self.close()
        
        # 如果点击ctrl+M键,窗口最大化显示
        elif event.key() == (Qt.Key.Key_Control and Qt.Key.Key_M):
            self.showMaximized()
            
        # 如果点击ALT+F键,窗口全屏显示;点击ALT+N键,窗口恢复到初始状态
        elif event.modifiers() == Qt.KeyboardModifier.AltModifier:
            if event.key() == Qt.Key.Key_F:
                self.showFullScreen()
            elif event.key() == Qt.Key.Key_N:
                self.showNormal()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = testWindow()
    win.show()
    sys.exit(app.exec())

上面例子无法演示过程,需要请自己复制代码进行测试。

另外,从上面的例子可以看出,当组合键使用Qt.Key进行组合时,是and运算符。而使用Qt.KeyboardModifier和组合时,使用的时“|”运算符。

3).事件与信号-槽的关系

信号与槽机制:只能解决窗口控件的某些特定行为,相当于功能的细化

事件处理机制:可以对窗口控件进行更深层次的研究,如自定义窗口

所以,事件处理机制更靠近底层,二信号与槽机制是对事件的封装。

exmple:这个例子就是通过事件机制实现clicked信号

# -*- codeing:uft-8 -*-
from PySide6.QtWidgets import QApplication,QWidget,QLabel
from PySide6.QtGui import QKeyEvent,QPalette,QColor,QPainter
from PySide6.QtCore import Qt
import sys

class clickSignl(object):
    """
    定义一个信号类,其connect方法接收一个方法名传递给
    实例属性self.solt
    """
    def connect(self,method):
        self.solt = method

class custombtn(QWidget):
    """
    使用QWidget模拟一个按钮,实现点击北京效果变换,及clicked信号的功能
    """
    def __init__(self,parent):
        super(custombtn, self).__init__(parent)
        # 使用调色板设置初始化背景色。这里没有用QSS,用调色板,后面高级课程会学习
        self.p = self.palette()
        self.p.setColor(self.backgroundRole(),QColor("Gainsboro"))
        self.setPalette(self.p)

        # 对于QWidget自定义子类,如果不设置setAutoFillBackground(),颜色不会改变
        self.setAutoFillBackground(True)

        # 创建一个clicked信号实例作为按钮的属性
        self.clicked = clickSignl()

    def setText(self,text):
        """
        使用QLabel作为子控件,实现按钮的setText功能
        """
        self.lab = QLabel(self)
        self.lab.resize(self.size())
        self.lab.setText(text)
        self.lab.setAlignment(Qt.AlignmentFlag.AlignCenter)

    def mousePressEvent(self, event):
        super(custombtn, self).mousePressEvent(event)
        # 鼠标按下改变背景色
        self.p.setColor(self.backgroundRole(),QColor("WhiteSmoke"))
        self.setPalette(self.p)

        # 鼠标按下,调用槽函数
        self.clicked.solt()

    def mouseReleaseEvent(self, event):
        super(custombtn, self).mouseReleaseEvent(event)
        # 鼠标抬起改变背景色
        self.p.setColor(self.backgroundRole(), QColor("Gainsboro"))
        self.setPalette(self.p)

    def paintEvent(self, event):
        super(custombtn, self).paintEvent(event)
        # 给按钮绘制一个边框。绘制将在画图章节学习。
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setPen(Qt.black)
        painter.setBrush(Qt.NoBrush)
        painter.drawRect(0, 0, self.width(),self.height())

class testWindow(QWidget):
    def __init__(self):
        super(testWindow, self).__init__()
        self.resize(400, 400)
        self.setWindowTitle("模拟按钮的示例")

        btn = custombtn(self)
        btn.move(100,100)
        btn.setText("自定义按钮")

        btn.clicked.connect(self.printContents)

    def printContents(self):
        print("鼠标点击了")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = testWindow()
    win.show()
    sys.exit(app.exec())

运行结果:

20240913-094815

控制台输出结果:

鼠标点击了
鼠标点击了
鼠标点击了
鼠标点击了

四、QWidget的鼠标设置

上一小节学习了鼠标和键盘的事件,这一小节接着学习QWidget对于鼠标的设置的一些方便函数。

1.鼠标样式设置

API函数

参数说明

返回值

功能作用

setCursor(self, a0)

a0: QCursor或Qt.CursorShape

None

设置或自定义鼠标样式及类型

unsetCursor(self)

None

None

重置鼠标

cursor(self)

None

QCursor

获取控件光标对象

setCursor( )函数设置以后只针对本控件,即当鼠标进入设置鼠标了鼠标样式的控件范围后,鼠标将改变,但是当子控件未自定义鼠标及样式时,将继承其父对象鼠标样式。另外,QCursor后下一小节学习。这里只说明CursorShape表明的是Qt给定的鼠标样式,他是一个枚举类,代表了各个样式的鼠标光标外观样式,具体见下:

枚举类

枚举常量

图标

功能描述

Qt.CursorShape

ArrowCursor

普通箭头光标

UpArrowCursor

向上箭头光标

CrossCursor

十字光标

IBeamCursor

工字梁光标

WaitCursor

等待光标

BusyCursor

繁忙光标

ForbiddenCursor

禁止光标

PointingHandCursor

点击光标

WhatsThisCursor

这是啥光标

SizeVerCursor

垂直尺寸光标(缩放用)

SizeHorCursor

水平尺寸光标(缩放用)

SizeBDiagCursor

斜向尺寸光标(缩放用)

SizeFDiagCursor

斜向尺寸光标(缩放用)

SizeAllCursor

全尺寸光标(移动用)

SplitVCursor

垂直分割线光标(移动用)

SplitHCursor

水平分割线光标(移动用)

OpenHandCursor

抓取光标(点击前)

ClosedHandCursor

抓取光标(点击后)

DragMoveCursor

拖拽移动光标

DragLinkCursor

拖拽链接光标

DragCopyCursor

拖拽复制光标

2.自定义鼠标及QCursor类

API函数

参数说明

返回值

功能作用

QCursor(Cursor)

Cursor:QCursor

None

创建一个鼠标光标对象

QCursor(Bitmap,mask, hotX, hotY)

Bitmap:QBitmap

Mask:QBitmap

hotX:int(默认-1)

hotY:int(默认-1)

None

创建一个鼠标光标对象。HotX和HotY的意思是,鼠标有效点击的坐标位置。

QCursor(CursorShape)

CursorShape Qt.CursorShape

None

创建一个鼠标光标对象。

bitmap(self)

None

QBitmap

返回光标所使用的位图图片,如果是Qt标准图片(Qt.cursorShape中的图标)将返回空位图

hotSpot(self)

None

QPoint

返回光标热点,如果是标准设置,将返回(0,0)

mask(self)

None

QBitmap

返回光标的蒙板位图,如果是标准设置,则返回空位图。

pixmap(self)

None

QPixmap

返回光标的像素贴图,只有当鼠标贴图使用QPixmap格式进行设置时,才用有返回值

pos(self

None

QPoint

返回光标热点在全局屏幕的坐标点

pos(self,screen

Screen:QScreen

QPoint

返回光标热点在全局屏幕的坐标点

QWidget.mapFromGlobal(self)

None

QPoint

将全局坐标点转换为控件的局部坐标点

QWidget.mapToGlobal(self)

None

QPoint

将小部件的坐标点转换为全局屏幕坐标点

shape( self)

None

Qt.CursorShape

返回鼠标的类型样式

swap(cursor)

Cursor:QCursor

None

将此光标与另一个预定光标进行交换

setShape(cursor)

Cursor:CursorShape

None

设置光标的类型样式

setPos(x,y)

X:int y:int

None

将光标热点移动到屏幕的全局坐标点(x,y

setPos(point)

Point:QPoint

None

将光标热点移动到屏幕的全局坐标点(x,y

hotspot(热点),所谓的热点就是鼠标点击生效为位置,如下图:

也就是说如果我要点击一个按钮,使得按钮生效,那么只有这个尖尖放在按钮的有效范围时点击才会有效果。并且如果hotX为负数,它将被设置为bitmap().width()/2。如果hotY为负数,它将被设置为bitmap().height()/2。

QScreen对象没有构造函数,只能通过QGuiApplicaition. primaryScreen()方法来获取。

对于自定义鼠标的图片只能通过构造函数进行设置,而其mask()方法则是设置图片的蒙版。这需要对图像处理有所了解,我们将在后面的图片处理章节简要介绍。

3.关于鼠标追踪

前面我们学习了鼠标关于点击和滚轮的事件,各事件都有相关的事件函数,如滚轮的wheelMoveEvent,键位的点击mousePressEvent等。那么鼠标还有一类重要的事件就是移动,mouseMoveEvent,这是在后面学习中我们也需要经常用的,他归属于QMouseEvent类,相关方法还是那些。但是,需要注意的是,对于移动时间,当我们实现了相应的功能后,要使其在程序运行后起作用,必须开启鼠标追踪。

API函数

参数说明

返回值

功能作用

setMouseTracking(self,enable)

enable:bool

None

设置是否开启鼠标追踪

example:这里例子综合了自动以鼠标的热点、图片以及移动事件的使用

# -*- codeing:uft-8 -*-
from PySide6.QtWidgets import QApplication,QWidget,QPushButton
from PySide6.QtGui import QPixmap,QCursor
from PySide6.QtCore import Qt
import sys

class testWindow(QWidget):
    def __init__(self):
        super(testWindow, self).__init__()
        self.resize(400, 300)
        self.setWindowTitle("自定义鼠标示例")

        # 获取鼠标对象
        self.mouse = self.cursor()
        
        self.point = None

        #创建三个按钮
        btn1 = QPushButton("点击设置鼠标为小手样式",self)
        btn1.move(100,50)
        btn2 = QPushButton("点击设置鼠标自定义样式",self)
        btn2.move(100,150)
        btn3 = QPushButton("恢复鼠标设置", self)
        btn3.move(100, 250)

        # 按钮链接到参函数
        btn1.clicked.connect(self.setMouseStyle)
        btn2.clicked.connect(self.customMouseStyle)
        btn3.clicked.connect(lambda :self.unsetCursor())

    def setMouseStyle(self):
        # 设置鼠标样式为标准样式的手型
        self.mouse.setShape(Qt.CursorShape.OpenHandCursor)
        self.setCursor(self.mouse)

    def customMouseStyle(self):
        # 自定义鼠标样式,添加了鼠标图片,鼠标图片原大小1080*72
        # QPixmap对象的scaled()方法缩放图片,参数Qt.AspectRatioMode是裁剪图片模式,同QSize
        # 参数Qt.TransformationMode是转换模式
        pix = QPixmap("宝剑.png").scaled(108,72,Qt.AspectRatioMode.KeepAspectRatio,Qt.TransformationMode.SmoothTransformation)
        customCusor = QCursor(pix,1,1)
        self.setCursor(customCusor)

    def mousePressEvent(self, event):
        super(testWindow, self).mousePressEvent(event)
        # 设置鼠标按下是开启鼠标追踪
        self.setMouseTracking(True)
        self.point = event.position().toPoint()

    def mouseReleaseEvent(self, event):
        super(testWindow, self).mouseReleaseEvent(event)
        # 设置鼠标按下时关闭鼠标追踪
        self.setMouseTracking(False)

    def mouseMoveEvent(self, event):
        super(testWindow, self).mouseMoveEvent(event)
        # 按下鼠标移动时,窗口跟随鼠标。注意,点击按钮子控件不起作用
        # 需要在空白处点击。因为点击按钮时,将调用按钮的点击事件
        if self.point != None:
            self.move(self.cursor().pos() - self.point)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = testWindow()
    win.show()
    sys.exit(app.exec())

运行结果:

20240913-132601

五、QWidget的父子关系扩展

API函数

参数说明

返回值

功能作用

childAt(x,y)

X:int

Y:int

QWidget

获取指定坐标点的控件

parentWidget(self)

None

QWidget

获取控件的父控件

childrenRect(self)

None

QRect

获取子控件组成的矩形区域

简单的方法,没啥说的。

六、QWidget的层级关系

1.层级关系的说明

前面在QObject类的父子关系一节中说过,一个控件如果设置了父控件,那么它将受到父控件的约束。如果这个父类有多个子控件,子控件在没有move()的情况下是堆叠显示的。比如:

# -*- codeing:utf-8 -*-
from PySide6.QtWidgets import QWidget, QApplication, QPushButton
from PySide6.QtCore import QPoint, QMargins
import sys


class testWindow(QWidget):
    def __init__(self):
        super(testWindow, self).__init__()
        self.resize(800, 800)
        self.setWindowTitle("QWidget的层级关系")

        win1 = QWidget(self)
        win1.resize(600,600)
        win1.setStyleSheet("background:red")

        win2 = QWidget(self)
        win2.resize(400, 400)
        win2.setStyleSheet("background:blue")

        win3 = QWidget(self)
        win3.resize(200, 200)
        win3.setStyleSheet("background:green")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = testWindow()
    win.show()
    sys.exit(app.exec())

运行结果:

可以看到,3个子控件垂直屏幕堆叠在一起,同时,堆叠的顺序是按照自下而上与其对象生成的顺序相对应的。那么,win3就是在顶层,win2在中层,win1在底层。由于为了能够看清各个空间之间的堆叠关系,所以设置了大小,如果三个子控件大小一致,也就只能看到顶层的win3。所以,本节所说的层级关系就是指同级子控件之间的上、下层之间的关系。对于同级子控件的含义,我们看前面的一个图:

上图中的把obj都换为QWidget,那么obj1、obj2、lab1是子控件,obj3、obj4、obj5就是孙控件,obj1、obj2、lab1就是同一级,obj3、obj4、obj5同一级。

2.层级关系的相关方法

API函数

参数说明

返回值

功能作用

lower(self)

None

None

将控件放到最底层

raise_(self)

None

None

将控件放到最顶层

stackUnder(self, w)

W:QWidget

None

将控件放置于另一个控件之下

example:

# -*- codeing:uft-8 -*-
from PySide6.QtWidgets import QApplication,QWidget
import sys

class testWindow(QWidget):
    def __init__(self):
        super(testWindow, self).__init__()
        self.resize(800, 800)
        self.setWindowTitle("QWidget的层级关系")

        win1 = QWidget(self)
        win1.resize(600,600)
        win1.setStyleSheet("background:red")

        win2 = QWidget(self)
        win2.resize(400, 400)
        win2.setStyleSheet("background:blue")

        win3 = QWidget(self)
        win3.resize(200, 200)
        win3.setStyleSheet("background:green")

    def mouseReleaseEvent(self, evt):
        """
        #重写鼠标事件,点谁谁掉底
        """
        win_x = self.childAt(evt.position().x(),evt.position().y())
        if win_x is not None:
            win_x.lower()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = testWindow()
    win.show()
    sys.exit(app.exec())

运行结果:

20240910-043215

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值