PySide2关于QUiLoader无法响应event的解决方法
测试1
去标题和边框后是无法移动的 ,但如果定义移动事件的话便可以移动窗口。所以可以通过窗口是否移动来判断我们的ui是否响应了事件。
代码如下:
//
from PySide2.QtUiTools import QUiLoader
from PySide2.QtWidgets import *
from PySide2.QtCore import *
from PySide2.QtGui import *
from traceback import print_exc
class Mainwindow(QWidget):
def __init__(self):
super(Mainwindow, self).__init__()
self.ui()
def ui(self):
self.test = QUiLoader().load('./ui/test用.ui')
self.test.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint) # 置顶,且去掉边框
# 鼠标移动事件
def mouseMoveEvent(self, e: QMouseEvent):
try:
self._endPos = e.pos() - self._startPos
self.move(self.pos() + self._endPos)
print(self.pos(),self._endPos) #输出坐标
except Exception:
pass
# 鼠标按下事件
def mousePressEvent(self, e: QMouseEvent):
try:
if e.button() == Qt.LeftButton:
self._isTracking = True
self._startPos = QPoint(e.x(), e.y())
except Exception:
print_exc()
# 鼠标松开事件
def mouseReleaseEvent(self, e: QMouseEvent):
try:
if e.button() == Qt.LeftButton:
self._isTracking = False
self._startPos = None
self._endPos = None
except Exception:
print_exc()
if __name__ == '__main__':
app = QApplication([])
window = Mainwindow()
window.test.show()
app.exec_();
结果:无法拖动,因此也无法输出坐标,故通过QUiLoader导入的ui并不能响应事件。
问题分析:
QuiLoader是使用组合的方法将控件塞入内部命名空间,并没有真正创建一个顶级类,因此无法响应事件。解决方式为改写QuiLoader函数。
下面展示改写 UiLoader
。
class UiLoader(QtUiTools.QUiLoader):
_baseinstance = None
def createWidget(self, classname, parent=None, name=''):
if parent is None and self._baseinstance is not None:
widget = self._baseinstance
else:
widget = super(UiLoader, self).createWidget(classname, parent, name)
if self._baseinstance is not None:
setattr(self._baseinstance, name, widget)
return widget
def loadUi(self, uifile, baseinstance=None):
self._baseinstance = baseinstance
widget = self.load(uifile)
QtCore.QMetaObject.connectSlotsByName(widget)
return widget;
测试2
改写代码,注意UiLoader不能命名为QuiLoader,注意要用UiLoader().loadUi,不要打成.load。
from PySide2.QtWidgets import *
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2 import QtCore,QtUiTools
from traceback import print_exc
class UiLoader(QtUiTools.QUiLoader):
_baseinstance = None
def createWidget(self, classname, parent=None, name=''):
if parent is None and self._baseinstance is not None:
widget = self._baseinstance
else:
widget = super(UiLoader, self).createWidget(classname, parent, name)
if self._baseinstance is not None:
setattr(self._baseinstance, name, widget)
return widget
def loadUi(self, uifile, baseinstance=None):
self._baseinstance = baseinstance
widget = self.load(uifile)
QtCore.QMetaObject.connectSlotsByName(widget)
return widget
class Mainwindow(QWidget):
def __init__(self):
super(Mainwindow, self).__init__()
self.ui()
def ui(self):
self.test = UiLoader().loadUi('./ui/test用.ui', self) #这里是改的地方
self.test.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint) # 置顶,且去掉边框
# 鼠标移动事件
def mouseMoveEvent(self, e: QMouseEvent):
try:
self._endPos = e.pos() - self._startPos
self.move(self.pos() + self._endPos)
print(self.pos(),self._endPos)
except Exception:
pass
# 鼠标按下事件
def mousePressEvent(self, e: QMouseEvent):
try:
if e.button() == Qt.LeftButton:
self._isTracking = True
self._startPos = QPoint(e.x(), e.y())
except Exception:
print_exc()
# 鼠标松开事件
def mouseReleaseEvent(self, e: QMouseEvent):
try:
if e.button() == Qt.LeftButton:
self._isTracking = False
self._startPos = None
self._endPos = None
except Exception:
print_exc()
if __name__ == '__main__':
app = QApplication([])
window = Mainwindow()
window.test.show()
app.exec_()
结果:成功移动了我们动态导入的ui,同时也打出了移动后的坐标