.pack() nicht ganz klar

Fragen zu Tkinter.
Antworten
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

Ich hab nun mal angefangen, für meine ganzen Scripte ne Oberfläche zu basteln.
Wobei ich nun aber Probleme habe, ist, das alles so anzuordnen wie ich es will.

Ich hätte gern immer das Label und Eingabefeld nebeneinander.

also so:

Label 0

label 1 eingabefeld 1
label 2 eingabefeld 2
...

radiobutton 1
radiobutton 2

button 1

Irgendwie krieg ich das nicht so richtig hin. Entweder steht alles nebeneinander (side = LEFT), ODER alles untereinander(side = TOP).
Wenn ich dabei LEFT und TOP misch kommt nur Mist raus.

Curios finde ich auch, das meine Radiobuttons nicht exakt untereinander stehen, sondern der letzte leich versetzt ist.

Hier der Code
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Du musst mehrere Frames verwenden, einen für label 1 und eingabefeld 1, einen für label 2 und eingabefeld 2, einen für label 0, frame 1, frame 2, buttons etc. Als einfaches Beispiel könnte das hier dienen: http://www.python-forum.de/topic-12550.html
MfG
HWK
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

Hmm okay. Danke.

Ist geschehen, fehlende anchors gesetzt. Nun sieht es ungefähr so aus, wie es soll. Finde es aber insgesamt recht umständlich und den Code sehr unübersichtlich. Aber da komm ich wohl nicht drumherum, oder?
BlackJack

Da wir nicht wissen wie der Quelltext und damit Ergebnis aussehen, kann man auch schlecht sagen, ob es zu umständlich ist und ob Du darum herum kommst. ;-)

Man kann eine etwas umfangreichere GUI, also *ein* Fenster, auch auf mehrere Klassen aufteilen wenn's zu gross und unübesichtlich wird.
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

BlackJack hat geschrieben:Da wir nicht wissen wie der Quelltext und damit Ergebnis aussehen, kann man auch schlecht sagen, ob es zu umständlich ist und ob Du darum herum kommst. ;-)

Man kann eine etwas umfangreichere GUI, also *ein* Fenster, auch auf mehrere Klassen aufteilen wenn's zu gross und unübesichtlich wird.
:D DA
pyStyler
User
Beiträge: 311
Registriert: Montag 12. Juni 2006, 14:24

Hallo,

mich wundert, warum keiner den Guibuilder mal vorschlägt.
http://sourceforge.net/project/showfile ... p_id=24918

so könnte dann die mit Guibuilder erstellte Oberfläche aussehen.
http://paste.pocoo.org/show/12481/


Gruss
pyStyler
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

Danke :) Das guck ich mir mal an

Wahrscheinlich, damit ich das erst ohne nen Builder ein bisschen übe, bevor ich dann einfach nur noch zusammenklicke :)
BlackJack

IIiiiiih schon wieder dieses ``global``. Das sollte man echt aus der Sprache entfernen. :-)

Die Konstante `PythonPath` müsste man sich auch dynamisch unter `sys.executable` holen können. Da steht der Pfad/Name des gerade laufenden Python-Interpreters.

Die Frames `eingabe`, `space`, `auswahl` und `start_f` sind nicht wirklich nötig.

Dann sind da einige Wiederholungen von Quelltext, wo man die kleinen Unterschiede herausziehen und die Gemeinsamkeiten in eine Schleife stecken kann. Die ersten drei Labels + Entries könnte man zum Beispiel so erstellen:

Code: Alles auswählen

  entries = dict()
  for text, entry_name in (('Gemeinden (Dataset)', 'gem_pfad'),
                           ('Aktualität (File)', 'akt_pfad'),
                           ('CSVs (Directory)', 'csv_pfad')):
    frame = Frame(root)
    Label(frame, text=text, width=20, anchor=W).pack(side=LEFT, expand=NO)
    entry = Entry(frame, width=55)
    entry.pack(side=LEFT)
    entries[entry_name] = entry
    frame.pack(side=TOP)
Weiterer Vorteil ist, dass man jetzt weniger ``global``\s braucht wenn man die Enries in ein Dictionary steckt.

So eine Schleife eignet sich auch gut für die Radiobuttons.

Aus `build_CSV()` kann man ebenfalls einiges an Wiederholungen vermeiden. Wenn man davon ausgeht, das die Entries mit den Eingaben für die Pfade alle in einem Dictionary `entries` gespeichert sind, liesse sich die Funktion so schreiben (ungetestet):

Code: Alles auswählen

def build_CSV():
  global root, entries, ebene
  pfade = dict((name, entry.get()) for name, entry in entries.iteritems())
  ebene2arguments = {'gemeinde': ('Gemeinden_To_CSV.py', None),
                     'kreis': ('Kreise.py', 'kreis_pfad'),
                     'regierungsbezirk': ('Regierungsbezirke.py',
                                          'regierungsbezirk')}
  try:
    script_name, pfad_name = ebene2arguments[ebene.get()]
  except KeyError:
      print 'Es wurde keine Auswahl getroffen.'
  else:
    arguments = ['python.exe', script_name]
    arguments.extend(pfade[p] for p in ('csv_pfad', 'gem_pfad', 'akt_pfad'))
    if pfad_name:
        arguments.append(pfade[pfad_name])
    os.spawnv(os.P_WAIT, PythonPath, arguments)

  root.destroy()
Was GUI-Builder, im allgemeinen ─ nicht nur der mit dem Namen GUI Builder, angeht bin ich da immer so ein bisschen hin und her gerissen. Der Quelltext sieht ziemlich "bloated" aus, und oft bietet es sich an GUI Elemente in einer Schleife aus Daten zu erzeugen oder eigene Widgets zu programmieren und dann gibt's mit vielen GUI-Buildern Probleme.
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

BlackJack hat geschrieben:IIiiiiih schon wieder dieses ``global``. Das sollte man echt aus der Sprache entfernen. :-)
Das stand in irgendeinem Beispiel so drin und ohne ging es auch nicht. Versteh nur nicht ganz warum nicht.
BlackJack hat geschrieben: Aus `build_CSV()` kann man ebenfalls einiges an Wiederholungen vermeiden. Wenn man davon ausgeht, das die Entries mit den Eingaben für die Pfade alle in einem Dictionary `entries` gespeichert sind, liesse sich die Funktion so schreiben (ungetestet):

Code: Alles auswählen

def build_CSV():
  global root, entries, ebene
  pfade = dict((name, entry.get()) for name, entry in entries.iteritems())
  ebene2arguments = {'gemeinde': ('Gemeinden_To_CSV.py', None),
                     'kreis': ('Kreise.py', 'kreis_pfad'),
                     'regierungsbezirk': ('Regierungsbezirke.py',
                                          'regierungsbezirk')}
  try:
    script_name, pfad_name = ebene2arguments[ebene.get()]
  except KeyError:
      print 'Es wurde keine Auswahl getroffen.'
  else:
    arguments = ['python.exe', script_name]
    arguments.extend(pfade[p] for p in ('csv_pfad', 'gem_pfad', 'akt_pfad'))
    if pfad_name:
        arguments.append(pfade[pfad_name])
    os.spawnv(os.P_WAIT, PythonPath, arguments)

  root.destroy()
Hmm ... aber für Kreise und Regierungsbezirke brauch ich ja immer ein 4. Argument, für Gemeinden mag das ja so funktionieren...
BlackJack

Das vierte Argument steht in `ebene2arguments` (Zeile 4) und wird in Zeile 15 der Argumentliste hinzugefügt.
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

...

es ist noch zu früh heute wohl ....

öhm ja... :)
pyStyler
User
Beiträge: 311
Registriert: Montag 12. Juni 2006, 14:24

BlackJack hat geschrieben: Was GUI-Builder, im allgemeinen ─ nicht nur der mit dem Namen GUI Builder, angeht bin ich da immer so ein bisschen hin und her gerissen. Der Quelltext sieht ziemlich "bloated" aus, und oft bietet es sich an GUI Elemente in einer Schleife aus Daten zu erzeugen oder eigene Widgets zu programmieren und dann gibt's mit vielen GUI-Buildern Probleme.
ok das mit Gui-Builder hast du recht!
Dass der Gui-Builder viel zu viel Code erzeugt hast auch recht.

Was eigene Widgets angeht, gehe ich so vor.
Ich baue mir eine Klasse myFrames und platziere die Frames an die jeweiligen stellen wo ich sie haben will.

zum beispiel so.
( ich weiss ziemlich aufgebläht )
http://paste.pocoo.org/show/12580/
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo meneliel !

Mit dem Grid-Layout-Manager geht das doch irgendwie einfacher !

Code: Alles auswählen

#! /usr/bin/env python
# -*- coding: utf-8

import Tkinter as tk
label_liste = list()
entry_liste = list()
buttons = (( 0, 0, 0), ( 1, 1, 0))

def text_einfuegen(index):
    label_liste[index].configure(text=entry_liste[index].get())
    
fenster = tk.Tk()
for  index, row, column in buttons:
    button = tk.Button(text='OK', command=lambda index=index:      
        text_einfuegen(index))
    label = tk.Label(width=10, relief=tk.RIDGE)
    label_liste.append(label)
    entry = tk.Entry(width=10)
    entry_liste.append(entry)
    button.grid(row=row, column=column)
    label.grid(row=row, column=column+1)
    entry.grid(row=row, column=column+2)
fenster.tk.mainloop()
gruß frank
Antworten