2 Programme in einem Frame zusammenfassen

Plattformunabhängige GUIs mit wxWidgets.
Antworten
Gast

Freitag 27. Mai 2005, 11:42

Hallo NG,

ich habe folgendes Problem:

Ich habe zwei Einzelapllikationen mit Python geschrieben und mittels wxPython ein Aussehen verliehen.
Ich möchte nun beide Programmteile unter einer Oberfläche zusammenfassen.

Bei Programmstart wird ein Frame angezeigt mit welchem je eines der Programme gestartet wird. In etwa so soll es aussehen.

|------------------|
|1. Senden |
|2. Empfangen |
|3. Beenden |
|------------------|

Wird nun z.B. der Senden Button gedrückt, soll der Hauptframe ausgeblendet werden und stattdessen der zur Applikation gehörende Frame angezeigt werden.

Wäre prima wenn mir diesbezüglich jemand eine Hinweis geben kann, wie ich das am Besten umsetze.

Danke

chronical_chaos
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Freitag 27. Mai 2005, 12:52

Hoi,

erzählst Du uns so ungefähr (vielleicht mit Code-Snippets), wie Deine wx-Anwendungen aussehen? Und auch was Deine Einzelapplikationen machen?

Ich frage mich nämlich was Du wirklich willst: Komplexe Dialoge öffnen? Threads starten und verwalten? Was ganz anderes?

Gruß,
Christian
chronical_chaos
User
Beiträge: 13
Registriert: Montag 21. März 2005, 15:50

Freitag 27. Mai 2005, 13:12

Hi,

anbei der Quelltext einer Applikation, welche eine Datei öffnet und über die serielle Schnittstelle versendet.
Analog dazu habe ich ein Programm, welches Daten über die RS-232 wieder einließt.

Ich möchte nun beide Programmteile in einer Oberfläche zusammenbringen, aber so, daß man aus einem Hauptfenster heraus eine der beiden Anwendungen startet. Solange die Anwendung läuft soll das Hauptfenster entweder inaktiv, nicht sichtbar oä. sein. Durch einen Zurück Button wird die Anwendung beendet und man gelangt wieder zum Hauptfenster, wo man sich erneut zwischen einer der beiden Anwendungen oder Beenden entscheiden kann... Da ich dieses Verhalten nicht genau beim Namen nennen kann, kann ich es leider nur so umschreiben...

Code: Alles auswählen

#---------------------------------------------------------------------------
#IMPORT ANDERER PYTHON MODULE
#---------------------------------------------------------------------------
## import all of the wxPython GUI package
from wxPython.wx import *
#from wxPython.lib.intctrl import *
#from wxPython.lib.imagebrowser import *
#from wxPython.lib.filebrowsebutton import FileBrowseButton, FileBrowseButtonWithHistory,DirBrowseButton
#import time
#import urllib
import os
import wx
from MySerial_v02 import *

#---------------------------------------------------------------------------
#WILDCARD
#---------------------------------------------------------------------------
wildcard = "CSV-Textdatei(*.csv)|*.csv|"     \
           "TXT-Datei (*.txt)|*.txt|"        \
           "All files (*.*)|*.*"


