Seite 1 von 1

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

Verfasst: Freitag 21. September 2007, 12:55
von alan
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()

Verfasst: Freitag 21. September 2007, 13:13
von 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.

Verfasst: Freitag 21. September 2007, 13:15
von alan
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?

Verfasst: Freitag 21. September 2007, 13:35
von 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.

Verfasst: Freitag 21. September 2007, 14:03
von alan
Hm...wie mach ich das?

Verfasst: Freitag 21. September 2007, 14:22
von gerold
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
:-)

Verfasst: Freitag 21. September 2007, 14:48
von alan
Wunderbar, danke! :wink:

Verfasst: Montag 5. November 2007, 10:16
von tomate
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?

Verfasst: Montag 5. November 2007, 10:27
von gerold
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
:-)

Verfasst: Montag 5. November 2007, 12:02
von tomate
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?