【发布时间】:2019-04-02 12:55:38
【问题描述】:
我正在尝试找出一种方法来自定义QListWidget 的滚动条,以使滚动条位于QListWidget 的上方和下方,而不是正常的垂直和水平滚动条。
如果您不明白我的意思,请查看下面的示例。
在下面的示例中,我使用 QPushButtons 和 QTimers 来控制滚动条来代替滚动条,但我正在寻找的是滚动条,如启用菜单滚动时 QMenu 中的滚动条。
如果这不是一个选项,我想知道是否有滚动条信号或我可以尝试使用什么来知道滚动条何时正常激活?这样我就可以根据需要显示/隐藏按钮。谢谢。
import sys
from PyQt5.QtCore import pyqtSignal, QTimer, Qt
from PyQt5.QtGui import QPainter
from PyQt5.QtWidgets import QWidget, QPushButton, QVBoxLayout, \
QApplication, QStyle, QListWidget, QStyleOptionButton, QListWidgetItem
class UpBtn(QPushButton):
mouseHover = pyqtSignal()
def __init__(self):
QPushButton.__init__(self)
self.setMouseTracking(True)
self.timer = QTimer()
def paintEvent(self, event):
painter = QPainter()
painter.begin(self)
opt = QStyleOptionButton()
self.initStyleOption(opt)
self.style().drawControl(QStyle.CE_ScrollBarSubLine, opt, painter, self)
painter.end()
def startScroll(self):
self.mouseHover.emit()
def enterEvent(self, event):
self.timer.timeout.connect(self.startScroll)
self.timer.start(120)
def leaveEvent(self, event):
self.timer.stop()
class DwnBtn(QPushButton):
mouseHover = pyqtSignal()
def __init__(self):
QPushButton.__init__(self)
self.setMouseTracking(True)
self.timer = QTimer()
def paintEvent(self, event):
painter = QPainter()
painter.begin(self)
opt = QStyleOptionButton()
self.initStyleOption(opt)
self.style().drawControl(QStyle.CE_ScrollBarAddLine, opt, painter, self)
painter.end()
def startScroll(self):
self.mouseHover.emit()
def enterEvent(self, event):
self.timer.timeout.connect(self.startScroll)
self.timer.start(120)
def leaveEvent(self, event):
self.timer.stop()
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
self.layout = QVBoxLayout()
self.layout.setContentsMargins(0, 0, 0, 0)
self.layout.setSpacing(0)
self.upBtn = UpBtn()
self.upBtn.setFixedWidth(230)
self.layout.addWidget(self.upBtn)
self.listWidget = QListWidget()
self.listWidget.setFixedWidth(230)
self.listWidget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.listWidget.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.layout.addWidget(self.listWidget)
self.downBtn = DwnBtn()
self.downBtn.setFixedWidth(230)
self.layout.addWidget(self.downBtn)
self.setLayout(self.layout)
self.upBtn.clicked.connect(self.upBtnClicked)
self.upBtn.mouseHover.connect(self.upBtnClicked)
self.downBtn.clicked.connect(self.downBtnClicked)
self.downBtn.mouseHover.connect(self.downBtnClicked)
for i in range(100):
item = QListWidgetItem()
item.setText("list item " + str(i))
self.listWidget.addItem(item)
def upBtnClicked(self):
cur = self.listWidget.currentRow()
self.listWidget.setCurrentRow(cur - 1)
def downBtnClicked(self):
cur = self.listWidget.currentRow()
self.listWidget.setCurrentRow(cur + 1)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
编辑:
这是我正在谈论的示例图像。这是一个可滚动的QMenu。
编辑:
可滚动QMenu 代码。
取消注释注释部分以获得图像中的固定大小。通常 Qmenu 滚动仅在菜单项超过屏幕高度时才起作用。我只是在寻找顶部和底部悬停样式滚动,但要在QListWidget 中使用。
import sys
from PyQt5.QtCore import QPoint, QEvent
from PyQt5.QtWidgets import QWidget, QPushButton, QVBoxLayout, \
QApplication, QAction, QMenu, QProxyStyle, QStyle
class MyMenu(QMenu):
def event(self, event):
if event.type() == QEvent.Show:
self.move(self.parent().mapToGlobal(QPoint(-108, 0)))
return super(MyMenu, self).event(event)
# class CustomStyle(QProxyStyle):
# def pixelMetric(self, QStyle_PixelMetric, option=None, widget=None):
# if QStyle_PixelMetric == QStyle.PM_MenuScrollerHeight:
# return 15
# if QStyle_PixelMetric == QStyle.PM_MenuDesktopFrameWidth:
# return 290
# else:
# return QProxyStyle.pixelMetric(self, QStyle_PixelMetric, option, widget)
class MainWindow(QWidget):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.layout = QVBoxLayout()
self.btn = QPushButton("Button")
self.btn.setFixedHeight(30)
self.btn.setFixedWidth(100)
self.myMenu = MyMenu("Menu", self.btn)
self.btn.setMenu(self.myMenu)
self.layout.addWidget(self.btn)
self.setLayout(self.layout)
menus = []
for _ in range(5):
myMenus = QMenu("Menu"+str(_+1), self.btn)
# myMenus.setFixedHeight(120)
myMenus.setStyleSheet("QMenu{menu-scrollable: 1; }")
menus.append(myMenus)
for i in menus:
self.btn.menu().addMenu(i)
for item in range(100):
action = QAction("item" + str(item), self)
i.addAction(action)
if __name__ == '__main__':
app = QApplication(sys.argv)
# app.setStyle(CustomStyle())
w = MainWindow()
w.show()
app.exec_()
【问题讨论】:
-
你可以展示你想要得到的东西的图片。您希望何时显示按钮?如果我执行你的代码,如果鼠标在按钮上,只看滚动,我不知道你想得到什么。
-
如果可能的话,我非常想获得相同的功能或接近 QMenu 中滚动的工作方式。如果我必须使用我的示例中的按钮,我希望按钮仅在需要时显示,就像滚动条通常在列表很长并且项目不在视野中时所做的那样。当列表很短且在列表小部件中完全显示时,我想隐藏按钮,这就是为什么我正在寻找使用滚动条的内置方法或尝试捕获滚动条何时正常激活以便我知道何时显示/隐藏按钮。
-
QMenu 依赖于样式和操作系统,所以我不明白您想要获得什么,您可以显示您想要更好地了解您的 QMenu 的图像。另一方面,第二点我已经明白了。
-
哦,对不起。我刚刚用一张图片更新了我的帖子。
-
最后一件事,你可以分享可滚动的 QMenu 代码
标签: python pyqt pyqt5 qlistwidget qscrollbar