简体   繁体   English

将标签从 QtabBar 拖放到拆分的 Widget PyQt Qt 中的其他 QtabBar

[英]drag and drop a Tab from a QtabBar to other QtabBar in a splitted Widget PyQt Qt

How could I archive this: - I need to drag and drop a tab from its tabBar to other tabBar in a splitted widget?我该如何存档: - 我需要将一个选项卡从其 tabBar 拖放到拆分小部件中的其他 tabBar? I already subclass the QtabBar and implement the drag and drop events, i already can drag it with the right pixmap and etc, and also i can drop it into the same tabBar, but not in the other one .. got this error in the output telling me that im not providing the right arguments, here is the code, that i simplified for make it and example, and plus a .JPG of the window.我已经将 QtabBar 子类化并实现了拖放事件,我已经可以使用正确的像素图等拖动它,并且我也可以将它放到同一个 tabBar 中,但不能放到另一个 tabBar 中……在输出中得到这个错误告诉我我没有提供正确的参数,这里是代码,我简化了 make it 和 example,以及窗口的 .JPG。

class EsceneTest(qg.QMainWindow):
    def __init__(self,parent=getMayaWindow()):
        super(EsceneTest,self).__init__(parent)
        #---------------------------------------------------------#        
        #check for open Window first
        winName = windowTitle
        if cmds.window(winName, exists =1):
            cmds.deleteUI(winName, wnd=True)

        self.setAttribute(qc.Qt.WA_DeleteOnClose) 
        self._initUI()      

    def _initUI(self):                     
        self.setObjectName(windowObject)
        self.setWindowTitle(windowTitle)
        self.setMinimumWidth(450)
        self.setMinimumHeight(500)
        self.resize(1080, 800) # re-size the window
        centralWidget = qg.QWidget()
        centralWidget.setObjectName('centralWidget')
        self.setCentralWidget(centralWidget)
        central_layout = qg.QVBoxLayout(centralWidget)

        ######################
        # tab container
        #
        self.tabWidget = qg.QTabWidget()
        self.tabWidget.setAcceptDrops(True)
        self.tab_layout = qg.QVBoxLayout(self.tabWidget)
        central_layout.addWidget(self.tabWidget)

        #######################
        # TabBar
        #                 
        custom_tabbar = ColtabBar()
        self.tabWidget.setTabBar(custom_tabbar)        

        #######################
        # ViewportTab
        #         
        tabCentral_wdg = qg.QWidget()
        self.top_lyt = qg.QVBoxLayout(tabCentral_wdg)
        self.tab_layout.addLayout(self.top_lyt)       

        fixedHBox_lyt = qg.QHBoxLayout()
        self.top_lyt.addLayout(fixedHBox_lyt)   
        self.tabWidget.addTab(tabCentral_wdg,'- Viewport')

        #######################
        # Example ExtraTab
        #        
        tabTwo_wdg = qg.QWidget()
        tabTwo_wdg_lyt = qg.QHBoxLayout(tabTwo_wdg)
        self.tab_layout.addLayout(tabTwo_wdg_lyt)        
        label = qg.QLabel(' -- This is an example -- ')
        label.setStyleSheet("""
                            background : qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(53, 57, 60), stop:1 rgb(33, 34, 36));
                            border-style : none;
                            font-size: 40px;
                            font-family: Calibri;
                            color : rgb(200,200,100);
                        """)
        label.setAlignment(qc.Qt.AlignVCenter | qc.Qt.AlignHCenter )
        tabTwo_wdg_lyt.addWidget(label)       
        tab_panel_lyt = qg.QVBoxLayout(label)    
        self.tabWidget.addTab(tabTwo_wdg,'- ExtraExample') 

        ############################
        #   Q Splitter Widget to insert the dragged Tabs
        #
        split = qg.QSplitter(qc.Qt.Orientation.Vertical, self)
        central_layout.addWidget(split)
        tab_splitted = qg.QTabWidget()
        split.setLayout(qg.QVBoxLayout())
        split.insertWidget(0,tab_splitted)
        tabBar_2 = ColtabBar()
        tab_splitted.setTabBar(tabBar_2)
        tabBar_2.addTab('- Insert-Here')
#---------------------------------------------------------------------------------------------#

