verdammt, ich kapier es einfach nicht

Fragen zu Tkinter.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo derkai

Die Konfiguration der Hauptfenster-Geometrie mittels:

Code: Alles auswählen

spiel.config(width=1024,height=768,bg="grey")
scheint Tkinter nicht so richtig zu mögen:

Es ist schon so, dass die Geometrie wie es das 'numerix' Beispiel zeigt über die Methode:

Code: Alles auswählen

spiel.geometry("1024x768")
konfiguriert werden sollte. Das unschöne daran ist nur noch, dass die Geometrie-Daten als String übergeben werden müssen.

Hier habe ich numerix Beispiel noch ein wenig erweitert:

Code: Alles auswählen

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

#~~ Skriptname: kais_code_1511_01

import Tkinter as tk
from funktionen import *

#Hauptfenster erzeugen
spiel = tk.Tk()

# #~~ System Bildschirm-Grösse
# OS_SCREEN_WIDTH  = spiel.winfo_screenwidth()
# OS_SCREEN_HEIGHT = spiel.winfo_screenheight()
# 
# #~~ Konstanten des Haupt-Fensters (Systembezogen)
# MAIN_WIN_WIDTH = OS_SCREEN_WIDTH
# MAIN_WIN_HEIGHT = OS_SCREEN_HEIGHT
# MAIN_WIN_XPOS = 0
# MAIN_WIN_YPOS = 0

#~~ Konstanten des Haupt-Fensters (Nach Vorgabe)
MAIN_WIN_WIDTH = 1024
MAIN_WIN_HEIGHT = 768
MAIN_WIN_XPOS = 0
MAIN_WIN_YPOS = 0

#~~ Geometrie für das Hauptfentser
spiel.geometry("%dx%d+%d+%d" % (MAIN_WIN_WIDTH, MAIN_WIN_HEIGHT, MAIN_WIN_XPOS,
    MAIN_WIN_YPOS))

spiel.title("Kai s Battle Game")

#Canvas im Frame Fenster2
spflaeche = tk.Canvas(spiel, bg="white")
erstelle_hexfeldobjekte (spielreihen, ungerade_spalten)

# for x in hexdic.iterkeys() :
# 
#     spflaeche.create_polygon (hexdic[x][0],fill=hexdic[x][2],outline="black")

spflaeche.pack(side='top', fill='both', expand='yes', padx=25, pady=30)



spiel.mainloop()
Gruss wuf :wink:
Take it easy Mates!
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Du musst zusätzlich eine Randstärke einstellen (z.B. bd=2), damit relief funktioniert ...
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

ja, ich habs in dem Moment auch geschnallt.
Nun versuche ich mal meine "Fläche" aufzubauen

DANKE
Kai
imac
20 Zoll
2,4 ghz
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

jetzt bleibt noch das Problem der Scrollbar :

Code: Alles auswählen

import Tkinter as tk
from funktionen import *

#Hauptfenster erzeugen
spiel = tk.Tk()
spiel.geometry("1024x768")
spiel.title("Kai s Battle Game")
spiel.config(bg="grey")

#Frame1 erzeugen
fenster1 = tk.Frame(spiel,bg="white",width=500,
                    height=500,bd=3,relief=tk.SUNKEN)
fenster1.pack(anchor=tk.NW,padx=5,pady=5)

#Scrollbar erzeugen
xleiste = tk.Scrollbar(spiel,orient=tk.HORIZONTAL,width=200)
xleiste.pack(anchor=tk.NW,padx=10)

#Canvas im Hauptfenster
spflaeche = tk.Canvas (fenster1,width=490,height=490)
erstelle_hexfeldobjekte (spielreihen, ungerade_spalten)

for x in hexdic.iterkeys() :
    
    spflaeche.create_polygon (hexdic[x][0],fill=hexdic[x][2],outline="black")

spflaeche.pack()

#Verknuepfung Scrollbar
xleiste.config(command=spflaeche.xview)


spiel.mainloop()
... die verhält sich echt "Sche..".
Das rechte Ende des Balkens ist irgendwo im Nirvana.

Was kann man denn dagegen tun ?

Kai
imac
20 Zoll
2,4 ghz
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo yipyip

Ich habe deinen Ratschlag auf folgender Tread-Seite befolgt:

