Wayland下Qt QWidget.move(x,y)无法更新组件位置问题求助
问题诊断与修复
核心问题
你的QMovableResizableWidget拖拽失效有两个关键原因:
- 坐标转换错误:无父级的顶级窗口,
self.pos()本身就是屏幕全局坐标,你用self.mapToGlobal(self.pos())会重复转换,得到错误的位置值。 - 拖拽基准未更新:每次移动后没有更新鼠标的初始基准点,导致后续偏移计算不断累加初始差值,最终窗口位置计算混乱,视觉上表现为不移动。
修复后的代码
import sys from PySide6 import QtWidgets, QtCore, QtGui Qt = QtCore.Qt QMouseEvent = QtGui.QMouseEvent QWidget = QtWidgets.QWidget QEvent = QtCore.QEvent CursorShape = Qt.CursorShape QApplication = QtWidgets.QApplication WindowTypes = Qt.WindowType QPoint = QtCore.QPoint class QCustomWidget(QWidget): def __init__(self, p, f): super().__init__(p, f) self.setMouseTracking(True) class QResizableWidget(QCustomWidget): def __init__(self,p, f): super().__init__(p, f) pass class QMovableResizableWidget(QCustomWidget): def __init__(self,p, f): super().__init__(p, f) self.__moveInitLoc = None self.__isDragging = False self.setAttribute(Qt.WidgetAttribute.WA_MouseTracking, True) def event(self, ev): if isinstance(ev, QMouseEvent): if ( ev.type() == QEvent.Type.MouseButtonPress and ev.button() == Qt.MouseButton.LeftButton ): self.__isDragging = True # 同时记录点击时的窗口位置和鼠标全局位置 self.__moveInitLoc = (self.pos(), ev.globalPos()) elif ( ev.type() == QEvent.Type.MouseMove and self.__isDragging ): if self.__moveInitLoc is not None: self.setCursor(CursorShape.DragMoveCursor) window_init_pos, mouse_init_pos = self.__moveInitLoc # 计算鼠标偏移,直接用初始窗口位置加偏移得到新位置 diff = ev.globalPos() - mouse_init_pos new_pos = window_init_pos + diff self.move(new_pos) # 更新基准点,避免后续计算偏移累加 self.__moveInitLoc = (new_pos, ev.globalPos()) return True elif ev.type() == QEvent.Type.MouseButtonRelease: self.__isDragging = False self.__moveInitLoc = None self.unsetCursor() return super().event(ev) if __name__ == "__main__": app = QApplication(sys.argv) app.setStyle("Fusion") window = QMovableResizableWidget(None, WindowTypes.Window | WindowTypes.FramelessWindowHint) window.resize(300, 300) window.show() sys.exit(app.exec())
关键修改点
- 调整基准数据存储:将
__moveInitLoc改为存储元组(窗口初始全局位置, 鼠标初始全局位置),避免坐标转换错误。 - 修正位置计算逻辑:直接通过
初始窗口位置 + 鼠标偏移量得到新位置,无需多余的坐标转换。 - 实时更新基准点:每次移动后更新
__moveInitLoc为当前窗口位置和鼠标位置,确保后续拖拽的偏移计算准确。
另外,关于你提到的直接调用move(x,y)无效的情况:修正拖拽逻辑后,顶级窗口直接调用move也能正常生效,因为问题根源在拖拽逻辑的坐标计算错误,而非move方法本身。
内容的提问来源于stack exchange,提问作者razor_chk
相关产品推荐
相关产品推荐

