[PyQt] Drag items across tabs - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: GUI (https://python-forum.io/forum-10.html) +--- Thread: [PyQt] Drag items across tabs (/thread-20817.html) |
Drag items across tabs - Alfalfa - Sep-01-2019 When a dragged item hovers on a tab, I want the view to switch on this tab. The problem is two fold; 1. How to trigger new events once the mouse entered the tagBar 2. How to know which tab is being hovered I tried subclassing the QTabBar, and catching dragMoveEvent, but the event is never triggered. Then I tried to reset or ignore the dragEnterEvent, so it might be trigered again without leaving the tabBar. What I tried are the commented lines below; #!/usr/bin/python3 import sys from PyQt5 import QtCore, QtGui, QtWidgets class TabBar(QtWidgets.QTabBar): def __init__(self, parent): super().__init__() self.setAcceptDrops(True) def dragEnterEvent(self, event): print("enter", event) #event.ignore() #QtCore.QCoreApplication.postEvent(self, QtGui.QDragLeaveEvent()) #QtCore.QCoreApplication.sendEvent(self, QtGui.QDragLeaveEvent()) #QtCore.QObject.event(self, QtGui.QDragLeaveEvent()) #self.dragLeaveEvent(QtGui.QDragLeaveEvent()) # This event is never called def dragMoveEvent(self, event): print("move", event) class TabWidget(QtWidgets.QTabWidget): def __init__(self, parent): super().__init__() tab1 = QtWidgets.QTreeWidget() self.setTabBar(TabBar(self)) self.addTab(tab1, "1st tab") self.addTab(QtWidgets.QTreeWidget(), "2nd tab") self.addTab(QtWidgets.QTreeWidget(), "3rd tab") item = QtWidgets.QTreeWidgetItem() item.setText(0, "drag me") tab1.addTopLevelItem(item) tab1.setDragDropMode(QtWidgets.QAbstractItemView.DragOnly) class Main(QtWidgets.QMainWindow): def __init__(self, parent): super().__init__() self.ui = QtWidgets.QWidget(self) self.ui.tab = TabWidget(self) self.ui.layout = QtWidgets.QVBoxLayout() self.ui.layout.addWidget(self.ui.tab) self.ui.setLayout(self.ui.layout) self.setCentralWidget(self.ui) self.show() if __name__== '__main__': app = QtWidgets.QApplication(sys.argv) gui = Main(app) sys.exit(app.exec_())I wonder if this is possible to do, as the tabBar is seen as a single object containing all the tabs, and I don't know how to access them directly. Any ideas? RE: Drag items across tabs; how to enable individuals drag events for each tab - Axel_Erfurt - Sep-01-2019 look at this example on github It shows how to drag/drop/move between TreeWidgets RE: Drag items across tabs; how to enable individuals drag events for each tab - Alfalfa - Sep-01-2019 Thanks for your reply. Yes I saw this already, but it is not what I am looking for. Accepting a drop in the TreeWidget is easy, but I want the tab to change once it is hovered, just like when something is hovered over tabs in Chrome or Firefox. The problem is that only a single even occur once the drag enter the tagbar, but I couldn't find how todo it for separate tabs. RE: Drag items across tabs; how to enable individuals drag events for each tab - Axel_Erfurt - Sep-01-2019 to get dragMoveEvent printing add to dragEnterEvent: event.accept() I tried it a bit, I can change the tab index with an eventFilter, but it works only after mouse button release. #!/usr/bin/python3 import sys from PyQt5 import QtCore, QtGui, QtWidgets class Main(QtWidgets.QMainWindow): def __init__(self, parent): super().__init__() self.tab1 = QtWidgets.QTreeWidget() self.tab2 = QtWidgets.QTreeWidget() self.tab3 = QtWidgets.QTreeWidget() self.tabIndex = 0 item = QtWidgets.QTreeWidgetItem() item.setText(0, "drag me") self.tab1.addTopLevelItem(item) self.tab1.setDragDropMode(QtWidgets.QAbstractItemView.DragOnly) self.TabBar = QtWidgets.QTabBar() self.ui = QtWidgets.QWidget(self) self.ui.tab = QtWidgets.QTabWidget(self) self.ui.tab.setTabBar(self.TabBar) self.ui.tab.addTab(self.tab1, "1st tab") self.ui.tab.addTab(self.tab2, "2nd tab") self.ui.tab.addTab(self.tab3, "3rd tab") self.tab2.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop) self.tab3.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop) self.ui.layout = QtWidgets.QVBoxLayout() self.ui.layout.addWidget(self.ui.tab) self.ui.setLayout(self.ui.layout) self.setCentralWidget(self.ui) self.TabBar.setCurrentIndex(self.tabIndex) self.mouseHoverOnTabBar() self.setAcceptDrops(True) self.show() def mouseHoverOnTabBar(self): self.ui.tab=self.ui.tab.tabBar() self.ui.tab.setMouseTracking(True) self.ui.tab.installEventFilter(self) def eventFilter(self, obj, event): if obj == self.ui.tab: if event.type() == QtCore.QEvent.Enter: pos = event.pos() self.tabIndex=self.TabBar.tabAt(pos) print("tab index:", self.tabIndex) # self.TabBar.setCurrentIndex (self.tabIndex) # self.TabBar.setTabEnabled(self.tabIndex, True) self.dragEnterEvent(event) event.accept() return True return super().eventFilter(obj, event) def dragEnterEvent(self, event): print("drag enter") # pos = QtGui.QCursor.pos() # self.tabIndex=self.TabBar.tabAt(pos) # print("tab index:", self.tabIndex, "\npos:", pos) self.TabBar.setCurrentIndex (self.tabIndex) event.accept() def dragMoveEvent(self, event): print("drag move enter") event.accept() def hoverEnter(self, event): print ("On Hover") event.accept() if __name__== '__main__': app = QtWidgets.QApplication(sys.argv) gui = Main(app) sys.exit(app.exec_()) RE: Drag items across tabs; how to enable individuals drag events for each tab - Axel_Erfurt - Sep-01-2019 forget the last post. It's so easy setChangeCurrentOnDrag import sys from PyQt5 import QtCore, QtGui, QtWidgets class Main(QtWidgets.QMainWindow): def __init__(self, parent): super().__init__() self.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents) self.tab1 = QtWidgets.QTreeWidget() self.tab2 = QtWidgets.QTreeWidget() self.tab3 = QtWidgets.QTreeWidget() self.tabIndex = 0 item = QtWidgets.QTreeWidgetItem() item.setText(0, "drag me") self.tab1.addTopLevelItem(item) self.tab1.setDragDropMode(QtWidgets.QAbstractItemView.DragOnly) self.TabBar = QtWidgets.QTabBar() self.ui = QtWidgets.QWidget(self) self.ui.tab = QtWidgets.QTabWidget(self) self.ui.tab.setTabBar(self.TabBar) self.ui.tab.addTab(self.tab1, "1st tab") self.ui.tab.addTab(self.tab2, "2nd tab") self.ui.tab.addTab(self.tab3, "3rd tab") self.tab2.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop) self.tab3.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop) self.ui.layout = QtWidgets.QVBoxLayout() self.ui.layout.addWidget(self.ui.tab) self.ui.setLayout(self.ui.layout) self.setCentralWidget(self.ui) self.TabBar.setCurrentIndex(self.tabIndex) self.TabBar.setChangeCurrentOnDrag(True) self.TabBar.setAcceptDrops(True) self.setAcceptDrops(True) self.show() if __name__== '__main__': app = QtWidgets.QApplication(sys.argv) gui = Main(app) sys.exit(app.exec_()) RE: Drag items across tabs; how to enable individuals drag events for each tab - Alfalfa - Sep-01-2019 dragMoveEvent required that event.acceptProposedAction() is called in dragEnterEvent. So by using tabAt(pos) as you suggested, this work: #!/usr/bin/python3 import sys from PyQt5 import QtCore, QtGui, QtWidgets class TabBar(QtWidgets.QTabBar): def __init__(self, parent): super().__init__() self.setAcceptDrops(True) def dragEnterEvent(self, event): event.acceptProposedAction() QtWidgets.QTabBar.dragEnterEvent(self, event) def dragMoveEvent(self, event): pos = event.pos() index = self.tabAt(pos) self.setCurrentIndex(index) class TabWidget(QtWidgets.QTabWidget): def __init__(self, parent): super().__init__() tab1 = QtWidgets.QTreeWidget() self.setTabBar(TabBar(self)) self.addTab(tab1, "1st tab") self.addTab(QtWidgets.QTreeWidget(), "2nd tab") self.addTab(QtWidgets.QTreeWidget(), "3rd tab") item = QtWidgets.QTreeWidgetItem() item.setText(0, "drag me") tab1.addTopLevelItem(item) tab1.setDragDropMode(QtWidgets.QAbstractItemView.DragOnly) class Main(QtWidgets.QMainWindow): def __init__(self, parent): super().__init__() self.ui = QtWidgets.QWidget(self) self.ui.tab = TabWidget(self) self.ui.layout = QtWidgets.QVBoxLayout() self.ui.layout.addWidget(self.ui.tab) self.ui.setLayout(self.ui.layout) self.setCentralWidget(self.ui) self.show() if __name__== '__main__': app = QtWidgets.QApplication(sys.argv) gui = Main(app) sys.exit(app.exec_()) (Sep-01-2019, 06:08 PM)Axel_Erfurt Wrote: forget the last post. It's so easy setChangeCurrentOnDrag Thanks for the tip, I did not see this in the docs.. Sometimes the solutions are simpler than expected |