PyNoAppError..?

Plattformunabhängige GUIs mit wxWidgets.
Antworten
CIB
User
Beiträge: 8
Registriert: Samstag 17. November 2007, 14:10

Code: Alles auswählen

class BaseApp(wx.App):
	def OnInit(self):
		global frame 
		frame = BaseGUI(None, "WesEdit")
		self.SetTopWindow(frame)
		frame.Show(True)
		return True

def included():
	print "creating app"
	app = BaseApp()
	print "app created"
	return True
...
...

		self.menus[name]=wx.Menu()
=>creating app
in self.menus[name]=wx.Menu()
wx._core.PyNoAppError: The wx.App object must be created first!

Wie man sehen kann, beschwert sich wxPython darüber, dass keine wx.App vorhanden wäre, aber ich weiß nicht warum, da ich ja eine gemacht habe(dass include aufgerufen wurde, sieht man daran, dass "creating app" ausgegeben wird"). Seltsam ist auch, dass nur "creating app", aber nicht "app created" ausgegeben wird. Weiß irgendjemand, wo hier das Problem liegt?[/code]
Jan-Peer
User
Beiträge: 166
Registriert: Dienstag 2. Oktober 2007, 10:55

Für mich sieht es so aus, als hättest du vergessen, die __init__-Methode der Superklasse (wx.App) aufzurufen.

Kann mich aber auch irren ...
CIB
User
Beiträge: 8
Registriert: Samstag 17. November 2007, 14:10

Nein, scheinbar nicht =/ OnInit() ist eine eigene Methode von wx.App und scheint die superclass nicht initialisieren zu müssen.
Jan-Peer
User
Beiträge: 166
Registriert: Dienstag 2. Oktober 2007, 10:55

Der Fehler tritt eigentlich immer dann auf, wenn man versucht, irgendwelche Widgets zu erzeugen, bevor app erzeugt wurde. Da du den anderen Code ausgeblendet hast, kann ich das leider nicht überprüfen. Gehe also alles noch mal Schritt für Schritt durch. Was mich ein wenig stutzig macht, ist das "global" - was soll das denn?
Jan-Peer
User
Beiträge: 166
Registriert: Dienstag 2. Oktober 2007, 10:55

Ansonsten kannst du auch noch mal probieren, BaseApp beim Erzeugen eine 0 mit auf den Weg zu geben. So wirds zumindest im wxpython-Wiki gemacht.
CIB
User
Beiträge: 8
Registriert: Samstag 17. November 2007, 14:10

Naja, ich konnte es lösen, indem ich app global gemacht habe. Was mich zu der Frage bringt: Wo sucht wxPython eigentlich nach der App?

Und zu dem, was das global soll: Ich muss von außerhalb der Funktion, ja sogar von außerhalb der Datei auf den frame zugreifen können. Daher das global.

Noch eine Frage zu wxPython: Bei der StyledTextControl hört der Cursor nicht auf zu blinken, wenn man einrückt. Das ist nervig, denn wenn der Cursor gerade nicht zu sehen ist, während man einrückt, muss man warten, bis er wieder zu sehen ist, um zu sehen, wie weit man eingerückt hat. Kann man das irgendwie ändern?
BlackJack

Dein Problem ist unzureichend beschrieben und wxPython sucht nirgends nach `App`. Du musst noch irgendetwas anderes gemacht haben als einen Namen ``global`` deklariert zu haben. ``global`` braucht man nicht. Wenn Du denkst Du brauchst es, dann stimmt etwas mit Deinem Entwurf nicht. Du hast zwar nur ein kleines Stückchen Quelltext gezeigt, aber mir scheint Du hast OOP nicht verstanden. Wenn Du auf `frame` zugreifen willst, dann musst Du es an das Objekt binden.
CIB
User
Beiträge: 8
Registriert: Samstag 17. November 2007, 14:10

BlackJack hat geschrieben:Du musst noch irgendetwas anderes gemacht haben als einen Namen ``global`` deklariert zu haben.
Uhm.. Folgende Tatsache: Sobald ich das "global app" entferne, funktioniert mein Programm nicht mehr und gibt die bereits erwähnte Fehlermeldung aus. Warum, weiß ich nicht.
Wenn Du auf `frame` zugreifen willst, dann musst Du es an das Objekt binden.
Mmm.. Ich verstehe nicht, welches Objekt du meinst.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

CIB hat geschrieben:
Wenn Du auf `frame` zugreifen willst, dann musst Du es an das Objekt binden.
Mmm.. Ich verstehe nicht, welches Objekt du meinst.
An die aktuelle Instanz des Objektes, also `self`.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

Vielleicht solltest du dir das Minmalbeispiel von Gerold genau anschauen:

http://www.python-forum.de/topic-5722.html

Außerdem ist's immer besser, einen ganzen Code zu posten oder zumindest eine lauffähige Version, damit wir den Fehler reproduzieren können. Dir braucht auch kein Code peinlich zu sein, vertrau mir. Auch wenn manches hier schroff wirkt, man meint es doch immer gut.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

CIB hat geschrieben:

Code: Alles auswählen

def included():
	print "creating app"
	app = BaseApp()
	print "app created"
	return True
...
Hallo CIB!

Da du ``app`` zwar in der Funktion ``included`` erstellst aber in dieser Funktion nicht bis zum Ende deines Programmes wartest, wird ``app`` von Python nach dem Verlassen der Funktion wieder zerstört.

Der Typische Ort für eine App-Instanz:

Code: Alles auswählen

def main():
    app = wx.PySimpleApp() # <-- hier
    ...
    ...
    app.MainLoop()

if __name__ == "__main__":
    main()
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
CIB
User
Beiträge: 8
Registriert: Samstag 17. November 2007, 14:10

Leonidas hat geschrieben: An die aktuelle Instanz des Objektes, also `self`.
Klar, wenn es das gäbe, wäre es natürlich die elegantere Lösung. Tatsache ist aber, dass die übergeordnete Instanz kein Objekt sondern ein Modul ist, und da kann man wohl nur global verwenden. Ich hab nicht das ganze gepostet, weil es ziemlich lang und komplex ist und scheinbar keine Möglichkeit besteht, Dateien anzuhängen. Ah ja, "globale" Variablen für Module brauche ich, weil jedes Modul ein Plugin darstellt, auf welches "von außen" zugegriffen werden können muss.

--edit--
@gerold: Ah, das macht Sinn! Das heißt also, dass eine App nur in der ihr zugewiesenen Variable gespeichert wird?
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

CIB hat geschrieben:Das heißt also, dass eine App nur in der ihr zugewiesenen Variable gespeichert wird?
Hallo CIB!

Ja.

Du musst dich also darum kümmern, dass diese Variable bis zum Schluss existiert. Deshalb gibt es eigentlich keinen besseren Ort dafür als die ``main``.

Wenn der Rest des Programmes schön in Funktionen und Klassen steht, dann wird die ``main`` als erste Funktion aufgerufen und als letzte verlassen.

mfg
Gerold
:-)

