GUI – 38 Eingabefelder und 38 Beschriftungen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo Nutzer! :)

Ich möchte meine HTML/PHP-Anwendung „Liverecord“ in Python umschreiben. Das Buch

THEIS, Thomas: Einstieg in Python. Ideal für Programmieranfänger. – Bonn: Rheinwerk Verlag GmbH 5., aktualisierte Auflage 2017 (4525)

habe ich bis Seite 387 minutiös durchgearbeitet. Leider scheitere ich noch daran, 38 Eingabefelder und ihre 38 Beschriftungen in einer tkinter-GUI schön anzuordnen. Bitte seht auf dem beigefügten Bild, wie die Sache aussehen soll. http://www.bilder-upload.eu/show.php?fi ... 217278.jpg

Weil ich mit mySQL und XAMPP arbeite, kann ich kein Python 3.6 benutzen, sondern bin auf Python 3.4 angewiesen.

Was sind die Layout-Manager „pack“, „grid“ und „place“, wie muss ich sie benutzen?

So weit bin ich bisher gekommen:

Code: Alles auswählen

import tkinter

def ende():
    main.destroy()

main = tkinter.Tk()

# 38 Eingabefelder mit Beschriftung

# Eingabefeld nummer
lb1 = tkinter.Entry(main, text= "")
'''
lb1["font"] = "Arial 8"
lb1["height"] = 1
lb1["width"] = 30
lb1["anchor"] = "w"
'''
lb1.pack(padx=100, pady=10)
# Eingabefeld nummer Beschriftung
lb1b = tkinter.Label(main, text = "nummer")
lb1b.pack(padx=100, pady=10)

main.mainloop()
Erbitte dringend eure wertvollen Tipps!

euer
Strawk
Ich programmiere erfolglos, also bin ich nicht.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das es Place gibt, solltest du schnell vergessen. Außer in sehr speziellen Situationen will man das nicht, weil es auf verschiedenen Rechnern mit anderen fonts und Bildschirmauflösungen dann schlecht aussieht. Und auch einem selbst viel Arbeit macht, wenn man zb ein Label vergrößert und manuell alles anschieben muss.

Grid und pack sind dein Freund. Und dein Problem ist einfach ein Grid 3x4 mit jeweils einem frame in dem du ein vertikales pack der 6 Widgets machst.
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo!

Könntest du mir dazu einen Beispielcode posten? Danke!

Grüße,
Strawk
Ich programmiere erfolglos, also bin ich nicht.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nein. Ich bin hier auf dem iPad unterwegs, da Programmier es sich nicht so gut. Man kann Grid Beispiele aber auch im Netz suchen. http://effbot.org/tkinterbook/grid.htm

Nachtrag: effbot suggeriert dabei sogar das man nur Grid verwendet. Dann wird dein Problem viel einfacher. Denn dann sind es pro Widget (Label oder Entry) eine Koordinate.
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo __deets__!

Ich bitte dich um einen lauffähigen Beispielcode, wenn du wieder daheim bist.

:)
Grüße,
Strawk
Ich programmiere erfolglos, also bin ich nicht.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich bin zuhause. Aber wenn ich den Rechner aufklappe, geht immer sich gleich das Rechnungsprogramm an, mit dem ich dir Programmieraufträge abrechne.

Alternativ kannst du das lauffähige Beispielprogramm aus dem Link von mir probieren und dich damit dann vertraut machen mit dem Grid Layouter. Wenn dann konkrete Fragen auftauchen, beantworte ich die gerne am iPad.
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo __deets__ :)

Erstmal vielen Dank für deine Hilfe. Hier siehst du meine bisherige GUI.

http://www.bilder-upload.eu/show.php?fi ... 292214.jpg

Sieht doch schon ganz passabel aus, nicht wahr?

Ich möchte nun testweise in die Felder Werte eintragen. Ein zweites Skript soll aufgerufen werden und die Werte ausgeben, mit „print“. Nun habe ich aber von Python-Modularisierung keine Ahnung. In PHP machte ich das mit „post“ und „get“. Wie modularisiert man eine Python-Anwendung?

Erbitte deine wertvollen Tipps!

Strawk
:)
Ich programmiere erfolglos, also bin ich nicht.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Strawk: was meinst Du mit zweitem Skript? Reicht Dir nicht, eine Funktion aufzurufen? Für's erste kann das dann auch alles in einer Datei stehen. Sollte das Skript mit der Zeit doch zu groß werden, kann man immer noch eine Einteilung in mehrere Module vornehmen.
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo Sirius3!

Das Ursprungsprogramm in PHP besteht aus 19 Skripten. Mein Ziel ist die Übertragung in Python. Eine Datenbank soll angesprochen und verändert werden können. Denke, ich komme um Modularisierung nicht drum rum.

Grüße
Strawk
:o
Ich programmiere erfolglos, also bin ich nicht.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Schön das du weitergekommen bist!

Das ein größeres Projekt modularisiert ist stimmt schon. Nur wirkt es so als ob du hier konkret versuchst, die gleiche Einteilung wie in PHP einzuführen. Und das ist fraglich. Es gibt ja technische Gründe, warum die Web Anwendung aufgebaut ist wie sie ist. Nämlich um die benötigten URL-Pfade zu erzeugen. Aber bei der GUI hast du diese Anforderungen ja nicht. Du kannst oder solltest also entlang anderer Grenzen schneiden.

Die Frage ist, welche das sind. Wenn du eine DB ansprichst, dann kann es zB sinnvoll sein, eben diese und die Operationen welche auf ihr durchgeführt werden in ein extra Modul zu packen.

Und das Modul System von Python ist gut dokumentiert, inklusive einer Tutorial-Sektion. Das einzige, das daran IMHO etwas schwierig ist, ist das Thema der Suchpfade. Aber das kriegen wir hin.

Hat deine Anwendung einen Namen?
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Hier noch der Code zum Erzeugen des Formulars.

Code: Alles auswählen

import tkinter as tk

LABELS = ["Name", "Geburtsname","Vorname",
    "Straße", "PLZ", "Ort",
    "Ortsteil", "Bundesland", "Land",
    "Fahrzeugfabrikat", "Fahrzeugtyp", "Kennzeichen",
    "Landesvorwahl", "Ortsvorwahl", "Telefonnummer",
    "aktiv", "Mobilvorwahl", "Mobilnummer",
    "Email 1", "Email 2", "URL"]

def generate_form(window, labels):
    entries = []
    for idx, label in enumerate(labels):
        framenum, idx = divmod(idx, 3)
        if idx == 0:
            frame = tk.Frame()
        entry = tk.Entry(frame)
        entry.pack()
        entries.append(entry)
        lb = tk.Label(frame, text=label)
        lb.pack()
        if idx == 2:
            row, column = divmod(framenum, 3)
            frame.grid(row=row, column=column, padx=5, pady=15)
    return entries

class Main(tk.Tk):
    def __init__():
        super(Main, __init__)(self)
        self.entries = generate_form(self, LABELS)

def main():
    root = Main()
    root.mainloop()

if __name__ == '__main__':
    main()
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo!

Ich habe seinerzeit das PHP-Projekt "Liverecord" getauft.

Momentan läuft meine GUI nicht mehr. Vor dem letzten Rechner-Ausschalten ist sie noch gelaufen.

Code: Alles auswählen

import Tkinter as tk

# Funktion zu den Schaltflächen
def ende():
    master.destroy()

# Hauptfenster
master = tk.Tk()
master.geometry("800x600+30+30") 

# nummer, codierung
e_nummer = Entry(master).grid(row=0, column=0)
e_codierung = Entry(master).grid(row=1, column=0)
Label(master, text="nummer").grid(row=0, column=1)
Label(master, text="codierung").grid(row=1, column=1)

# name_oder_firmenname, geburtsname, vorname_bezeichnung
Entry(master).grid(row=0, column=2)
Entry(master).grid(row=2, column=2)
Entry(master).grid(row=4, column=2)
Label(master, text="name_oder_firmenname").grid(row=1, column=2)
Label(master, text="geburtsname").grid(row=3, column=2)
Label(master, text="vorname_bezeichnung").grid(row=5, column=2)

# strasse_hausnummer, plz, ort_stadt
Entry(master).grid(row=0, column=3)
Entry(master).grid(row=2, column=3)
Entry(master).grid(row=4, column=3)
Label(master, text="strasse_hausnummer").grid(row=1, column=3)
Label(master, text="plz").grid(row=3, column=3)
Label(master, text="ort_stadt").grid(row=5, column=3)

# ortsteil, bundesland_provinz_kanton, land_nation
Entry(master).grid(row=0, column=4)
Entry(master).grid(row=2, column=4)
Entry(master).grid(row=4, column=4)
Label(master, text="ortsteil").grid(row=1, column=4)
Label(master, text="bundesland_provinz_kanton").grid(row=3, column=4)
Label(master, text="land_nation").grid(row=5, column=4)

# fahrzeugfabrikat, fahrzeugtyp, kfz_kennzeichen_historie
Entry(master).grid(row=6, column=2)
Entry(master).grid(row=8, column=2)
Entry(master).grid(row=10, column=2)
Label(master, text="fahrzeugfabrikat").grid(row=7, column=2)
Label(master, text="fahrzeugtyp").grid(row=9, column=2)
Label(master, text="kfz_kennzeichen_historie").grid(row=11, column=2)

# landesvorwahl, festnetzvorwahl, festnetznummer
Entry(master).grid(row=6, column=3)
Entry(master).grid(row=8, column=3)
Entry(master).grid(row=10, column=3)
Label(master, text="landesvorwahl").grid(row=7, column=3)
Label(master, text="festnetzvorwahl").grid(row=9, column=3)
Label(master, text="festnetznummer").grid(row=11, column=3)

# aktiv, mobile_vorwahl, mobiler_anschluss
Entry(master).grid(row=6, column=4)
Entry(master).grid(row=8, column=4)
Entry(master).grid(row=10, column=4)
Label(master, text="aktiv").grid(row=7, column=4)
Label(master, text="mobile_vorwahl").grid(row=9, column=4)
Label(master, text="mobiler_anschluss").grid(row=11, column=4)

# e_mail_1, e_mail_2, url
Entry(master).grid(row=12, column=2)
Entry(master).grid(row=14, column=2)
Entry(master).grid(row=16, column=2)
Label(master, text="e_mail_1").grid(row=13, column=2)
Label(master, text="e_mail_2").grid(row=15, column=2)
Label(master, text="url").grid(row=17, column=2)

# geschlecht, anzahl_kinder, verstorben_am_um
Entry(master).grid(row=12, column=3)
Entry(master).grid(row=14, column=3)
Entry(master).grid(row=16, column=3)
Label(master, text="geschlecht").grid(row=13, column=3)
Label(master, text="anzahl_kinder").grid(row=15, column=3)
Label(master, text="verstorben_am_um").grid(row=17, column=3)

# geburtstag, anzahl_ereignisse, memos
Entry(master).grid(row=12, column=4)
Entry(master).grid(row=14, column=4)
Entry(master).grid(row=16, column=4)
Label(master, text="geburtstag").grid(row=13, column=4)
Label(master, text="anzahl_ereignisse").grid(row=15, column=4)
Label(master, text="memos").grid(row=17, column=4)

# fax, titel, beruf
Entry(master).grid(row=18, column=2)
Entry(master).grid(row=20, column=2)
Entry(master).grid(row=22, column=2)
Label(master, text="fax").grid(row=19, column=2)
Label(master, text="titel").grid(row=21, column=2)
Label(master, text="beruf").grid(row=23, column=2)

