父子关系扩充
obj2.setParent(obj1) # 设置父类,把obj2设置为obj1的父对象
obj2.parent() # 获取父对象
obj1.children() # 获取所有直接子对象,返回一个列表
obj1.findChild(参数1, 参数2, 参数3) # 获取第一个指定类型和名称的后代对象,找到第一个就返回结果
# 参数1:类型如 QObject;类型元组如 (QPushButton, QLabel)
# 参数2:对象名称(可以省略)<通过setObjectName()设置的对象名称>
# 参数3:查找选项
Qt.FindChildrenRecursively # 递归查找,默认选项;
Qt.FindDirectChildrenOnly # 只查找直接子对象;
obj1.findChildren(参数1, 参数2, 参数3) # 获取所有指定类型和名称的后代对象,返回一个列表
# 参数同上
父控件.childAt(x, y) # 获取在指定坐标的控件
子控件.parentWidget() # 获取指定控件的父控件
父控件.childrenRect() # 所有子控件组成的边界矩形区域左上角和右下角的坐标点
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
window = QWidget()
window.setObjectName('window')
window.resize(500, 500)
window.setWindowTitle('父子关系扩充')
label1 = QLabel(window)
label1.setText('标签1')
label1.setObjectName('label1')
label1.move(10, 10)
label1.setStyleSheet('background-color: cyan;')
label2 = QLabel(window)
label2.setText('标签2')
label2.setObjectName('label2')
label2.move(50, 50)
label2.setStyleSheet('background-color: red;')
label3 = QLabel(window)
label3.setText('标签3')
label1.setObjectName('label3')
label3.move(100, 100)
label3.setStyleSheet('background-color: green;')
# 获取指定坐标子控件的控件名称
print(window.childAt(55, 55).objectName())
# 输出结果:label2
# 获取指定控件的父控件的控件名称
print(label2.parentWidget().objectName())
# 输出结果:window
# 获取所有子控件边界矩形组成的区域左上角和右下角的坐标点
print(window.childrenRect())
# 输出结果:PyQt5.QtCore.QRect(10, 10, 190, 120)
window.show()
sys.exit(app.exec_())
案例1:创建一个窗口, 包含若干Label控件,点击哪个标签, 就让哪个标签背景变红
from PyQt5.Qt import *
import sys
class MyWidget(QWidget):
def __init__(self):
super().__init__()
self.mouse_x = None
self.mouse_y = None
self.lab = None
def mousePressEvent(self, ev: QMouseEvent) -> None:
# 获取鼠标的坐标
self.mouse_x = ev.x()
self.mouse_y = ev.y()
# 根据鼠标的坐标,获取当前坐标的子控件
self.lab = self.childAt(self.mouse_x, self.mouse_y)
self.lab.setStyleSheet('background-color: red;border: 1px solid gray;')
def mouseReleaseEvent(self, a0: QMouseEvent) -> None:
# 设置鼠标按键释放时候,恢复标签原来的样式
self.lab.setStyleSheet('border: 1px solid gray;')
app = QApplication(sys.argv)
window = MyWidget()
window.resize(500, 500)
window.setWindowTitle('父子控件扩充案例1')
label_count = 20
column_count = 3
row_count = (label_count - 1) // column_count + 1
label_width = int(window.width() / column_count)
label_height = int(window.height() / row_count)
for i in range(0, label_count):
label = QLabel(window)
label.setText('label' + str(i + 1))
label.resize(label_width, label_height)
move_x = i % column_count * label_width
move_y = i // column_count * label_height
label.move(move_x, move_y)
label.setStyleSheet('border: 1px solid gray;')
window.show()
sys.exit(app.exec_())
此时,运行这个代码看上去已经满足了要求。但是当鼠标单击到没有控件的地方的时候,系统程序就会崩溃掉。
原因:当鼠标点击没有子控件的位置时候,mousePressEvent()还是会获取到x和y坐标。但是childAt()通过x和y坐标返回的结果为None。后面又对None进行样式设置setStyleSheet(),所以就会报错
解决方法:在设置样式之前加一个判断,判断返回的子控件不为None才执行样式设置(鼠标释放事件中同理,加上判断)
from PyQt5.Qt import *
import sys
class MyWidget(QWidget):
def __init__(self):
super().__init__()
self.mouse_x = None
self.mouse_y = None
self.lab = None
def mousePressEvent(self, ev: QMouseEvent) -> None:
# 获取鼠标的坐标
self.mouse_x = ev.x()
self.mouse_y = ev.y()
# 根据鼠标的坐标,获取当前坐标的子控件
self.lab = self.childAt(self.mouse_x, self.mouse_y)
if self.lab is not None:
self.lab.setStyleSheet('background-color: red;border: 1px solid gray;')
def mouseReleaseEvent(self, a0: QMouseEvent) -> None:
if self.lab is not None:
# 设置鼠标按键释放时候,恢复标签原来的样式
self.lab.setStyleSheet('border: 1px solid gray;')
app = QApplication(sys.argv)
window = MyWidget()
window.resize(500, 500)
window.setWindowTitle('父子控件扩充案例1')
label_count = 20
column_count = 3
row_count = (label_count - 1) // column_count + 1
label_width = int(window.width() / column_count)
label_height = int(window.height() / row_count)
for i in range(0, label_count):
label = QLabel(window)
label.setText('label' + str(i + 1))
label.resize(label_width, label_height)
move_x = i % column_count * label_width
move_y = i // column_count * label_height
label.move(move_x, move_y)
label.setStyleSheet('border: 1px solid gray;')
window.show()
sys.exit(app.exec_())
案例2:创建一个窗口, 包含若干Label控件,鼠标移动到哪个标签上, 就让哪个标签背景变红
from PyQt5.Qt import *
import sys
class MyLabel(QLabel):
# enterEvent(QEvent) # 鼠标进入时触发
# leaveEvent(QEvent) # 鼠标离开时触发
def enterEvent(self, a0: QEvent) -> None:
self.setStyleSheet('background-color: red;border: 1px solid gray;')
def leaveEvent(self, a0: QEvent) -> None:
self.setStyleSheet('border: 1px solid gray;')
app = QApplication(sys.argv)
window = QWidget()
window.resize(500, 500)
window.setWindowTitle('父子控件扩充案例2')
label_count = 20
column_count = 3
row_count = (label_count - 1) // column_count + 1
label_width = int(window.width() / column_count)
label_height = int(window.height() / row_count)
for i in range(0, label_count):
label = MyLabel(window)
label.setText('label' + str(i + 1))
label.resize(label_width, label_height)
move_x = i % column_count * label_width
move_y = i // column_count * label_height
label.move(move_x, move_y)
label.setStyleSheet('border: 1px solid gray;')
window.show()
sys.exit(app.exec_())