【问题标题】:How can I add a "new tab" button next to the tabs of a QMdiArea in tabbed view mode?如何在选项卡式视图模式下在 QMdiArea 的选项卡旁边添加“新选项卡”按钮?
【发布时间】:2013-11-27 07:33:27
【问题描述】:

我想为我的QMdiArea 提供一个类似于 Chrome 或 Firefox 的“新标签”按钮。

我可以在某处创建一个按钮或菜单项,将新的子文档添加到 MDI 事物中,但我怎样才能使它成为一个带有“+”作为标签的视觉上吸引人的小标签?或者,如果QTabWidget 带有这样的按钮,我会很高兴的。

【问题讨论】:

  • 我不知道QMdiArea,但QTabWidget 有一个QTabBar,它有一个setTabButton() 函数。也许你应该检查一下?

标签: qt tabs qtabwidget qmdiarea


【解决方案1】:

有一个特殊的方法:

void QTabWidget::setCornerWidget(QWidget *widget, Qt::Corner corner = Qt::TopRightCorner)

我是这样使用的:

QIcon icon = QIcon::fromTheme(QLatin1String("window-new"));
QToolButton *btn = new QToolButton();
btn->setIcon(icon);
connect(btn, &QAbstractButton::clicked, this, &App::OpenNewTab);
tab_widget_->setCornerWidget(btn, Qt::TopRightCorner);

