03 июл. 2009 г., 13:26 отAnurag Uniyal

Меню wxPython не отображает изображение

Я создаю меню и назначаю изображения для пунктов меню, иногда первый элемент в меню не отображает изображения, я не могу найти причину. Я попытался сделать простой автономный пример, и ниже приведен код, который демонстрирует проблему на моей машине. Я использую Windows XP, WX 2.8.7.1 (MSW-Unicode) '

import wx

def getBmp():
    bmp = wx.EmptyBitmap(16,16)
    return bmp

class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, style=wx.DEFAULT_FRAME_STYLE, parent=None)

        self.SetTitle("why New has no image?")

        menuBar = wx.MenuBar()
        fileMenu=wx.Menu()
        item = fileMenu.Append(wx.ID_NEW, "New")
        item.SetBitmap(getBmp())
        item = fileMenu.Append(wx.ID_OPEN, "Open")
        item.SetBitmap(getBmp())
        item = fileMenu.Append(wx.ID_SAVE, "Save")
        item.SetBitmap(getBmp())
        menuBar.Append(fileMenu, "File")
        self.SetMenuBar(menuBar) 


app = wx.PySimpleApp()
frame=MyFrame()
frame.Show()
app.SetTopWindow(frame)
app.MainLoop()

Так ты видишь проблему и в чем причина?

Выво: Да, это официальная ошибка, я создал простой класс Menu для преодоления этой ошибки, используя трюк, заданный "balpha" в выбранном ответе

Он переопределяет каждое меню. Добавляет метод и видит, добавляется ли элемент меню с изображением в первый раз, если да, создает фиктивный элемент и удаляет его позже.

Это также добавляет функцию / ограничение, так что вместо вызова SetBitmap вы должны передать битовое изображение в качестве необязательного аргумента image

import wx

class MockMenu(wx.Menu):
    """
    A custom menu class in which image param can be passed to each Append method
    it also takes care of bug http://trac.wxwidgets.org/ticket/4011
    """

    def __init__(self, *args, **kwargs):
        wx.Menu.__init__(self, *args, **kwargs)
        self._count = 0

    def applyBmp(self, unboundMethod, *args, **kwargs):
        """
        there is a bug in wxPython so that it will not display first item bitmap
        http://trac.wxwidgets.org/ticket/4011
        so we keep track and add a dummy before it and delete it after words
        may not work if menu has only one item
        """

        bmp = None
        if 'image' in kwargs:
            bmp = kwargs['image']

        tempitem = None
        # add temp item so it is first item with bmp 
        if bmp and self._count == 1:
            tempitem = wx.Menu.Append(self, -1,"HACK")
            tempitem.SetBitmap(bmp)

        ret = unboundMethod(self, *args, **kwargs)
        if bmp:
            ret.SetBitmap(bmp)

        # delete temp item
        if tempitem is not None:
            self.Remove(tempitem.GetId())

        self._lastRet = ret
        return ret

    def Append(self, *args, **kwargs):
        return self.applyBmp(wx.Menu.Append, *args, **kwargs)

    def AppendCheckItem(self, *args, **kwargs):
        return self.applyBmp(wx.Menu.AppendCheckItem, *args, **kwargs)

    def AppendMenu(self, *args, **kwargs):
        return self.applyBmp(wx.Menu.AppendMenu, *args, **kwargs)

Ответы на вопрос(2)

03 авг. 2009 г., 22:35 от

если вы создаете каждый элемент меню с помощью wx.MenuItem (), устанавливаете его растровое изображение и только затем добавляете его в меню. Это приводит к правильному отображению растровых изображений. Я тестирую с wxPython 2.8.10.1 для Windows.

03 июл. 2009 г., 09:44 отbalpha

Это подтвержденная ошибка который, видимо, был открыт довольно давно. Попробовав немного, этот обходной путь, кажется, делает это:

    menuBar = wx.MenuBar()
    fileMenu=wx.Menu()
    tempitem = fileMenu.Append(-1,"X")       # !!!
    tempitem.SetBitmap(getBmp())             # !!!
    item = fileMenu.Append(wx.ID_NEW, "New")
    fileMenu.Remove(tempitem.GetId())        # !!!
    item.SetBitmap(getBmp())
    item = fileMenu.Append(wx.ID_OPEN, "Open")
    item.SetBitmap(getBmp())
    item = fileMenu.Append(wx.ID_SAVE, "Save")
    item.SetBitmap(getBmp())
    menuBar.Append(fileMenu, "File")
    self.SetMenuBar(menuBar) 

Обратите внимание, что позиция вызова fileMenu.Remove - это самая ранняя позиция, которая работает, но вы также можете переместить ее вниз. НТН.

ВАШ ОТВЕТ НА ВОПРОС