Brauche dringend Hilfe!!!

Fragen zu Tkinter.
Antworten
_so10_
User
Beiträge: 4
Registriert: Mittwoch 21. Dezember 2016, 08:12

Hallo!

Ich brauche dringend Hilfe,ich muss bis zum 01.01.2017 ein Programm fertig entwickelt haben.
Ich will ein Programm entwickeln,das die Durchbiegung eines Kragarms mit Gleichstreckenlast berechnet.

In dem Fall muss ich auch ein Rechteck programmieren,dessen Höhe und Breite mit der Maus variabel sind und sich die neu erlangten Werte sich automatisch in die Eingabefelder eintragen.

Das bekomme ich aber nicht hin. Wie sehen die einzelnen Schritte dafür aus und welche Formeln benötigt man dafür bzw braucht man dafür überhaupt irgendwelche Formeln?

Danke schon mal!
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@_so10_: warum antwortest Du nicht BlackJack in Deinem anderen Thread? Am besten mit Code, was Du schon versucht hast, und wo Du nicht weiter kommst.
_so10_
User
Beiträge: 4
Registriert: Mittwoch 21. Dezember 2016, 08:12

Welchen Code meinst du?
Ich bin mir nicht bewusst,welchen Code ich verwendet habe..
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@_so10_: wenn ich Dich richtig verstehe, hast Du schon ein fast fertiges Programm, das ein Rechteck darstellen kann, das man über Eingabefelder verändern kann. Nun fehlt Dir noch die Interaktion mit der Maus. Dazu hat Dir BlackJack schon Tipps gegeben. Also kannst Du doch das, was Du bisher hast und was noch nicht funktioniert hier zeigen, dann kann man gezielter sagen, wo es noch hakt.
_so10_
User
Beiträge: 4
Registriert: Mittwoch 21. Dezember 2016, 08:12

Das ist das Programm, welches ich bis jetzt geschrieben habe..
Sorry, konnte es nicht kürzen und ich habe vieles kommentiert, weil wir das vom Professor aus mussten.
In diesem Programm müsste eigentlich schon alles programmiert sein, bis auf die Interaktion der Maus.
Ich habe zwar etwas zur Maus-Funktion in dem Programm geschrieben, aber es"rennt" nicht.
Das Rechteck, bei dem sich die Höhe und Breite mit der Maus verschieben lassen sollen, ist quasi der einzige Teil der noch fehlt und ich weiß nicht, wie ich den zum laufen bringen soll..

BlackJack hat mir als Tipp gegeben, dass ich erst einmal zwei Seiten des Rechtecks mit der Maus verschiebbar machen sollte, da weiß ich schon nicht, wie ich das machen soll und danach soll ich die Canvas-Koodrinaten auf die Weltkoordinaten umrechnen. Zum einen, wie geht das und warum muss man die auf die Weltkoordinaten umrechnen?

Code: Alles auswählen

# Bibliothek tkinter importieren
from tkinter import *
from time import time

# Hauptfenster erstellen
H = Tk()
H.title("Berechnung von Durchbiegungen und Winkeländerungen eines Kragarms")
Leinwand = Canvas(H, width=500, height=300, bg="white")
Leinwand.grid(row = 1, column = 0)

# Einspannung des Balkens
Leinwand.create_line(200,15, 200,90, width = 2)

# Balken
Leinwand.create_line(200,55, 400,55, width=2)

# Maßlinie (Länge) des Balkens
Leinwand.create_line(200,100, 400,100)
Leinwand.create_line(200,95, 200,105)
Leinwand.create_line(400,95, 400,105)
Leinwand.create_text(300,92, text = "l = 6,00m")

# Last q
Leinwand.create_line(200,25, 400,25, width = 2)
for x in range(205,405,15):
    Leinwand.create_line(x,25, x,50, width = 2, arrow = "last")
Leinwand.create_text(300,16, text = "q = 15 kN/m")
    
# Rechteckquerschnitt
Leinwand.create_text(100,150, text="Rechteckquerschnitt:")

def zeichne():
    # Canvas wird gelöscht 
    Leinwand.delete("all")
    # Bezugsordinaten:
    Leinwand.y1 = y1 = 150 # y -Ordinate von der linken oberen Ecke 
    Leinwand.x1 = x1 = 150 # x-Ordinate von der linken oberern Ecke
    Leinwand.xa = xa = 200 # Balkenbeginn
    Leinwand.xb = xb = 400 # Balkenende
    Leinwand.ys = ys = 55  # statisches System
    Leinwand.yw = yw = 55 # Momentenlinie
    # Canvas wird gelöscht
    Leinwand.delete("all")
    # Lastbeginn als Canvasordinate
    xc = 55
    # Momentenlinie
    Ws = 15*(6*3(3**2/2)-(6**2/2))
    # Startpunkt der Momentenlinie
    PW = ([xa,yw])
    # Monentenlinie in 10 Teilstücken
    for i in range(11):
        Wi = A*(a+c*i/10)-q*(c*i/10)**2/2
        # Canvasordinate an Liste anhängen
        PW.append((xc + (xb-xc)*i/20, yw + Wi*Ws))
    # Nulinie; zurück zum Startpunkt
    PW.append((xa,yw))
    Leinwand.create_line(PW, width = 2)
    # Durchbiegung w
    w = float(Ew.get())
    Leinwand.create_line(200,55, 202,55, 400,55+w*10,smooth = 1, width = 2)
    Leinwand.create_text(450,75, text = "w = %.2f m")
    # Lastbeginn als Canvasordinate
    yd = 55
    # Skalierung der Durchbiegung (Höhe maximal 100)
    Ds = (100/(q*l**2/8)) if q else 0
    # Startpunkt der Durchbiegungslinie
    PD = [(x1, yd)]
    # quadtratische Parabel in 20 Teilstücken
    for i in range(21):
        # Durchbiegung an der Stelle xi
        Di = B*(l*i/20)-q*(l*i/20)**2/2
        # Canvasordinate an Liste anhängen
        PD.append(yd + Di*Ds)
        # Nullinie; zurück zum Stratpunkt
        PD.append((x1,yd))
        Leinwand.create_line(PD, width = 2)
        
    # Rechteckquerschnitt
    # Zeichenbeginn als Canvasordinate
    x1 = 150
    # Skalierung des Rechtecks (Höhe maximal 100)
    Rs = (100/b*h**2/8)
    # Startpunkt des Rechtecks
    PR = [(x1, xr)]
    # Rechteck in 20 Teilstücken  

def liesZahl(E):
    try:
        return float(E.get().replace(",","."))
    except:
        return None

# Die Funktion für den Knopf "Berechnen!"
def berechnen(event=None):
    b = float(Eb.get())
    h = float(Eh.get())

    try:
        b = x1+50
        h = y1+50
        I = (b*h**3)/12
        E = 21000
        q = 1,5
        l = 600
        w = (5/384)*((q*l**4)/(E*I))
        α = (q*l**4)/(8*E*I)
        zeichne()

    except ValueError:
        print("Das war keine gültige Zahleneingabe. Bitte überprüfen Sie Ihre \
               Zahleneingabe.")

def Mausklick(event):
    # Canvasordinate der Maus:
    Mx, My = event.x, event.y

    if Leinwand.x1 <= Mx < Leinwand.x2:
        l = liesZahl(El)
        # neue Balkenbreite
        a = b*(Mx-Leinwand.xa)/(Leinwand.xb-Leinwand.xa)
        # berechneten Wert ins Eingabefeld schreiben
        Ea.delete(0,"end")
        Ea.insert(0,"%.2f"%n)
        # Lastordinate ...
        q =(Leinwand.ys-My)/2
        # ... ins Eingabefeld eintragen
        Eq.delet(0,"end")
        Eq.insert(0,"%.2f"%q)
        berechne()
        
################
# GUI zeichnen #
################

# Eingabe der Überschrift
L1=Label(text="Informatikhausarbeit Ws 2016/2017, Maren Duda")
L1.grid(row = 0, column = 0, columnspan = 3, sticky = "n")

# Mausklick in Canvas setzt Breite und Höhe des Rechteckquerschnitts
Leinwand.bind("Button-1>",Mausklick)  # Mausklick
Leinwand.bind("B1-Motion>",Mausklick) # Bewegung bei gedrückter Taste

# Eingabetasten
H.bind("<Return>",berechnen)   # Eingabetaste
H.bind("<KP_Enter>",berechnen) # Ziffernblock

# Zeile 1: Eingabe von b
Label(text = "b = ").grid(row = 2, column = 0, sticky = "e")
Eb = Entry(width = 20)
Eb.grid(row = 2, column = 1, sticky = "we")
Label(text = "cm").grid(row = 2, column = 2, sticky = "w")
    
# Zeile 2: Eingabe von h
Label(text = "h = ").grid(row = 3, column = 0, sticky = "e")
Eh = Entry(width = 20)
Eh.grid(row = 3, column = 1, sticky = "we")
Label(text = "cm").grid(row = 3, column = 2, sticky = "w")
    
# Zeile 3: Der Button "Berechne!"
b1 = Button(H, text = "Berechne!", command = berechnen, width = 20)
b1.grid(row = 4, column = 1, sticky = "e")

# Zeile 4: Ausgabe von wx
Label(text = "w = ").grid(row = 5, column = 0, sticky = "e")
Ew = Entry(width = 20)
Ew.grid(row = 5, column = 1, sticky = "we")
Label(text = "cm").grid(row = 5, column = 2, sticky = "w")

# Zeile 5: Ausgabe von α
Label(text = "α = ").grid(row = 6, column = 0, sticky = "e")
Eα = Entry(width = 20)
Eα.grid(row = 6, column = 1, sticky = "we")
Label(text = "°").grid(row = 6, column = 2, sticky = "w")

# Hauptschleife
H.mainloop()
Zuletzt geändert von Anonymous am Mittwoch 28. Dezember 2016, 19:14, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@_so10_: Das ist bereits viel zu viel Code der überhaupt nicht funktioniert. Programme entwickelt man üblicherweise so, dass man das Problem in immer kleinere Teilprobleme aufteilt, bis diese so klein sind, das man sie mit einer Funktion mit ein paar Zeilen Code lösen kann. Und erst wenn so eine Teillösung funktioniert, macht man mit der nächsten Teillösung weiter, die entweder für sich alleine steht, oder bereits implementierte Teillösungen zu einer grösseren Teillösung zusammenfügt. Und auch da testet man erst ob das tatsächlich das macht was es soll bevor man weiteren Code schreibt, der vielleicht auch nicht funktioniert.

Die Interaktion mit dem Querschnitt ist ja letztlich nur eine zusätzliche Eingabemöglichkeit zu den Eingabefeldern. Also würde es Sinn machen das erst einmal ohne diesen Querschnitt *überhaupt* zum laufen zu bringen, statt sich jetzt schon mit dieser Eingabemöglichkeit zu beschäftigen wo man schon viel Code hat der doch deutlich fehlerbehaftet ist.

In Zeile 47 wird versucht das Ergebnis von 6*3 als Funktion aufzurufen, was nicht gehen wird. In Zeile 52 wird ein `c` verwendet was wirklich *nirgends* definiert wurde. In den Zeile 65 und 71 wird auf ein undefiniertes `l` zugegriffen. In den Zeilen 99 und 100 sind `x1` und `y1` undefiniert. In Zeile 103 wird `q` als Tupel mit den Zahlen 1 und 5 definiert wo Du ziemlich sicher 1.5 meintest und nicht 1,5. Das wird spätestens in Zeile 106 zu einem Folgefehler führen. In `Mausklick()` werden `Ea` und `Eq` verwendet die aber ebenfalls nirgends definiert wurden.

Ich würde zudem nicht einfach irgendwelche Werte an ein `Canvas`-Exemplar binden. Du hast da ein GUI-Programm, da wirst Du letztendlich sowieso eigene Klassen schreiben müssen wenn das sauber und nachvollziehbar werden soll. Da muss man sich dann nicht irgendwelche Objekte als Behelfsspeicher hernehmen, denn man hat ja eigene, die dafür explizit vorgesehen sind zusammengehörige Daten zu speichern.

Insgesamt fehlen da noch Python-Grundlagen, zum Beispiel was den Sichtbarkeitsbereich von Namen angeht. Du scheinst davon auszugehen, dass Namen die man lokal in einer Funktion definiert, im ganzen Programm einfach so sichtbar sind. Das sind sie nicht. Sie sind nur innerhalb der Funktion sichtbar, und da auch nur während der Aufruf abgearbeitet wird. Funktionen sind als in sich geschlossene Handlungsanweisungen gedacht bei denen man beim Aufruf Argumente hinein steckt und eventuell Rückgabewerte an den Aufrufer zurück gibt. Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Trenne die Berechnung von der Anzeige. So kann man die Berechnung testen ohne eine GUI zu benötigen und auch leichter wiederverwenden. Und es ist klarer welche Zahlen zu dem physikalischen Modell gehören das berechnet wird, und welche Zahlen und Rechnungen zur Anzeige gehören. Zudem sind dort verdammt viele ”magische” Werte als Zahlen und auch in Zeichenketten. Zum Beispiel die 6 Meter Länge, sollte als Konstante definiert werden und dann sowohl in der Zeichenkette für die Beschriftung als auch bei der Berechnung der Linienlänge berücksichtigt werden. So wie es jetzt ist sind da ein Haufen Zahlen im Programm bei denen man erst herausfinden muss was die eigentlich bedeuten. Das betrifft erst einmal nur ”fremde” Leser, aber erfahrungsgemäss wird man mit der Zeit selbst zum ”Fremden”, nämlich dann wenn man sich den Quelltext in ein paar Monaten noch mal anschaut und sich selbst erst wieder einarbeiten muss als wäre das Code von jemand anderem. Teilweise wird das schon gemacht, dann aber nicht verwendet. Die 55 wird sogar an zwei verschiedene Namen mit jeweils der gleichen Erklärung als Kommentar (dazu weiter unten noch etwas) gebunden, aber dann doch an mehreren Stellen wieder als magische Zahl ins Programm geschrieben.

Ich würde bei so einem Programm erwarten, dass da von Anfang an schon Werte eingetragen sind und eine berechnete Grafik angezeigt wird.

Die Namen sind fast alle schlecht gewählt. Ein- oder zweibuchstabige Namen sind zwar in der Mathematik oder Physik üblich, bei Programmen wählt man normalerweise Namen die dem Leser die Bedeutung eines Wertes hinter einem Namen vermitteln ohne das man irgendwelche Abkürzungen kennen muss oder die Zeile mit dem Kommentar suchen muss die einen nichtssagenden Namen erklärt. Solche Kommentare sind oft ein Zeichen, dass man einen besseren Namen finden sollte, den man nicht extra erklären muss. Insbesondere wenn die Erklärung nur aus einem Wort/Begriff besteht, stellt sich die Frage warum man nicht gleich das als Namen verwendet hat.
Antworten