Scrollbares Fenster mit darin platzierbaren Inhalten..?

Fragen zu Tkinter.
Antworten
RobinB
User
Beiträge: 6
Registriert: Samstag 18. Februar 2017, 15:03

Hallo zusammen,

Ich arbeite gerade an einem Fenster für ein Programm, welches so eine Art Erinnerungscollage mit Bildern und Texten werden soll. Weil natürlich nicht 20 große Bilder gleichzeitig auf den Bildschirm passen muss eine Scrollbar helfen.
Leider kann man diese ja nur in einem Canvas realisieren, in dem ich wohl anscheinend ein Frame brauche, um darin etwas darstellen zu können, so weit habe ich das zumindest verstanden.
Mein Problem: Ich kann zwar dieses Fenster mit Bildern usw. und einer Scrollbar erstellen, kann die Bilder usw. aber nur mit pack oder grid platzieren, brauche aber place, um Sie da hin zu patzieren wo ich sie gerne hätte. Wenn ich ihnen allerdings mit place Koordinaten zuweise, wird nichts mehr angezeigt.

Diesen Code habe ich mir von verschiedenen Quellen zusammengesucht und an mich angepasst:

Code: Alles auswählen

import tkinter as tk


def onFrameConfigure(canvas):
    '''Reset the scroll region to encompass the inner frame'''
    canvas.configure(scrollregion=canvas.bbox("all"))

root = tk.Tk()
root.minsize(800,700)
img1 = tk.PhotoImage(file = "example.gif")

canvas = tk.Canvas(root, borderwidth=0, background="#ffffff")
frame = tk.Frame(canvas, background="#0040FF")
vsb = tk.Scrollbar(root, orient="vertical", command=canvas.yview)
canvas.configure(yscrollcommand=vsb.set)

vsb.pack(side="right", fill="y")
canvas.pack(side="left", fill="both", expand=True)
canvas.create_window((4,4), window=frame, anchor="nw")

frame.bind("<Configure>", lambda event, canvas=canvas: onFrameConfigure(canvas))

label1 = tk.Label(frame, text="hi")
label2 = tk.Label(frame, image=img1)

label1.place(x=0, y=0)
#label2.place(x=0, y=0)


root.mainloop()
Es wäre super wenn mir jemand weiterhelfen oder eine Alternative vorschlagen könnte.
Vielen Dank!

Liebe Grüße, RobinB
Zuletzt geändert von Anonymous am Sonntag 19. Februar 2017, 10:35, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@RobinB: Warum `place()` in einem Frame statt die Bilder gleich auf dem Canvas zu platzieren?
RobinB
User
Beiträge: 6
Registriert: Samstag 18. Februar 2017, 15:03

Ehrlich gesagt habe ich noch nie mit Canvas und Frames in tkinter gearbeitet und kenne mich entsprechend wenig aus.
Kann ich denn images, Labels, messages pixelgenau in einem Canvas platzieren und die Hintergrundfarbe ändern, damit es nicht so stupide weiß aussieht?

Wäre toll wenn mir jemand ein Codebeispiel geben könnte wie ich das anstellen könnte.

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

Hi RobinB

Hier ein kleines Testskript für die Platzierung plus Bewegung eines Widgets auf einer Canvas:

Code: Alles auswählen

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

try:
    # Tkinter for Python 2.xx
    import Tkinter as tk
except ImportError:
    # Tkinter for Python 3.xx
    import tkinter as tk

APP_TITLE = "Place Widget on Canvas"
APP_XPOS = 100
APP_YPOS = 100
APP_WIDTH = 300
APP_HEIGHT = 200
STEP_TIME = 100 # Milliseconds
MAX_COUNT = 100



class Application(tk.Frame):

    def __init__(self, master):
        self.master = master
        tk.Frame.__init__(self, master)
        self.canvas = tk.Canvas(self, bg='steelblue', highlightthickness=0)
        self.canvas.pack()
        
        self.label = tk.Label(self.canvas, text="Lablel-Widget auf Canvas",
            relief='raised', padx=5)
        self.label.pack()
        
        self.canvas.create_window(10, 10, window=self.label, anchor='nw',
            tag='label')
        
        self.move_widget_on_canvas()
        
    def move_widget_on_canvas(self, count=0):
        count += 1
        self.canvas.move('label', 1, 1)
        if count > MAX_COUNT: return
        
        self.canvas.after(STEP_TIME, self.move_widget_on_canvas, count)
                
           
def main():
    app_win = tk.Tk()
    app_win.title(APP_TITLE)
    app_win.geometry("+{}+{}".format(APP_XPOS, APP_YPOS))
    app_win.geometry("{}x{}".format(APP_WIDTH, APP_HEIGHT))
    
    app = Application(app_win).pack(fill='both', expand=True)
    
    app_win.mainloop()
 
 
if __name__ == '__main__':
    main()      
Gruss wuf :wink:
Take it easy Mates!
RobinB
User
Beiträge: 6
Registriert: Samstag 18. Februar 2017, 15:03

Vielen Dank für das Beispiel!
Sobald ich Zeit finde werde ich es mal testen :D

Gruß, Robin
RobinB
User
Beiträge: 6
Registriert: Samstag 18. Februar 2017, 15:03