http://www.python-forum.de/topic-15264,180.html
Einen Pfad von einem Feld (i, j) zu einem Feld (n, m)
kann man mit Hilfe eines 'Flood Fill' Algorithmus
bestimmen (rein informell):

1. Markieriere alle Felder als unbesucht
2. setze Feld(n, m) auf 0
3. setze die 6er-Nachbarn von Feld (n, m) auf 1
4. setze deren unbesuchte Nachbarn auf 2
5. deren unbesuchte auf 3
usw.
(Hindernisse werden nicht besucht.)
Hier die Spielfläche als nicht geflutet dargestellt:

Code: Alles auswählen

    Spielfläche  Geometrie: 7x8

    x:    0    1    2    3    4    5    6
 y:   -------------------------------------
   0 |   -1        -1        -1        -1  |
     |        -1        -1        -1       |
   1 |   -1        -1        -1        -1  |
     |        -1        -1        -1       |
   2 |   -1        -1        -1        -1  |
     |        -1        -1        -1       |
   3 |   -1        -1        -1        -1  |
     |        -1        -1        -1       |
   4 |   -1        -1        -1        -1  |
     |        -1        -1        -1       |
   5 |   -1        -1        -1        -1  |
     |        -1        -1        -1       |
   6 |   -1        -1        -1        -1  |
     |        -1        -1        -1       |
   7 |   -1        -1        -1        -1  |
     |        -1        -1        -1       |
      -------------------------------------
Hier das Spielfeld auf zwei Ebenen geflutet. Das Zielfeld ist auf Koordinate 3,3:

Code: Alles auswählen

     Spielfläche  Geometrie: 7x8

    x:    0    1    2    3    4    5    6
 y:   -------------------------------------
   0 |   -1        -1        -1        -1  |
     |        -1        -1        -1       |
   1 |   -1        -1        -1        -1  |
     |        -1         2        -1       |
   2 |   -1         2         2        -1  |
     |         2         1         2       |
   3 |   -1         1         1        -1  |
     |         2         0         2       |
   4 |   -1         1         1        -1  |
     |         2         1         2       |
   5 |   -1         2         2        -1  |
     |        -1         2        -1       |
   6 |   -1        -1        -1        -1  |
     |        -1        -1        -1       |
   7 |   -1        -1        -1        -1  |
     |        -1        -1        -1       |
      -------------------------------------
Hier das Spielfeld voll geflutet. Das Zielfeld ist immer noch auf Koordinate 3,3:

Code: Alles auswählen

     Spielfläche  Geometrie: 7x8

    x:    0    1    2    3    4    5    6
 y:   -------------------------------------
   0 |    5         4         4         5  |
     |         4         3         4       |
   1 |    4         3         3         4  |
     |         3         2         3       |
   2 |    3         2         2         3  |
     |         2         1         2       |
   3 |    3         1         1         3  |
     |         2         0         2       |
   4 |    3         1         1         3  |
     |         2         1         2       |
   5 |    3         2         2         3  |
     |         3         2         3       |
   6 |    4         3         3         4  |
     |         4         3         4       |
   7 |    5         4         4         5  |
     |         5         4         5       |
      -------------------------------------
Hier das Spielfeld voll geflutet. Das Zielfeld ist in der untere rechten Ecke auf Koordinate 6,7:

Code: Alles auswählen

     Spielfläche  Geometrie: 7x8

    x:    0    1    2    3    4    5    6
 y:   -------------------------------------
   0 |   10         9         8         7  |
     |         9         8         7       |
   1 |    9         8         7         6  |
     |         8         7         6       |
   2 |    8         7         6         5  |
     |         7         6         5       |
   3 |    7         6         5         4  |
     |         6         5         4       |
   4 |    6         5         4         3  |
     |         5         4         3       |
   5 |    6         4         3         2  |
     |         5         3         2       |
   6 |    6         4         2         1  |
     |         5         3         1       |
   7 |    6         4         2         0  |
     |         5         3         1       |
      -------------------------------------
Das Spielfeld enthält noch keine Hindernisse!

@vipvip Frage: Habe ich deinen Ratschlag richtig interpretiert? Ich wäre die dankbar, wenn du mir dies bestätigen könntest.

