You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt5在QMenu中集成QFontComboBox的实现问题

问题描述

在PyQt5 GUI开发过程中,尝试将QFontComboBox组件集成到QMenu菜单内,需要在菜单中选中特定字体时实现两个效果:

  • 自动关闭当前打开的QMenu菜单
  • 打印输出选中的字体名称
    原有测试代码运行后无法达到预期效果,原始代码如下:
from PyQt5.QtCore import QObject
from PyQt5.QtGui import QIcon, QFont, QCursor
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QFontComboBox, QWidgetAction, QMenu, QPushButton
class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Pyside2 FontCombo Box")
        self.setGeometry(300,200,300,250)
        self.setFontBox()
        self.setIcon()
        self.show()
    def setIcon(self):
        appIcon = QIcon("icon.png")
        self.setWindowIcon(appIcon)
    def setFontBox(self):
        self.font_button = QPushButton(self)
        self.font_button.setFixedWidth(300)
        self.font_button.clicked.connect(lambda: self.setFontmenu())
        vbox = QVBoxLayout()
        vbox.addWidget(self.font_button)
        self.setLayout(vbox)
    def setFontmenu(self):
        font_menu = QMenu()
        font_submenu = QFontComboBox()
        font_submenu.setCurrentFont(QFont("Arial"))
        objectTest = QObject()
        widget = QWidgetAction(objectTest)
        widget.setDefaultWidget(font_submenu)
        font_menu.addAction(widget)
        font_menu.exec_(QCursor.pos())
        menu = font_menu
        menu.addSeparator()
        font_submenu.showPopup()
        font_submenu.setFocus()
        font_submenu.currentFontChanged.connect(self._changed)
    def _changed(self):
        font = self.currentFont().family()
        print(font)
        return
myapp = QApplication(sys.argv)
window = Window()
myapp.exec_()
sys.exit()
原代码问题排查
  • 缺少sys模块导入,代码启动时会直接抛出NameError
  • 代码执行顺序错误:QMenu.exec_()会阻塞当前流程,后续的信号绑定、分隔符添加、下拉框弹出逻辑全部要等菜单关闭后才会执行,完全不生效
  • _changed槽函数逻辑错误:调用self.currentFont()时self指向窗口实例,窗口类不存在该方法,无法获取选中字体
  • 对象父级绑定错误:QWidgetAction绑定到临时创建的QObject实例上,容易被Python垃圾回收导致组件异常
  • 未添加字体选中后关闭菜单的逻辑
修正后完整代码
import sys
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QIcon, QFont, QCursor
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QFontComboBox, QWidgetAction, QMenu, QPushButton

class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("PyQt5 FontCombo Box in Menu")
        self.setGeometry(300,200,300,250)
        self.setFontBox()
        self.setIcon()
        self.show()

    def setIcon(self):
        appIcon = QIcon("icon.png")
        self.setWindowIcon(appIcon)

    def setFontBox(self):
        self.font_button = QPushButton("选择字体", self)
        self.font_button.setFixedWidth(300)
        self.font_button.clicked.connect(self.setFontmenu)
        vbox = QVBoxLayout()
        vbox.addWidget(self.font_button)
        self.setLayout(vbox)

    def setFontmenu(self):
        font_menu = QMenu(self)
        font_submenu = QFontComboBox()
        font_submenu.setCurrentFont(QFont("Arial"))
        
        # 初始化组件动作,绑定父对象为菜单避免被回收
        widget_action = QWidgetAction(font_menu)
        widget_action.setDefaultWidget(font_submenu)
        font_menu.addAction(widget_action)
        font_menu.addSeparator()

        # 字体选中回调逻辑
        def on_font_selected(current_font):
            # 打印选中字体名称
            print(current_font.family())
            # 关闭当前菜单
            font_menu.close()

        # 菜单弹出前绑定信号
        font_submenu.currentFontChanged.connect(on_font_selected)

        # 弹出菜单
        font_menu.exec_(QCursor.pos())
        # 延迟展开字体下拉框,避免和菜单弹出冲突
        QTimer.singleShot(100, font_submenu.showPopup)

if __name__ == "__main__":
    myapp = QApplication(sys.argv)
    window = Window()
    sys.exit(myapp.exec_())
关键实现说明
  • 所有组件初始化、信号绑定逻辑全部放在exec_()调用前完成,避开菜单弹出的阻塞流程
  • 为QMenu、QWidgetAction绑定正确的父对象,避免临时对象被垃圾回收引发异常
  • 利用QFontComboBox.currentFontChanged信号自带的QFont参数直接获取选中字体,不需要额外调用组件方法
  • 选中字体后在回调内直接调用QMenu.close()实现菜单自动关闭
  • 用QTimer.singleShot做短延迟后再展开字体组合框的下拉列表,解决组件弹出冲突问题

内容的提问来源于stack exchange,提问作者ROOMBON

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 06:51:37