我有一个qtabwidget,在任何给定时间都有一个或多个标签。 我希望用户能够以任何顺序重新排列第二个到最后一个选项卡,但第一个选项卡保留在索引0处。
从我发现的所有内容中,无法为每个标签单独启用setMovable。
到目前为止,我提出的最佳解决方法是,如果用户移动它(或前面的另一个标签),只需将第一个标签移回位置0。这显然不是理想的,但如果它正常工作就可以接受......它可以工作一段时间,但它偶尔会使应用程序崩溃(当用户在它之前拖动一个标签并持有鼠标时似乎会发生这种情况那里,所以它在一个不断循环的尝试重新排列和低级别的崩溃)
关于可行解决方法的任何其他建议(对于此方法,或者此类功能更容易实现的类似小部件)?我认为可能有可能重新对QTabWidget进行重新分类,它会忽略第一个选项卡上的鼠标拖动,但我不确定如何防止另一个选项卡在它之前被移动... < / p>
答案 0 :(得分:2)
我发现的唯一方法是&#34; pin&#34; QTabWidget的第一个标签是使用QTabBar的子类。全局策略包括在eventFilter
的子类上安装QTabBar
并有条件地阻止MouseMove
事件以便:
下面的代码提供了一个简单的应用程序来展示如何做到这一点。
import sys
from PySide import QtGui, QtCore
class myQTabBar(QtGui.QTabBar):
def __init__(self, *args, **kargs):
super(myQTabBar, self).__init__(*args, **kargs)
self.setMovable(True)
self.installEventFilter(self)
def eventFilter(self, source, event):
if event.type() == QtCore.QEvent.Type.MouseMove:
if source.currentIndex() == 0: # Block MouseMove for first tab.
return True
else: # For remaining tabs:
# block MouseMove if the left edge of the moving tab goes
# farther to the left than the right edge of first tab.
moving_leftEdge = event.pos().x() - self.edge_offset
fixed_rightEdge = self.tabRect(0).width()
if moving_leftEdge < fixed_rightEdge:
return True
elif event.type() == QtCore.QEvent.Type.MouseButtonPress:
# Get mouse click horizontal position.
xclick = event.pos().x()
# Get the left edge horizontal position of the targeted tab.
xleft = self.tabRect(self.tabAt(event.pos())).x()
# Compute and store offset between mouse click horizontal
# position and the left edge of the targeted tab
self.edge_offset = xclick - xleft
return QtGui.QWidget.eventFilter(self, source, event)
class myQTabWidget(QtGui.QTabWidget):
def __init__(self, *args, **kargs):
super(myQTabWidget, self).__init__(*args, **kargs)
tab_bar = myQTabBar()
self.setTabBar(tab_bar)
self.addTab(QtGui.QWidget(), 'Tab1')
self.addTab(QtGui.QWidget(), 'Tab2')
self.addTab(QtGui.QWidget(), 'Tab3')
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
instance1 = myQTabWidget()
instance1.show()
sys.exit(app.exec_())
结果是: