2015-08-15 1 views
0

Я пытаюсь создать Gtk.MenuBar в моем приложении Python. This - это то, что я использовал в качестве учебника. Ниже мой код для создания MenuBar:Что вызывает утверждение 'GTK_IS_MENU_ITEM (child)' не удалось?

# -*- coding: utf-8 -*- 
import GTKSignal 

__author__ = 'xiaolong' 

from gi.repository import Gtk 


class XLDMenuBar(Gtk.MenuBar): 
    MENUBAR_UI_INFO = """<ui> 
      <menubar name='MenuBar'> 
       <menu action='FileMenu'> 

        <menu action='File_New'> 
         <menuitem action='File_New_Dictionary' /> 
        </menu> 

        <separator /> 

        <menuitem action='File_Open' /> 

        <menuitem action='File_Save' /> 

        <menu action='File_SaveAs'> 
         <menuitem action='File_SaveAs_Dictionary' /> 
         <menuitem action='File_SaveAs_SearchResult' /> 
         <menuitem action='File_SaveAs_SelectedVocables' /> 
        </menu> 

        <menuitem action='File_Exit' /> 

       </menu> 
      </menubar> 
     </ui>""" 

    def __init__(self, parent): 
     super().__init__() 

     self.parent = parent 
     self.toplevel_menubar_action_group = Gtk.ActionGroup("toplevel_menubar_action_group") 

     self.initialize_file_menu() 
     self.add_file_menu() 
     self.add_menu_action_handlers() 

     # TODO: add other actions, so far only file menu 

     self.load_ui_info() 

    def initialize_file_menu(self): 
     self.action_filemenu = Gtk.Action(name='FileMenu', label='File', tooltip='opens the file menu', stock_id=None) 

     # file -> new 
     self.action_filemenu_new = Gtk.Action(name='File_New', label='New', tooltip=None, stock_id=None) 
     self.action_filemenu_new_dictionary = Gtk.Action(
      name='File_New_Dictionary', 
      label='New dictionary …', 
      tooltip='opens the dialog for creating a new dictionary', 
      stock_id=Gtk.STOCK_NEW 
     ) 

     # file -> open 
     self.action_filemenu_open = Gtk.Action(
      name='File_Open', 
      label='Open …', 
      tooltip='opens the dialog for opening files', 
      stock_id=Gtk.STOCK_OPEN 
     ) 

     # file -> save 
     self.action_filemenu_save = Gtk.Action(
      name='File_Save', 
      label='Save', 
      tooltip='saves current changes of the dictionary to the dictionary file', 
      stock_id=Gtk.STOCK_SAVE 
     ) 

     # file -> saveas 
     self.action_filemenu_saveas = Gtk.Action(name='File_SaveAs', label='Save As', tooltip=None, stock_id=None) 
     self.action_filemenu_saveas_dictionary = Gtk.Action(
      name='File_SaveAs_Dictionary', 
      label='Save dictionary as …', 
      tooltip='saves the current dictionary with current changes to a specified file', 
      stock_id=Gtk.STOCK_SAVE_AS 
     ) 
     self.action_filemenu_saveas_searchresult = Gtk.Action(
      name='File_SaveAs_SearchResult', 
      label='Save search result as …', 
      tooltip='saves the current search result to a specified file', 
      stock_id=Gtk.STOCK_SAVE_AS 
     ) 
     self.action_filemenu_saveas_selectedvocables = Gtk.Action(
      name='File_SaveAs_SelectedVocables', 
      label='Save selected vocables as …', 
      tooltip='saves the currently selected vocables to a specified file', 
      stock_id=Gtk.STOCK_SAVE_AS 
     ) 

     # file -> exit 
     self.action_filemenu_exit = Gtk.Action(
      name='File_Exit', 
      label='Exit', 
      tooltip='Closes the application', 
      stock_id=Gtk.STOCK_QUIT 
     ) 

    def add_file_menu(self): 
     self.toplevel_menubar_action_group.add_action(self.action_filemenu) 
     self.toplevel_menubar_action_group.add_action(self.action_filemenu_new) 
     self.toplevel_menubar_action_group.add_action_with_accel(action=self.action_filemenu_new_dictionary, accelerator=None) 
     self.toplevel_menubar_action_group.add_action(self.action_filemenu_open) 
     self.toplevel_menubar_action_group.add_action(self.action_filemenu_save) 
     self.toplevel_menubar_action_group.add_action(self.action_filemenu_saveas) 
     self.toplevel_menubar_action_group.add_action(self.action_filemenu_saveas_dictionary) 
     self.toplevel_menubar_action_group.add_action(self.action_filemenu_saveas_searchresult) 
     self.toplevel_menubar_action_group.add_action(self.action_filemenu_saveas_selectedvocables) 
     self.toplevel_menubar_action_group.add_action(self.action_filemenu_exit) 

    def add_menu_action_handlers(self): 
     self.action_filemenu_new_dictionary.connect(GTKSignal.ACTIVATE, lambda widget: print('You\'ve clicked \"New dictionary\"!')) 
     self.action_filemenu_exit.connect(GTKSignal.ACTIVATE, lambda widget: print('You\'ve clicked Exit!')) 
     # TODO: add other action handlers 

    def load_ui_info(self): 
     uimanager = self.parent.create_ui_manager() 
     uimanager.insert_action_group(self.toplevel_menubar_action_group) 

     menubar = uimanager.get_widget("/MenuBar") 

     vertical_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) 
     vertical_box.pack_start(child=menubar, expand=False, fill=False, padding=0) 

     self.add(vertical_box) 

