wxXmlResource - LoadMenuBar()-Fehler

Plattformunabhängige GUIs mit wxWidgets.
Antworten
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Samstag 4. Dezember 2004, 00:08

Hab hier ein kleines Beispiel:

Code: Alles auswählen

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- generated by wxGlade 0.3.5.1 on Sat Dec 04 00:01:17 2004 -->

<resource version="2.3.0.1">
    <object class="wxFrame" name="frame_1" subclass="MyFrame">
        <style>wxDEFAULT_FRAME_STYLE</style>
        <title>frame_1</title>
        <object class="wxBoxSizer">
            <orient>wxVERTICAL</orient>
            <object class="sizeritem">
                <option>1</option>
                <flag>wxEXPAND</flag>
                <object class="wxPanel" name="panel_1">
                    <style>wxTAB_TRAVERSAL</style>
                </object>
            </object>
        </object>
        <object class="wxMenuBar" name="frame_1_menubar">
            <object class="wxMenuItem" name="item_Name">
                <label>item</label>
            </object>
        </object>
    </object>
</resource>

Code: Alles auswählen

from wxPython.wx import *
from wxPython.xrc import *

class MyApp(wxApp):
    def OnInit(self):
        self.res = wxXmlResource("test.xrc", wxXRC_NO_SUBCLASSING)
        self.Frame = self.res.LoadFrame(None, "frame_1")
        self.MenuBar = self.res.LoadMenuBar("frame_1_menubar")
        self.Frame.Show()

        return True

app = MyApp(redirect=False)
app.MainLoop()
Ich erhalte immer einen Fehler beim Laden der MenuBar:
No handler found for XML node 'object', class 'wxMenuItem'!
XRC resource 'frame_1_menubar' (class 'wxMenuBar') not found!
Lustigerweise meckert es gleichzeitig, das kein Handler für den einen Menü-Punkt gefunden hat, obwohl er eigentlich gar kein Menü finden ?!?!?

Ich sehe auch keine MenuBar... Aber man muß wohl mit SetMenuBar() diese wohl auch erst an's Frame binden...
Zuletzt geändert von jens am Dienstag 7. Dezember 2004, 14:45, insgesamt 2-mal geändert.
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Samstag 4. Dezember 2004, 22:05

Hab Rückmeldung von Robin Dunn über die wx Mailingliste bekommen:
> No handler found for XML node 'object', class 'wxMenuItem'!
This is because the wxMenuBar handler is not able to use a wxMenuItem direclty, it can only have wxMenu's embedded within it.

> XRC resource 'frame_1_menubar' (class 'wxMenuBar') not found!
This is because you can only load top-level items from the XRC, and since frame_1_menubar is embedded within the frame it is not seen by the LoadMenu function. It will, however, be loaded automatically by the frame when it is loaded from the XRC.
Hilft mir jetzt aber nicht ganz so viel weiter... OK, die MenuBar wurde wohl zusammen mit dem Frame geladen, weil sie in der Hierarchie ein Objekt unter dem Frame ist...
Nur, warum sehe ich sie dann nicht??? Wahrscheinlich weil ich dennoch mit SetMenuBar() ans Frame pappen muß... Aber das klappt zumindest so nicht:

Code: Alles auswählen

        self.MenuBar = XRCCTRL(self.Frame, "frame_1_menubar")
        self.Frame.SetMenuBar( self.MenuBar )
