Have tabs keep focus on mousewheel over them in a PyQt5 scrollarea?

家住魔仙堡 提交于 2019-12-13 03:56:07

问题


With the code below, I get a tabbed widget inside a scroll area.

The tabs are quite long horizontally, forcing the user to use scrollbar to get to the right, and then click on the rightmost tab chooser, in order to get from tab 1 to, say, tab 5 - I'd like to avoid this with mousewheel.

However, I get the following behavior:

... that is:

  • When I use mousewheel over an area of the "page", it scrolls up and down, as expected (and wanted)
  • When I use mousewheel "down" over the area of the tabs, first it switches from current tab (N) to next (N+1) tab - and then it proceeds scrolling down on further mousewheel down, which I do not want
  • When I use mousewheel "up" over the area of the tabs, it goes from current tab (N) to previous (N-1) tab - all the way up to tab 1 on further mousewheel up events, which is what I want

So, in brief - when the mouse is over the tabs area, I would like mousewheel up/down events to only switch between tabs, and not do any scrolling - and as soon as the mouse is outside of the tabs area and within the area of a "page", that is when I want scrolling upon mousewheel. How can I achieve this?

The code, test-tabs.py:

from PyQt5 import QtCore, QtGui, QtWidgets
import sys, os

class DataItem(object):
  def __init__(self):
    self.label = ""
    self.type = "" # SECTION or LINE
    self.children = []

class SectionWidget(QtWidgets.QWidget):
  def __init__(self, indataitem, parent=None):
    QtWidgets.QWidget.__init__(self, parent)
    self.setLayout(QtWidgets.QFormLayout())
    child_count = len(indataitem.children)
    if child_count < 1:
      return
    tabs = None
    for child in indataitem.children:
      label = child.label
      child_type = child.type
      if child_type == "SECTION":
        if not tabs:
          tabs = QtWidgets.QTabWidget()
          self.layout().insertRow(0, tabs)
        tabs.addTab(SectionWidget(child), label)
      elif child_type == "LINE":
        self.layout().addRow(label.upper(), QtWidgets.QPushButton(label, self))


class MainWindow(QtWidgets.QMainWindow):
  def __init__(self, parent=None):
    super(MainWindow, self).__init__(parent)
    self.setMinimumSize(600, 400)

    self.frame = QtWidgets.QFrame(self)
    self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
    self.framelayout = QtWidgets.QHBoxLayout(self.frame)
    self.framelayout.setSpacing(0);
    self.framelayout.setContentsMargins(0,0,0,0);
    self.scroll = QtWidgets.QScrollArea(self)
    self.scroll.setWidgetResizable(False)
    self.scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
    self.scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)

    self.framelayout.addWidget(self.scroll)

    self.widget = QtWidgets.QWidget()
    self.widget.setLayout(QtWidgets.QGridLayout())
    self.widget.setStyleSheet("""
      .QWidget { border: 2px solid blue; border-radius: 2px; background-color: rgb(30, 255, 30); }
    """)

    self.uidata = DataItem()
    LINESPERROUND=10
    for ix in range(5):
      theading = DataItem()
      theading.label = "Very-very-very-very-very-long-heading-{:02d}".format(ix+1)
      theading.type = "SECTION"
      for iy in range(LINESPERROUND*(ix+1)):
        tline = DataItem()
        tline.label = (ix+1)*"Entry-{:02d}-{:02d}".format(ix+1, iy+1)
        tline.type = "LINE"
        theading.children.append(tline)
      self.uidata.children.append(theading)

    self.uisection = SectionWidget(self.uidata)
    self.widget.layout().addWidget(self.uisection, 0, 0, 1, 3)
    self.widget.layout().setColumnStretch(0, 1)
    self.scroll.setWidget(self.widget)

    self.setCentralWidget(self.frame)

if __name__ == '__main__':
  import sys
  app = QtWidgets.QApplication(sys.argv)
  w = MainWindow()
  w.resize(640, 480)
  w.show()
  sys.exit(app.exec_())

来源:https://stackoverflow.com/questions/54371585/have-tabs-keep-focus-on-mousewheel-over-them-in-a-pyqt5-scrollarea

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!