#---------------------------------------------------------------------------
#KLASSE TestPanel
#---------------------------------------------------------------------------
## Hier wird zuerst ein Fenster geöffnet mit den nötigen Komponenentenen
class TestPanel(wxFrame):
    def __init__(self, parent, id, title):
        
        #-------------
        #DEFAULT INITs
        self.port= 1
        self.bus= 1

        #--------------------------------------
        #FRAME ZUR SCHNITTSTELLEN KONFIGURATION
        dlg = wxDialog(NULL,-1,"Schnittstellenkonfiguration",wxDefaultPosition,wxSize(200,150))
        dlg.CenterOnScreen()

        #----------------------
        #ABFRAGE Com1 oder Com2
        EVT_RADIOBOX (dlg,444, self.port_aenderung )      
        self.radiobox_port= wxRadioBox(dlg,444,"Schnittstelle zur Hardware?",wxPoint(20,10),wxDefaultSize,["COM 1","COM 2"],2,wxRA_SPECIFY_ROWS)
        line = wxStaticLine(dlg,-1,wxPoint(7,200),wxSize(280,-1),wxLI_HORIZONTAL)
        button_ok=wxButton(dlg,wxID_OK," OK ",wxPoint(50,90),wxSize(100,25))
        dlg.ShowModal()
        dlg.Destroy()   #Frame zur Schnittstellenkonfiguration beenden

        self.path = []  #Pfad Variable

        #---------------------------------------------------
        #UEBERPRUEFEN OB ANGEGEBENE SCHNITTSTELLE VERFUEGBAR
        try:
            self.communication =  Communication(self.port)
        except:
            self.communication = NULL
            sys.exit()
            
        #---------------------------------------------------
        #HAUPT FRAME ERSTELLEN
        wxFrame.__init__(self, parent, id, title,wxPoint(200, 300), wxSize(520, 195))
        panel = wxPanel(self, -1)

        #---------------------------------------------------
        #BUTTONS DEFINIEREN u. POSITIONIEREN (MAIN FRAME)
        button = wxButton(panel, 100, "Datei öffnen")
        button.SetPosition(wxPoint(415, 10))
        button.SetSize(wxSize(95,30))           
        self.SendButton=wxButton(panel,200,"Senden an RS-232")
        self.SendButton.SetPosition(wxPoint(415,50))
        self.SendButton.SetSize(wxSize(95,30))
        self.SendButton.Disable()
        BeendenButton=wxButton(panel,300,"Beenden")
        BeendenButton.SetPosition(wxPoint(415,130))
        BeendenButton.SetSize(wxSize(95,30))

        #---------------------------------------------------
        #EVENT ZUORDNUNG FUER BUTTONS 
        EVT_BUTTON(self,100, self.onFOpen) #FileOpen
        EVT_BUTTON(self,200, self.onDSend) #DataSend
        EVT_BUTTON(self,300, self.__onExit) #Beenden

        EVT_CLOSE(self, self.__onExit) #Frame beenden  

        #---------------------------------------------------
        #INFO TEXT FUER TEXTFELDER
        #wxStaticText(panel, -1, "Impossible is Nothing!", wxDLG_PNT(panel, wxPoint(100,10)),wxDefaultSize)
        #wxStaticText(panel, -1, "Quelldatei:",wxDLG_PNT(panel, wxPoint(15,27)),wxDefaultSize)
        wxStaticText(panel, -1, "Datei:",wxDLG_PNT(panel, wxPoint(5,35)),wxDefaultSize)
        
        #---------------------------------------------------
        #DEFINITION TEXTFELD
        cb1 = wxTextCtrl(panel, -1,"", wxDLG_PNT(panel, wxPoint(30,33)), wxDLG_SZE(panel, wxSize(240,-1)))
        #EVT_TEXT(panel, cb1.GetId(), self.onFOpen)  #Dieses Event bezieht sich auf das Textfeld
        self.cb1 = cb1

    #---------------------------------------------------
    #EVENT HANDLING
    def onFOpen(self, event):
        #Dateiauswahl Dialog
        dlg = wxFileDialog(self, "Datei öffnen...", os.getcwd(), "", wildcard,wxOPEN
                            | wxMULTIPLE
                            | wxCHANGE_DIR
                            )
        if dlg.ShowModal() == wxID_OK:
            self.path = dlg.GetPaths()
            #self.cb1.WriteText(self.path[0])
            self.cb1.SetValue(self.path[0])
        else:
            self.cb1.SetValue("")
            self.path=[]
            self.SendButton.Disable() #Schaltflaeche disabled falls leerer Pfad 
        #return self.path
        dlg.Destroy() #Datei Auswahldialog beenden
        if self.path != []: #SendButton nur 'clickable' falls Pfad nicht leer 
            self.SendButton.Enable()



    def onDSend(self,event):

        self.communication.send_file ( self.path[0])
        dlg = wxDialog(NULL,-1,"Meldung!",wxDefaultPosition,wxSize(170,95))
        text = wxStaticText(dlg,-1,"Übertragung abgeschlossen!",wxPoint(15,10),wxDefaultSize)
        dlg.CenterOnScreen()
        button_ok=wxButton(dlg,wxID_OK," OK ",wxPoint(65,40),wxSize(38,25))
        dlg.ShowModal()
        dlg.Destroy()


    def __onExit(self, event):
        self.Destroy()

        
    def port_aenderung(self,event):
        self.port=self.radiobox_port.FindString(self.radiobox_port.GetStringSelection())+1

      
      
#-----------------------------------------------------------------------

# Every wxWindows application must have a class derived from wxApp

#---------------------------------------------------------------------------
#KLASSE MyApp
#---------------------------------------------------------------------------
class MyApp(wxApp):

    # wxWindows calls this method to initialize the application
    def OnInit(self):

        # Create an instance of our customized Frame class
        frame = TestPanel(NULL, -1, "Daten senden")
        frame.Show(true)
        

        # Tell wxWindows that this is our main window
        self.SetTopWindow(frame)

        # Return a success flag
        return true

#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
#MAIN
#---------------------------------------------------------------------------

if __name__ == '__main__':
    
    app = MyApp(0)     # Create an instance of the application class
    app.MainLoop()     # Tell it to start processing events
    #del com_obj.close()   
#----------------------------------------------------------------------------
Edit (Leonidas): Code in Python-Tags gesetzt.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Freitag 27. Mai 2005, 18:04

Hoi,

also zunächst einmal möchte ich Dir vorschlagen Dein wxPython zu aktualisieren. Du benutzt eine Syntax von vor 2.4! Die Umstellung ist schnell und einfach und sie lohnt sich, weil mehr Stabilität und bessere Features.

Ansonsten könnte ich mir als Lösung ein wx.Notebook vorstellen. Du hättest zwei Tabs und im jeweils aktiven würde der Nutzer sehen, was vor sich geht. Im anderen wären beispielsweise die Buttons ausgegraut und nicht aktiv.

Oder, wenn nicht so viel sichtbares für den Nutzer geschieht, könntest Du auch mit zwei modalen Dialogen arbeiten.

Oder, Du öffnest jedes Mal ein neues Panel - je nachdem welcher Prozess aktiv ist und setzt den Fokus auf das aktive Panel. Das schwebte Dir wohl vor, oder?

Aber man sieht noch keine zwei grundsätzlich verschiedenen Applikationen, so daß man auch keine konkreten Vorschläge möglich sind. Oder hat jemand eine bessere Idee?

Gruß,
Christian
chronical_chaos
User
Beiträge: 13
Registriert: Montag 21. März 2005, 15:50

Freitag 27. Mai 2005, 18:59

Hi,
Ansonsten könnte ich mir als Lösung ein wx.Notebook vorstellen. Du hättest zwei Tabs und im jeweils aktiven würde der Nutzer sehen, was vor sich geht. Im anderen wären beispielsweise die Buttons ausgegraut und nicht aktiv.
Das hört sich gut an. Ich habe mittlerweile die zwei Programmteile in einem Frame zusammengefasst und die jeweils nicht benötigten Schaltflächen werden ausgegraut (s.u.). Wie müßte ich das Programm geändert werden um die Tabs einzufügen?

Code: Alles auswählen

#---------------------------------------------------------------------------
#IMPORT ANDERER PYTHON MODULE
#---------------------------------------------------------------------------
## import all of the wxPython GUI package
from wxPython.wx import *
#from wxPython.lib.intctrl import *
#from wxPython.lib.imagebrowser import *
#from wxPython.lib.filebrowsebutton import FileBrowseButton, FileBrowseButtonWithHistory,DirBrowseButton
#import time
#import urllib
import os
import wx
import exceptions
from sio import *
from MySerial_v02 import *


#---------------------------------------------------------------------------
#WILDCARDs
#---------------------------------------------------------------------------
wildcard1 = "CSV-Textdatei(*.csv)|*.csv|"     \
            "TXT-Datei (*.txt)|*.txt|"        \
           "All files (*.*)|*.*"

wildcard2 = "TXT-Datei (*.txt)|*.txt|"        \
           "CSV-Textdatei(*.csv)|*.csv|"     \
           "All files (*.*)|*.*"

#---------------------------------------------------------------------------
#KLASSE KombiPanel
#---------------------------------------------------------------------------
## Hier wird zuerst ein Fenster geöffnet mit den nötigen Komponenentenen
class KombiPanel(wxFrame):
    def __init__(self, parent, id, title):
        
        #-------------
        #DEFAULT INITs
        self.port= 1
        self.bus= 1

        #--------------------------------------
        #FRAME ZUR SCHNITTSTELLEN KONFIGURATION
        dlg = wxDialog(NULL,-1,"Schnittstellenkonfiguration",wxDefaultPosition,wxSize(200,150))
        dlg.CenterOnScreen()

        #----------------------
        #ABFRAGE Com1 oder Com2
        EVT_RADIOBOX (dlg,444, self.port_aenderung )      
        self.radiobox_port= wxRadioBox(dlg,444,"Schnittstelle zur Hardware?",wxPoint(20,10),wxDefaultSize,["COM 1","COM 2"],2,wxRA_SPECIFY_ROWS)
        line = wxStaticLine(dlg,-1,wxPoint(7,200),wxSize(280,-1),wxLI_HORIZONTAL)
        button_ok=wxButton(dlg,wxID_OK," OK ",wxPoint(50,90),wxSize(100,25))
        dlg.ShowModal()
        dlg.Destroy()   #Frame zur Schnittstellenkonfiguration beenden

        self.path = []  #Pfad Variable
        self.string= ""
        self.SendDataAvailable_Fl= 0

        #---------------------------------------------------
        #UEBERPRUEFEN OB ANGEGEBENE SCHNITTSTELLE VERFUEGBAR
        try:
            self.communication =  Communication(self.port)
        except:
            self.communication = NULL
            sys.exit()
            
        #---------------------------------------------------
        #HAUPT FRAME ERSTELLEN
        wxFrame.__init__(self, parent, id, title,wxPoint(200, 300), wxSize(520, 285))
        panel = wxPanel(self, -1)


        #---------------------------------------------------
        #BUTTONS DEFINIEREN u. POSITIONIEREN (MAIN FRAME)

        self.FOpenButton = wxButton(panel, 100, "Datei öffnen")
        self.FOpenButton.SetPosition(wxPoint(10, 15))
        self.FOpenButton.SetSize(wxSize(95,30))           
        self.SendButton=wxButton(panel,200,"Datei senden")
        self.SendButton.SetPosition(wxPoint(10,55))
        self.SendButton.SetSize(wxSize(95,30))
        self.SendButton.Disable()
        
        self.ReceiveButton = wxButton(panel, 150, "Daten empfangen")
        self.ReceiveButton.SetPosition(wxPoint(10, 115))
        self.ReceiveButton.SetSize(wxSize(95,30))           
        self.SaveButton=wxButton(panel,250,"Datei speichern")
        self.SaveButton.SetPosition(wxPoint(10,155))
        self.SaveButton.SetSize(wxSize(95,30))
        self.SaveButton.Disable()
        BeendenButton=wxButton(panel,350,"Beenden")
        BeendenButton.SetPosition(wxPoint(410,220))
        BeendenButton.SetSize(wxSize(95,30))

        #---------------------------------------------------
        #EVENT ZUORDNUNG FUER BUTTONS 
        EVT_BUTTON(self,100, self.onFOpen) #FileOpen
        EVT_BUTTON(self,200, self.onDSend) #DataSend

        EVT_BUTTON(self,150, self.onReceiveData) #Daten empfangen
        EVT_BUTTON(self,250, self.onSaveData) #Daten speichern
        EVT_BUTTON(self,350, self.__onExit) #Beenden

        EVT_CLOSE(self, self.__onExit) #Frame beenden  

      
        #---------------------------------------------------
        #DEFINITION TEXTFELD
        cb1 = wxTextCtrl(panel, -1,"", wxDLG_PNT(panel, wxPoint(80,37)), wxDLG_SZE(panel, wxSize(257,-1)))
        #EVT_TEXT(panel, cb1.GetId(), self.onFOpen)  #Dieses Event bezieht sich auf das Textfeld
        self.cb1 = cb1

    #---------------------------------------------------
    #FNKTIONEN

    def onFOpen(self, event):
        #Dateiauswahl Dialog
        dlg = wxFileDialog(self, "Datei öffnen...", os.getcwd(), "", wildcard1,wxOPEN
                            | wxMULTIPLE
                            | wxCHANGE_DIR
                            )
        if dlg.ShowModal() == wxID_OK:
            self.path = dlg.GetPaths()
            #self.cb1.WriteText(self.path[0])
            self.cb1.SetValue(self.path[0])
        else:
            self.cb1.SetValue("")
            self.path=[]
            self.SendButton.Disable() #Schaltflaeche disabled falls leerer Pfad 
        #return self.path
        dlg.Destroy() #Datei Auswahldialog beenden
        if self.path != []: #SendButton nur 'clickable' falls Pfad nicht leer 
            self.SendButton.Enable()
            self.SendDataAvailable_Fl= 1



    def onDSend(self,event):
        self.SendButton.Disable()
        self.FOpenButton.Disable()
        self.ReceiveButton.Disable()
        self.communication.send_file ( self.path[0])
        dlg = wxDialog(NULL,-1,"Meldung!",wxDefaultPosition,wxSize(170,95))
        text = wxStaticText(dlg,-1,"Übertragung abgeschlossen!",wxPoint(15,10),wxDefaultSize)
        dlg.CenterOnScreen()
        button_ok=wxButton(dlg,wxID_OK," OK ",wxPoint(65,40),wxSize(38,25))
        dlg.ShowModal()
        self.SendButton.Enable()
        self.FOpenButton.Enable()
        self.ReceiveButton.Enable()
        dlg.Destroy()


    def onSaveData(self, event):
        #Dateiauswahl Dialog
        dlg = wxFileDialog(self, "Datei speichern...", os.getcwd(), "", wildcard2, wxSAVE
                            | wxMULTIPLE
                            | wxCHANGE_DIR
                           )
        if dlg.ShowModal() == wxID_OK:
            path = dlg.GetPath()
            #data= "Testdaten"
            fp = file(path, 'w') # Create a new file
            fp.write(self.string)
            fp.close()
        dlg.Destroy() #Datei Auswahldialog beenden


    def onReceiveData(self, event):
        self.string="" #String loeschen
        self.SaveButton.Disable() #SaveButton disablen
        self.SendButton.Disable()
        self.FOpenButton.Disable()
        self.ReceiveButton.Disable() #ReceiveButton disablen
        NoDataRecv_Fl= 0 

        try:
          self.string= self.communication.receive_data() #Daten empfangen 
        except:
            dlg = wxDialog(NULL,-1,"Meldung!",wxDefaultPosition,wxSize(200,95))
            text = wxStaticText(dlg,-1,"Timeout erreicht!",wxPoint(55,10),wxDefaultSize)
            dlg.CenterOnScreen()
            button_ok=wxButton(dlg,wxID_OK," OK ",wxPoint(75,35),wxSize(50,25))
            dlg.ShowModal()
            dlg.Destroy()
            NoDataRecv_Fl= 1
            #sys.exit()
        

        #self.string= self.communication.receive_data() #Daten empfangen 
        #print self.string[0:]
        self.ReceiveButton.Enable() #ReceiveButton enablen
        self.FOpenButton.Enable()
        if self.SendDataAvailable_Fl == 1:
            self.SendButton.Enable()
        
        if self.string != "": #SaveButton nur 'clickable' falls string nicht leer 
            dlg= wxDialog(NULL,-1,"Meldung!",wxDefaultPosition,wxSize(170,95))
            text= wxStaticText(dlg,-1,"Empfang abgeschlossen!",wxPoint(23,10),wxDefaultSize)
            dlg.CenterOnScreen()
            self.SaveButton.Enable()
            button_ok= wxButton(dlg,wxID_OK," OK ",wxPoint(65,40),wxSize(38,25))
            dlg.ShowModal()
        elif ((self.string == "") & (NoDataRecv_Fl == 0)):
            dlg= wxDialog(NULL,-1,"Meldung!",wxDefaultPosition,wxSize(170,95))
            text= wxStaticText(dlg,-1,"Keine Daten empfangen",wxPoint(15,10),wxDefaultSize)
            dlg.CenterOnScreen()
            self.SaveButton.Enable()
            button_ok= wxButton(dlg,wxID_OK," OK ",wxPoint(65,40),wxSize(38,25))
            dlg.ShowModal()    
            
        dlg.Destroy()


    def __onExit(self, event):
        self.Destroy()

        
    def port_aenderung(self,event):
        self.port=self.radiobox_port.FindString(self.radiobox_port.GetStringSelection())+1

      
      
