最近练习一个不用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())