从 ui 文件加载的 PySide2 QMainWindow 未触发 window 事件
PySide2 QMainWindow loaded from ui file not triggering window events
我正在从 .ui 文件加载 QMainWindow - 它工作正常,但不会触发 window 调整大小等事件。我真的不知道我做错了什么。
这是代码:
class TestWindow(QMainWindow):
def __init__(self, parent=None):
super(TestWindow, self).__init__(parent)
loader = QUiLoader()
file = QFile(abspath("ui/mainwindow.ui"))
file.open(QFile.ReadOnly)
self.window = loader.load(file, parent)
file.close()
self.window.show()
def resizeEvent(self, event):
print "resize"
app = QApplication(sys.argv)
test = TestWindow()
sys.exit(app.exec_())
可以找到 .ui 文件 here.
看来你是一头雾水,为了让你明白调用TestWindow的测试方法:
import os
from PySide2 import QtCore, QtWidgets, QtUiTools
class TestWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(TestWindow, self).__init__(parent)
loader = QtUiTools.QUiLoader()
file = QtCore.QFile(os.path.abspath("ui/mainwindow.ui"))
file.open(QtCore.QFile.ReadOnly)
self.window = loader.load(file, parent)
file.close()
self.window.show()
self.show()
def resizeEvent(self, event):
print("resize")
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
test = TestWindow()
sys.exit(app.exec_())
如果你移动小 window 观察事件被触发。
为什么会这样?:QUiLoader 基于 .ui 创建一个小部件,这与 PyQt5 的 uic.loadUi()
或 ui.loadUiType()
不同不加载主小部件,而是创建一个新的小部件,这可能是一个缺点,但这就是限制。
所以根据你想做什么,有几种选择:
- 要用
QUiLoader()
加载 .ui 没有必要将 TestWindow
作为父级,因为它可以是 QObject
通过事件过滤器。
import os
from PySide2 import QtCore, QtWidgets, QtUiTools
class Manager(QtCore.QObject):
def __init__(self, parent_widget=None, parent=None):
super(Manager, self).__init__(parent)
loader = QtUiTools.QUiLoader()
file = QtCore.QFile(os.path.abspath("ui/mainwindow.ui"))
file.open(QtCore.QFile.ReadOnly)
self.window = loader.load(file, parent_widget)
file.close()
self.window.installEventFilter(self)
self.window.show()
self.setParent(self.window)
self.window.destroyed.connect(lambda *args: print(">>>>>>"))
def eventFilter(self, obj, event):
if event.type() == QtCore.QEvent.Close and self.window is obj:
self.window.removeEventFilter(self)
elif event.type() == QtCore.QEvent.Resize and self.window is obj:
print("resize")
return super(Manager, self).eventFilter(obj, event)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
test = Manager()
sys.exit(app.exec_())
- 另一种选择是使 self.widow 成为中心部件(.ui 中的 QMainWindow 将成为 TestWindow 的中心部件,因此调整大小将来自 TestWindow 而不是来自 .ui 但好像 .ui 的大小发生了变化,TestWindow 也会发生同样的情况):
import os
from PySide2 import QtCore, QtWidgets, QtUiTools
class TestWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(TestWindow, self).__init__(parent)
loader = QtUiTools.QUiLoader()
file = QtCore.QFile(os.path.abspath("ui/mainwindow.ui"))
if file.open(QtCore.QFile.ReadOnly):
self.window = loader.load(file, parent)
file.close()
self.setCentralWidget(self.window)
self.show()
def resizeEvent(self, event):
print("resize")
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
test = TestWindow()
sys.exit(app.exec_())
- 以前的方法只是用来通知你事件,但如果你想覆盖,最好使用 pyuic 将 .ui 转换为 .py
我正在从 .ui 文件加载 QMainWindow - 它工作正常,但不会触发 window 调整大小等事件。我真的不知道我做错了什么。
这是代码:
class TestWindow(QMainWindow):
def __init__(self, parent=None):
super(TestWindow, self).__init__(parent)
loader = QUiLoader()
file = QFile(abspath("ui/mainwindow.ui"))
file.open(QFile.ReadOnly)
self.window = loader.load(file, parent)
file.close()
self.window.show()
def resizeEvent(self, event):
print "resize"
app = QApplication(sys.argv)
test = TestWindow()
sys.exit(app.exec_())
可以找到 .ui 文件 here.
看来你是一头雾水,为了让你明白调用TestWindow的测试方法:
import os
from PySide2 import QtCore, QtWidgets, QtUiTools
class TestWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(TestWindow, self).__init__(parent)
loader = QtUiTools.QUiLoader()
file = QtCore.QFile(os.path.abspath("ui/mainwindow.ui"))
file.open(QtCore.QFile.ReadOnly)
self.window = loader.load(file, parent)
file.close()
self.window.show()
self.show()
def resizeEvent(self, event):
print("resize")
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
test = TestWindow()
sys.exit(app.exec_())
如果你移动小 window 观察事件被触发。
为什么会这样?:QUiLoader 基于 .ui 创建一个小部件,这与 PyQt5 的 uic.loadUi()
或 ui.loadUiType()
不同不加载主小部件,而是创建一个新的小部件,这可能是一个缺点,但这就是限制。
所以根据你想做什么,有几种选择:
- 要用
QUiLoader()
加载 .ui 没有必要将TestWindow
作为父级,因为它可以是QObject
通过事件过滤器。
import os
from PySide2 import QtCore, QtWidgets, QtUiTools
class Manager(QtCore.QObject):
def __init__(self, parent_widget=None, parent=None):
super(Manager, self).__init__(parent)
loader = QtUiTools.QUiLoader()
file = QtCore.QFile(os.path.abspath("ui/mainwindow.ui"))
file.open(QtCore.QFile.ReadOnly)
self.window = loader.load(file, parent_widget)
file.close()
self.window.installEventFilter(self)
self.window.show()
self.setParent(self.window)
self.window.destroyed.connect(lambda *args: print(">>>>>>"))
def eventFilter(self, obj, event):
if event.type() == QtCore.QEvent.Close and self.window is obj:
self.window.removeEventFilter(self)
elif event.type() == QtCore.QEvent.Resize and self.window is obj:
print("resize")
return super(Manager, self).eventFilter(obj, event)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
test = Manager()
sys.exit(app.exec_())
- 另一种选择是使 self.widow 成为中心部件(.ui 中的 QMainWindow 将成为 TestWindow 的中心部件,因此调整大小将来自 TestWindow 而不是来自 .ui 但好像 .ui 的大小发生了变化,TestWindow 也会发生同样的情况):
import os
from PySide2 import QtCore, QtWidgets, QtUiTools
class TestWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(TestWindow, self).__init__(parent)
loader = QtUiTools.QUiLoader()
file = QtCore.QFile(os.path.abspath("ui/mainwindow.ui"))
if file.open(QtCore.QFile.ReadOnly):
self.window = loader.load(file, parent)
file.close()
self.setCentralWidget(self.window)
self.show()
def resizeEvent(self, event):
print("resize")
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
test = TestWindow()
sys.exit(app.exec_())
- 以前的方法只是用来通知你事件,但如果你想覆盖,最好使用 pyuic 将 .ui 转换为 .py