【讨论】:

    【解决方案2】:

    首先,为您的小部件添加一个空选项卡,然后连接currentChanged 信号:

    TabsView::TabsView(QWidget *parent) :
      QWidget(parent),
      ui(new Ui::TabsView)
    {
        ui->setupUi(this);
        ui->tabWidget->clear();
        ui->tabWidget->addTab(new QLabel("+"), QString("+"));
        connect(ui->tabWidget, &QTabWidget::currentChanged, this, &TabsView::onChangeTab);
        newTab();
    }
    

    然后,在您的 onChangeTab 插槽上,检查用户是否单击了最后一个选项卡,然后调用 newTab

    void TabsView::onChangeTab(int index)
    {
        if (index == this->ui->tabWidget->count() - 1) {
            newTab();
        }
    }
    

    最后,在您的 newTab 方法上,创建新选项卡并选择它:

    void TabsView::newTab()
    {
        int position = ui->tabWidget->count() - 1;
        ui->tabWidget->insertTab(position, new QLabel("Your new tab here"), QString("New tab"));
        ui->tabWidget->setCurrentIndex(position);
        auto tabBar = ui->tabWidget->tabBar();
        tabBar->scroll(tabBar->width(), 0);
    }
    

    【讨论】:

      【解决方案3】:

      为什么不在 QTabWidget 的最后一个选项卡中制作一个按钮?只需创建最后一个带有“+”符号的选项卡并使用 currentChanged 事件。

      class Trace_Tabs(QTabWidget):
      
          def __init__(self):
              QTabWidget.__init__(self)       
              self._build_tabs()
      
          def _build_tabs(self):
              self.setUpdatesEnabled(True)
      
              self.insertTab(0,QWidget(), "Trace" )
              self.insertTab(1,QWidget(),'  +  ') 
      
              self.currentChanged.connect(self._add_trace) 
      
          def _add_trace(self, index):    
      
              if index == self.count()-1 :    
                  '''last tab was clicked. add tab'''
                  self.insertTab(index, QWidget(), "Trace %d" %(index+1)) 
                  self.setCurrentIndex(index)
      
      if __name__ == '__main__':    
          app = QApplication([])    
          tabs = Trace_Tabs()
          tabs.show()    
          app.exec_()
      

      【讨论】:

      • 解决该问题的方法是使用:self.tabBar().setSelectionBehaviorOnRemove(QTabBar.SelectLeftTab)
      【解决方案4】:

      与@Garjy 的回答类似的概念:

      您可以使用“空白”标签并向该标签添加一个按钮。如果您使用TabWidget.setTabsCloseable(True),这也将替换“关闭”按钮。可以进入“空白”选项卡,因此我建议结合@Garjy 的答案或添加一些文本/另一个新按钮。

      import sys
      from qtpy.QtWidgets import QTabWidget, QWidget, QToolButton, QTabBar, QApplication
      
      class Trace_Tabs(QTabWidget):
      
          def __init__(self):
              QTabWidget.__init__(self)
              self.setTabsClosable(True)
              self._build_tabs()
      
          def _build_tabs(self):
      
              self.insertTab(0, QWidget(), "Trace 0" )
      
              # create the "new tab" tab with button
              self.insertTab(1, QWidget(),'')
              nb = self.new_btn = QToolButton()
              nb.setText('+') # you could set an icon instead of text
              nb.setAutoRaise(True)
              nb.clicked.connect(self.new_tab)
              self.tabBar().setTabButton(1, QTabBar.RightSide, nb)
      
          def new_tab(self):
              index = self.count() - 1
              self.insertTab(index, QWidget(), "Trace %d" % index)
              self.setCurrentIndex(index)
      
      if __name__ == '__main__':
      
          app = QApplication(sys.argv)
      
          tabs = Trace_Tabs()
          tabs.show()
      
          app.exec_()
      

      【讨论】:

        【解决方案5】:

        您必须为 QTabBar 编写自己的类。加号按钮可以使用绝对定位添加。

        我这里有一些 PySide 的代码;它应该给你基本的想法。

        class TabBarPlus(QtGui.QTabBar):
            """Tab bar that has a plus button floating to the right of the tabs."""
        
            plusClicked = QtCore.Signal()
        
            def __init__(self):
                super().__init__()
        
                # Plus Button
                self.plusButton = QtGui.QPushButton("+")
                self.plusButton.setParent(self)
                self.plusButton.setFixedSize(20, 20)  # Small Fixed size
                self.plusButton.clicked.connect(self.plusClicked.emit)
                self.movePlusButton() # Move to the correct location
            # end Constructor
        
            def sizeHint(self):
                """Return the size of the TabBar with increased width for the plus button."""
                sizeHint = QtGui.QTabBar.sizeHint(self) 
                width = sizeHint.width()
                height = sizeHint.height()
                return QtCore.QSize(width+25, height)
            # end tabSizeHint
        
            def resizeEvent(self, event):
                """Resize the widget and make sure the plus button is in the correct location."""
                super().resizeEvent(event)
        
                self.movePlusButton()
            # end resizeEvent
        
            def tabLayoutChange(self):
                """This virtual handler is called whenever the tab layout changes.
                If anything changes make sure the plus button is in the correct location.
                """
                super().tabLayoutChange()
        
                self.movePlusButton()
            # end tabLayoutChange
        
            def movePlusButton(self):
                """Move the plus button to the correct location."""
                # Find the width of all of the tabs
                size = sum([self.tabRect(i).width() for i in range(self.count())])
                # size = 0
                # for i in range(self.count()):
                #     size += self.tabRect(i).width()
        
                # Set the plus button location in a visible area
                h = self.geometry().top()
                w = self.width()
                if size > w: # Show just to the left of the scroll buttons
                    self.plusButton.move(w-54, h)
                else:
                    self.plusButton.move(size, h)
            # end movePlusButton
        # end class MyClass
        
        class CustomTabWidget(QtGui.QTabWidget):
            """Tab Widget that that can have new tabs easily added to it."""
        
            def __init__(self):
                super().__init__()
        
                # Tab Bar
                self.tab = TabBarPlus()
                self.setTabBar(self.tab)
        
                # Properties
                self.setMovable(True)
                self.setTabsClosable(True)
        
                # Signals
                self.tab.plusClicked.connect(self.addTab)
                self.tab.tabMoved.connect(self.moveTab)
                self.tabCloseRequested.connect(self.removeTab)
            # end Constructor
        # end class CustomTabWidget
        

        【讨论】:

        • 这非常有效。你能告诉我一些我可以用你的方法面对的问题吗?像调整大小一样
        【解决方案6】:

        我知道这个问题已经过时了,但前段时间我一直在寻找您要求的功能的即用型实现。我挖掘了一下并为 Qt 5 实现了这个——take a look at repo

        主要思路是:

        // Create button what must be placed in tabs row
        QToolButton *tb = new QToolButton();
        tb->setText("+");
        // Add empty, not enabled tab to tabWidget
        tabWidget->addTab(new QLabel("Add tabs by pressing \"+\""), QString());
        tabWidget->setTabEnabled(0, false);
        // Add tab button to current tab. Button will be enabled, but tab -- not
        tabWidget->tabBar()->setTabButton(0, QTabBar::RightSide, tb);
        

        【讨论】:

        • 这在 Qt 5 中效果很好,但是对于 Qt 4,这给了我一个错误:error: 'QTabBar* QTabWidget::tabBar() const' is protected,所以我想我只需要为此忘记 Qt 4!虽然简单而优雅。而且原则上我可以为 QLabel 使用任何图像,这是一个不错的加分项。
        • 我已经检查并看到 tabBar 确实在 Qt 4.8 中受到保护。所以我在我的答案中添加了“Qt 5”。感谢您的评论。
        • 如果选项卡是可移动的(setMovable(true)),则可以在“new-tab”特殊栏之后拖放选项卡,即使它被禁用:(。跨度>
        猜你喜欢
        • 2011-12-18
        • 1970-01-01
        • 2017-12-06
        • 2020-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多