So bekomme ich das Menu nicht, denn self.MenuBar == None :(
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Samstag 4. Dezember 2004, 23:13

Ich habe in meinem Prog in der __init__ des Frames das:

Code: Alles auswählen

self.SetMenuBar(menubar)
und es hat problemlos funktioniert.
DU kannst versuchen von deinem XRC wx.Frame zu erben und das zusätzlich noch in ide __init__ zu schreiben. Allerdings ist das ein hässlicher Hack.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Samstag 4. Dezember 2004, 23:18

Leonidas hat geschrieben:Ich habe in meinem Prog in der __init__ des Frames das:

Code: Alles auswählen

self.SetMenuBar(menubar)
und es hat problemlos funktioniert.
Ergebnis bei mir:

Code: Alles auswählen

AttributeError: 'MyApp' object has no attribute 'SetMenuBar'
Leonidas hat geschrieben:DU kannst versuchen von deinem XRC wx.Frame zu erben und das zusätzlich noch in ide __init__ zu schreiben. Allerdings ist das ein hässlicher Hack.
Verstehe ich nicht... Kannst du es im obrigen Beispiel mal reinfrimeln???
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Sonntag 5. Dezember 2004, 00:00

Also ich habe bis jetzt folgendes:

Code: Alles auswählen

import wx, wx.xrc

app = wx.PySimpleApp()
win = wx.Frame(None, -1)
res = wx.xrc.XmlResource("test.xrc")

f = res.LoadFrame(win, "frame_1")
mb = res.LoadMenuBar("frame_1_menubar") 
mi = res.LoadMenu("item_Name")
mb.Append(mi, 'bla')
print f
print mi
print mb
f.SetMenuBar(mb)
f.Show()

app.MainLoop()
und

Code: Alles auswählen

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- generated by wxGlade 0.3.5.1 on Sat Dec 04 00:01:17 2004 -->

<resource version="2.3.0.1">
    <object class="wxFrame" name="frame_1">
        <style>wxDEFAULT_FRAME_STYLE</style>
        <title>frame_1</title>
        <object class="wxBoxSizer">
            <orient>wxVERTICAL</orient>
            <object class="sizeritem">
                <option>1</option>
                <flag>wxEXPAND</flag>
                <object class="wxPanel" name="panel_1">
                    <style>wxTAB_TRAVERSAL</style>
                </object>
            </object>
        </object>
    </object>
    <object class="wxMenuBar" name="frame_1_menubar" />
    <object class="wxMenu" name="item_Name">
                <label>item</label>
    </object> 
</resource>  
Das geht, zwar mehr schlecht als recht, aber immerhin. Ich habe jetzt wieder dieses wx-Feeling: "das muss doch irgendwie so gehen, wie geht das jetzt genau, was habe ich denn noch für Möglichkeiten?"
Mit etwas Arbeit könnte das sogar exakt so funktionieren wie du willst. Aja, ich habe den wx Namespace benutzt weil ich äußerst ungern import * nutze und das wx.PySimpleApp weil es für das meiste reicht.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Sonntag 5. Dezember 2004, 00:06

Also ich möchte gern auch nur XML-Dateien für die GUI nutzen... Das sollte natürlich auch gehen, scheint aber sehr schwierig zu sein... Außerdem bekommt man hierfür nur unzureichend Information, oder finde ich diese nur nicht ?


Naja, jetzt bin ich wieder bei der alten Geschichte... d.h. aus wxGlade Pythonskripte erzeugen lassen... ABER: diese möchte ich auch so nutzen, das ich in den Skripten nichts verändern muß! Also alle verknüpfungen von Events werden in meinem eigentlichen Programm vorgenommen...
Somit ist es im Prinzip fast so als wenn man XML-Dateien benutzt, nur es geht viel einfacher!

Hab jetzt auch entlich raus, wie ich einen Dialog aus der wxGlade.py-Datei "aufrufen" kann...
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Sonntag 5. Dezember 2004, 00:16

Tja, was Dukumentation angeht ist wx nur sehr ärmlich ausgestattet, aber das hast du ja schon festgestellt.

Pears nutzt solche generierten wxGlade Dateien, du kannst mal einen Blick reinwerfen.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 6. Dezember 2004, 22:47

Leonidas hat geschrieben:Also ich habe bis jetzt folgendes:

Code: Alles auswählen

import wx, wx.xrc

app = wx.PySimpleApp()
win = wx.Frame(None, -1)
res = wx.xrc.XmlResource("test.xrc")

f = res.LoadFrame(win, "frame_1")
mb = res.LoadMenuBar("frame_1_menubar") 
mi = res.LoadMenu("item_Name")
mb.Append(mi, 'bla')
print f
print mi
print mb
f.SetMenuBar(mb)
f.Show()

app.MainLoop()
und

Code: Alles auswählen

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- generated by wxGlade 0.3.5.1 on Sat Dec 04 00:01:17 2004 -->

<resource version="2.3.0.1">
    <object class="wxFrame" name="frame_1">
        <style>wxDEFAULT_FRAME_STYLE</style>
        <title>frame_1</title>
        <object class="wxBoxSizer">
            <orient>wxVERTICAL</orient>
            <object class="sizeritem">
                <option>1</option>
                <flag>wxEXPAND</flag>
                <object class="wxPanel" name="panel_1">
                    <style>wxTAB_TRAVERSAL</style>
                </object>
            </object>
        </object>
    </object>
    <object class="wxMenuBar" name="frame_1_menubar" />
    <object class="wxMenu" name="item_Name">
                <label>item</label>
    </object> 
</resource>  
OK, das geht, weil "wxMenuBar" ein Top-Level-Object ist... Leider spuckt wxGlade aber immer eine MenuBar als Kind vom zugehörigen Frame raus (Schau nochmal das XML aus dem ersten Beitrag an)... Und das ist das Problem... Die Menüs sollten eigentlich mit dem Frame autom. geladen werden... Das scheinen sie auch zu tun, denn ich kann Events mit den MenüPunken "verbinden"...

Aber ich sehe das Menü nicht :(
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Dienstag 7. Dezember 2004, 14:04

jens hat geschrieben:OK, das geht, weil "wxMenuBar" ein Top-Level-Object ist... Leider spuckt wxGlade aber immer eine MenuBar als Kind vom zugehörigen Frame raus (Schau nochmal das XML aus dem ersten Beitrag an)...
Ja, ich weiß, deswegen ahbe ich es auch so geändert. Vielleicht kann man irgendwie per Child des Frames darauf zugreifen..
jens hat geschrieben:Und das ist das Problem... Die Menüs sollten eigentlich mit dem Frame autom. geladen werden... Das scheinen sie auch zu tun, denn ich kann Events mit den MenüPunken "verbinden"...

Aber ich sehe das Menü nicht :(
Wenn du ein Handle auf die Leiste hast (siehe oben) hast musst du sie vermutlich danach mit SetMenuBar anzeigen..

Mehr weiß ich auch nicht mehr.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 7. Dezember 2004, 14:10

Leonidas hat geschrieben:Ja, ich weiß, deswegen ahbe ich es auch so geändert. Vielleicht kann man irgendwie per Child des Frames darauf zugreifen..
Aber es muß auch so gehen... Warum spuckt wxGlade es sonst so aus? Und es muß so gehen, weil ich einfach keine Lust hab, die XRC-Daten nachträglich per Hand zu ändern ;)

Leonidas hat geschrieben:Wenn du ein Handle auf die Leiste hast (siehe oben) hast musst du sie vermutlich danach mit SetMenuBar anzeigen..
Tja, also LoadMenuBar() soll wohl nur mit Top-Level Objekte funktionieren... Allerdings komme ich mit XRCID("frame_1_menubar") zumindest an die ID herran... Somit ist es wirklich irgendwo da...
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 8. Dezember 2004, 21:31

Endlich ist der Fehler gefunden!!!

Eine MenüBar mit nur einem HauptMenüPunkt ohne Untermenüpunkte wird einfach nicht angezeigt :( Und mein Minimalistisches Beispiel hatte einfach nur einen Hauptmenüpunkt...

Ob das so gewollt ist? Ich denke nicht... Zumindest könnte die Fehlermeldung aussagekräftiger sein!

Also das hier geht:

Code: Alles auswählen

import wx, wx.xrc

class MyApp(wx.App):
    def OnInit(self):
        self.res = wx.xrc.XmlResource("test.xrc", wx.xrc.XRC_NO_SUBCLASSING)
        self.Frame = self.res.LoadFrame(None, "frame_1")
        self.Frame.Show()

        wx.EVT_MENU(self.Frame, wx.xrc.XRCID("SubItem"), self.test)

        return True

    def test(self, event):
        print "Function!"

app = MyApp(redirect=False)
app.MainLoop()

Code: Alles auswählen

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- generated by wxGlade 0.3.5.1 on Wed Dec 08 21:30:06 2004 -->

<resource version="2.3.0.1">
    <object class="wxFrame" name="frame_1" subclass="MyFrame">
        <style>wxDEFAULT_FRAME_STYLE</style>
        <title>frame_1</title>
        <object class="wxMenuBar" name="frame_1_menubar">
            <object class="wxMenu" name="TopItem">
                <label>TopItem</label>
                <object class="wxMenuItem" name="SubItem">
                    <label>SubItem</label>
                </object>
            </object>
        </object>
        <object class="wxBoxSizer">
            <orient>wxVERTICAL</orient>
            <object class="sizeritem">
                <option>1</option>
                <flag>wxEXPAND</flag>
                <object class="wxPanel" name="panel_2">
                    <style>wxTAB_TRAVERSAL</style>
                </object>
            </object>
        </object>
    </object>
</resource>
Antworten