019.PyQt5_QWidget_父子关系扩充

父子关系扩充

  • 父子关系
    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_())
    
    • 019.PyQt5_QWidget_父子关系扩充_第1张图片


  • 案例1:创建一个窗口, 包含若干Label控件,点击哪个标签, 就让哪个标签背景变红

    • 要求:使用父控件处理, 不要自定义QLabel子类
    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_())
    
    • 019.PyQt5_QWidget_父子关系扩充_第2张图片

  • 案例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_())
    
    • 019.PyQt5_QWidget_父子关系扩充_第3张图片

你可能感兴趣的:(PyQt5,qt,pyqt,python,qt5,开发语言)