PyQt5拖拽问题:如何识别当前被拖拽的按钮?
多按钮拖拽异常的解决方案
问题现象
- 点击Spawn按钮可生成依次命名为Table 1、Table 2的按钮
- 右键按住拖动按钮可移动,但生成Table 2后,拖拽Table 1时移动的却是Table 2,且Table 1失去拖拽功能
问题根源
mainMenu类的addTable方法用self.btn存储生成的按钮,每次生成新按钮都会覆盖该变量,导致始终仅记录最后一个生成的按钮;同时拖拽的drop逻辑依赖这个全局变量,所以拖拽操作只会作用在最后一个按钮上。
修复方案
将拖拽的完整逻辑封装到barTable类内部,让每个按钮独立处理自身的拖拽事件,无需主窗口记录当前操作的按钮:
- 移除mainMenu类中用于存储单个按钮的
self.btn变量,以及主窗口的dragEnterEvent和dropEvent方法 - 在barTable类中开启拖拽接收,并重写
dragEnterEvent和dropEvent,让按钮自己处理拖拽位置更新 - 确保每个按钮的拖拽逻辑独立,互不干扰
修改后的完整代码
import sys from PyQt5.QtCore import Qt, QMimeData, QPoint from PyQt5.QtGui import QDrag from PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication class mainMenu(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setGeometry(300, 300, 550, 450) self.spawnButton = QPushButton(self) self.spawnButton.move(150, 150) self.spawnButton.show() self.spawnButton.setText('Spawn') self.spawnButton.clicked.connect(self.addTable) def addTable(self): barTable(self) class barTable(QPushButton): allTables = [] def __init__(self, win): super().__init__(win) self.setGeometry(300, 300, 60, 50) self.allTables.append(self) self.setText("Table\n" + str(len(self.allTables))) self.setAcceptDrops(True) self.show() def mouseMoveEvent(self, e): if e.buttons() != Qt.RightButton: return mimeData = QMimeData() # 存储拖拽时鼠标相对于按钮左上角的偏移 mimeData.setData("hotSpot", f"{e.x()},{e.y()}".encode()) drag = QDrag(self) drag.setMimeData(mimeData) drag.setHotSpot(e.pos() - self.rect().topLeft()) drag.exec_(Qt.MoveAction) def dragEnterEvent(self, e): e.accept() def dropEvent(self, e): # 读取存储的偏移量 hot_spot_data = e.mimeData().data("hotSpot").decode().split(",") hot_spot = QPoint(int(hot_spot_data[0]), int(hot_spot_data[1])) # 计算按钮需要移动到的位置 position = e.pos() - hot_spot self.move(position) e.setDropAction(Qt.MoveAction) e.accept() def main(): app = QApplication(sys.argv) ex = mainMenu() ex.show() app.exec_() if __name__ == '__main__': main()
说明
修改后每个按钮独立处理自身的拖拽逻辑,主窗口不再需要管理按钮的拖拽状态,无论生成多少个按钮,都能正常独立拖拽,不会出现互相干扰的情况。
内容的提问来源于stack exchange,提问作者Solomon Baker
相关产品推荐
相关产品推荐

