PySide Qt4 - Qtabwidget - 禁用单个 q 选项卡小部件的拖放
PySide Qt4 - Qtabwidget - Disable drag and drop of a single q tab widget
我有一个 qtabwidget 在任何给定时间都有一个或多个选项卡。
我希望用户能够以任何顺序重新排列第二个到最后一个选项卡,但第一个选项卡保留在索引 0 处。
根据我发现的所有内容,无法为每个选项卡独立启用 setMovable。
到目前为止,我想出的最佳解决方法是,如果用户移动第一个选项卡(或它前面的另一个选项卡),只需将第一个选项卡移回位置 0。这显然不是理想的,但如果它正常工作是可以接受的......它工作了一小会儿,但它偶尔会导致应用程序崩溃(当用户在它之前拖动一个选项卡并将鼠标放在那里时,它似乎会发生,所以它一直在尝试重新排列和一些低级别的崩溃)
关于可行解决方法的任何其他建议(对于此方法,或更容易实现此功能的类似小部件)?我认为它可能会重新 class QTabWidget 以忽略第一个选项卡上的鼠标拖动的方式,但我不确定如何防止另一个选项卡在它之前移动.. .
我找到的唯一方法是 "pin" QTabWidget is by using a subclass of QTabBar 的第一个选项卡。全局策略包括在 QTabBar
的子类上安装 eventFilter
并有条件地阻止 MouseMove
事件,以便:
- 将第一个选项卡的位置固定在索引 0 处;
- 防止其他选项卡的左边缘移动到第一个选项卡右边缘的左侧。这样可以防止其他选项卡移动到第一个选项卡的前面。
下面的代码展示了一个简单的应用程序来展示如何做到这一点。
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_())
这导致:
我有一个 qtabwidget 在任何给定时间都有一个或多个选项卡。 我希望用户能够以任何顺序重新排列第二个到最后一个选项卡,但第一个选项卡保留在索引 0 处。
根据我发现的所有内容,无法为每个选项卡独立启用 setMovable。
到目前为止,我想出的最佳解决方法是,如果用户移动第一个选项卡(或它前面的另一个选项卡),只需将第一个选项卡移回位置 0。这显然不是理想的,但如果它正常工作是可以接受的......它工作了一小会儿,但它偶尔会导致应用程序崩溃(当用户在它之前拖动一个选项卡并将鼠标放在那里时,它似乎会发生,所以它一直在尝试重新排列和一些低级别的崩溃)
关于可行解决方法的任何其他建议(对于此方法,或更容易实现此功能的类似小部件)?我认为它可能会重新 class QTabWidget 以忽略第一个选项卡上的鼠标拖动的方式,但我不确定如何防止另一个选项卡在它之前移动.. .
我找到的唯一方法是 "pin" QTabWidget is by using a subclass of QTabBar 的第一个选项卡。全局策略包括在 QTabBar
的子类上安装 eventFilter
并有条件地阻止 MouseMove
事件,以便:
- 将第一个选项卡的位置固定在索引 0 处;
- 防止其他选项卡的左边缘移动到第一个选项卡右边缘的左侧。这样可以防止其他选项卡移动到第一个选项卡的前面。
下面的代码展示了一个简单的应用程序来展示如何做到这一点。
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_())
这导致: