Dynamische Eingabe

Plattformunabhängige GUIs mit wxWidgets.
Antworten
JensP-Anfaenger

Hallo,
ich bin blutiger Anfaenger, Maschinenbaustudent und muss einen Teil meiner Diplomarbeit mit einem Python-Skript schreiben.

Die Programmierung hat nichts mit der eigentlichen Arbeit zu tun!

Ich möchte eine dynamische Eingabemaske verwirklichen, in der man beliegig häufig folgende Reihenfolge auf einem Frame darstellen kann:
Die Eingabe soll eine Combobox enthalten, dann eine CheckBox und eine Tabelle.

Wie kann ich verwirklichen, dass z.B. durch drücken eines Buttons diese Reihenfolge in der Eingabe wiederholt dargestellt wird.

Vielen Dank für eure Hilfe!

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

Hoi,

herzlich Willkommen im Forum.
Hm, gar nicht so einfach, finde ich. Vielleicht kommt jemandem ja auch noch eine bessere Idee, aber ich würde folgendes vorschlagen:

Du hast eine Basisklasse mit allem drum und dran und vor allem einem Haufen Parameter. Außerdem einen Dialog mit Deinen Kontrollen. Jetzt kannst Du Paramter, die Deine Basisklasse schon kennt ("self.parameter") Deinem Dialog übergeben und dieser trägt diese Werte dann ein Textfeld ein oder wählt den Wert in einer Combobox aus. "self.paramter" kann ja auch eine Liste sein.
Sähe dann z. B. so aus:

Code: Alles auswählen

class CustomDialog(wx.Dialog):
	def __init__(self, *args, **cmds):
		wx.Dialog.__init__(self, *args, **cmds)
		self.parent = args[0]
              for x in sel.parent.parameterlist:  #oder weniger "verbose"
                  #hier eine Liste von Comboboxen, CheckBoxen und Tabellen
                  #schön in Sizer packen
In der aufrufende Funktion in der Basisklasse muß dann überprüft werden, ob oder wie neue Paramter übergeben werden und was geschehen soll - z. B. den Dialog mit den neuen Werten und einer leeren Zeile neu starten.

Gruß,
Christian
JensP-Anfaenger

Danke für die Antwort, werd' mal schauen, ob ich damit zurecht komme!
JensP-Anfaenger
User
Beiträge: 23
Registriert: Montag 25. April 2005, 08:31
Wohnort: Schleswig-Holstein

Hallo,

leider habe ich doch so wenig Ahnung von Python, dass ich den Python-Code von CM noch nicht so wirklich verstanden habe.
Ich habe mich dann mit einer direkten Mail an ihn gewandt, ein paar Verständnisfragen gestellt und ob er mir vielleicht ein kurzes Beispiel schreibt, von dem aus ich alles für meine Anweendung ableiten könnte.
Er will mir helfen, hat mir jedoch zusätzlich geraten, noch mal im Forum nachzufragen.
CM schrieb folgendes:
Hallo Jens,

tut mir leid, so ad hoc kann ich keine Antwort geben - ich muß jetzt
auch erst mal ein bißchen arbeiten. Aber ich will mal schauen, was sich
machen läßt - frühestens (!) heute Abend wirst Du eine Antwort
erhalten.

Was den Boa-Construktor angeht, kann ich Dir gar nicht helfen, da ich
ihn nicht benutze. Es wäre ohnehin besser, wenn Du Deine Fragen
öffentlich stellen würdest, da dann alle mitlesen und helfen werden,
wenn sie es können. Wenn Du mal im wx-Bereich die Beiträge liest, wirst
Du sehen, das es noch viel kompetentere Leute gibt als mich.

Gruß,
Christian
Also: Gibt es hier noch Leute, die mir weiterhelfen können?

Am liebsten wäre mir, wenn es hier auch Leute gibt, mit denen man mal direkt sprechen könnte!

Gibt es Python-ianer aus Schleswig-Holstein?
Vielleicht sogar mit wx-Erfahrung?

Bitte meldet euch!

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

Hallo Jens,

ja, ja, schon gut. Ich bin wirklich nicht eher dazu gekommen Dir zu antworten. Ob Du es glaubst oder nicht: Gestern hat mich mein Chef bis Mitternacht in einem Restaurant festgehalten und wir haben an einem Antrag geschrieben. Danach hatte ich wahrlich keine Lust mehr an Deinem Problem zu werkeln. Heute war es nicht viel besser ...
Im Übrigen ist es wirklich oft besser sich nicht direkt an irgendwelche Leute zu wenden, sondern eben an das ganze Forum - dann fallen auch solche Ausfälle wie meiner nicht so ins Gewicht.

Also: Hier habe ich ein kurzes Beispielprogramm, das das was Du fragst am Beispiel eines TextCtrl-Feldes durchhechelt. Es ist alles andere als stabil und fehlerfrei - halt ein "dirty-hack" - aber das Beste, was ich so auf die Schnelle machen konnte.

Code: Alles auswählen

#! /usr/bin/python

import wx

class MyFrame(wx.Frame):
	def __init__(self,parent,id,title):
		self.data = [] #your data here
		self.flag = False #dummy
		
		wx.Frame.__init__(self,None,-1,"EnterApp")
		p = wx.Panel(self,-1)
		
		#initialize menu bar
		menu = wx.Menu()
		menu.Append(101,"&Enter data")
		menu.Append(102,"&Quit")
		
		menuBar = wx.MenuBar()
		menuBar.Append(menu,"&To Enter Dialog")
		self.SetMenuBar(menuBar)
		
		self.Bind(wx.EVT_MENU,self.OnEnter,id=101)
		
		sizer = self.sizer = wx.BoxSizer(wx.VERTICAL)
		
		TextField = wx.TextCtrl(p,-1,"Nothing to do here",size=(650,400),style=wx.TE_MULTILINE)
		self.TextField = TextField
		sizer.Add(TextField)
		
		p.SetSizerAndFit(sizer)
		self.SetClientSize(p.GetSize())
		
	def OnEnter(self,event):
		self.entered = EnterDialog(self)
		self.entered.Show()
		
	def Handle(self):
		if self.flag:
			self.entered.Show(0)
			self.entered = EnterDialog(self)
			self.entered.Show()
		else:
			self.entered.Show(0)
		
class EnterDialog(wx.Dialog):
	def __init__(self,*args,**cmds): 
              #zu den Sternchen steht einiges im Tutorial!
              #siehe Punkt 4.7.2 Keyword Arguments
		wx.Dialog.__init__(self,*args,**cmds)
		self.parent = args[0]
		self.boxes = [] #container for current data
		
		sizer = wx.BoxSizer(wx.VERTICAL)
		VSPACE = 10
		sizer.Add((-1,VSPACE),0)
		sizer.Add(wx.StaticText(self,-1,"Enter your data here"))
		sizer.Add((-1,VSPACE),0)
		if len(self.parent.data) == 0:
			box = wx.TextCtrl(self,-1,"",size=wx.DefaultSize)
			sizer.Add(box)
			self.boxes.append(box)
		else:
			for item in self.parent.data:
				box = wx.TextCtrl(self,-1,item,size=wx.DefaultSize)
				self.boxes.append(box)
				sizer.Add(box)
				sizer.Add((-1,VSPACE),0)
			box = wx.TextCtrl(self,-1,"",size=wx.DefaultSize)
			sizer.Add(box)
			self.boxes.append(box)
			sizer.Add((-1,VSPACE),0)
			
		buttons = wx.BoxSizer(wx.HORIZONTAL)
		buttons.Add((VSPACE,-1),0)
		b = wx.Button(self, 10, "Enter")
		self.Bind(wx.EVT_BUTTON,self.PutValue,b)
		b.SetDefault()
		buttons.Add(b,0,wx.ALL,10)
		b = wx.Button(self,20,"Finish")
		self.Bind(wx.EVT_BUTTON,self.PutValue,b)
		buttons.Add(b,0,wx.ALL,10)
		
		border=wx.BoxSizer(wx.VERTICAL)
		border.Add(sizer,1,wx.GROW|wx.ALL,25)
		border.Add(buttons)
		self.SetSizer(border)
		border.Fit(self)
		self.Layout()
		
			
	def PutValue(self,event):
		#if enter & refresh
		if event.GetId() == 10:
			for item in self.boxes:
				self.parent.data.append(item.GetValue())
			self.parent.flag = True
			self.parent.Handle()
			#self.Show(0)
		#if finish
		elif event.GetId() == 20:
			for item in self.boxes:
				self.parent.data.append(item.GetValue())
			self.parent.Handle()
			self.parent.flag = False
			#self.Show(0)
		
class EnterApp(wx.App):
	def OnInit(self):
		frame = MyFrame(None,-1,"Enter here")
		frame.Show(True)
		self.SetTopWindow(frame)
		return True
		
app = EnterApp(0)
app.MainLoop()
Hoffe es hilft Dir weiter. Schaue mal Zeile für Zeile über den Code und frage dann wenn Du etwas nicht verstehst ruhig hier nach (wie gesagt, es gibt Fehler im Code, aber es läuft), aber ein Blick ins Tutorial zu Python kann auch nicht schaden ;-).
Solltest Du noch Verständnisprobleme haben: Stelle Deine Fragen bitte hier.

Gruß,
Christian