# ausbildung, taetigkeit, taetig_in_firma
Entry(master).grid(row=18, column=3)
Entry(master).grid(row=20, column=3)
Entry(master).grid(row=22, column=3)
Label(master, text="ausbildung").grid(row=19, column=3)
Label(master, text="taetigkeit").grid(row=21, column=3)
Label(master, text="taetig_in_firma").grid(row=23, column=3)

# hobbys, herkunftsland, bekanntschaft_seit
Entry(master).grid(row=18, column=4)
Entry(master).grid(row=20, column=4)
Entry(master).grid(row=22, column=4)
Label(master, text="hobbys").grid(row=19, column=4)
Label(master, text="herkunftsland").grid(row=21, column=4)
Label(master, text="bekanntschaft_seit").grid(row=23, column=4)

def buttonSucheClick():
    nummer = str(e_nummer)
    # codierung = str(e_codierung.get())
    
buttonSuche = Button(master, text="Suche", width="4", command=buttonSucheClick)
buttonSuche.grid(row=30, column=0)

root.mainloop()

print(nummer)
Fehlermeldung: "NameError: name 'Entry' is not defined"

Sirius3, dein Code läuft auch nicht, Fehlermeldung: "TypeError: __init__() takes no arguments (1 given)"

Grüße
Strawk
:(
:D
Ich programmiere erfolglos, also bin ich nicht.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du hast den import verdaddelt. Entry ist im tkinter Modul. Du importierst das als tk, also musst du tk.Entry schreiben.

Für eine so umfangreiche Anwendung wirst du um Objekt orientierte Programmierung nicht rum kommen. Hast du dich damit schonmal beschäftigt? Dann kannst du auch den Fehler von Sirius selbst beheben.
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo!

Ja, mit

tk.Entry
tk.Label
tk.Button

funktioniert es. Ja, ich kenne mich mit OOP einigermaßen aus. Den Fehler von Sirius3 habe ich aber noch nicht gefunden.

Grüße
Strawk
:)
Ich programmiere erfolglos, also bin ich nicht.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wie sieht denn normalerweise ein konstruktiv aus? Da fehlt doch was bei ihm. Und der Aufruf von super ist auch nicht super. Schau mal genau hin.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Konstruktor. Nicht konstruktiv. Doofes iPad.
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo!

Mit der bekannten GUI möchte ich derzeit nur erreichen, dass in einem Anzeige-Label ausgegeben wird, was ins Feld "nummer" eingetragen wurde. Jedoch erhalte ich ständig:
AttributeError: 'NoneType' object has no attribute 'get'
Bei einem Vergleichsprogramm funktioniert das tadellos und ich habe keinerlei Idee, wo der Unterschied sein soll.

Erbitte Hilfe!
Grüße
Strawk
Ich programmiere erfolglos, also bin ich nicht.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Strawk: die Glaskugel sagt nur Schneegestöber und der Kaffeesatz ist schon in der Bio-Tonne.

Ach ja, Nachtrag:

Code: Alles auswählen

class Main(tk.Tk):
    def __init__(self):
        super(Main, self).__init__()
        self.entries = generate_form(self, LABELS)
narpfel
User
Beiträge: 643
Registriert: Freitag 20. Oktober 2017, 16:10

`super` ist in Python 3 noch superer geworden:

Code: Alles auswählen

class Main(tk.Tk):
    def __init__(self):
        super().__init__()
        self.entries = generate_form(self, LABELS)
Die beiden Argumente sind optional.
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo!

Ich konnte das Unter-Problem identifizieren.

Code: Alles auswählen

e_nummer = tkinter.Entry(master).grid(row=0, column=0)
funktioniert nicht und macht:
AttributeError: 'NoneType' object has no attribute 'get'
Aber

Code: Alles auswählen

e_nummer = tkinter.Entry(master)
e_nummer.grid(row=0, column=0)
funktioniert.

Grüße
Strawk
:D
Ich programmiere erfolglos, also bin ich nicht.
Antworten