【问题标题】:drag and drop a Tab from a QtabBar to other QtabBar in a splitted Widget PyQt Qt在拆分的 Widget PyQt Qt 中,将 Tab 从 QtabBar 拖放到其他 QtabBar
【发布时间】:2017-09-24 16:48:27
【问题描述】:

我该如何存档: - 我需要将选项卡从其 tabBar 拖放到拆分小部件中的其他 tabBar? 我已经对 QtabBar 进行了子类化并实现了拖放事件,我已经可以使用正确的像素图等将其拖放到同一个 tabBar 中,但不能放在另一个 tabBar 中。 在输出中收到此错误,告诉我我没有提供正确的参数,这是我为制作和示例而简化的代码,以及窗口的 .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)

ColtabBar 是我执行拖放事件的子类。

图片->

【问题讨论】:

  • 你考虑过使用 QDockWidgets 吗?用户可以通过标签和拖动它们
  • 是的,我以这种方式尝试过,但我做到了,但不是我想要的方式..我喜欢做我当时脑子里想的事情,好吧,终于做到了,结束12 小时 ufff 现在将发布结果 :) 非常感谢您的建议。 @SteakOverflow

标签: python python-2.7 qt pyqt pyqt5


【解决方案1】:

经过几个小时,今天在网上吃了很多很多 Qt 页面,我以自己的方式做到了,现在我可以将选项卡从一个选项卡拖放到另一个选项卡,反之亦然,而不仅仅是从选择当前标签,我可以在标签栏中选择我想要的每个标签,并在拖动时向我显示小标签的像素图......

代码如下:

** 已编辑 **

我让它更加防弹,当我使用超过 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)


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

图片->

【讨论】:

    【解决方案2】:

    发现这个帖子很有用。使用您的解决方案在 PyQt5 中创建了一个自包含的通用示例。将来可能会帮助某人。

    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_())
    

    【讨论】:

      【解决方案3】:

      这是根据别人的代码修改的,可能是上面的示例之一。

      无论如何,这是标签到标签或标签到窗口拖放标签内容的最少代码。

      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_())
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-12-16
        • 1970-01-01
        • 1970-01-01
        • 2019-04-10
        • 2012-07-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多