Wie kann man tkinter canvas dazu bringen, die Größe dynamisch an die Fensterbreite anzupassen?

Lesezeit: 5 Minuten

Wie kann man tkinter canvas dazu bringen die Grose dynamisch
Anonym

Ich muss eine Leinwand in tkinter abrufen, um ihre Breite auf die Breite des Fensters einzustellen, und dann die Größe der Leinwand dynamisch ändern, wenn der Benutzer das Fenster kleiner/größer macht.

Gibt es eine Möglichkeit, dies (einfach) zu tun?

Wie kann man tkinter canvas dazu bringen die Grose dynamisch
ebar

Ich dachte, ich würde zusätzlichen Code hinzufügen, um die Antwort von @fredtantini zu erweitern, da es nicht darum geht, wie die Form von Widgets aktualisiert wird, die auf gezeichnet werden Canvas.

Dazu müssen Sie die verwenden scale -Methode und markieren Sie alle Widgets. Ein vollständiges Beispiel finden Sie unten.

from Tkinter import *

# a subclass of Canvas for dealing with resizing of windows
class ResizingCanvas(Canvas):
    def __init__(self,parent,**kwargs):
        Canvas.__init__(self,parent,**kwargs)
        self.bind("<Configure>", self.on_resize)
        self.height = self.winfo_reqheight()
        self.width = self.winfo_reqwidth()

    def on_resize(self,event):
        # determine the ratio of old width/height to new width/height
        wscale = float(event.width)/self.width
        hscale = float(event.height)/self.height
        self.width = event.width
        self.height = event.height
        # resize the canvas 
        self.config(width=self.width, height=self.height)
        # rescale all the objects tagged with the "all" tag
        self.scale("all",0,0,wscale,hscale)

def main():
    root = Tk()
    myframe = Frame(root)
    myframe.pack(fill=BOTH, expand=YES)
    mycanvas = ResizingCanvas(myframe,width=850, height=400, bg="red", highlightthickness=0)
    mycanvas.pack(fill=BOTH, expand=YES)

    # add some widgets to the canvas
    mycanvas.create_line(0, 0, 200, 100)
    mycanvas.create_line(0, 100, 200, 0, fill="red", dash=(4, 4))
    mycanvas.create_rectangle(50, 25, 150, 75, fill="blue")

    # tag all of the drawn widgets
    mycanvas.addtag_all("all")
    root.mainloop()

if __name__ == "__main__":
    main()

  • Ein Wort der Vorsicht: Verwenden Sie dies mit grid wird Ihren Fenstermanager töten!

    – Stefan

    3. April 16 um 19:53 Uhr

  • Und jetzt: Wie bekomme ich es zum Laufen, wenn der Canvas nicht das einzige Widget ist? In meinem Fall befindet sich unter der Leinwand ein Rahmen mit Knopf, der von der Leinwand herausgedrückt wird …

    – Stefan

    3. April 16 um 20:03 Uhr

  • Das ist ausgezeichnet. Ich möchte nur die Wichtigkeit betonen highlightthickness=0 beim Erstellen der ResizingCanvas, andernfalls wird die Leinwand so lange erweitert, bis Sie sie beenden.

    – Plasma

    22. Mai 17 um 8:23 Uhr

  • Vielen Dank! Aber es scheint, dass alle Objekte neu skaliert werden, außer Bilder, die mit auf die Leinwand hinzugefügt wurden mycanvas.create_image(cur_image_width/2, cur_image_height/2, image=cur_image_bg). Kennen Sie eine Möglichkeit, das Bild mit der self.scale-Funktion neu zu skalieren?

    – schrottulk

    26. Januar 19 um 11:53 Uhr

  • Sehr schön außer entfernen bg="red", was ablenkt und die rote Linie unsichtbar macht.

    – WinEunuuchs2Unix

    24. November 19 um 13:40 Uhr

1642131064 198 Wie kann man tkinter canvas dazu bringen die Grose dynamisch
Fredtantini

Du kannst den … benutzen .pack Geometriemanager:

self.c=Canvas(…)
self.c.pack(fill="both", expand=True)