class ColtabBar(qg.QTabBar):
    def __init__(self):
        super(ColtabBar, self).__init__()
        self.indexTab = None        
        self.setAcceptDrops(True)   

    ##################################
    # Events
    def mouseMoveEvent(self, e):
        if e.buttons() != qc.Qt.MiddleButton:
            return

        globalPos = self.mapToGlobal(e.pos())
        posInTab = self.mapFromGlobal(globalPos)
        self.indexTab = self.tabAt(e.pos())
        tabRect = self.tabRect(self.indexTab)


        pixmap = qg.QPixmap(tabRect.size())
        self.render(pixmap,qc.QPoint(),qg.QRegion(tabRect))
        mimeData = qc.QMimeData()
        drag = qg.QDrag(self)
        drag.setMimeData(mimeData)
        drag.setPixmap(pixmap)

        cursor = qg.QCursor(qc.Qt.OpenHandCursor)    
        drag.setHotSpot(e.pos() - posInTab)
        drag.setDragCursor(cursor.pixmap(),qc.Qt.MoveAction)       
        dropAction = drag.exec_(qc.Qt.MoveAction)


    def mousePressEvent(self, e):
        #super(qg.QWidget).mousePressEvent(e)
        if e.button() == qc.Qt.RightButton:
            print('press')

        if e.button() == qc.Qt.LeftButton:            
            globalPos = self.mapToGlobal(e.pos())
            posInTab = self.mapFromGlobal(globalPos)
            self.indexTab = self.tabAt(e.pos())
            self.setCurrentIndex(self.indexTab)

    def dragEnterEvent(self, e):
        e.accept()


    def dropEvent(self, e):
        e.setDropAction(qc.Qt.MoveAction)
        e.accept()        
        self.insertTab(self.indexTab, self.tabText(self.indexTab)) 
        self.removeTab(self.indexTab)

the ColtabBar is the subclass where im doing the drag and drop events. ColtabBar是我执行拖放事件的子类。

IMAGE - >图像 - > 例子

After many hours and have eaten many manyyyy pages of Qt today over the web, I did it in my way, now I can drag and drop tabs from one tabBar to the other and vice-versa and not just from selection the current tab, i could select every tab that I want in my tab bar and will show me the pixmap of the little tab while dragging...几个小时后,今天在网上吃了很多 Qt 页面,我按照自己的方式做了,现在我可以将标签从一个 tabBar 拖放到另一个 tabBar,反之亦然,而不仅仅是从选择当前选项卡,我可以在选项卡栏中选择我想要的每个选项卡,并在拖动时向我显示小选项卡的像素图...

Here is the code:这是代码:

** EDITED ** ** 编辑 **

I made it more bullet proof, I had a bug when I was using more than 2 tabs with the index, now is working better, and when I drop it in the same widget it return the event and not execute the code, plus the hovering tabs select with the right mouse button as well .. I hope this can help anybody in the future.我使它更加防弹,当我使用超过 2 个标签的索引时,我有一个错误,现在工作得更好,当我把它放在同一个小部件中时,它返回事件而不执行代码,加上悬停也可以使用鼠标右键选择选项卡.. 我希望这可以帮助将来的任何人。

TABINDEX = int()

def getTabIndex(index):
    global TABINDEX
    if index == -1 or index == TABINDEX:
        return
    TABINDEX = index
    print (TABINDEX)
    return TABINDEX


