问题
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