Однако, когда я пытаюсь создать экземпляр и добавить к моему главному окну, я получаю следующее утверждение FAIL:

(__main__.py:12392): Gtk-CRITICAL **: gtk_menu_shell_insert: assertion 'GTK_IS_MENU_ITEM (child)' failed 

для меня это звучит, как будто он говорит, что я пытаюсь добавить не MenuItem в Menu, но я не могу найти это в своем коде. В примере на веб-сайте учебника они добавили Gtk.Action s в Gtk.ActionGroups так же, как и я, но их код не вызывает этого утверждения. Я также проверил UI XML несколько раз уже и нет menu, к которому я пытаюсь добавить не menuitem, либо не menu, поэтому я действительно не знаю, что происходит.

Где ошибка, которую я делаю?

EDIT # 1

Чтобы добавить рабочий пример, я вставить код для главного окна приложения и вызов его.

Главное окно программы:

# -*- coding: utf-8 -*- 
from gi.repository import Gtk 
from gui.XLDMenuBar import XLDMenuBar 

__author__ = 'xiaolong' 


class XLDMainWindow(Gtk.Window): 

    WINDOW_TITLE = 'Xiaolong Dictionary' 
    DEFAULT_X_SIZE = 400 
    DEFAULT_Y_SIZE = 300 
    menubar = None 

    def __init__(self): 
     # super().__init__(title='Xiaolong Dictionary') 
     super(XLDMainWindow, self).__init__(title=self.WINDOW_TITLE) 

     self.set_default_size(self.DEFAULT_X_SIZE, self.DEFAULT_Y_SIZE) 

     self.initialize_widgets() 
     self.add_widgets() 

    def initialize_widgets(self): 
     self.menubar = XLDMenuBar(self) 

    def add_widgets(self): 
     self.add(self.menubar) 

    def connect_signals(self): 
     pass 

    def create_ui_manager(self): 
     uimanager = Gtk.UIManager() 

     # Throws exception if something went wrong 
     uimanager.add_ui_from_string(XLDMenuBar.MENUBAR_UI_INFO) 

     # Add the accelerator group to the toplevel window 
     accelgroup = uimanager.get_accel_group() 
     self.add_accel_group(accelgroup) 
     return uimanager 

И призыв к созданию самого приложения:

from gi.repository import Gtk 
from gtkplustool import GTKSignal 
from gtkplustool.gui.XLDMainWindow import XLDMainWindow 

__author__ = 'xiaolong' 

if __name__ == '__main__': 
    xld_main_window = XLDMainWindow() 
    xld_main_window.connect(GTKSignal.DELETE, Gtk.main_quit) 
    xld_main_window.show_all() 
    Gtk.main() 

и GTKSignal файл, который я создал:

__author__ = 'xiaolong' 

DELETE = 'delete-event' 
CLICKED = 'clicked' 
ACTIVATE = 'activate' 

Поставлен в правильное структура каталогов, эти файлы должны быть рабочим примером. У меня есть каталоги, установленные следующим образом:

gtkplustool --> __main__.py 
gtkplustool --> GTKSignal.py 
gtkplustool --> gui --> XLDMainWindow.py 
gtkplustool --> gui --> XLDMenuBar.py 
+0

Можете ли вы обеспечить * работу * пример? Включая минимальное окно, которое вы используете для него. – elya5

+0

Я попробую. Редактирование вопроса. – Zelphir

ответ

2

ошибка возникает из-за линии self.add(vertical_box) в XLDMenuBar.py, где вы пытаетесь добавить Gtk.Box (а не пункт меню) в меню.

Чтобы заставить его работать, вы можете просто удалить эту строку и выше три и изменить XLDMainWindow.py на следующее (и сделать UIManager атрибут класса):

def add_widgets(self): 
     menubar = self.uimanager.get_widget("/MenuBar") 
     box = Gtk.VBox() 
     box.pack_start(menubar, False, False, 0) 
     self.add(box)