Gruss wuf :wink:
Take it easy Mates!
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Ja genau, das meinte ich.
:D
Jetzt kann man das Hexfeld
(ich hab's bisher nur auf Pixelfeldern mit 4/8er-Nachbarschaft ausprobiert)
entsprechend den Nachbarschaftswerten mit
passenden Farben einfaerben, so dass sich 'schoene'
Farbverlaeufe ergeben; insbesondere mit 'Verzerrungen'
durch Hindernisse.
Dann erhaelt man eine Visualisierung der von mir schon
beschriebenen Pfadplanungsmethode.
(Von hohen Werten zu niedrigeren laufen...)
Ich befuerchte aber, das schweift im Moment
noch etwas vom Thema ab...

:wink:
yipyip
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo yipyip

Besten Dank für deine positive Antwort! Super! Unglaublich wie es möglich ist mit nur einer fünf Punkte-Beschreibung ohne komplizierte seitenlangen mathematischen Abhandlungen etwas rüberzubringen, so das beim Empfänger die Lampe zu leuchten anfängt. :lol:

Ich habe dich schon richtig verstanden, dass dies die Basis ist für eine Pfadsuche von einem Startfeld zu einem Zielfeld indem vom Startfeld beginnend immer das Nachbarfeld mit der nächst tieferen Flut-Nummer gesucht wird bis das Zielfeld mit der Flut-Nummer '0' gefunden wird?

Gruss wuf :wink:
Take it easy Mates!
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

derkai hat geschrieben:jetzt bleibt noch das Problem der Scrollbar :
Das rechte Ende des Balkens ist irgendwo im Nirvana.
Was kann man denn dagegen tun ?

Code: Alles auswählen

import Tkinter as tk

spiel = tk.Tk()
spiel.geometry("1024x768")
linkeseite = tk.Frame(spiel,bg="tomato",width=100)
linkeseite.pack(side=tk.LEFT,fill=tk.Y)
rechteseite = tk.Frame(spiel,bg="peachpuff",bd=3,relief=tk.SUNKEN)
rechteseite.pack(side=tk.LEFT,fill=tk.BOTH,expand=True)
spflaeche = tk.Canvas(rechteseite,bg="white")
spflaeche.pack(expand=True,fill=tk.BOTH,padx=25,pady=30)
schieber = tk.Scrollbar(rechteseite,orient=tk.HORIZONTAL)
schieber.pack(fill=tk.X)
spiel.mainloop()
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Ich habe dich schon richtig verstanden, dass dies die Basis ist für eine Pfadsuche von einem Startfeld zu einem Zielfeld indem vom Startfeld beginnend immer das Nachbarfeld mit der nächst tieferen Flut-Nummer gesucht wird bis das Zielfeld mit der Flut-Nummer '0' gefunden wird?
Haargenau... :D
Aufgrund der Konstruktion des Flood-Fill Algo findet man immer ein Feld mit einem kleinerem Wert, deshalb ist der Begriff "Nachbarschaft" von so entscheidender Bedeutung.

Im Allgemeinen existieren natuerlich mehrere Wege, aber solange die Spiellogik es nicht verbietet, kann man
das naechste Feld fuer den Pfad zufaellig auswaehlen.

(Immer vorausgesetzt, das Startfeld ist nicht isoliert
vom Zielfeld.)

Hat man jedoch Spielkriterien wie
'zuegig befahrbar'
...
'schwer befahrbar'
fuer ein Feld, landet man wieder bei einem Graphen mit gewichteten Kanten, d.h. Dijkstra usw. .

:wink:
yipyip
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

ich verstehe die Logik bei pack einfach nicht.
Warum kann ich jetzt neben die Spielfläche kein Widget positionieren ?

Kai

Code: Alles auswählen

import Tkinter as tk
from funktionen import *

#Hauptfenster erzeugen
spiel = tk.Tk()
spiel.geometry("1024x768")
spiel.title("Kai s Battle Game")
spiel.config(bg="grey")

#Frame1 erzeugen
fenster1 = tk.Frame(spiel,bg="white",width=500,
                    height=500,bd=2,relief=tk.SUNKEN)
fenster1.pack(anchor=tk.NW,padx=2,pady=2)

#Scrollbar erzeugen
xleiste = tk.Scrollbar(fenster1,orient=tk.HORIZONTAL)
yleiste = tk.Scrollbar(fenster1,orient=tk.VERTICAL)
xleiste.pack(side=tk.BOTTOM,pady=2,fill=tk.X)
yleiste.pack(side=tk.RIGHT,pady=2,fill=tk.Y)

#Canvas im Hauptfenster
spflaeche = tk.Canvas (fenster1,width=495,height=495)
erstelle_hexfeldobjekte (spielreihen, ungerade_spalten)

for x in hexdic.iterkeys() :
    
    spflaeche.create_polygon (hexdic[x][0],fill=hexdic[x][2],outline="black")

spflaeche.pack(fill=tk.X)

#Verknuepfung Scrollbar
xleiste.config(command=spflaeche.xview)
yleiste.config(command=spflaeche.yview)

#Frame2 erzeugen -> Miniaturansicht
fenster2 = tk.Frame(spiel,bg="white",width=200,height=200,
                   bd=2,relief=tk.SUNKEN)
fenster2.pack(side=tk.RIGHT,expand=1)


spiel.mainloop()
imac
20 Zoll
2,4 ghz
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

sagt mal, kann ich denn nicht auch grid nehmen ?

Kai
imac
20 Zoll
2,4 ghz
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

derkai hat geschrieben:sagt mal, kann ich denn nicht auch grid nehmen ?
Klar, kannst du. Aber einfacher wird es dadurch m.E. nicht.
Da du - bisher jedenfalls - auch keine Widgets hast, die gleiche Abmessungen bekommen sollen, musst du sehen, dass du durch geeignetes Zusammenfassen von Zellen entsprechende Megazellen bekommst. Ich persönlich finde das wesentlich unpraktischer als die Arbeit mit dem pack-Manager und ggf. einigen verschachtelten Frames. Wenn man denen ordentliche Namen gibt, dann behält man auch bei etwas Verschachtelung gut den Überblick.
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

...musste auch erst einen Abend und einen Nachmittag
googeln und experimentieren bis ich's so hatte wie es sein soll:

Das Canvas-Scroll-Resizing Pattern

Code: Alles auswählen

import Tkinter as tk

class Scroller(object):
  
  def __init__(self, root):

    self.root = root
    self.frame = tk.Frame(self.root)
    self.canvas = tk.Canvas(self.frame, width=100, height=100, bg='white')

    xscroll = tk.Scrollbar(self.root, orient='horizontal')
    self.canvas.config(xscrollcommand=xscroll.set)
    xscroll.config(command=self.canvas.xview)

    yscroll = tk.Scrollbar(self.root, orient='vertical')
    self.canvas.config(yscrollcommand=yscroll.set)
    yscroll.config(command=self.canvas.yview)

    w = 999  
    self.canvas.config(scrollregion=(0, 0, w, w))
    self.canvas.pack(side=tk.LEFT, expand=1, fill=tk.BOTH)

    self.frame.grid(row=0, column=0, sticky=tk.N+tk.S+tk.E+tk.W)
    yscroll.grid(row=0, column=1, sticky=tk.N+tk.S)
    xscroll.grid(row=1, column=0, sticky=tk.E+tk.W)

    self.root.grid_columnconfigure(0, weight=1)
    self.root.grid_rowconfigure(0, weight=1)

    p0 = (0, 0)
    p1 = (w >> 1, w - 1)
    p2 = (w - 1, 0) 
    self.canvas.create_line(p0, p1)
    self.canvas.create_line(p1, p2)


if __name__ == '__main__':
    
  root = tk.Tk()
  Scroller(root)
  root.mainloop()
Versuche das mal. :D

Bei Dir fehlte u.a. ein

Code: Alles auswählen

fenster1.pack(side=tk.LEFT, ...
...mehr sage ich lieber nicht...
:roll:

Wichtigste Regel:
Tkinter-Funktionalitaet nie mit eigenem umfangreichen Code testen, sondern nur mit Minimalfunktionen.
:wink:
yipyip
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

ja, aber warum bekomme ich denn dann keinen Frame mehr RECHTS NEBEN die Spielfläche ?

Kai
imac
20 Zoll
2,4 ghz
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

ups, war etwas zu spaet...
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

@yip yip

ne ne, nicht zu spät. ich gucke mir alles an
ich glaube aber inzwischen, dass die CANVAS bereits etwas
eingebaut haben, was die Funktion xview vereinfacht.

schönen Dank -
cih schaue es mir gleich mal an.
Ich habe aber gesehen, dass auch Du grid verwendet hast.

Davon raten ja leider alle ab.

Kai
imac
20 Zoll
2,4 ghz
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

derkai hat geschrieben:ja, aber warum bekomme ich denn dann keinen Frame mehr RECHTS NEBEN die Spielfläche ?
Weil du den pack()-Manager nicht richtig einsetzt ...

Guckst du hier:

Code: Alles auswählen

import Tkinter as tk

spiel = tk.Tk()
spiel.geometry("1024x768")
linkeseite = tk.Frame(spiel,bg="tomato",width=100)
linkeseite.pack(side=tk.LEFT,fill=tk.Y)
rechteseite = tk.Frame(spiel,bg="peachpuff",bd=3,relief=tk.SUNKEN)
rechteseite.pack(side=tk.LEFT,fill=tk.BOTH,expand=True)
spflaeche = tk.Canvas(rechteseite,bg="white")
spflaeche.pack(expand=True,fill=tk.BOTH,padx=25,pady=30)
rechtsnebencanvas = tk.Frame(spiel,bg="lightblue",width=100)
rechtsnebencanvas.pack(side=tk.LEFT,fill=tk.Y)
schieber = tk.Scrollbar(rechteseite,orient=tk.HORIZONTAL)
schieber.pack(fill=tk.X)
spiel.mainloop()
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

ok, aber wenn ich jetzt mal einen Teil aus deinem Code nehme :


Code: Alles auswählen

import Tkinter as tk

spiel = tk.Tk()
spiel.geometry("1024x768")

linkeseite = tk.Frame(spiel,bg="tomato",width=100)
linkeseite.pack(side=tk.LEFT,fill=tk.Y)

spiel.mainloop()
dann füllst Du nach oben auf : fill=tk.Y

lasse ich das jetzt weg und begrenze das Spielfeld auch in der Höhe,
dann komme ich mit side=tk.LEFT nicht weiter.

dann hilft nur :anchor=tk.nw


Code: Alles auswählen

import Tkinter as tk

spiel = tk.Tk()
spiel.geometry("1024x768")

linkeseite = tk.Frame(spiel,bg="tomato",width=100,height=100)
linkeseite.pack(side=tk.LEFT)

spiel.mainloop()
imac
20 Zoll
2,4 ghz
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

kommt jetzt die rechte seite dazu, dann baut der die aber nicht nach rechts, sondern drunter :

Code: Alles auswählen

import Tkinter as tk

spiel = tk.Tk()
spiel.geometry("1024x768")

linkeseite = tk.Frame(spiel,bg="tomato",width=100,height=100)
linkeseite.pack(anchor=tk.NW)

rechteseite = tk.Frame(spiel,bg="peachpuff",bd=3,relief=tk.SUNKEN)
rechteseite.pack(side=tk.LEFT,fill=tk.BOTH,expand=True)

spiel.mainloop()

auch anchor hilft dann nicht mehr weiter - ist immer noch drunter :

Code: Alles auswählen

rechteseite = tk.Frame(spiel,bg="peachpuff",bd=3,relief=tk.SUNKEN)
rechteseite.pack(anchor=tk.NE,fill=tk.BOTH,expand=True)

imac
20 Zoll
2,4 ghz
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Das wird sich hier noch reichlich in die Länge ziehen, wenn du immer Scheibchenweise mit dem herausrückst, was deine GUI sonst noch für Features haben soll ...

Wenn ich etwas aufwändigere GUIs zu gestalten habe, dann nehme ich erstmal Papier und Stift (manchmal sogar Buntstifte und Geodreieck ...) und mache per Hand einen Entwurf. Meistens sieht es zwar am Ende dann doch (gewollt) anders aus, aber es hilft mir ungemein, mit einer Vorlage neben der Tastatur an dem zu bauen, was herauskommen soll.

In deinem Fall könntest du z.B. mit einem Zeichenprogramm mal einen Oberflächenentwurf aufbauen, der so ist, wie du es (am Ende veraussichtlich) gerne hättest - mit allem drum und dran. Und das zeigst du uns dann. Oder du beschreibst den vorgesehenen Endaufbau so präzise, dass man sich ein ausreichend genaues Bild davon machen kann.

Und dann sehen wir weiter ...
Antworten