需求:
在PYQT5中土陪,點(diǎn)擊主窗口中的按鈕昼汗,彈出子窗口。
測試代碼:
例1:
在主窗口添加按鈕鬼雀,并把按鈕信號(hào)關(guān)聯(lián)槽顷窒,在槽函數(shù)中創(chuàng)建子窗口對(duì)象賦值到普通變量,并調(diào)用其 show 方法源哩。
from PyQt5.QtWidgets import *
import sys
class Main(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("主窗口")
button = QPushButton("彈出子窗", self)
button.clicked.connect(self.show_child)
def show_child(self):
child_window = Child()
child_window.show()
class Child(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("我是子窗口啊")
# 運(yùn)行主窗口
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Main()
window.show()
sys.exit(app.exec_())
運(yùn)行結(jié)果: 該段代碼運(yùn)行后鞋吉,點(diǎn)擊主窗口中的按鈕,子窗口一閃而過励烦。
例2:
在主窗口添加按鈕谓着,并把按鈕信號(hào)關(guān)聯(lián)槽,在槽函數(shù)中創(chuàng)建子窗口對(duì)象并賦值為對(duì)象屬性坛掠,并調(diào)用其 show 方法赊锚。
from PyQt5.QtWidgets import *
import sys
class Main(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("主窗口")
button = QPushButton("彈出子窗", self)
button.clicked.connect(self.show_child)
def show_child(self):
self.child_window = Child()
self.child_window.show()
class Child(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("我是子窗口啊")
# 運(yùn)行主窗口
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Main()
window.show()
sys.exit(app.exec_())
運(yùn)行結(jié)果: 該段代碼運(yùn)行后,點(diǎn)擊主窗口中的按鈕屉栓,子窗口正常打開舷蒲,重復(fù)點(diǎn)擊按鈕,子窗口重復(fù)彈出友多。
例3:
在主窗口init方法中創(chuàng)建子窗口對(duì)象并賦值為對(duì)象屬性牲平,添加按鈕,并把按鈕信號(hào)關(guān)聯(lián)槽夷陋,在槽函數(shù)中調(diào)用子窗口對(duì)象的 show 方法欠拾。
from PyQt5.QtWidgets import *
import sys
class Main(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("主窗口")
button = QPushButton("彈出子窗", self)
button.clicked.connect(self.show_child)
self.child_window = Child()
def show_child(self):
self.child_window.show()
class Child(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("我是子窗口啊")
# 運(yùn)行主窗口
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Main()
window.show()
sys.exit(app.exec_())
運(yùn)行結(jié)果: 重復(fù)點(diǎn)擊按鈕,子窗口不重復(fù)彈出骗绕。
例4:
把例1的show()方法改為exec()方法
from PyQt5.QtWidgets import *
import sys
class Main(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("主窗口")
button = QPushButton("彈出子窗", self)
button.clicked.connect(self.show_child)
def show_child(self):
child_window = Child()
child_window.exec()
class Child(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("我是子窗口啊")
# 運(yùn)行主窗口
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Main()
window.show()
sys.exit(app.exec_())
運(yùn)行結(jié)果:子窗口順利彈出藐窄,且不能重新選擇父窗口
結(jié)論:
例2比例1僅僅多了一個(gè)self怎么就運(yùn)行正常了呢?
例4與例1僅改了一個(gè)一個(gè)方法怎么又能正常顯示了呢酬土?
這里涉及到一個(gè)概念 模式對(duì)話框 與 非模式對(duì)話框 (modeless dialog | modal dialog)
模式對(duì)話框荆忍,就是在彈出窗口的時(shí)候,整個(gè)程序就被鎖定了撤缴,處于等待狀態(tài)刹枉,直到對(duì)話框被關(guān)閉。這時(shí)往往是需要對(duì)話框的返回值進(jìn)行下面的操作屈呕。如:確認(rèn)窗口(選擇“是”或“否”)微宝。
非模式對(duì)話框,在調(diào)用彈出窗口之后虎眨,調(diào)用即刻返回蟋软,繼續(xù)下面的操作。這里只是一個(gè)調(diào)用指令的發(fā)出嗽桩,不等待也不做任何處理岳守。如:查找框。
show() ------ modeless dialog
exec() ------- modal dialog
- 例1中 子窗口 通過 show() 方法顯示碌冶,為非模態(tài)窗口湿痢,它的實(shí)例為父窗口show_child()方法中的局部變量,當(dāng)窗口顯示后扑庞,父窗口的show_child()方法繼續(xù)執(zhí)行譬重,當(dāng)方法運(yùn)行完后,python的回收機(jī)制就把局部變量銷毀了嫩挤,相當(dāng)于子窗口實(shí)例被銷毀害幅,故子窗口一閃而過;
- 例2中 子窗口實(shí)例為 主窗口類的變量岂昭,當(dāng)show_child()方法運(yùn)行完后以现,主窗口對(duì)象依舊存在,子窗口實(shí)例也存在约啊,故子窗口正常顯示邑遏,但是每一次運(yùn)行槽函數(shù)都會(huì)重新創(chuàng)建子窗口對(duì)象;
- 例3中 子窗口實(shí)例為 主窗口類的變量恰矩,當(dāng)show_child()方法運(yùn)行完后记盒,主窗口對(duì)象依舊存在,子窗口實(shí)例也存在外傅,故子窗口正常顯示纪吮,每一次show_child()函數(shù)俩檬,重新調(diào)用子窗口對(duì)象show_child()方法,不會(huì)創(chuàng)建新窗口碾盟,且可隨意在父棚辽,子窗口間切換;
- 例3中 子窗口 通過 exec() 方法顯示冰肴,為模態(tài)窗口屈藐,雖然他為父窗口show_child()方法中的局部變量,由于阻塞的機(jī)制熙尉,父窗口show_child()并沒有繼續(xù)執(zhí)行联逻,故其不會(huì)像 例1 中 一閃而過,且不能在父检痰,子窗口間切換包归;