sollte den Trick machen. Wenn sich Ihre Leinwand in einem Rahmen befindet, machen Sie dasselbe für den Rahmen:

self.r = root
self.f = Frame(self.r)
self.f.pack(fill="both", expand=True)
self.c = Canvas(…)
self.c.pack(fill="both", expand=True)

Sehen effbot Für mehr Information.

Bearbeiten: Wenn Sie keine Leinwand in “voller Größe” möchten, können Sie Ihre Leinwand an eine Funktion binden:

self.c.bind('<Configure>', self.resize)

def resize(self, event):
    w,h = event.width-100, event.height-100
    self.c.config(width=w, height=h)

Sehen effbot wieder für Ereignisse und Bindungen

  • Können Sie Pack in einem anderen Rahmen mit Raster verwenden?

    – Gründino

    27. Mai 20 um 9:09 Uhr


  • Ja, du kannst. nur die Widgets auf demselben Master sollten auch denselben Manager verwenden pack, grid oder place.

    – Billi

    16. November 21 um 17:12 Uhr

Das tut es – zumindest in meiner Version von Python. Die Leinwandgröße wird sowohl horizontal (sticky=E+W & rowconfigure) als auch vertikal (sticky=N+S & columnconfigure) angepasst. Ich habe den Canvas-Hintergrund auf eine eklige Farbe gesetzt – aber zumindest sieht man, wann es funktioniert.

from tkinter import *
root=Tk()
root.rowconfigure(0,weight=1)
root.columnconfigure(0,weight=1)
canv=Canvas(root, width=600, height=400, bg='#f0f0c0')
canv.grid(row=0, column=0, sticky=N+S+E+W)
root.mainloop()

Um die Größe des Canvas-Objekts an die neue Fenstergröße anzupassen, verwenden Sie einfach die tkinter-Geometrie-Manager richtig.

Bei pack gibt es die expand- und fill-Optionen, bei grid müssen Sie die columnconfigure- und rowconfigure-Methoden des canvas master (das Widget, das die canvas enthält) verwenden und bei place manager gibt es die relwidth- und relheight-Optionen. Andererseits ändert dies nur die Leinwandabmessungen, ohne die Abmessungen seiner Objekte zu ändern. Um die Größe der Canvas-Objekte zu ändern, müssen Sie die Skalierungsmethode verwenden, wie vorgeschlagen wurde. Eine andere zu berücksichtigende Sache ist, dass einige Canvas-Objekte wie Text nicht von der Canvas-Skalierungsmethode betroffen sind.

Hier ist der Antwortcode ein wenig geändert:

import tkinter as tk


# a subclass of Canvas for dealing with resizing of windows
class ResizingCanvas(tk.Canvas):
    def __init__(self, parent, **kwargs):
        tk.Canvas.__init__(self, parent, **kwargs)
        self.bind("<Configure>", self.on_resize)
        self.height = self.winfo_reqheight()
        self.width = self.winfo_reqwidth()

    def on_resize(self,event):
        # determine the ratio of old width/height to new width/height
        wscale = event.width/self.width
        hscale = event.height/self.height
        self.width = event.width
        self.height = event.height
        # rescale all the objects
        self.scale("all", 0, 0, wscale, hscale)


def main():
    root = tk.Tk()
    myframe = tk.Frame(root)
    myframe.pack(fill=tk.BOTH, expand=tk.YES)
    mycanvas = ResizingCanvas(myframe,width=850, height=400, bg="light blue")#, highlightthickness=0)
    mycanvas.pack(fill=tk.BOTH, expand=tk.YES)

    # add some widgets to the canvas
    mycanvas.create_line(0, 0, 200, 100)
    mycanvas.create_line(0, 100, 200, 0, fill="red", dash=(4, 4))
    mycanvas.create_rectangle(50, 25, 150, 75, fill="blue")

    # tag all of the drawn widgets
    root.mainloop()

if __name__ == "__main__":
    main()

.

494760cookie-checkWie kann man tkinter canvas dazu bringen, die Größe dynamisch an die Fensterbreite anzupassen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy