Я создал пример кода Toy, чтобы воспроизвести проблему, которую мне нужно решить, которая также происходит в основном приложении, которое я разрабатываю.
Код был выполнен на Python 3.13.5.
Пример кода Toy
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Small toy example reproducing the tooltip problem
"""
import wx
class MyFrame(wx.Frame):
def __init__(self):
# Ensure a wx.App exists. Some callers may import this module
# and instantiate MyFrame before an App is created; guard against that.
try:
app_exists = bool(wx.GetApp())
except Exception:
app_exists = False
if not app_exists:
self._created_app = True
# Create a non-redirected App but do NOT start the MainLoop here.
self._app = wx.App(False)
else:
self._created_app = False
wx.Frame.__init__(self, None, title="Debug Tooltips with Submenus", size=(400, 300))
# Create status bar
self.CreateStatusBar()
self.SetStatusText("Ready. Right-click to open the menu.")
panel = wx.Panel(self)
panel.SetBackgroundColour(wx.Colour(200, 200, 200))
panel.Bind(wx.EVT_RIGHT_UP, self.on_right_click)
sizer = wx.BoxSizer(wx.VERTICAL)
label = wx.StaticText(panel, label="Right-click the window to open the menu with submenus")
sizer.Add(label, 0, wx.ALL, 10)
panel.SetSizer(sizer)
def on_right_click(self, event):
menu = wx.Menu()
menu.Bind(wx.EVT_MENU_HIGHLIGHT, self.on_menu_highlight)
menu.Bind(wx.EVT_MENU_CLOSE, self.on_menu_close)
# Simple item (no submenu)
simple_item = wx.MenuItem(menu, wx.NewId(), "Simple Option", "This is a simple tooltip without submenu")
menu.Append(simple_item)
menu.AppendSeparator()
# Submenu with options
sub_menu = wx.Menu()
sub_menu.Bind(wx.EVT_MENU_HIGHLIGHT, self.on_menu_highlight)
sub_item_1 = wx.MenuItem(sub_menu, wx.NewId(), "Sub Option 1", "Tooltip for sub-option 1")
sub_menu.Append(sub_item_1)
sub_item_2 = wx.MenuItem(sub_menu, wx.NewId(), "Sub Option 2", "Tooltip for sub-option 2")
sub_menu.Append(sub_item_2)
sub_item_3 = wx.MenuItem(sub_menu, wx.NewId(), "Sub Option 3", "Tooltip for sub-option 3")
sub_menu.Append(sub_item_3)
# Add submenu to the main menu
sub_menu_item = wx.MenuItem(menu, wx.NewId(), "Submenu", "Submenu options", wx.ITEM_NORMAL, sub_menu)
menu.Append(sub_menu_item)
self.PopupMenu(menu, event.GetPosition())
menu.Destroy()
def on_menu_highlight(self, event):
"""Show the menu item's help string in the status bar."""
try:
menu = event.GetMenu()
if not menu:
return
# Find the MenuItem first; GetHelpString will assert if item doesn't exist
item = None
if hasattr(menu, 'FindItem'):
try:
item = menu.FindItem(event.GetId())
except Exception:
item = None
if not item and hasattr(menu, 'FindItemById'):
try:
item = menu.FindItemById(event.GetId())
except Exception:
item = None
if not item:
# No corresponding MenuItem in this menu (e.g. hovering a submenu label)
self.SetStatusText("")
print(f"No MenuItem for ID: {event.GetId()}")
return
# Prefer the MenuItem's help getter
help_text = None
if hasattr(item, 'GetHelp'):
help_text = item.GetHelp()
elif hasattr(item, 'GetHelpString'):
help_text = item.GetHelpString()
else:
# Fallback: attempt menu.GetHelpString safely
try:
help_text = menu.GetHelpString(event.GetId())
except Exception:
help_text = None
if help_text:
self.SetStatusText(help_text)
print(f"Help text found: {help_text}")
else:
self.SetStatusText("")
print(f"No help text for MenuItem ID: {event.GetId()}")
except Exception as e:
print(f"Error in on_menu_highlight: {e}")
def on_menu_close(self, event):
"""Clear the status bar when the menu closes."""
self.SetStatusText("")
if __name__ == '__main__':
app = wx.App()
frame = MyFrame()
frame.Show()
app.MainLoop()
Проблема
Подсказка отображается для меню, не имеющих подменю.
Однако для меню, имеющих подменю, и для элементов в этих подменю, всплывающая подсказка не отображается, как вы можете видеть ниже.
Чего я хочу
Я хотел бы знать, есть ли простой способ получить всплывающую подсказку для подменю в wxPython отображаться в строке состояния.
Примечание
Имейте в виду, что я пробовал и другие варианты, но ни один из них пока не увенчался успехом. Однако в моем основном приложении случается, что в некоторых подменю отображаются всплывающие подсказки, но только для параметров подменю, которые имеют те же идентификаторы, что и некоторые из них, которые я ранее определил в основной строке меню. Однако мне не удалось воспроизвести такое поведение в примере кода Toy. Но не все подменю должны находиться в строке главного меню, поэтому этот обходной путь мне не подходит.
Я создал пример кода Toy, чтобы воспроизвести проблему, которую мне нужно решить, которая также происходит в основном приложении, которое я разрабатываю. Код был выполнен на Python 3.13.5. Пример кода Toy [code]#!/usr/bin/env python # -*- coding: utf-8 -*- """ Small toy example reproducing the tooltip problem """
import wx
class MyFrame(wx.Frame): def __init__(self): # Ensure a wx.App exists. Some callers may import this module # and instantiate MyFrame before an App is created; guard against that. try: app_exists = bool(wx.GetApp()) except Exception: app_exists = False
if not app_exists: self._created_app = True # Create a non-redirected App but do NOT start the MainLoop here. self._app = wx.App(False) else: self._created_app = False
wx.Frame.__init__(self, None, title="Debug Tooltips with Submenus", size=(400, 300))
# Create status bar self.CreateStatusBar() self.SetStatusText("Ready. Right-click to open the menu.")
sizer = wx.BoxSizer(wx.VERTICAL) label = wx.StaticText(panel, label="Right-click the window to open the menu with submenus") sizer.Add(label, 0, wx.ALL, 10) panel.SetSizer(sizer)
def on_right_click(self, event): menu = wx.Menu() menu.Bind(wx.EVT_MENU_HIGHLIGHT, self.on_menu_highlight) menu.Bind(wx.EVT_MENU_CLOSE, self.on_menu_close)
# Simple item (no submenu) simple_item = wx.MenuItem(menu, wx.NewId(), "Simple Option", "This is a simple tooltip without submenu") menu.Append(simple_item)
menu.AppendSeparator()
# Submenu with options sub_menu = wx.Menu() sub_menu.Bind(wx.EVT_MENU_HIGHLIGHT, self.on_menu_highlight)
# Add submenu to the main menu sub_menu_item = wx.MenuItem(menu, wx.NewId(), "Submenu", "Submenu options", wx.ITEM_NORMAL, sub_menu) menu.Append(sub_menu_item)
def on_menu_highlight(self, event): """Show the menu item's help string in the status bar.""" try: menu = event.GetMenu() if not menu: return
# Find the MenuItem first; GetHelpString will assert if item doesn't exist item = None if hasattr(menu, 'FindItem'): try: item = menu.FindItem(event.GetId()) except Exception: item = None if not item and hasattr(menu, 'FindItemById'): try: item = menu.FindItemById(event.GetId()) except Exception: item = None
if not item: # No corresponding MenuItem in this menu (e.g. hovering a submenu label) self.SetStatusText("") print(f"No MenuItem for ID: {event.GetId()}") return
if help_text: self.SetStatusText(help_text) print(f"Help text found: {help_text}") else: self.SetStatusText("") print(f"No help text for MenuItem ID: {event.GetId()}") except Exception as e: print(f"Error in on_menu_highlight: {e}")
def on_menu_close(self, event): """Clear the status bar when the menu closes.""" self.SetStatusText("")
if __name__ == '__main__': app = wx.App() frame = MyFrame() frame.Show() app.MainLoop() [/code] Проблема Подсказка отображается для меню, не имеющих подменю. [img]https://i.sstatic.net/ZL4P5yAm.png[/img]
Однако для меню, имеющих подменю, и для элементов в этих подменю, всплывающая подсказка не отображается, как вы можете видеть ниже. [img]https://i.sstatic.net/JRy8xf2C.png[/img]
Чего я хочу Я хотел бы знать, есть ли простой способ получить всплывающую подсказку для подменю в wxPython отображаться в строке состояния. Примечание Имейте в виду, что я пробовал и другие варианты, но ни один из них пока не увенчался успехом. Однако в моем основном приложении случается, что в некоторых подменю отображаются всплывающие подсказки, но только для параметров подменю, которые имеют те же идентификаторы, что и некоторые из них, которые я ранее определил в основной строке меню. Однако мне не удалось воспроизвести такое поведение в примере кода Toy. Но не все подменю должны находиться в строке главного меню, поэтому этот обходной путь мне не подходит.