PyQT中__init__(self,parent==None)的parent含义
在PyQt中,所以class都是从QObject派生而来,QWidget对象就可以有一个parent。这种parent-child关系主要用于两个方面:
没有parent的QWidget类被认为是最上层的窗体(通常是MainWindow),由于MainWindow的一些操作生成的新窗体对象,parent都应该指向MainWindow。
由于parent-child关系的存在,它保证了child窗体在主窗体被回收之时也被回收。
parent作为构造函数的最后一个参数被传入,但通常情况下不必显示去指定parent对象。因为当调用局管理器时,部局管理器会自动处理这种parent-child关系。但是在一些特殊的情况下,我们必须显示的指定parent-child关系。如当生成的子类不是QWidget对象但继承了QObject对象,用作dock widgets的QWidget对象。
来自:
https://blog.youkuaiyun.com/thumb3344/article/details/5644789
一个 子控件 在主窗口show之前,设置主窗口为其父类,主窗口show的时候,会显示这个字控件。
如果这个子控件在 主控口show之后,设置主窗口为其父类, 这个控件就不会被显示
代码示例1:显示的是两个独立的窗口
multi_win1.py
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
import urllib.request
class ChildWidget(QWidget):
def __init__(self, parent=None, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
print('ChildWidget init')
self.setAttribute(Qt.WA_StyledBackground, True)
self.setWindowTitle('ChildWidget 模板')
self.top_layout = QHBoxLayout()
self.setLayout(self.top_layout)
self.resize(500, 300)
self.left_widget = QWidget()
self.mid_layout = QHBoxLayout()
self.right_widget = QWidget()
self.setObjectName('Top_ChildWidget')
self.setStyleSheet("#Top_ChildWidget{border: 2px solid red;}")
self.top_layout.addWidget(self.left_widget)
self.top_layout.addLayout(self.mid_layout)
self.top_layout.addWidget(self.right_widget)
self.next_btn = QPushButton('下一页')
self.back_btn = QPushButton('返回')
self.mid_layout.addWidget(self.next_btn)
self.mid_layout.addWidget(self.back_btn)
class MainWidget(QWidget):
main_widget_signal = pyqtSignal(dict)
def __init__(self, parent=None, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
print("MainWidget init")
self.setAttribute(Qt.WA_StyledBackground, True)
self.setWindowTitle('MainWidget 模板')
#print(type(self).__name__)
self.top_layout = QVBoxLayout()
self.setLayout(self.top_layout)
self.resize(500, 300)
self.dataView = QTableView()
self.model = QStandardItemModel(3, 0, self)
self.model.setHorizontalHeaderItem(0, QStandardItem("姓名"))
self.model.setHorizontalHeaderItem(1, QStandardItem("性别"))
self.model.setHorizontalHeaderItem(2, QStandardItem("体重(kg)"))
self.dataView.setModel(self.model)
self.child_layout = QHBoxLayout()
self.next_btn = QPushButton('下一页')
self.back_btn = QPushButton('返回')
self.child_layout.addWidget(self.next_btn)
self.child_layout.addWidget(self.back_btn)
self.top_layout.addLayout(self.child_layout)
self.top_layout.addWidget(self.dataView)
self.next_btn.clicked.connect(self.slot_next_btn_func)
self.back_btn.clicked.connect(self.slot_back_btn_func)
def slot_next_btn_func(self):
msg_dict = {}
msg_dict['name'] = 'MainWidget'
print('slot_next_btn_func')
msg_dict['action'] = 'next'
self.main_widget_signal.emit(msg_dict)
#print('MainWidget slot_next_btn_func', msg_dict)
def slot_back_btn_func(self):
msg_dict = {}
msg_dict['name'] = 'MainWidget'
msg_dict['action'] = 'back'
self.main_widget_signal.emit(msg_dict)
print('MainWidget slot_back_btn_func', msg_dict)
def slot_call_back_func(my_dict):
print("slot_call_back_func", my_dict)
if __name__ == '__main__':
app = QApplication(sys.argv)
main = MainWidget()
main.main_widget_signal.connect(slot_call_back_func)
child_win = ChildWidget()
main.show()
child_win.show()
sys.exit(app.exec_())
代码示例2:显示的是两个独立的窗口 变为 父子窗口 show在后
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
import urllib.request
class ChildWidget(QWidget):
def __init__(self, parent=None, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
print('ChildWidget init')
self.setAttribute(Qt.WA_StyledBackground, True)
self.setWindowTitle('ChildWidget 模板')
self.top_layout = QHBoxLayout()
self.setLayout(self.top_layout)
self.resize(500, 300)
self.left_widget = QWidget()
self.mid_layout = QHBoxLayout()
self.right_widget = QWidget()
self.setObjectName('Top_ChildWidget')
self.setStyleSheet("#Top_ChildWidget{border: 2px solid red;background:rgba(0,0,0,0.2)}")
self.top_layout.addWidget(self.left_widget)
self.top_layout.addLayout(self.mid_layout)
self.top_layout.addWidget(self.right_widget)
self.next_btn = QPushButton('下一页')
self.back_btn = QPushButton('返回')
self.mid_layout.addWidget(self.next_btn)
self.mid_layout.addWidget(self.back_btn)
class MainWidget(QWidget):
main_widget_signal = pyqtSignal(dict)
def __init__(self, parent=None, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
print("MainWidget init")
self.setAttribute(Qt.WA_StyledBackground, True)
self.setWindowTitle('MainWidget 模板')
#print(type(self).__name__)
self.top_layout = QVBoxLayout()
self.setLayout(self.top_layout)
self.resize(500, 300)
self.dataView = QTableView()
self.model = QStandardItemModel(3, 0, self)
self.model.setHorizontalHeaderItem(0, QStandardItem("姓名"))
self.model.setHorizontalHeaderItem(1, QStandardItem("性别"))
self.model.setHorizontalHeaderItem(2, QStandardItem("体重(kg)"))
self.dataView.setModel(self.model)
self.child_layout = QHBoxLayout()
self.next_btn = QPushButton('下一页')
self.back_btn = QPushButton('返回')
self.child_layout.addWidget(self.next_btn)
self.child_layout.addWidget(self.back_btn)
self.top_layout.addLayout(self.child_layout)
self.top_layout.addWidget(self.dataView)
self.next_btn.clicked.connect(self.slot_next_btn_func)
self.back_btn.clicked.connect(self.slot_back_btn_func)
def slot_next_btn_func(self):
msg_dict = {}
msg_dict['name'] = 'MainWidget'
print('slot_next_btn_func')
msg_dict['action'] = 'next'
self.main_widget_signal.emit(msg_dict)
#print('MainWidget slot_next_btn_func', msg_dict)
def slot_back_btn_func(self):
msg_dict = {}
msg_dict['name'] = 'MainWidget'
msg_dict['action'] = 'back'
self.main_widget_signal.emit(msg_dict)
print('MainWidget slot_back_btn_func', msg_dict)
def slot_call_back_func(my_dict):
print("slot_call_back_func", my_dict)
if __name__ == '__main__':
app = QApplication(sys.argv)
main = MainWidget()
main.main_widget_signal.connect(slot_call_back_func)
child_win = ChildWidget(main)
main.show()
sys.exit(app.exec_())
显示效果:
代码示例3:显示的是两个独立的窗口 变为 父子窗口 show在前
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
import urllib.request
class ChildWidget(QWidget):
def __init__(self, parent=None, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
print('ChildWidget init')
self.setAttribute(Qt.WA_StyledBackground, True)
self.setWindowTitle('ChildWidget 模板')
self.top_layout = QHBoxLayout()
self.setLayout(self.top_layout)
self.resize(500, 300)
self.left_widget = QWidget()
self.mid_layout = QHBoxLayout()
self.right_widget = QWidget()
self.setObjectName('Top_ChildWidget')
self.setStyleSheet("#Top_ChildWidget{border: 2px solid red;background:rgba(0,0,0,0.2)}")
self.top_layout.addWidget(self.left_widget)
self.top_layout.addLayout(self.mid_layout)
self.top_layout.addWidget(self.right_widget)
self.next_btn = QPushButton('下一页')
self.back_btn = QPushButton('返回')
self.mid_layout.addWidget(self.next_btn)
self.mid_layout.addWidget(self.back_btn)
class MainWidget(QWidget):
main_widget_signal = pyqtSignal(dict)
def __init__(self, parent=None, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
print("MainWidget init")
self.setAttribute(Qt.WA_StyledBackground, True)
self.setWindowTitle('MainWidget 模板')
#print(type(self).__name__)
self.top_layout = QVBoxLayout()
self.setLayout(self.top_layout)
self.resize(500, 300)
self.dataView = QTableView()
self.model = QStandardItemModel(3, 0, self)
self.model.setHorizontalHeaderItem(0, QStandardItem("姓名"))
self.model.setHorizontalHeaderItem(1, QStandardItem("性别"))
self.model.setHorizontalHeaderItem(2, QStandardItem("体重(kg)"))
self.dataView.setModel(self.model)
self.child_layout = QHBoxLayout()
self.next_btn = QPushButton('下一页')
self.back_btn = QPushButton('返回')
self.child_layout.addWidget(self.next_btn)
self.child_layout.addWidget(self.back_btn)
self.top_layout.addLayout(self.child_layout)
self.top_layout.addWidget(self.dataView)
self.next_btn.clicked.connect(self.slot_next_btn_func)
self.back_btn.clicked.connect(self.slot_back_btn_func)
def slot_next_btn_func(self):
msg_dict = {}
msg_dict['name'] = 'MainWidget'
print('slot_next_btn_func')
msg_dict['action'] = 'next'
self.main_widget_signal.emit(msg_dict)
#print('MainWidget slot_next_btn_func', msg_dict)
def slot_back_btn_func(self):
msg_dict = {}
msg_dict['name'] = 'MainWidget'
msg_dict['action'] = 'back'
self.main_widget_signal.emit(msg_dict)
print('MainWidget slot_back_btn_func', msg_dict)
def slot_call_back_func(my_dict):
print("slot_call_back_func", my_dict)
if __name__ == '__main__':
app = QApplication(sys.argv)
main = MainWidget()
main.main_widget_signal.connect(slot_call_back_func)
main.show()
child_win = ChildWidget(main)
#main.show()
sys.exit(app.exec_())
代码示例4:显示的是两个独立的窗口 变为 父子窗口 子窗口show
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
import urllib.request
class ChildWidget(QWidget):
def __init__(self, parent=None, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
print('ChildWidget init')
self.setAttribute(Qt.WA_StyledBackground, True)
self.setWindowTitle('ChildWidget 模板')
self.top_layout = QHBoxLayout()
self.setLayout(self.top_layout)
self.resize(500, 300)
self.left_widget = QWidget()
self.mid_layout = QHBoxLayout()
self.right_widget = QWidget()
self.setObjectName('Top_ChildWidget')
self.setStyleSheet("#Top_ChildWidget{border: 2px solid red;background:rgba(0,0,0,0.2)}")
self.top_layout.addWidget(self.left_widget)
self.top_layout.addLayout(self.mid_layout)
self.top_layout.addWidget(self.right_widget)
self.next_btn = QPushButton('下一页')
self.back_btn = QPushButton('返回')
self.mid_layout.addWidget(self.next_btn)
self.mid_layout.addWidget(self.back_btn)
class MainWidget(QWidget):
main_widget_signal = pyqtSignal(dict)
def __init__(self, parent=None, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
print("MainWidget init")
self.setAttribute(Qt.WA_StyledBackground, True)
self.setWindowTitle('MainWidget 模板')
#print(type(self).__name__)
self.top_layout = QVBoxLayout()
self.setLayout(self.top_layout)
self.resize(500, 300)
self.dataView = QTableView()
self.model = QStandardItemModel(3, 0, self)
self.model.setHorizontalHeaderItem(0, QStandardItem("姓名"))
self.model.setHorizontalHeaderItem(1, QStandardItem("性别"))
self.model.setHorizontalHeaderItem(2, QStandardItem("体重(kg)"))
self.dataView.setModel(self.model)
self.child_layout = QHBoxLayout()
self.next_btn = QPushButton('下一页')
self.back_btn = QPushButton('返回')
self.child_layout.addWidget(self.next_btn)
self.child_layout.addWidget(self.back_btn)
self.top_layout.addLayout(self.child_layout)
self.top_layout.addWidget(self.dataView)
self.next_btn.clicked.connect(self.slot_next_btn_func)
self.back_btn.clicked.connect(self.slot_back_btn_func)
def slot_next_btn_func(self):
msg_dict = {}
msg_dict['name'] = 'MainWidget'
print('slot_next_btn_func')
msg_dict['action'] = 'next'
self.main_widget_signal.emit(msg_dict)
#print('MainWidget slot_next_btn_func', msg_dict)
def slot_back_btn_func(self):
msg_dict = {}
msg_dict['name'] = 'MainWidget'
msg_dict['action'] = 'back'
self.main_widget_signal.emit(msg_dict)
print('MainWidget slot_back_btn_func', msg_dict)
def slot_call_back_func(my_dict):
print("slot_call_back_func", my_dict)
if __name__ == '__main__':
app = QApplication(sys.argv)
main = MainWidget()
main.main_widget_signal.connect(slot_call_back_func)
main.show()
child_win = ChildWidget(main)
#main.show()
child_win.show()
sys.exit(app.exec_())
代码示例5:显示的是 父子窗口 子窗口show 向下move
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
import urllib.request
class ChildWidget(QWidget):
def __init__(self, parent=None, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
print('ChildWidget init')
self.setAttribute(Qt.WA_StyledBackground, True)
self.setWindowTitle('ChildWidget 模板')
self.top_layout = QHBoxLayout()
self.setLayout(self.top_layout)
self.resize(500, 300)
self.left_widget = QWidget()
self.mid_layout = QHBoxLayout()
self.right_widget = QWidget()
self.setObjectName('Top_ChildWidget')
self.setStyleSheet("#Top_ChildWidget{border: 2px solid red;background:rgba(0,0,0,0.2)}")
self.top_layout.addWidget(self.left_widget)
self.top_layout.addLayout(self.mid_layout)
self.top_layout.addWidget(self.right_widget)
self.next_btn = QPushButton('下一页')
self.back_btn = QPushButton('返回')
self.mid_layout.addWidget(self.next_btn)
self.mid_layout.addWidget(self.back_btn)
class MainWidget(QWidget):
main_widget_signal = pyqtSignal(dict)
def __init__(self, parent=None, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
print("MainWidget init")
self.setAttribute(Qt.WA_StyledBackground, True)
self.setWindowTitle('MainWidget 模板')
#print(type(self).__name__)
self.top_layout = QVBoxLayout()
self.setLayout(self.top_layout)
self.resize(500, 300)
self.dataView = QTableView()
self.model = QStandardItemModel(3, 0, self)
self.model.setHorizontalHeaderItem(0, QStandardItem("姓名"))
self.model.setHorizontalHeaderItem(1, QStandardItem("性别"))
self.model.setHorizontalHeaderItem(2, QStandardItem("体重(kg)"))
self.dataView.setModel(self.model)
self.child_layout = QHBoxLayout()
self.next_btn = QPushButton('下一页')
self.back_btn = QPushButton('返回')
self.child_layout.addWidget(self.next_btn)
self.child_layout.addWidget(self.back_btn)
self.top_layout.addLayout(self.child_layout)
self.top_layout.addWidget(self.dataView)
self.next_btn.clicked.connect(self.slot_next_btn_func)
self.back_btn.clicked.connect(self.slot_back_btn_func)
def slot_next_btn_func(self):
msg_dict = {}
msg_dict['name'] = 'MainWidget'
print('slot_next_btn_func')
msg_dict['action'] = 'next'
self.main_widget_signal.emit(msg_dict)
#print('MainWidget slot_next_btn_func', msg_dict)
def slot_back_btn_func(self):
msg_dict = {}
msg_dict['name'] = 'MainWidget'
msg_dict['action'] = 'back'
self.main_widget_signal.emit(msg_dict)
print('MainWidget slot_back_btn_func', msg_dict)
def slot_call_back_func(my_dict):
print("slot_call_back_func", my_dict)
if __name__ == '__main__':
app = QApplication(sys.argv)
main = MainWidget()
main.main_widget_signal.connect(slot_call_back_func)
main.show()
child_win = ChildWidget(main)
#main.show()
child_win.show()
child_win.move(0, main.height()/3)
sys.exit(app.exec_())
上面的可以点击 ,下面的也可以点击了
子控件被隐藏的 1/3 窗体去哪儿了,会影响其他的,紧挨着的 其他应用的窗口不?
代码示例6:显示的是 父子窗口 子窗口show 动画
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
import urllib.request
class ChildWidget(QWidget):
child_widget_signal = pyqtSignal(dict)
def __init__(self, parent=None, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
print('ChildWidget init')
self.setAttribute(Qt.WA_StyledBackground, True)
self.setWindowTitle('ChildWidget 模板')
self.top_layout = QHBoxLayout()
self.setLayout(self.top_layout)
self.resize(500, 300)
self.left_widget = QWidget()
self.mid_layout = QHBoxLayout()
self.right_widget = QWidget()
self.setObjectName('Top_ChildWidget')
self.setStyleSheet("#Top_ChildWidget{border: 2px solid red;background:rgba(0,0,0,0.2)}")
self.top_layout.addWidget(self.left_widget)
self.top_layout.addLayout(self.mid_layout)
self.top_layout.addWidget(self.right_widget)
self.next_btn = QPushButton('下一页')
self.back_btn = QPushButton('返回')
self.mid_layout.addWidget(self.next_btn)
self.mid_layout.addWidget(self.back_btn)
self.next_btn.clicked.connect(self.slot_next_btn_func)
def slot_next_btn_func(self):
pass
msg_dict = dict()
msg_dict['name'] = 'ChildWidget'
msg_dict['action'] = 'next'
self.child_widget_signal.emit(msg_dict)
class MainWidget(QWidget):
main_widget_signal = pyqtSignal(dict)
def __init__(self, parent=None, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
print("MainWidget init")
self.setAttribute(Qt.WA_StyledBackground, True)
self.setWindowTitle('MainWidget 模板')
#print(type(self).__name__)
self.top_layout = QVBoxLayout()
self.setLayout(self.top_layout)
self.resize(500, 300)
self.dataView = QTableView()
self.model = QStandardItemModel(3, 0, self)
self.model.setHorizontalHeaderItem(0, QStandardItem("姓名"))
self.model.setHorizontalHeaderItem(1, QStandardItem("性别"))
self.model.setHorizontalHeaderItem(2, QStandardItem("体重(kg)"))
self.dataView.setModel(self.model)
self.child_layout = QHBoxLayout()
self.next_btn = QPushButton('下一页')
self.back_btn = QPushButton('返回')
self.child_layout.addWidget(self.next_btn)
self.child_layout.addWidget(self.back_btn)
self.top_layout.addLayout(self.child_layout)
self.top_layout.addWidget(self.dataView)
self.next_btn.clicked.connect(self.slot_next_btn_func)
self.back_btn.clicked.connect(self.slot_back_btn_func)
def slot_next_btn_func(self):
msg_dict = {}
msg_dict['name'] = 'MainWidget'
print('slot_next_btn_func')
msg_dict['action'] = 'next'
self.main_widget_signal.emit(msg_dict)
#print('MainWidget slot_next_btn_func', msg_dict)
def slot_back_btn_func(self):
msg_dict = {}
msg_dict['name'] = 'MainWidget'
msg_dict['action'] = 'back'
self.main_widget_signal.emit(msg_dict)
print('MainWidget slot_back_btn_func', msg_dict)
def slot_call_back_func(my_dict):
print("slot_call_back_func", my_dict)
animation = QPropertyAnimation(child_win)
animation.setTargetObject(child_win)
animation.setPropertyName(b"pos")
x_start = 0
y_start = child_win.height()
point_start = QPoint(x_start, y_start)
animation.setStartValue(point_start)
x_end = 0
y_end = 0
point_end = QPoint(x_end, y_end)
animation.setEndValue(point_end)
animation.setDuration(1000)
animation.start(QAbstractAnimation.DeleteWhenStopped)
animation.setEasingCurve(QEasingCurve.OutBounce)
def slot_child_widget_signal_func(my_dict):
pass
child_win.move(0, main.height())
if __name__ == '__main__':
app = QApplication(sys.argv)
main = MainWidget()
main.main_widget_signal.connect(slot_call_back_func)
main.show()
child_win = ChildWidget(main)
#main.show()
child_win.show()
child_win.move(0, main.height())
child_win.child_widget_signal.connect(slot_child_widget_signal_func)
sys.exit(app.exec_())
显示效果: