Drop-Down Box Binding

Fragen zu Tkinter.
Antworten
HTLEisenstadt
User
Beiträge: 28
Registriert: Mittwoch 30. Januar 2013, 16:40

Hallo liebes Python-Forum,

Mithilfe von Python habe ich zwei Programme geschrieben: Ein Rechenprogramm in dem am Anfang eine Eingabe definiert ist, die man im Shell eingaben muss. Es wird am Ende dann ein Diagramm gezeigt. Als zweites Programm habe ich ein grafisches Programm mit Tkinter geschrieben.
Ich würde nun die beiden (das reine Rechenprogramm und das grafische Programm) gerne binden und stehe vor einem (für mich) Problem:
Das grafische Programm besteht aus mehreren Drop-Down Boxen, die mit der Eingabe des Rechenprogramms gebindet werden sollen.
Hier die Oberfläche des grafischen Programms:
Bild

Hier die dazu gemachte Drop-Down Definition für die erste Dop-Down Box:
Bild

Für das Rechnen im Rechenprogramm brauche ich logischerweise nur die Zahlen, also z.B. wie im ersten Bild sichtbar "4415", das NACA soll aber in der Drop-Down schon erscheinen.
Meine erste Frage: Wie kann ich denn das mit der Eingabe Binden?

Problem ist, ich brauche die Zahlen nicht alle gemeinsam, sondern die erste Zahl einzeln, dann die zweite einzeln und dann die letzten zwei gemeinsam (Es sind immer nur 4!)!

Die Eingabe im Rechenprogramm sieht dazu noch wie folgt aus:
Bild

D.h. z.B., der erste 4er im "NACA 4415" des Drop-Down Menüs soll mit der stelle1 der Eingabe gebindet werden, der 4er mit der stelle2 und die letzten beiden mit der stelle3!

Ist das möglich? :?:
Ich bin leider nicht so firm mit dem Programmieren, hab mich aber schon die letzten 3Tage nur mit dem Binding auseinandergesetzt und schaff es leider nicht, alles andere der beiden Programme ging eigentlich mit ein bisschen Hilfe!

Ich danke euch schon einmal im Voraus! Schönen Ostersonntag,
Grüße, HTLEisenstadt
Benutzeravatar
daemonTutorials
User
Beiträge: 171
Registriert: Sonntag 6. Februar 2011, 12:06
Kontaktdaten:

Hallo,

du hast die Zahlen doch bereits aufgesplittet im ersten Programm vorliegen. Übergebe die doch einfach dem Programm als Parameter. Oder du kannst dem Programm auch die ganze Zahl geben und einfach folgendes tun:

Code: Alles auswählen

number = str(sys.argv[1]) # Sicherstellen, dass es als String kopiert wird
number1 = number[0:1]
number2 = number[1:2]
number3 = number[2:4]
Das wäre die eine Methode, ein subprocess-Call aufrufen, was recht unsauber erscheint, weil Python ja objektorientiert ist. Wie wird dein zweites Programm denn aufgerufen? Falls es in einer Klasse verpackt ist, kannst du auch im ersten Programm folgendes tun:

Code: Alles auswählen

import programm2

prg2 = new GUI(stelle1,stelle2,stelle3)
Falls dein Code prozedural ist, kannst du ja den gesamten Code in eine Funktion schreiben und die Werte dort empfangen und in eigene Variablen speichern und weiterverwenden:

Code: Alles auswählen

def main(stelle1,stelle2,stelle3):
    number1=stelle1
    number2=stelle2
    number3=stelle3
    # …
und im ersten Programm:

Code: Alles auswählen

import programm2

# …
# Aufruf Programm 2
programm2.main(stelle1,stelle2,stelle3)
Damit hättest du bereits die Werte im anderen Programm, wie du das machst, bleibt dir überlassen.

Aber wenn du beide Programm parallel offen hast, haben wir mit diesen Methoden ein kleines Problem. Und zwar ist dein Python-Programm bereits gestartet und du kannst ohne weiteres keine Einfluss von Programm1 auf Programm2 nehmen. In diesem Fall könntest du die Daten in einer CSV-Datei speichern und im anderen Programm eine weitere Routine hinzufügen und die Datei regelmäßig auslesen und die Daten eintragen, und wenn sie stehen, die Routine verlassen. Oder du könntest in einem Open-Dialog auffordern eine CSV Datei auszuwählen und die Daten dann reinschreiben.

Der UseCase entscheidet bekanntlich:

Entweder du hast IMMER den Workflow Programm1->Programm2 oder die Programme können auch unabhängig von einander ablaufen. Bei Variante 1 löst du das mit einem Programm1-internen Aufruf von Programm2 und übergibst die Werte so. Bei Variante2 musst du ein "Protokoll" schaffen und einen gemeinsamen Speicherpunkt ausmachen bzw. optional eine CSV-File vom Nutzer verlangen, der die Daten dadurch einlesen kann.

Bei Variante1 bervorzuge ich persönlich die Instanzierung der Klasse mit Initial-Werten. (Wenn du OOP benutzt hast) Bei Variante2 bevorzuge ich die optionale Auswahl der CSV-File, weil ständig im Hintergrund einen Watchdog zu haben, der die Datei überwacht frisst Ressourcen und Performance. Wie sonst werden in großer Software Projekte übertragen, per Dateiimport. Damit ist dein Programm auch für andere intuitiv bedienbar, weil sie wissen: Hier importiere ich eine Datei und das Programm das nicht für sie im Hintergrund tut, was recht unschön ist, wenn die eigenen Werte plötzlich überschrieben werden.

Was das "nur NACA" angeht: Füge es doch einfach als ersten Eintrag hinzu und überprüfe dann später beim Verarbeiten der Daten, ob die Auswahl NICHT der erste Eintrag ist.

http://www.tutorialspoint.com/python/py ... uments.htm
http://docs.python.org/2/library/subpro ... subprocess
http://docs.python.org/2/library/csv.html
http://docs.python.org/2/library/tkinte ... filedialog und http://tkinter.unpythonic.net/wiki/tkFileDialog
LG Maik
HTLEisenstadt
User
Beiträge: 28
Registriert: Mittwoch 30. Januar 2013, 16:40

Hallo Maik,

erstmal vielen Dank für deine Antwort,

ich glaube ich wurde falsch verstanden. Ich habe die Zahlen NICHT gesplittet vorliegen!
Was ich habe:
Ein .py-File nur mit der grafischen Oberfläche und ein .py-File das das ganze dann rechnen soll!
Den Code der grafischen .py-Datei habe ich in die rechnerische gegeben.
Wenn ein Nutzer das Programm startet, so soll er im Drop-Down-Menü z.B. "NACA 4412" auswählen können!
Bild

Im Code sieht das noch wie folgt aus:
Bild

Jetzt soll aus dem vom Nutzer ausgewählten "NACA 4412" nur die Zahlen genommen werden, wobei die erste, die zweite und die letzten beiden gesplittet werden sollen.
Sie sollen dann in dem rechnerischen Teil der .py-Datei jeweils übernommen werden!
Bild

Ist schwierig zu erklären, ich weiß, aber wie definiere ich das denn im Drop-Down Menü?

Grüße, HTLEisenstadt
Benutzeravatar
daemonTutorials
User
Beiträge: 171
Registriert: Sonntag 6. Februar 2011, 12:06
Kontaktdaten:

Jetzt sehe ich das Problem.
  1. NACA muss als Anfangswert eingestellt werden
  2. Das DropDown Menü hat nichts mit dem rechnerischen Teil zutun, du fragst lediglich die Variablen davon ab
Um den Wert abfragen zu können, musst du deinen Code etwas modifizieren.

Code: Alles auswählen

sar = StringVar(master)
sar.set("NACA") # Anfangswert

option = OptionMenu(master, sar, "NACA", "NACA 2412", "NACA 2415", "NACA 2418", "NACA 4408", "NACA 4412", "NACA 4415", "NACA 4418")
option.config(justify=RIGHT, anchor=N, padx=20, pady=10, font=("Arial",15))
option.place(x=30,y=40)
und um dann die gewählte Nummer abgreifen zu können:

Code: Alles auswählen

number = str(sar.get()) # Beispiel: NACA 1234
nr1 = number[5:6] # 1
nr2 = number[6:7] # 2
nr3 = number[7:9] # 34
So kriegst du deine Nummern:

Code: Alles auswählen

>>> number = "NACA 2312"
>>> number[6:7]
'3'
>>> number[7:9]
'12'
>>> 
Jetzt bin ich gerade noch etwas verwirrt. Wenn beide Sachen in einer Py-File stecken, einfach in die Variablen lesen wie oben und nutzen. Wenn du vom Grafischen aus, das ganze ausrechnen willst, dann bau dir eine Funktion darein, die du aufrufst und dir die Werte berechnet.

Code: Alles auswählen

def calculate(nr1,nr2,nr3):
    # Hier die Berechnung

    return [nr1,nr2,n3]

Code: Alles auswählen

import mycalculate

mycalculate.calculate(nr1,nr2,nr3)
Aber jetzt wieder UseCase:
  • Die GUI berechnet und zeigt an
  • Die GUI schickt Daten an Calc, die dort verwendet werden sollen | GUI ruft Calc auf
  • GUI speichert Daten und Calc liest aus | GUI und Calc unabhängig
Ich habe das so verstanden, dass deine GUI die Calc-Routine aufruft und dort die Werte eingesetzt werden sollen. Das geht wie gesagt über eine der oben genannten Wege. Und wie du die dort einbaust:

Code: Alles auswählen

stelle1 = float(nr1)
stelle2 = float(nr2)
stelle3 = float(nr3)
print("Profilwölbung in %: "+str(stelle1))
print("Wölbungsrücklage in 10-%: "+str(stelle2))
print("Profildicke in % (zweistellig): "+str(stelle3))
Soll der Nutzer trotzdem selber Eingaben machen können:

Code: Alles auswählen

stelle1 = float(input("Profilwölbung in % [%s]: " %nr1))
stelle1 = stelle1 or nr1
stelle2 = float(input("Wölbungsrücklage in 10-% [%s]: " %nr2))
stelle2 = stelle2 or nr2
stelle3 = float(input("Profildicke in % (zweistellig) [%s]: " %nr3))
stelle2 = stelle3 or nr3
Wie du die Daten bei zwei seperaten Files rüberbekommst, musst du wie gesagt über die vorher gezeigten Wege machen.
LG Maik
HTLEisenstadt
User
Beiträge: 28
Registriert: Mittwoch 30. Januar 2013, 16:40

Hallo Maik,
Aber jetzt wieder UseCase:
Die GUI berechnet und zeigt an
Die GUI schickt Daten an Calc, die dort verwendet werden sollen | GUI ruft Calc auf
GUI speichert Daten und Calc liest aus | GUI und Calc unabhängig
Ich habe das so verstanden, dass deine GUI die Calc-Routine aufruft und dort die Werte eingesetzt werden sollen. Das geht wie gesagt über eine der oben genannten Wege. Und wie du die dort einbaust:
Genau das meinte ich - vielen Dank! :-) Gott sei Dank wurde ich vom Python-Forum schon auf die Funktion hingewiesen! Jetzt funktioniert alles. Den Anstellwinkel habe ich noch mit einem Slider gestaltet... Funkt PERFEKT! Vielen Dank nochmal an euch! :D

Kannst du mir ein geeignetes Modul zum schönen darstellen von Diagrammen sagen? (MATHPLOT, GNUPLOT etc..). Was würdest du mir empfehlen? Ich hätte gerne etwas, dass ich direkt in der .py-Datei habe, d.h., dass ich kein extra File benötige auf das das Hauptprogramm zugreifen muss!

Grüße, HTLEst.
Benutzeravatar
daemonTutorials
User
Beiträge: 171
Registriert: Sonntag 6. Februar 2011, 12:06
Kontaktdaten:

Das TK-Canvas Modul.

Musst dich halt ein bisschen reinfuchsen, ein Basis-Pattern für Diagramme basteln und dann kannst du deine Punkte ja setzen und verbinden usw.
LG Maik
lunar

@HTLEisenstadt Zwei Dinge für die Zukunft: Bitte erstelle Screenshots im PNG-Format. JPEG erzeugt an harten Kanten (e.g. Schrift) Artefakte. Und erstelle bitte keine Screenshots von Quelltext, sondern kopiere den Quelltext einfach in Deinen Beitrag, und versehe ihn mit Python-Tags (siehe den Knopf über dem Eingabefeld).

Danke.
Antworten