#-----------------------------------------------------------------------

# Every wxWindows application must have a class derived from wxApp

#---------------------------------------------------------------------------
#KLASSE MyApp
#---------------------------------------------------------------------------
class MyApp(wxApp):

    # wxWindows calls this method to initialize the application
    def OnInit(self):

        # Create an instance of our customized Frame class
        frame = KombiPanel(NULL, -1, "RoMo Transfer")
        frame.Show(true)
        

        # Tell wxWindows that this is our main window
        self.SetTopWindow(frame)

        # Return a success flag
        return true

#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
#MAIN
#---------------------------------------------------------------------------

if __name__ == '__main__':
    
    app = MyApp(0)     # Create an instance of the application class
    app.MainLoop()     # Tell it to start processing events
    #del com_obj.close()   
#----------------------------------------------------------------------------
Gruß

chronical_chaos

Edit (Leonidas): Code in Python-Tags gesetzt.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Sonntag 29. Mai 2005, 00:39

Hoi,

will gerne mal schauen, wenn ich die Zeit finde. Aber bis dahin könntest Du ja mal selber versuchen, ob die Demo Dir weiterhelfen kann. (Irgendwo in Deinem wxPythondownload sollte es eine Demo geben.)
Außerdem wäre es ganz praktisch, wenn Du Deinen Code in Pythontags setzten könntest - durch die Umstellung des Forums gibt es noch ein paar Probleme. Alles was Du machen mußt, ist Deinen letzten Beitrag zum editieren öffnen und an den Stellen wo in eckigen Klammern "code" steht "python" einfügen, dann ist das Syntaxhighlighting angeschaltet und das erleichtert auch anderen Dein Problem nachzuvollziehen. Bei so einem langen Beispiel ist es die Sache schon wert.

Und schließlich war das mit der neueren wxPythonversion ernst gemeint. Was benutzt Du eigentlich?

Gruß,
Christian
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Sonntag 29. Mai 2005, 15:28

CM hat geschrieben:(Irgendwo in Deinem wxPythondownload sollte es eine Demo geben.)
Die Doku wurde vor ein paar Releases aus den Builds rausgenommen, jetzt ist sie einzeln.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Sonntag 29. Mai 2005, 19:00

Hoi

Oh, da sollte wohl noch jemand updaten ... :oops:
Aber gut, daß Du darauf aufmerksam machst. Was Robin auf der wxPython-homepage als Grund für die Trennung von Demo und Quelle angibt ist natürlich einleuchtend. Aber ich brauche noch ein Weilchen bevor ich eine neue Version draufspielen kann ...

Gruß,
Christian
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Sonntag 5. Juni 2005, 20:25

Brauchst Du noch Hilfe? Hat sich das Problem erledigt?

Feedback bitte.

Gruß,
Christian
Antworten