Edit:
PS Nein, aus Schleswig-Holstein komme ich nicht und ich würde es auch vorziehen, wenn ich nicht für solche Dinge privat kontaktiert werden würde. Ist schon ok, daß Du mich gefragt hast, aber ich habe nun mal auch andere "Hobbys" - wie oben angedeutet ;-).
JensP-Anfaenger
User
Beiträge: 23
Registriert: Montag 25. April 2005, 08:31
Wohnort: Schleswig-Holstein

Ja, ich hoffe, ich gehe dir (CM) nicht auf die Nerven!

Ersteinmal vielen Dank für deine Hilfe, werde das Programm gleich in Ruhe ausprobieren und versuchen es zu verstehen!

Ich wollte die Schleswig-Holstein-Frage auch nicht explizit dir stellen, hatte nur gehofft, dass sich hier lokal auch jemand findet!

Mir ist schon klar, dass alle hier im Forum sicher auch andere Beschäftigungen, und sicher auch spannendere, finden, als einem Python-Dummie zu helfen.

Allerdings muss ich sagen, dass ich den Mitgliedern, mit denen ich hier kommuniziert habe, ein 'dickes' Lob ausspreche.
Soweit scheinen hier alle, auch oder gerade blutigen Anfängern gegenüber, sehr aufgeschlossen und mitteilsam!


Also falls sich doch noch jemand findet, der aus dem Norden der Republik mitliest, wäre ich sehr dankbar, wenn er/sie sich bei mir meldet!

Gruß

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

Aber nein, bin doch nicht genervt. Ich habe bloß alles genau hinschreiben wollen, um Mißverständnisse zu vermeiden. Außerdem sind wir alle klein angefangen und bei mir ist es a) nicht so lange her und b) bin ich noch nicht so weit drüber hinaus. ;-)
Nach allem, was ich hier so gelesen habe, halte ich allerdings für unwahrscheinlich, daß Du andere Pythonnutzer im Norden findest - sie sind hier im Forum klar in der Minderheit.

Und sonst? Soweit alles klar?

Gruß,
Christian
JensP-Anfaenger
User
Beiträge: 23
Registriert: Montag 25. April 2005, 08:31
Wohnort: Schleswig-Holstein

Hallo,

habe mir mittlerweile das Programm angeschaut und denke, dass ich damit zurecht komme!

Eigentlich müsste ich jetzt das 'Handwerkszeug' zusammen haben, um mein Programm so schreiben zu können, wie ich es mir vorstelle!

Falls ich noch auf Probleme stoße, werde ich hier mal wieder nachfragen!

Also soweit vielen Dank!

Gruß

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

Nachtrag:
Bei allen Dingen, wo dieses Mini-Skript zu kurz kommt, PutValue() muß wirklich in geistiger Umnachtung zustande gekommen sein ...
Etwas besser ist:

Code: Alles auswählen

	def PutValue(self,event):
		#if enter & refresh
		self.parent.data = []
		if event.GetId() == 10:
			for item in self.boxes:			
				self.parent.data.append(item.GetValue())
			self.parent.flag = True
			self.parent.Handle()
		#if finish
		elif event.GetId() == 20:
			for item in self.boxes:
				self.parent.data.append(item.GetValue())
			self.parent.flag = False
			self.parent.Handle()
Gruß,
Christian
JensP-Anfaenger
User
Beiträge: 23
Registriert: Montag 25. April 2005, 08:31
Wohnort: Schleswig-Holstein

Hallo,

mittlerweile bin ich mit dem Aussehen meines Programms ganz zufrieden,
ich habe ein Frame mit einem Scrolled Panel, in dem durch das Drücken eines Buttons meine Eingabefelder wiederholt angehängt werden werden.

Meine Frage:
Wie kann ich auf die Werte in den Eingabefeldern zurückgreifen?

Ich übergebe dem Panel jetzt einen Namen, der meiner Tabelle (wxGrid)
zugeordnet wird, ich kann aber nicht auf die Tabelle zurückgreifen!
Oder macht man eine solche Abfrage eher über die ID?

Vielen Dank!

Gruß

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

Hoi Jens,

Hast Du Deine Eingabefelder in einem Dialog oder im Main-Frame?

Ich unterstelle mal folgendes: Du lehnst Dich - zumindest grob - an mein Beispiel an. Du benutzt einen Dialog, um Felder in einem Grid mit Daten zu versehen.

Na, in diesem Fall kennt Dein Mainframe ja Deine Daten, nicht wahr? Oder wie hast Du das gelöst?

Und was das Grid angeht: Dazu gibt es GetCellValue() von wxGrid. Das ist leider nicht sehr gut dokumentiert - wie so oft bei wx - aber führt Dich best. weiter.

Gruß,
Christian
JensP

Hallo,

warum funktioniert das bei mir nicht mit dem Login über Cookies sobald ich im Forum bin?

