Я пытаюсь создать пользовательское меню фиксированного размера, которое может прокручивать элементы подменю вверх и вниз.
Использование 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_()