0

我目前正在尝试设置边界,以便选项卡不能超出 QTabBar 的每一端。默认情况下,只要将可移动选项卡拖到 QTabBar 区域之外,它就会消失在 void 中 - QTab 被拖到 QTabBar 区域之外的示例。

这在大多数情况下都很好,但在视觉上我希望标签在到达 QTabBar 的边缘后完全停止移动。我试图通过 Qt 的事件系统来实现这个目标,目前只支持左边界。每当用户单击 QTab 时,我都会记录他的鼠标的初始位置以及当前选项卡未移动的位置和大小。然后,我使用这些值来确定如果用户将鼠标向左移动,当前选项卡将在哪个 x 位置到达 QTabBar 的边缘。如果达到此位置,则过滤事件以防止选项卡的任何进一步移动。

    def eventFilter(self, source, event):
    if event.type() == QEvent.Type.MouseButtonPress:
        self.startingpos = event.x()
        self.tabOrigin = self.curTab.x()
        self.tabRoom = self.startingpos - self.tabOrigin

    if event.type() == QEvent.Type.MouseMove:
        if self.curIndex != self.tabs.currentIndex():
            self.curIndex = self.tabs.currentIndex()
            self.curTab = self.tabs.tabBar().tabRect(self.curIndex)

        if event.x() < self.tabRoom:
            return True
    return False

这种策略是有效的,除非用户快速向左移动鼠标。这会导致移动选项卡在到达 QTabBar 的边缘之前,在经过指定边界之前卡在鼠标的最后记录位置 - QTab 在到达 QTabBar 左侧之前卡住的示例。

我不确定如何解决这个问题。我了解移动选项卡实际上与最初单击的选项卡不同。无论如何可以访问移动标签的位置并手动设置其位置?如果没有,任何有关如何解决此问题的建议将不胜感激。

4

1 回答 1

1

鼠标事件不是线性的,如果用户移动鼠标太快,它们会“跳过”像素。

问题是“移动选项卡”完全在内部实现,因此无法访问该选项卡(实际上,它暂时是绘制在其余选项卡上的“假”小部件)。

一种可能的解决方案是检测当前按下的标签,获取鼠标相对于该标签的水平位置,检查移动是否超出限制(左侧为0,右边距为最后一个标签的右侧),合成一个新的基于此的鼠标事件,并发布该事件。

    def eventFilter(self, source, event):
        if (event.type() == event.MouseButtonPress and 
            event.button() == QtCore.Qt.LeftButton):
                tabRect = source.tabRect(source.tabAt(event.pos()))
                self.leftDistance = event.x() - tabRect.left()
                self.rightMargin = tabRect.right() - event.x()
                self.rightLimit = source.tabRect(self.tabs.count() - 1).right()
        elif (event.type() == event.MouseMove and 
            event.buttons() == QtCore.Qt.LeftButton):
                if event.x() - self.leftDistance < 0:
                    pos = QtCore.QPoint(self.leftDistance, event.y())
                    newEvent = QtGui.QMouseEvent(
                        event.type(), pos, 
                        event.button(), event.buttons(), 
                        event.modifiers())
                    QtWidgets.QApplication.postEvent(source, newEvent)
                    return True
                elif event.x() + self.rightMargin > self.rightLimit:
                    pos = QtCore.QPoint(
                        self.rightLimit - self.rightMargin, event.y())
                    newEvent = QtGui.QMouseEvent(
                        event.type(), pos, 
                        event.button(), event.buttons(), 
                        event.modifiers())
                    QtWidgets.QApplication.postEvent(source, newEvent)
                    return True
        return super().eventFilter(source, event)

请注意,eventFilter()始终返回基本实现,否则在某些情况下您可能会遇到意外行为。

于 2021-07-14T20:40:37.037 回答