【问题标题】:How to track the local position of a movable QTab?如何跟踪可移动 QTab 的本地位置?
【发布时间】:2021-07-14 19:34:22
【问题描述】:

我目前正在尝试设置边界,以便标签不能超出 QTabBar 的每一端。默认情况下,只要将可移动选项卡拖到 QTabBar 区域之外,它就会消失为空 - An example of the QTab being dragged outside of the QTabBar's Area.

这在大多数情况下都很好,但在视觉上我希望标签在到达 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 的边缘 - An example of the QTab getting stuck before reaching the left side of the QTabBar.

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

【问题讨论】:

    标签: python-3.x pyqt5 qtabbar


    【解决方案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() 应该始终返回基本实现,否则在某些情况下您可能会遇到意外行为。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-10
      • 2015-09-02
      相关资源
      最近更新 更多