ich habe einen Frame erstellt, in diesem Frame gibt es dann ein ScrolledPanel, in diesem ScrolledPanel ist ein Sizer, dem dann über meinen Button jeweils wieder das zusätzliche Panel (mit dem Grid etc.) angehängt wird.

Hier ein Teil des Codes:

Code: Alles auswählen

fgs1=wx.FlexGridSizer(cols=2, vgap=4, hgap=a)
EingabePanel=PanelModul.PanelTabelle(parent=panel1, id=-1, pos=,size=,style=0, name=variablername)
fgs.Add(EingabePanel)
Und jetzt ein Teil des PanelModuls:

Code: Alles auswählen

class PanelTabelle(wx.Panel)
   def__init__ctrls(self,parent)
      self.grid=wx.grid.Grid(id=-1,name=self.name,  parent=self, pos=, size=, style=)
   def__init__(self,parent,id,pos,size,style,name)
      self.name=name
      self.__init__ctrls(parent)
Ich hätte gedacht, man könnte über den 'variablen Namen', der dann im 'PanelModul' dem Grid zugewiesen wird, irgendwie direkt auf die Tabelle zugreifen?!

Gruß

Jens

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

Hoi Jens,

wegen des Logins: Beschreibe doch mal Dein Problem in den "Verbesserungsvorschlägen" zum Forum. Ich habe ein ähnliches Problem und habe piddon auch schon versucht Bescheid zu geben. Bei der Umstellung zum neuen Theme hat es wohl einige Probleme gegeben. Außerdem gibt es noch nicht den Kopf mit dem Python-Code ...

Zu Deinem Problem: Ich kapiere den Code nicht.
- Du definierst fgs1 und hängst an fgs an. Was ist fgs?
- parent dabei ist panel1. Was ist panel1?
- Bei der PanelTablle-Klasse gibt es zwei __init__-Funktionen?!? Das ist ein absolutes No-No.
- Außerdem verstehe ich die letzte Zeile nicht: Gibt es da einen Fehler beim Kopieren des Codes? Oder was ist self.__init__ctrls()?

Die letzten beiden Punkte können aber auch daher rühren, daß Du in Code-Tags aber nicht in Python-Code-Tags eingebunden hast. Versuche das doch mal zu ändern: Einfach zwischen (python) und (/python) mit eckigen statt runden Klammern einbetten.

Ansonsten frage Dich doch selber mal wo Du Deine Daten ablegst. Die müssen ja schließlich irgendwo sein. Dann finden wir auch heraus wie Du drauf zugreifen kannst. Aber dieses Snippet erzählt mir das leider nicht. GUI-Code ist immer sehr lang, aber Du kannst gerne auch etwas mehr kopieren, wenn es nötig ist, um Deinen Code zu verstehen.

Gruß,
Christian
JensP

Hallo,

das mit dem doppelten __init__ kommt vom Erstellen der GUI mit dem Boa-Construktor, der erstellt immer mehrfache __init__!!!

Zu meinem Code:
Ich programmiere an meinem Laptop, bin aber mit dem Desktop-Rechner online, daher habe ich mich wohl beim kopieren und überarbeiten geirrt,
fgs entspricht fgs1 und soll flexgridsizer abkürzen!

Ich werde in den nächsten Tagen meinen Code mal soweit überarbeiten, dass diese doppelten __init__ etc. verschwinden und dann werde ich ihn hier wieder posten, damit mir bei meinem Daten-Zugriff-Problem geholfen werden kann!

Soweit erstmal vielen Dank!

Außerdem werde ich gleich noch das Login-Problem posten!

Gruß!

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

Hoi Jens,

das mit den verschiedenen Rechnern kenne ich - ist ziemlicher Mist. Noch schlimmer allerdings ist es, wenn - wie jetzt bei mir - der Laptop ein kaputtes Teilchen hat und in Reperatur muß. In der nächsten Woche kann ich damit keinen Pythoncode checken. Ich hoffe jemand anderer springt ein.

Gruß,
Christian
JensP-Anfaenger
User
Beiträge: 23
Registriert: Montag 25. April 2005, 08:31
Wohnort: Schleswig-Holstein

Jaja, wer lesen kann ist klar im vorteil!

Ich habe mir gerade das mit der Login-Problematik durchgelesen und festgestellt, dass ich mich über http://python.sandtner.net eingeloggt habe.

Jetzt unter www.python-forum.de funktioniert es!

Schade, dass es die nächste Woche bei dir nichts wird!

Ich würde mich sehr freuen, wenn sich jemand findet, der genauso freundlich und hilfreich wie CM ist!

Ansonsten hoffe ich, dass du mir nach deiner Laptop-Reperatur wieder helfen magst!

Vielen Dank!

Gruß!
Jens
Antworten