PS: Hier findest du ein Beispiel dafür: http://www.python-forum.de/topic-5722.html
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
BlackJack

CIB hat geschrieben:
Leonidas hat geschrieben: An die aktuelle Instanz des Objektes, also `self`.
Klar, wenn es das gäbe, wäre es natürlich die elegantere Lösung. Tatsache ist aber, dass die übergeordnete Instanz kein Objekt sondern ein Modul ist, und da kann man wohl nur global verwenden. Ich hab nicht das ganze gepostet, weil es ziemlich lang und komplex ist und scheinbar keine Möglichkeit besteht, Dateien anzuhängen. Ah ja, "globale" Variablen für Module brauche ich, weil jedes Modul ein Plugin darstellt, auf welches "von außen" zugegriffen werden können muss.
Module sind auch Objekte und wer sprach von der (lexikalisch) übergeordneten Instanz? Das `frame` was Du da im ersten Beitrag ``global`` deklarierst steckt ja wohl recht deutlich in einer Methode die ein `self` bekommt.

Auch für Plugins braucht man nicht zwingend ``global``.
CIB
User
Beiträge: 8
Registriert: Samstag 17. November 2007, 14:10

BlackJack hat geschrieben: Module sind auch Objekte
OK, aber wohl keine Klassen, sonst könnte man self verwenden.
Das `frame` was Du da im ersten Beitrag ``global`` deklarierst steckt ja wohl recht deutlich in einer Methode die ein `self` bekommt.
Nein. Das zweite Bruchstück kommt nicht aus der zuerst definierten Methode.
Auch für Plugins braucht man nicht zwingend ``global``.
Dann sag mir, wie es anders geht. Was ich will ist folgendes:

Code: Alles auswählen

[i]auto.py[/i]
geschwindigkeit=0
def losfahren():
   geschwindigkeit=30

Code: Alles auswählen

[i]main.py[/i]
import auto
auto.losfahren()
auto.geschwindigkeit
=>30
Wär schön, wenn das eleganter ginge als mit global, aber bis jetzt konnte mir niemand sagen, wie.
BlackJack

Eine Instanz einer Klasse statt des Moduls verwenden.

Code: Alles auswählen

class Auto(object):
    def __init__(self):
        self.geschwindigkeit = 0
    
    def losfahren(self):
        self.geschwindigkeit = 30

auto = Auto()

Code: Alles auswählen

from auto import auto

auto.losfahren()
print auto.geschwindigkeit
CIB
User
Beiträge: 8
Registriert: Samstag 17. November 2007, 14:10

Hmm.. Stimmt, sieht besser aus.
Antworten