class ColtTab(qg.QTabWidget):
    def __init__(self):
        super(ColtTab,self).__init__()
        self.setAcceptDrops(True)
        self.tabBar = self.tabBar()
        self.tabBar.setMouseTracking(True)
        self.setDocumentMode(True)
        self.indexTab = int()
        self.setMovable(True)
        self.setStyleSheet(style_sheet_file)


    # test for hovering and selecting tabs automatic while mouser over then - not working for now...
    def eventFilter(self, obj, event):
        if obj == self.tabBar:
            if event.type() == qc.QEvent.MouseMove:
                index=self.tabBar.tabAt(event.pos())
                self.tabBar.setCurrentIndex (index)
                return True
            else:
                return
        else:
            return

    ##################################
    # Events
    #
    def mouseMoveEvent(self, e):
        if e.buttons() != qc.Qt.MiddleButton:
            return

        globalPos = self.mapToGlobal(e.pos())
        #print(globalPos)
        tabBar = self.tabBar
        #print(tabBar)
        posInTab = tabBar.mapFromGlobal(globalPos)
        #print(posInTab)
        self.indexTab = tabBar.tabAt(e.pos())
        #print(self.indexTab)
        tabRect = tabBar.tabRect(self.indexTab)
        #print(tabRect)
        #print(tabRect.size())

        pixmap = qg.QPixmap(tabRect.size())
        tabBar.render(pixmap,qc.QPoint(),qg.QRegion(tabRect))
        mimeData = qc.QMimeData()
        drag = qg.QDrag(tabBar)
        drag.setMimeData(mimeData)
        drag.setPixmap(pixmap)
        cursor = qg.QCursor(qc.Qt.OpenHandCursor)
        drag.setHotSpot(e.pos() - posInTab)
        drag.setDragCursor(cursor.pixmap(),qc.Qt.MoveAction)
        dropAction = drag.exec_(qc.Qt.MoveAction)


    def mousePressEvent(self, e):
        if e.button() == qc.Qt.RightButton:
            self.tabBar.installEventFilter(self)
            print('Right button pressed')

        super(ColtTab, self).mousePressEvent(e)


    def dragEnterEvent(self, e):
        e.accept()
        if e.source().parentWidget() != self:
            return

        # Helper function for retrieving the Tab index into a global Var
        getTabIndex(self.indexOf(self.widget(self.indexTab)))


    def dragLeaveEvent(self,e):
        e.accept()


    def dropEvent(self, e):
        if e.source().parentWidget() == self:
            return

        e.setDropAction(qc.Qt.MoveAction)
        e.accept()
        counter = self.count()

        if counter == 0:
            self.addTab(e.source().parentWidget().widget(TABINDEX),e.source().tabText(TABINDEX))
        else:
            self.insertTab(counter + 1 ,e.source().parentWidget().widget(TABINDEX),e.source().tabText(TABINDEX))

        print ('Tab dropped')

    def mouseReleaseEvent(self, e):
        if e.button() == qc.Qt.RightButton:
            print('Right button released')
            self.tabBar.removeEventFilter(self)

        super(ColtTab, self).mouseReleaseEvent(e)


    #---------------------------------------------------------------------------------#

Pic ->图片->

示例:

Found this thread useful.发现这个线程很有用。 Used your solution to create a self contained generic example in PyQt5.使用您的解决方案在 PyQt5 中创建了一个自包含的通用示例。 May help someone in the future.将来可能会帮助某人。

import sys

from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class Tabs(QTabWidget):
    def __init__(self, parent):
        super().__init__(parent)
        self.parent = parent
        self.setAcceptDrops(True)
        self.tabBar = self.tabBar()
        self.tabBar.setMouseTracking(True)
        self.indexTab = None
        self.setMovable(True)

        self.addTab(QWidget(self), 'Tab One')
        self.addTab(QWidget(self), 'Tab Two')

    def mouseMoveEvent(self, e):
        if e.buttons() != Qt.RightButton:
            return

        globalPos = self.mapToGlobal(e.pos())
        tabBar = self.tabBar
        posInTab = tabBar.mapFromGlobal(globalPos)
        self.indexTab = tabBar.tabAt(e.pos())
        tabRect = tabBar.tabRect(self.indexTab)

        pixmap = QPixmap(tabRect.size())
        tabBar.render(pixmap,QPoint(),QRegion(tabRect))
        mimeData = QMimeData()
        drag = QDrag(tabBar)
        drag.setMimeData(mimeData)
        drag.setPixmap(pixmap)
        cursor = QCursor(Qt.OpenHandCursor)
        drag.setHotSpot(e.pos() - posInTab)
        drag.setDragCursor(cursor.pixmap(),Qt.MoveAction)
        dropAction = drag.exec_(Qt.MoveAction)


    def dragEnterEvent(self, e):
        e.accept()
        if e.source().parentWidget() != self:
            return

        print(self.indexOf(self.widget(self.indexTab)))
        self.parent.TABINDEX = self.indexOf(self.widget(self.indexTab))


    def dragLeaveEvent(self,e):
        e.accept()


    def dropEvent(self, e):
        print(self.parent.TABINDEX)
        if e.source().parentWidget() == self:
            return

        e.setDropAction(Qt.MoveAction)
        e.accept()
        counter = self.count()

        if counter == 0:
            self.addTab(e.source().parentWidget().widget(self.parent.TABINDEX),e.source().tabText(self.parent.TABINDEX))
        else:
            self.insertTab(counter + 1 ,e.source().parentWidget().widget(self.parent.TABINDEX),e.source().tabText(self.parent.TABINDEX))


