Event in einer Klasse -> Zugriff auf Obj. in anderer Klas

Plattformunabhängige GUIs mit wxWidgets.
Antworten
alan
User
Beiträge: 81
Registriert: Dienstag 10. April 2007, 11:30

Hallo

ich hab gerade ein kleines Problem. Ich arbeite mit einem SplitterWindow, das zwei Panel anzeigt. Da beide recht lang sind, sind die in eigenen Klassen definiert, PanelTop und PanelBottom.

In PanelTop ist ein Label label, das ich bei einem Klick auf einen Button button in PanelBottom verändern will.

Ich habs mal stark vereinfacht, lauffähig:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-d

import wx

class PanelTop(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)

        label = wx.StaticText(self, -1, "Unchanged text")


class PanelBottom(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)

        button = wx.Button(self, label="Change the text label")
        self.Bind(wx.EVT_BUTTON, self.OnButton, button)

    def OnButton(self, event):
        # do some magic to change the label in PanelTop to 'Changed text'
        pass


class MyFrame(wx.Frame):
    def __init__(self, parent=None, title="SplittedApp", size=(100, 50)):
        wx.Frame.__init__(self, parent, -1, title)

        hsplitter = wx.SplitterWindow(self)

        panel_top = PanelTop(hsplitter)
        panel_bottom = PanelBottom(hsplitter)

        hsplitter.SplitHorizontally(panel_top, panel_bottom)


class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame()
        frame.Show(True)
        return True


if __name__ == '__main__':
    app = MyApp()
    app.MainLoop()
BlackJack

Vergiss Magie: Du musst einfach nur dafür sorgen, das es im `PanelBottom`-Objekt eine Referenz auf das `PanelTop`-Objekt gibt, oder zumindest auf das Label.
alan
User
Beiträge: 81
Registriert: Dienstag 10. April 2007, 11:30

Wenn das heißt, was ich glaube, dass es heißt, dann müsste ich in PanelBottom die Klasse PanelTop nochmal instanzieren und das label zum Klassenattribut machen. Richtig?
BlackJack

Das Label müsste ein *Instanz*attribut werden und Du musst nicht noch eine Instanz erzeugen sondern die vorhandene, oder eben nur das Label, an das `PanelBottom`-Objekt binden.
alan
User
Beiträge: 81
Registriert: Dienstag 10. April 2007, 11:30

Hm...wie mach ich das?
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

alan hat geschrieben:Hm...wie mach ich das?
Hallo alan!

Du bindest die Panel einfach an ein Objekt, das von beiden Panels aus zugänglich ist. Dafür könntest du an __init__ einen zusätzlichen Parameter übergeben, oder du bindest die Panels an den hsplitter. Der wird ja bereits als "parent" übergeben.

Code: Alles auswählen

class PanelTop(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)

        self.label = wx.StaticText(self, -1, "Unchanged text")


class PanelBottom(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        
        self.parent = parent

        button = wx.Button(self, label="Change the text label")
        button.Bind(wx.EVT_BUTTON, self.OnButton)

    def OnButton(self, event):
        # do some magic to change the label in PanelTop to 'Changed text'
        self.parent.panel_top.label.SetLabel("Hallo Welt")


class MyFrame(wx.Frame):
    def __init__(self, parent=None, title="SplittedApp", size=(100, 50)):
        wx.Frame.__init__(self, parent, -1, title)

        hsplitter = wx.SplitterWindow(self)

        hsplitter.panel_top = PanelTop(hsplitter)
        hsplitter.panel_bottom = PanelBottom(hsplitter)

        hsplitter.SplitHorizontally(hsplitter.panel_top, hsplitter.panel_bottom)
mfg
Gerold
:-)
Zuletzt geändert von gerold am Freitag 21. September 2007, 15:01, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
alan
User
Beiträge: 81
Registriert: Dienstag 10. April 2007, 11:30

Wunderbar, danke! :wink:
tomate
User
Beiträge: 48
Registriert: Sonntag 5. August 2007, 12:07

Angenommen ich würde in der Klasse Paneltop ein weiteres Fenster (Objekt) erzeugen.
Dann hätte ich ja mit self.parent Zugriff auf Paneltop.
Aber wie kann ich jetzt von dem neuen Fenster auf MyFrame zugreifen?
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

tomate hat geschrieben:Aber wie kann ich jetzt von dem neuen Fenster auf MyFrame zugreifen?
Hallo tomate!

So bald du mehr als ein kleines "Miniprogramm" mit ein paar Widgets schreiben möchtest, empfiehlt es sich, eine App-Klasse anzulegen und diese als Programmbasis zu verwenden.

Code: Alles auswählen

class MyApp(wx.PySimpleApp):
    
    def OnInit(self):
        self.show_main_frame()
        return True
    
    
    def show_main_frame(self):
        self.my_frame = MyFrame()
        self.my_frame.Show()
    
    
    def show_other_frame(self):
        self.other_frame = OtherFrame()
        self.other_frame.Show()
So kannst du von jedem Objekt aus über die Instanz von MyApp auf die Frames zugreifen.

Z.B. so:

Code: Alles auswählen

app = wx.GetApp()
app.other_frame.Close()
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
tomate
User
Beiträge: 48
Registriert: Sonntag 5. August 2007, 12:07

Hallo Gerold!

Vielen Dank für deine Hilfe. Ich werde mal versuchen, eine App-Klasse zu verwenden.
Eine Frage hab ich noch.
Ich würde gerne ein Popup-Menü erzeugen:

Code: Alles auswählen

class PopupMenu(wx.Menu):
    def __init__(self, parent):
        wx.Menu.__init__(self)
        
        self.parent = parent

        properties = wx.MenuItem(self, wx.NewId(), 'Benutzer hinzufügen')
        self.AppendItem(properties)
        self.Bind(wx.EVT_MENU, self.AddItem, id=properties.GetId())

    def AddItem(self, event):
        ....
Welche Voraussetzungen muss eine Klasse haben, damit ich das Objekt mit ".Show()" anzeigen und mit ".Close()" schließen kann?
Antworten