von einem panel auf ein anderes zugreifen

Plattformunabhängige GUIs mit wxWidgets.
Antworten
rkruggel
User
Beiträge: 21
Registriert: Mittwoch 9. März 2005, 11:40
Wohnort: Altena, Westf.
Kontaktdaten:

hallo,

ja,ja. Aller Anfang ist schwer. Besonders in der GUI.

Folgendes Probem macht mir momentan Kopfzerbrechen.

file1.py
Hier wird ein wxPanel-1 definiert. dieses enthält verschiedene widgets.

main.py
Hier wird ein wxTextCtrl definiert und ein wxPanel-2. In das wxPanel-2 wird das wxPanel-1 aus file1.py geladen und dargestellt.

Wie erhalte ich jetzt zugriff (z.B. schreiben in ein wxTextCtrl) von wxPanel-1 (file1.py) auf wxPanel-2 (main.py) ?

Ich hoffe ich hab es verständlich beschrieben :)
cu
Roland
Benutzeravatar
DatenMetzgerX
User
Beiträge: 398
Registriert: Freitag 28. April 2006, 06:28
Wohnort: Zürich Seebach (CH)

erstellst eine Klasse Panel1(wx.Panel)

Code: Alles auswählen

class Panel1(wx.Panel):
    def __init__(self, parent):
         wx.Panel(self, parent)
         self.text1 = wx.TextCtrl(self, -1)

Nachher kannst du eine instanz erstellen

p1 = Panel1(frame)
und mit
p1.text1 auf das TextCtrl zugreiffen ;)
rkruggel
User
Beiträge: 21
Registriert: Mittwoch 9. März 2005, 11:40
Wohnort: Altena, Westf.
Kontaktdaten:

DatenMetzgerX hat geschrieben: p1 = Panel1(frame)
und mit
p1.text1 auf das TextCtrl zugreiffen ;)
Ja, das ist klar. Aber das meine ich nicht. Die Klasse besteht ja, allerdings in einem anderen file. Ich weis nur nicht wie ich an diese klasse rankommen soll.

Code: Alles auswählen

file1.py
App --> MainFrame -+--> textCtrl1
                   +--> Panel1

file2.py
Panel2 --> textCtrl2
Für Panel1 und Panel2 gibt es jeweils eine Instanz in dem jeweiligen File.
Solange sich das alles in einem File/Klasse befindet ist alles kein Problem. Es sind jedoch zwei Klassen und in der Klasse von Panel2 gibt es keine Instanz für das textCtrl1. Klar, das gibt es ja nur in der Klasse MainFrame.

Ich muss jetzt den 'weg' von Panel2 zu App.MainFrame.textCtrl1 Herrausbekommen. Versuche mit wx.GetApp(), self.GetParent(), self.GetGranParent() schlugen leider fehl.

Ich hoffe mal das diese Erklärung besser ist :) Schwierig so etwas in Worte zu fassen.
cu
Roland
Benutzeravatar
DatenMetzgerX
User
Beiträge: 398
Registriert: Freitag 28. April 2006, 06:28
Wohnort: Zürich Seebach (CH)

wenn ich das richtig verstanden ahbe, möchtest du das panel nicht neu instanzieren, dann kannst du es so machen ;)

Code: Alles auswählen

class myPanel1(wx.Panel):
    instanace = None
    def __init__(self, parent):
         wx.Panel(self, parent)
         self.text = wx.TextCtrl(self, -1)
    @staticmethode #glaube mit e am schluss
    def getInstance(parent=None):
         if myPanel1.instance is None:
             myPanel1.instance = myPanel1(parent)
         return myPanel1.instance
von panel2 auf text von panel1 zugreifen

Code: Alles auswählen

mypanel1file.myPanel1.getInstance(None)   #None, da das Panel1 schon mal instanziert wurde
Allerdings setzt das voraus, das du myPanel1.instance schon mal "definiert hast". Also würde ich, wenn du myPanel1 isntanzierst mit
myPanel1object = myPanel1.getInstance() ansonst ist myPanel1.instance nicht die aktuelle Instanz sondern None

Hoffentlich ist das das was du gesucht hast ;)
rkruggel
User
Beiträge: 21
Registriert: Mittwoch 9. März 2005, 11:40
Wohnort: Altena, Westf.
Kontaktdaten:

ich habe mal ein Beispiel geschrieben. Dann wir es vllt. klarer was ich will. Der Code ist mit VisualWX erzeugt worden, man möge mir des 'Zuviel' drumherrum verzeihen.

Ich habe Zwei Programme geschrieben. Es hat zwei textCtrl. Alles was im oberen textCtrl eingegeben wird erscheint auch im unteren.

Das Erste besteht nur aus einem File und funktioniert. Das Zweite besteht aus zwei Files und da liegt der Haken.

Ein allgemeines Startprog. Nur der Vollständigkeits halber. Ist für beide Programme gleich.

Code: Alles auswählen

# -*- coding: iso-8859-1 -*- 
import wx 
import Frame1 
 
class App(wx.App):
    def OnInit(self):
        wx.InitAllImageHandlers() 
        self.main = Frame1.mainFrame(None, -1, '') 
        self.main.Show() 
        self.SetTopWindow(self.main) 
        return 1 

if __name__ == '__main__':
    application = App(0) 
    application.MainLoop()

Dieses Programm funktioniert.
Frame1.py

Code: Alles auswählen

# -*- coding: iso-8859-1 -*- 
import wx

class mainFrame(wx.Frame):
    def __init__(self,parent,id = -1,title='',pos = wx.Point(0,0),size = wx.Size(300,300),style = wx.DEFAULT_FRAME_STYLE,name = 'frame'):
        pre=wx.PreFrame()
        pre.Create(parent,id,title,pos,size,style,name)
        self.PostCreate(pre)
        self.VwXinit()

    def VwXinit(self):
        self.Show(True)
        self.tx_1 = wx.TextCtrl(self,-1,"",wx.Point(55,165),wx.Size(145,21))
        self.panel_1 = wx.Panel(self,-1,wx.Point(35,25),wx.Size(185,90))
        self.tx_2 = wx.TextCtrl(self.panel_1,-1,"",wx.Point(20,35),wx.Size(145,21))
        self.Bind(wx.EVT_TEXT,self.tx_2_VwXEvOnText,self.tx_2)
        self.Refresh()
        return
    def VwXDelComp(self):
        return

    def tx_2_VwXEvOnText(self,event):
        inp = self.tx_2.GetValue()
        self.tx_1.SetValue(inp)
        return
Das Zweite Programm. Von der funktionalität das gleiche, allerdings aufgeteilt in zwei Klassen/Files.

Frame1.py

Code: Alles auswählen

# -*- coding: iso-8859-1 -*- 

import wx
import Panel2

class mainFrame(wx.Frame):
    def __init__(self,parent,id = -1,title='',pos = wx.Point(0,0),size = wx.Size(300,300),style = wx.DEFAULT_FRAME_STYLE,name = 'frame'):
        pre=wx.PreFrame()
        pre.Create(parent,id,title,pos,size,style,name)
        self.PostCreate(pre)
        self.VwXinit()
        self.initAfter()

    def VwXinit(self):
        self.Show(True)
        self.tx_1 = wx.TextCtrl(self,-1,"",wx.Point(55,165),wx.Size(145,21))
        self.panel_1 = wx.Panel(self,-1,wx.Point(35,25),wx.Size(185,90))
        self.Refresh()
        return
    def VwXDelComp(self):
        return

    def initAfter(self):
        self.pan1 = Panel2.panel_2(self.panel_1)
        return
und der zweite File/classe

Code: Alles auswählen

# -*- coding: iso-8859-1 -*- 
import wx

class panel_2(wx.Panel):
    def __init__(self,parent,id = -1,pos = wx.Point(0,0),size = wx.Size(190,95),style = wx.TAB_TRAVERSAL,name = 'panel'):
        pre=wx.PrePanel()
        pre.Create(parent,id,pos,size,style,name)
        self.PostCreate(pre)
        self.VwXinit()

    def VwXinit(self):
        self.Show(True)
        self.tx_2 = wx.TextCtrl(self,-1,"",wx.Point(40,40),wx.Size(100,21))
        self.Bind(wx.EVT_TEXT,self.tx_2_VwXEvOnText,self.tx_2)
        self.Refresh()
        return
    def VwXDelComp(self):
        return

    def tx_2_VwXEvOnText(self,event): #init function
        inp = self.tx_2.GetValue()
        print ':1', inp
        
        # Ab hier funtioniert es nicht mehr.
        # ich finde den Bezug auf tx_1 aus dem file frame1.py nicht mehr
        self.tx_1.SetValue(inp)         # !! DAS FUNKTIONIERT NICHT !!
        
        return #end function

Ich hoffe das es nicht zu viel code ist. Kleiner habe ich es nicht hinbekommen.
cu
Roland
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi,

ah, jetzt verstehe ich, worauf Du überhaupt hinaus willst. Vielleicht magst Du beim nächsten Mal eher etwas Code zeigen?

Also ich finde diesen automatisch generierten Code seltsam und nicht sehr pythonisch, aber davon ab:

Code: Alles auswählen

# -*- coding: iso-8859-1 -*- 
 
import wx 
import Panel2 

class mainFrame(wx.Frame):
    def __init__(self,parent,id = -1,title='',pos = wx.Point(0,0),size = wx.Size(300,300),style = wx.DEFAULT_FRAME_STYLE,name = 'frame'): 
        pre=wx.PreFrame() 
        pre.Create(parent,id,title,pos,size,style,name) 
        self.PostCreate(pre) 
        self.VwXinit() 
        self.initAfter() 
 
    def VwXinit(self): 
        self.Show(True) 
        self.tx_1 = wx.TextCtrl(self,-1,"",wx.Point(55,165),wx.Size(145,21)) 
        self.panel_1 = wx.Panel(self,-1,wx.Point(35,25),wx.Size(185,90)) 
        self.Refresh() 
        return 
    def VwXDelComp(self): 
        return 

    def initAfter(self): 
        self.pan1 = Panel2.panel_2(self) # Änderung hier!!!
        return 
und

Code: Alles auswählen

# -*- coding: iso-8859-1 -*- 
import wx 
 
class panel_2(wx.Panel): 
    def __init__(self,parent,id = -1,pos = wx.Point(0,0),size = wx.Size(190,95),style = wx.TAB_TRAVERSAL,name = 'panel'): 
        pre=wx.PrePanel() 
        pre.Create(parent,id,pos,size,style,name) 
        self.PostCreate(pre) 
        self.VwXinit()
        self.parent = parent # Änderung hier!!!
 
    def VwXinit(self): 
        self.Show(True) 
        self.tx_2 = wx.TextCtrl(self,-1,"",wx.Point(40,40),wx.Size(100,21)) 
        self.Bind(wx.EVT_TEXT,self.tx_2_VwXEvOnText,self.tx_2) 
        self.Refresh() 
        return 
    def VwXDelComp(self): 
        return 
 
    def tx_2_VwXEvOnText(self,event): #init function 
        inp = self.tx_2.GetValue() 
        print ':1', inp 

         # Änderung hier!!!
        self.parent.tx_1.SetValue(inp)         # !! DAS FUNKTIONIERT DOCH!! 
        
        return
Wichtig ist, daß jede Klasse Deiner Applikation genau weiß wie ihr "Elterteil" genau ausschaut. Also: Dieses übergeben und dann auch drauf zugreifen, dann klappt das auch. ;-)

Gruß,
Christian

edit: Kommentare im Code angepasst, damit leichter nachzuvollziehen ist, was geändert wurde.
rkruggel
User
Beiträge: 21
Registriert: Mittwoch 9. März 2005, 11:40
Wohnort: Altena, Westf.
Kontaktdaten:

Ich danke dir. So geht's.
Ist wie immer, gewusst wie :)

Du sagst das der Code von VisualWX nix taugt. Ist der Code von Boa besser?
cu
Roland
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi,

ein Kollege von mir hat den Spruch drauf: "Wenn man alles richtig macht, dann geht es!" Dafür hätte ich ihn schon manchmal umbringen können :oops: .

Aber zum Thema: Nein, ich habe nicht gesagt, daß der Code "nix taugt", sondern, daß er seltsam (ich meinte unschön in Bezug auf wxPython, um genau zu sein) und unpythonisch ausschaut. Kurze Begründung (sicher lassen sich mehr Argumente finden):
- Unmotiviert eingestreute return statements ohne Funktion
- was bringt das Aufsplitten in Funktionen, wenn es doch alles sequentiell durchgearbeitet wird?
- absolute Zahlenwerte für Größenangabe in einem GUI???
- keine Verwendung von Sizern
- selbst dieser Code-Generator beherzigt nicht guten Pythonstil, wobei ich ja nicht päpstlicher sein will als der Papst, aber das ist ja nicht selbstgeschriebener Code, sondern Du nutzt ein Tool, daß diese Dinge beherrschen sollte. Oder erwarte ich zuviel?

Was Boa angeht: Habe ich mal getestet, aber ich weiß schon nicht mehr wie es aussieht. Die Frage muß ein Anderer beantworten.

Gruß,
Christian

edit: Das zweite "nicht mehr" aus dem vorletzten Satz gestrichen.
Antworten