class Window(QWidget):
    def __init__(self):

        super().__init__()

        self.TABINDEX = 0
        tabWidgetOne = Tabs(self)
        tabWidgetTwo = Tabs(self)

        layout = QHBoxLayout()

        self.moveWidget = None

        layout.addWidget(tabWidgetOne)
        layout.addWidget(tabWidgetTwo)

        self.setLayout(layout)

if __name__ == '__main__':

    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

This is modified from someone elses code, perhaps one of the examples above.这是从别人的代码修改而来的,也许是上面的例子之一。

Anyhow, it's a minimal code for tab-to-tab or tab-to-window drag / droping of tab's contents.无论如何,这是选项卡到选项卡或选项卡到窗口拖/放选项卡内容的最小代码。

from PyQt5.QtWidgets import QTabWidget
from PyQt5.QtCore import Qt, QPoint, QMimeData
from PyQt5.QtGui import QPixmap, QRegion, QDrag, QCursor

class TabWidget(QTabWidget):
   def __init__(self, parent=None, new=None):
      super().__init__(parent)
      self.setAcceptDrops(True)
      self.tabBar().setMouseTracking(True)
      self.setMovable(True)
      if new:
         TabWidget.setup(self)

   def __setstate__(self, data):
      self.__init__(new=False)
      self.setParent(data['parent'])
      for widget, tabname in data['tabs']:
         self.addTab(widget, tabname)
      TabWidget.setup(self)

   def __getstate__(self):
      data = {
         'parent' : self.parent(),
         'tabs' : [],
      }
      tab_list = data['tabs']
      for k in range(self.count()):
         tab_name = self.tabText(k)
         widget = self.widget(k)
         tab_list.append((widget, tab_name))
      return data

   def setup(self):
      pass

   def mouseMoveEvent(self, e):
      if e.buttons() != Qt.RightButton:
         return

      globalPos = self.mapToGlobal(e.pos())
      tabBar = self.tabBar()
      posInTab = tabBar.mapFromGlobal(globalPos)
      index = tabBar.tabAt(e.pos())
      tabBar.dragged_content = self.widget(index)
      tabBar.dragged_tabname = self.tabText(index)
      tabRect = tabBar.tabRect(index)

      pixmap = QPixmap(tabRect.size())
      tabBar.render(pixmap,QPoint(),QRegion(tabRect))
      mimeData = QMimeData()

      drag = QDrag(tabBar)
      drag.setMimeData(mimeData)
      drag.setPixmap(pixmap)

      cursor = QCursor(Qt.OpenHandCursor)

      drag.setHotSpot(e.pos() - posInTab)
      drag.setDragCursor(cursor.pixmap(),Qt.MoveAction)
      drag.exec_(Qt.MoveAction)

   def dragEnterEvent(self, e):
      e.accept()
      #self.parent().dragged_index = self.indexOf(self.widget(self.dragged_index))

   def dragLeaveEvent(self,e):
      e.accept()

   def dropEvent(self, e):
      if e.source().parentWidget() == self:
         return

      e.setDropAction(Qt.MoveAction)
      e.accept()
      tabBar = e.source()
      self.addTab(tabBar.dragged_content, tabBar.dragged_tabname)


if __name__ == '__main__':
   from PyQt5.QtWidgets import QWidget, QApplication, QHBoxLayout
   import sys

   class Window(QWidget):
      def __init__(self):

         super().__init__()

         self.dragged_index = None
         tabWidgetOne = TabWidget(self)
         tabWidgetTwo = TabWidget(self)
         tabWidgetOne.addTab(QWidget(), "tab1")
         tabWidgetTwo.addTab(QWidget(), "tab2")

         layout = QHBoxLayout()

         self.moveWidget = None

         layout.addWidget(tabWidgetOne)
         layout.addWidget(tabWidgetTwo)

         self.setLayout(layout)

   app = QApplication(sys.argv)
   window = Window()
   window1 = Window()
   window.show()
   window1.show()
   sys.exit(app.exec_())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM