我正在尝试创建一个固定大小的自定义菜单,该菜单能够在子菜单项中上下滚动。
使用QMenu{menu-scrollable: 1; }
有效,但仅当列表非常大且超过屏幕长度但子菜单从屏幕顶部开始而不是菜单旁边时才有效。我想知道是否有一种方法可以启用滚动功能,或者只是将子菜单从屏幕顶部向下移动。
下面的代码通过菜单将子菜单添加为固定大小,但无法访问未显示的项目。如果您取消注释for i in range(100):
,您将在屏幕顶部看到关于子菜单的我的意思,但是具有滚动功能。
有人有什么想法吗?
import sys
from PyQt5.QtCore import QPoint, QEvent
from PyQt5.QtWidgets import QWidget, QPushButton, QVBoxLayout, QApplication, QAction, QMenu
class MyMenu(QMenu):
def event(self, event):
if event.type() == QEvent.Show:
self.move(self.parent().mapToGlobal(QPoint(-88, 0)))
return super(MyMenu, self).event(event)
class MainWindow(QWidget):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setStyleSheet("QMenu::item {height: 40px;margin: 0px;padding: 2px 25px 2px 20px;border: none;}")
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)
self.menu = QMenu("Menu1", self.btn)
self.menu.setStyleSheet("QMenu{menu-scrollable: 1; }")
self.menu.setMaximumHeight(226)
self.btn.menu().addMenu(self.menu)
self.menu2 = QMenu("Menu2", self.btn)
self.menu2.setStyleSheet("QMenu{menu-scrollable: 1; }")
self.menu2.setMaximumHeight(226)
self.btn.menu().addMenu(self.menu2)
self.menu3 = QMenu("Menu3", self.btn)
self.menu3.setStyleSheet("QMenu{menu-scrollable: 1; }")
self.menu3.setMaximumHeight(226)
self.btn.menu().addMenu(self.menu3)
self.menu4 = QMenu("Menu4", self.btn)
self.menu4.setStyleSheet("QMenu{menu-scrollable: 1; }")
self.menu4.setMaximumHeight(226)
self.btn.menu().addMenu(self.menu4)
self.menu5 = QMenu("Menu5", self.btn)
self.menu5.setStyleSheet("QMenu{menu-scrollable: 1; }")
self.menu5.setMaximumHeight(226)
self.btn.menu().addMenu(self.menu5)
for i in range(15):
# for i in range(100):
action = QAction("item"+str(i), self)
self.menu.addAction(action)
self.menu2.addAction(action)
self.menu3.addAction(action)
self.menu4.addAction(action)
self.menu5.addAction(action)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()
编辑:
我现在有一个有效的示例,尽管我不确定它为什么起作用。
我可以使用QStyle.PM_MenuScrollerHeight
和QStyle.PM_MenuDesktopFrameWidth
来工作,但是必须有更好的方法。
下面的代码可以工作,但是在子菜单中至少需要23个项目才能激活滚动条。我敢肯定,只需进行一些配置即可解决此问题,但现在这就是我得到的。
如果有人有任何建议,将不胜感激。
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.myMenu.setFixedHeight(120)
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(23):
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_()