python - QScrollArea 是否对 wheelEvent 做出反应,也在儿童占用的空间中?
问题描述
考虑这个例子:
#!/usr/bin/env python
import sys,os
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtCore import Qt
class MainWindow(QtWidgets.QMainWindow):
class ScrollAreaWheel(QtWidgets.QScrollArea): # SO:9475772
def __init__(self, parent=None):
super(MainWindow.ScrollAreaWheel, self).__init__(parent)
self.parent = parent
def wheelEvent(self, event):
print("wheelEvent", event.angleDelta().y())
def __init__(self):
#~ self.do_init = QtCore.QEvent.registerEventType()
QtWidgets.QMainWindow.__init__(self)
self.setMinimumWidth(1000)
self.setMinimumHeight(400)
self.frame1 = QtWidgets.QFrame(self)
self.frame1.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame1layout = QtWidgets.QGridLayout(self.frame1)
self.frame1layout.setSpacing(0);
self.frame1layout.setContentsMargins(0,0,0,0);
self.frame1widget = QtWidgets.QWidget()
self.frame1widget.setLayout(QtWidgets.QGridLayout())
self.frame1layout.addWidget(self.frame1widget)
self.frame1scroll = MainWindow.ScrollAreaWheel(self) #QtWidgets.QScrollArea()
self.frame1scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.frame1scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.frame1widget.layout().addWidget(self.frame1scroll, 0, 0) #, Qt.AlignCenter)
#self.frame1scrolllayout = QtWidgets.QHBoxLayout(self.frame1scroll)
self.frame1scrolllayout = QtWidgets.QGridLayout(self.frame1scroll)
self.frame1scroll.setWidget(self.frame1scrolllayout.widget())
self.frame1scroll.setWidgetResizable(True)
self.frame1scroll.setAlignment(Qt.AlignCenter)
self.frame1label = QtWidgets.QLabel()
self.frame1scrolllayout.addWidget(self.frame1label, 0, 0, Qt.AlignCenter) ##
pixmap = QtGui.QPixmap(200, 100)
pixmap.fill(Qt.red)
self.frame1label.setPixmap(pixmap)
self.frame2 = QtWidgets.QFrame(self)
self.frame2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame2layout = QtWidgets.QHBoxLayout(self.frame2)
self.frame2layout.setSpacing(0);
self.frame2layout.setContentsMargins(0,0,0,0);
self.frame2scroll = QtWidgets.QScrollArea(self)
self.frame2scroll.setWidgetResizable(True)
self.frame2widget = QtWidgets.QWidget()
self.frame2widget.setLayout(QtWidgets.QGridLayout())
self.frame2scroll.setWidget(self.frame2widget)
self.frame2layout.addWidget(self.frame2scroll)
self.mainwid = QtWidgets.QWidget()
self.mainwid.setLayout(QtWidgets.QGridLayout())
self.setCentralWidget(self.mainwid)
self.splitter1 = QtWidgets.QSplitter(Qt.Horizontal)
self.splitter1.addWidget(self.frame1)
self.splitter1.addWidget(self.frame2)
self.splitter1.setSizes([600, 600]); # equal splitter at start
self.mainwid.layout().addWidget(self.splitter1)
self.mainwid.layout().update()
if __name__ == "__main__":
app = QtWidgets.QApplication([])
main = MainWindow()
main.show()
sys.exit(app.exec_())
它生成这个(Ubuntu 18.04):
我只想在左侧 QScrollArea 上使用鼠标滚轮,为此我创建了一个单独的类。但是,它的 wheelEvent 仅在我在红色框外时触发,而不是在我将鼠标悬停在它上方时触发。即使鼠标悬停在子标签(红色框)上,如何使 ScrollAreaWheel.wheelEvent 触发?
解决方案
您是QLabel
放置在顶部QScrollArea
而不是将其放置在内部,在视觉上它是相同的,但在事件级别上却不是。
from PyQt5 import QtCore, QtGui, QtWidgets
class ScrollAreaWheel(QtWidgets.QScrollArea):
def wheelEvent(self, event):
print("wheelEvent", event.angleDelta().y())
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setMinimumSize(1000, 400)
frame1 = QtWidgets.QFrame(frameShape=QtWidgets.QFrame.StyledPanel)
scrollarea1 = ScrollAreaWheel(widgetResizable=True)
scrollarea1.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
scrollarea1.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
widget1 = QtWidgets.QWidget()
scrollarea1.setWidget(widget1)
label_lay = QtWidgets.QGridLayout(widget1)
lay1 = QtWidgets.QVBoxLayout(frame1)
lay1.addWidget(scrollarea1)
pixmap = QtGui.QPixmap(200, 100)
pixmap.fill(QtCore.Qt.red)
label = QtWidgets.QLabel(pixmap=pixmap)
label_lay.addWidget(label, 0, 0, QtCore.Qt.AlignCenter)
#==============================
frame2 = QtWidgets.QFrame(frameShape=QtWidgets.QFrame.StyledPanel)
scrollarea2 = QtWidgets.QScrollArea(widgetResizable=True)
scrollarea2.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
scrollarea2.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
widget2 = QtWidgets.QWidget()
scrollarea2.setWidget(widget2)
splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
splitter.addWidget(frame1)
splitter.addWidget(frame2)
splitter.setSizes([600, 600])
self.setCentralWidget(splitter)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
推荐阅读
- python - 在 lambda 语句中的 for 语句中使用 if else 语句
- android - Flutter 列显示 Android 中小部件之间的额外空间
- javascript - 表格行 (JS) 的编辑/保存按钮的可见性问题
- discord.py - 如何在 discord.py 中发出 ping 命令?
- xml - xsd:sequence: 发现问题开始于:simpleType
- c# - C# CopyBlock 与 CopyBlockUnaligned 用例
- javascript - 如何将其转换为在用户更改下拉框时触发的回调?
- c# - 位图加载内存增加 10 倍文件大小
- c# - Xamarin 发送 IR 信号 (Android)
- python - Python骰子程序,随机整数不变