Have tabs keep focus on mousewheel over them in a

2019-08-31 04:02发布

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:

test-tabs.gif

... 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_())

0条回答
登录 后发表回答