-1

所以,我想将文本和 ICON 都显示为菜单栏项。

我已将以下语句用作:

self.helpMenu = menubar1.addMenu(QtGui.QIcon("home.png"),"&TEXT")

但这仅显示图标而不显示文本。所以需要帮助来修复它

4

2 回答 2

1

前提

看起来,尽管 Qt 提供了addMenu()创建一个同时具有图标和文本的菜单的功能,但它并未得到完全支持。

关于此事有一个相关且非常古老的错误报告,已被标记为已关闭和“超出范围”。我现在无法对其进行测试,但我会假设这是由于本机菜单栏支持,它主要用于支持该功能的 macOS 和 Linux 发行版。

也就是说,一种解决方法可能的,这是通过 QProxyStyle 完成的。

这有点复杂,但它可以无缝地工作,因为:

  1. 它仅在不使用本机菜单栏功能时启用(无论是可用还是刚刚禁用);
  2. 它使用 'fusion' 样式或 Windows 上的默认样式;

诀窍是确保代理返回正确的大小sizeFromContents(),包括文本图标(如果两者都存在),并尽可能在drawControl()and中使用默认实现drawItemText()(从更标准的样式中调用)。

带有图标和文本的菜单栏

class MenuProxy(QtWidgets.QProxyStyle):
    menuHack = False
    alertShown = False

    def useMenuHack(self, element, opt, widget):
        if (element in (self.CT_MenuBarItem, self.CE_MenuBarItem) and
            isinstance(widget, QtWidgets.QMenuBar) and
            opt.icon and not opt.icon.isNull() and opt.text):
                if not self.alertShown:
                    if widget.isNativeMenuBar():
                        # this will probably not be shown...
                        print('WARNING: menubar items with icons and text not supported for native menu bars')
                    styleName = self.baseStyle().objectName()
                    if not 'windows' in styleName and styleName != 'fusion':
                        print('WARNING: menubar items with icons and text not supported for "{}" style'.format(
                            styleName))
                    self.alertShown = True
                return True
        return False

    def sizeFromContents(self, content, opt, size, widget=None):
        if self.useMenuHack(content, opt, widget):
            # return a valid size that includes both the icon and the text
            alignment = (QtCore.Qt.AlignCenter | QtCore.Qt.TextShowMnemonic |
                QtCore.Qt.TextDontClip | QtCore.Qt.TextSingleLine)
            if not self.proxy().styleHint(self.SH_UnderlineShortcut, opt, widget):
                alignment |= QtCore.Qt.TextHideMnemonic

            width = (opt.fontMetrics.size(alignment, opt.text).width() +
                self.pixelMetric(self.PM_SmallIconSize) +
                self.pixelMetric(self.PM_LayoutLeftMargin) * 2)

            textOpt = QtWidgets.QStyleOptionMenuItem(opt)
            textOpt.icon = QtGui.QIcon()
            height = super().sizeFromContents(content, textOpt, size, widget).height()

            return QtCore.QSize(width, height)

        return super().sizeFromContents(content, opt, size, widget)

    def drawControl(self, ctl, opt, qp, widget=None):
        if self.useMenuHack(ctl, opt, widget):
            # create a new option with no icon to draw a menubar item; setting
            # the menuHack allows us to ensure that the icon size is taken into
            # account from the drawItemText function
            textOpt = QtWidgets.QStyleOptionMenuItem(opt)
            textOpt.icon = QtGui.QIcon()
            self.menuHack = True
            self.drawControl(ctl, textOpt, qp, widget)
            self.menuHack = False

            # compute the rectangle for the icon and call the default 
            # implementation to draw it
            iconExtent = self.pixelMetric(self.PM_SmallIconSize)
            margin = self.pixelMetric(self.PM_LayoutLeftMargin) / 2
            top = opt.rect.y() + (opt.rect.height() - iconExtent) / 2
            iconRect = QtCore.QRect(opt.rect.x() + margin, top, iconExtent, iconExtent)
            pm = opt.icon.pixmap(widget.window().windowHandle(), 
                QtCore.QSize(iconExtent, iconExtent), 
                QtGui.QIcon.Normal if opt.state & self.State_Enabled else QtGui.QIcon.Disabled)
            self.drawItemPixmap(qp, iconRect, QtCore.Qt.AlignCenter, pm)
            return
        super().drawControl(ctl, opt, qp, widget)

    def drawItemText(self, qp, rect, alignment, palette, enabled, text, role=QtGui.QPalette.NoRole):
        if self.menuHack:
            margin = (self.pixelMetric(self.PM_SmallIconSize) + 
                self.pixelMetric(self.PM_LayoutLeftMargin))
            rect = rect.adjusted(margin, 0, 0, 0)
        super().drawItemText(qp, rect, alignment, palette, enabled, text, role)


class Test(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        menu = self.menuBar().addMenu(QtGui.QIcon.fromTheme('document-new'), 'File')
        menu.addAction(QtGui.QIcon.fromTheme('application-exit'), 'Quit')
        self.menuBar().addMenu(QtGui.QIcon.fromTheme('edit-cut'), 'Edit')


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    app.setStyle(MenuProxy(QtWidgets.QStyleFactory.create('fusion')))
    # or, for windows systems:
    # app.setStyle(MenuProxy())

    test = Test()
    test.show()
    sys.exit(app.exec_())
于 2021-01-14T04:35:21.377 回答
0

我对 Windows 7 和 PyQt 5.12.2 有同样的故事,并试图像这样解决它:

import sys
from PyQt5.Qt import *


class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        self.centralWidget = QLabel("Hello, World")
        self.centralWidget.setAlignment(Qt.AlignCenter)
        self.setCentralWidget(self.centralWidget)

        menuBar = QMenuBar(self)
        self.setMenuBar(menuBar)    
        
        self.helpContentAction = QAction(QIcon("img/readMe.png"), "&Help Content", self)
        self.aboutAction = QAction("&About", self)

#        helpMenu = menuBar.addMenu(QIcon("img/qtlogo.png"), "&Help")
        helpMenu = menuBar.addMenu("            &Help")                   # +++
#                                   ^^^^^^^^^^^^        
        
        helpMenu.addAction(self.helpContentAction)
        helpMenu.addAction(self.aboutAction)
 
qss = """        
QMenuBar {
    background-color: qlineargradient(
        x1:0, y1:0, x2:0, y2:1,
        stop:0 lightgray, stop:1 darkgray
    );
}
QMenuBar::item {
    background-color: darkgray;      
    padding: 1px 5px 1px -25px;                                           /* +++  */
    background: transparent;
    image: url(img/qtlogo.png);                                           /* +++ * /
}
QMenuBar::item:selected {    
    background-color: lightgray;
}
QMenuBar::item:pressed {
    background: lightgray;
}        
"""


if __name__ == "__main__":
    app = QApplication(sys.argv)
    
#    app.setStyle('Fusion')  
    app.setStyleSheet(qss)                                                # +++
    app.setFont(QFont("Times", 10, QFont.Bold))
    
    win = Window()
    win.setWindowTitle("Python Menus")
    win.resize(600, 350)
    win.show()
    sys.exit(app.exec_())

在此处输入图像描述

于 2021-01-14T07:44:55.177 回答