PYQT5/6上窗体堆叠控件被单击时的响应探究

最近练习一个不用pygame等第三方库作一个类似游戏框架界面,用到了大量的QLabel标签控件来加载各渐变图片形成类似角色在动的动画,控件堆叠在一起时对鼠标单击等的先后顺序是什么样的,作了一个简单的示例来验证,即鼠标单击在点位置上有多个控件对象实例时,总是只对堆叠在最上面的一控件触发相关事件或信号,下面的控件不会响应此单击事件。被单击的控件单击事件被触发后可以再发送信号到主窗体,通过主窗体对应响应的槽函数来对堆叠在下面的控件进行处理。

示例PYTHON + QT5码的代码如下:

import sys 	
import PyQt5
from PyQt5 import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5 import QtCore 
######################################################################################
class MyMainFrm(QMainWindow):
    def __init__(self, parent=None):    
        super(MyMainFrm, self).__init__(parent)      
        self.setWindowIcon(QIcon("5G.JPG"))
        self.resize(800,800)
        self.setFixedSize(800,800)
        self.resize(400,300)     #设置了固定尺寸之后,尺寸便不可修改!
        w=25
        h=25
        n=0
        self.labs=[]  #定义标签集列表
        while n<5:  #创建5个标签控件
            s='第'+str(n)+'号标签'
            lab=MyLabel(s,n,self)                           #不论是否用的self变量,lab不会自行消失,此时从下到上的叠加顺序为0,1,2,3,4,此时单击的范围如果在4和0重叠区,并只会触发4标签的信号槽
            lab.setGeometry(5+h*n, 80+h*n, 400, 400)
            lab.setFrameShape(QFrame.Box)
            lab.setToolTip(f'{n}号标签')
            self.labs.append(lab)  #将创建的标签控件加入标签集
            self.labs[n].signal_clicked.connect(self.labClick2)  
            
            #lab.close()  #保留此语句,窗体上不会有任何标签控件,原理没懂,是不是lab被释放了,但内存数据还在,标签集引用的地址self.labs[]还可以正确得到标签对象的全部二进制码
            n+=1
        self.labs[0].close()  #示例,关闭第0号标签.如果循环体中有 lab.close(),此代码也不会报错,调用重载的标签close事件
        self.labs[0].show()   #示例,如果循环体中有 lab.close(),且重载的close()中没有self.deleteLater()代码,此代码还会显示出0号标签,即close并不会真正删除控件循环体内建立的标签
                                    #如果循环体中有 lab.close(),且重载的close()中有self.deleteLater()代码,则此时show()不会再显示出0号标签,但也不报错
        
        self.setTabOrder(self.labs[4],self.labs[0])  #调整TAB顺序对重叠触发用
        self.labs[2].raise_()   #1标签提到重叠最上面,此时从下到上的叠加顺序为1,3,4,0(如果colose没有释放掉还在),2,  即点击的区域如果在2和其他号标签重叠的区域,将会只触发2的信号槽函数,
        self.labs[4].lower()    #4标签提到重叠最下面,此时从下到上的叠加顺序为4,1,3,0,2,即点击的区域如果在4和其他号标签重叠的区域,将会不会触发4标签的信号槽函数,而是其他相对最上面的标签,
                                #但如果0标签在clolse函数中被deleteLater()了,界面中不会出现0标签控件,从下到上的叠加顺序为4,1,2,3

    #主窗体中绑定的同标签关联的信号signal_clicked对应的槽函数,此信号同时发送了一个id的变量参数过来供槽函数labClick1使用
    def labClick2(self,id):
        print(f'后:主窗口中接收到的标签被单击时的槽函数:id={id}标签被单击')  #id变量靠槽函数传递
        self.labs[2].lower() #2标签放在最下,此时从下到上的叠加顺序为2,1,4,0(如果colose没有释放掉还在)或3,即点击的区域如果在0和其他号标签重叠的区域,将会只触发0的信号槽函数,

#重载标签类        
class MyLabel(QLabel):
    signal_clicked = QtCore.pyqtSignal(int)   #自定义标签的信号槽
    #初始化
    def __init__(self,text='',id=0,parent=None):    
        super(QLabel, self).__init__(parent)   
        self.setText(text)   
        self.id=id
        self.signal_clicked.connect(self.labClick1)  
    #鼠标按下事件重载   
    def mousePressEvent(self, event):
        #print(f'当前鼠标压下坐标:x={event.pos().x()},y={event.pos().y()}')
        # 鼠标左键按下
        if event.button() == Qt.LeftButton:
            self.signal_clicked.emit(self.id)   #在DEMO标签上按下鼠标键后,发送此信号出去,主窗体接收此信号,调用对应定义的槽函数响应
        
    #重载标签类中的同单击事件绑定的本类槽函数,即单击标签后
    def labClick1(self):
        print(f'先:标签类中接收到的标签被单击时的槽函数:id={self.id}标签被单击')   #标签实例化对象id值为自有属性,可不必使用槽来接收变量,当然也可以用槽变量
    
    def close(self):
        print('重载标签关闭函数')
        super().close()          #调用父类的close,也不会影响在show()后又被显出来,表示close并没完全释放控件窗体
        self.deleteLater()      #加了此代码,将会彻底释放被创建的窗体,上面因0号标签被close了,故show时不会再显示0号标签,但奇怪的是self.labs[0].show()   self.labs[0].raise_()等也不会报错
                                #如此语句存在,主窗体循环体中调用了lab.close(),界面上将不会出现任何标签控件,自已测试效果
    
if __name__=="__main__":  
    app = QApplication(sys.argv)  
    myWin = MyMainFrm()  
    myWin.show()  
    sys.exit(app.exec())  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mr_LuoWei2009

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值