Also, ich habe deinen Code mal auf meinen Stil umgeformt (vereinfacht) und ein bisschen getestet. Ich habe soweit verstanden wie ich die Labels platzieren kann, habe aber noch ein Problem mit der Scrollbar. Vermutlich habe ich etwas vergessen oder falsch verknüpft usw., aber diese wird bei mir leider unter dem Canvas angezeigt, und ich verstehe nicht genau warum. Vielleicht kann einer von euch meinen Fehler erkennen, vielen Dank!
Wie ich den Quelltext in Python-Codebox-Tags darstelle habe ich leider noch nicht herausgefunden :?

Code: Alles auswählen

import tkinter as tk

app_win = tk.Tk()
app_win.title("test")
app_win.minsize(100, 100)

canvas = tk.Canvas(app_win, bg='steelblue', highlightthickness=0)
canvas.pack()


label = tk.Label(canvas, text="Lablel-Widget auf Canvas")
label1 = tk.Label(canvas, text="test")
label.pack()
label1.pack()

canvas.create_window(100, 10, window=label, anchor='nw', tag='label')
canvas.create_window(100, 40, window=label1, anchor="nw")

scrollbar = tk.Scrollbar(app_win, orient="vertical", command=canvas.yview)
canvas.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side="right", fill="y")

app_win.mainloop()
Edit: Habe gerade gelesen dass ich die Scrollbar wohl nur in einem Frame platzieren kann, was mich aber wieder zu meinem Ursprünglichen Problem zurückwirft, nämlich dass ich dort keine Widgets mit place() platzieren kann. Ich bin leider gerade ziemlich verwirrt wie ich das anstellen soll :?
Zuletzt geändert von Anonymous am Donnerstag 23. Februar 2017, 12:02, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
RobinB
User
Beiträge: 6
Registriert: Samstag 18. Februar 2017, 15:03

Nach weiterem suchen und rumprobieren habe ich es nun glaube ich hinbekommen, hier der Code:

Code: Alles auswählen

import tkinter as tk

app_win = tk.Tk()
app_win.title("test")
app_win.resizable(width=False, height=False)
frame=tk.Frame(app_win,width=300,height=300)
frame.grid(row=0,column=0)

canvas = tk.Canvas(frame, bg='steelblue', width=300, height=300,
                   scrollregion=(0,0,500,500), highlightthickness=0)

vbar=tk.Scrollbar(frame,orient="vertical") #scrollbar
vbar.pack(side="right",fill="y")
vbar.config(command=canvas.yview)

canvas.config(width=300,height=300)
canvas.config(yscrollcommand=vbar.set)
canvas.pack(side="left",expand=True,fill="both")


"""widgets"""
label = tk.Label(canvas, text="Lablel-Widget auf Canvas")
label1 = tk.Label(canvas, text="test")

canvas.create_window(100, 10, window=label, anchor='nw', tag='label')
canvas.create_window(100, 40, window=label1, anchor="nw")

app_win.mainloop()
Meinen vorherigen Beitrag konnte ich leider nicht mehr bearbeiten.
Auf das label.pack() verzichte ich, da es ohne keinen Unterschied macht. Mithilfe des canvas.create_window kann ich Labels mit Text oder Images nun endlich wie bei place() pixelgenau platzieren und die Scrollbar funktioniert auch. Vielen Dank für die Hilfe! Bei weiteren Fragen melde ich mich gerne wieder.

Gruß, Robin
Zuletzt geändert von Anonymous am Donnerstag 23. Februar 2017, 13:03, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@RobinB: Kleiner Hinweis: Zeichenketten sind keine Kommentare und man sollte sie dazu auch nicht missbrauchen.
Benutzeravatar
Kebap
User
Beiträge: 686
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

RobinB hat geschrieben:Wie ich den Quelltext in Python-Codebox-Tags darstelle habe ich leider noch nicht herausgefunden :?
Hallo RobinB,

dazu gehst du in deinen alten Beitrag oben, wo ein netter Moderator das für dich übernommen hat. Klick auf "bearbeiten" und schau es dir an. Es gibt dazu auch einen Button auf der Seite, wo du deinen Text eingibt. Der Button heißt praktischerweise "Code" :wink:
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
BlackJack

@Kebap: Den Button der „Code“ finden die meisten ja, so auch RobinB, das Dumme ist nur dass der das falsche macht. Man muss das „Code auswählen“-Ausklappmenü verwenden und nicht den Button. Das ist alles andere als selbsterklärend.
RobinB
User
Beiträge: 6
Registriert: Samstag 18. Februar 2017, 15:03

Kebap hat geschrieben:
RobinB hat geschrieben:Wie ich den Quelltext in Python-Codebox-Tags darstelle habe ich leider noch nicht herausgefunden :?
Hallo RobinB,

dazu gehst du in deinen alten Beitrag oben, wo ein netter Moderator das für dich übernommen hat. Klick auf "bearbeiten" und schau es dir an. Es gibt dazu auch einen Button auf der Seite, wo du deinen Text eingibt. Der Button heißt praktischerweise "Code" :wink:
Das war auch meine erste Idee, nur leider konnte ich den Beitrag dann schon nicht mehr bearbeiten.

@BlackJack: Danke für die Info!
Antworten