我想有一个"新标签"按钮,就像Chrome或Firefox为我的QMdiArea
所做的那样。
我可以在某处创建一个按钮或菜单项,将新的子文档添加到 MDI 事物中,但是如何使其成为带有"+"作为标签的视觉上吸引人的小选项卡?或者,我会很高兴有这样一个按钮的QTabWidget
。
这个问题已经过时了,但前段时间我一直在寻找您请求的功能的现成实现。我挖掘了一些并为Qt 5实现了这一点 - 看看存储库。
主要思想是做:
// 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);
您必须为 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
为什么不在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_()
有一个特殊的方法:
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);
首先,向小部件添加一个空选项卡,并连接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);
}
@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_()
我在这里尝试了所有答案,但没有一个看起来像我想要的那样,所以这是我想出的解决方案:
QTabWidget tabs(&mainwin);
QToolButton newTabButton(&tabs);
newTabButton.setText("+");
auto update_newtab_button_position = [&newTabButton, &tabs](int index){
int c = tabs.tabBar()->count();
int x = 0;
for(int i = 0; i < c; i++){
x += tabs.tabBar()->tabRect(i).width();
}
newTabButton.move(x+1, 2);
newTabButton.resize(tabs.tabBar()->rect().height() - 4, tabs.tabBar()->rect().height() - 4);
};
QObject::connect(tabs.tabBar(), &QTabBar::tabBarClicked, update_newtab_button_position);
// ...
mainwin.show();
update_newtab_button_position(0);