Je voudrais afficher une image en utilisant tkinter (Python 3). L'image est très longue. Par conséquent, je voudrais ajouter une barre de défilement verticale. Voici ce que j'ai essayé:
(basé sur cette question: Scrollbars pour une image .jpg sur un Tkinter Canvas en Python )
import tkinter import PIL.Image, PIL.ImageTk # Create a window window = tkinter.Tk() frame = tkinter.Frame(window, bd=2) # relief=SUNKEN) frame.grid_rowconfigure(0, weight=1) frame.grid_columnconfigure(0, weight=1) xscrollbar = tkinter.Scrollbar(frame, orient=tkinter.HORIZONTAL) xscrollbar.grid(row=1, column=0, sticky=tkinter.E+tkinter.W) yscrollbar = tkinter.Scrollbar(frame) yscrollbar.grid(row=0, column=1, sticky=tkinter.N+tkinter.S) canvas = tkinter.Canvas(frame, bd=0, xscrollcommand=xscrollbar.set, yscrollcommand=yscrollbar.set) canvas.grid(row=0, column=0, sticky=tkinter.N+tkinter.S+tkinter.E+tkinter.W) canvas.config(scrollregion=canvas.bbox(tkinter.ALL)) File = "FILEPATH" img = PIL.ImageTk.PhotoImage(PIL.Image.open(File)) canvas.create_image(0,0,image=img, anchor="nw") xscrollbar.config(command=canvas.xview) yscrollbar.config(command=canvas.yview) frame.pack() window.mainloop()
J'obtiens ce qui suit:
Je suis capable de tracer l'image, mais les barres de défilement ne fonctionnent pas. Ils sont simplement gris et ne fonctionnent pas.
3 Réponses :
Mettez la ligne:
canvas.create_image(0,0,image=img, anchor="nw")
après:
canvas.config(scrollregion=canvas.bbox(tkinter.ALL))
ou le canevas n'inclut pas l'image dans scrollregion.
p>
Définissez la zone de défilement du canevas après avoir dessiné l'image:
canvas.create_image(0, 0, image=img, anchor="nw") canvas.config(scrollregion=canvas.bbox(tkinter.ALL))
Question rapide: sauriez-vous comment augmenter la taille de la figure tkinter?
@henry - Si vous vouliez dire PhotoImage, vous pouvez utiliser PIL.ImageTk.PhotoImage (PIL.Image.open (File) .resize ((width, height)))
Génial. Merci !
Si vous voulez un widget d'image défilante, le meilleur moyen serait de créer une classe d'image défilante qui arrangera et ressemblera mieux à votre code. J'ai donc créé une classe pour le même et également ajouté bind
afin que l'on puisse faire défiler leur souris pour voir l'image plus facilement.
Voici l'exemple de code
import tkinter as tk # Import the package if saved in a different .py file else paste # the ScrollableImage class right after your imports. from scrollimage import ScrollableImage root = tk.Tk() # PhotoImage from tkinter only supports:- PGM, PPM, GIF, PNG format. # To use more formats use PIL ImageTk.PhotoImage img = tk.PhotoImage(file="logo.png") image_window = ScrollableImage(root, image=img, scrollbarwidth=6, width=200, height=200) image_window.pack() root.mainloop()
Traitez la classe ScrollableImage
comme un widget de Tkinter et utilisez comme vous utilisez n'importe quel autre widget Tkinter car tous les autres widgets sont une classe à eux seuls si vous voyez le code source de tkinter .
Vous pouvez utiliser ScrollableImage
de différentes manières.
Enregistrez le code ci-dessus dans un nouveau fichier
(par exemple: "scrollimage.py") en tant que package dans le même répertoire puis importez dans votre classe principale comme from scrollimage import ScrollableImage
puis utilisez-le comme un widget normal.
Ou vous pouvez garder la classe ScrollableImage
en haut après les importations de votre fichier principal et l'utiliser comme d'habitude.
import tkinter class ScrollableImage(tkinter.Frame): def __init__(self, master=None, **kw): self.image = kw.pop('image', None) sw = kw.pop('scrollbarwidth', 10) super(ScrollableImage, self).__init__(master=master, **kw) self.cnvs = tkinter.Canvas(self, highlightthickness=0, **kw) self.cnvs.create_image(0, 0, anchor='nw', image=self.image) # Vertical and Horizontal scrollbars self.v_scroll = tkinter.Scrollbar(self, orient='vertical', width=sw) self.h_scroll = tkinter.Scrollbar(self, orient='horizontal', width=sw) # Grid and configure weight. self.cnvs.grid(row=0, column=0, sticky='nsew') self.h_scroll.grid(row=1, column=0, sticky='ew') self.v_scroll.grid(row=0, column=1, sticky='ns') self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) # Set the scrollbars to the canvas self.cnvs.config(xscrollcommand=self.h_scroll.set, yscrollcommand=self.v_scroll.set) # Set canvas view to the scrollbars self.v_scroll.config(command=self.cnvs.yview) self.h_scroll.config(command=self.cnvs.xview) # Assign the region to be scrolled self.cnvs.config(scrollregion=self.cnvs.bbox('all')) self.cnvs.bind_class(self.cnvs, "<MouseWheel>", self.mouse_scroll) def mouse_scroll(self, evt): if evt.state == 0 : self.cnvs.yview_scroll(-1*(evt.delta), 'units') # For MacOS self.cnvs.yview_scroll(int(-1*(evt.delta/120)), 'units') # For windows if evt.state == 1: self.cnvs.xview_scroll(-1*(evt.delta), 'units') # For MacOS self.cnvs.xview_scroll(int(-1*(evt.delta/120)), 'units') # For windows
La liaison
nécessite quelques modifications sur fenêtres comme diviser event.delta
par 120. Sur macOS, aucune modification n'est nécessaire. Et sur X11, vous devez lier à la fois
,
et également diviser event.delta
par 120.
Pour plus de détails sur bind
et comment cela fonctionne sur différentes plates-formes, vous pouvez consulter le lien ci-dessus.
Meilleur moyen de structurer l'application Tkinter.
Vous pouvez vous référer au lien ci-dessus pour lire en détail comment vous pouvez appliquer correctement Oops dans Tkinter. Lorsque vous utilisez les POO, vous pouvez toujours hériter de n'importe quel widget de Tkinter et le modifier pour créer de nouveaux widgets et des classes utiles qui vous aideront à améliorer votre application avec Tkinter.
Hou la la ! Merci beaucoup pour votre classe! Cela semble très utile. Je suis assez nouveau sur tkinter. Comment l'utiliseriez-vous? Pourriez-vous ajouter un petit exemple? Merci.
@Henry: J'ai ajouté des informations plus utiles qui vous aideront à mieux apprendre.
Merci beaucoup ! C'est très gentil de votre part et très utile!
J'obtiens l'erreur suivante: Exception dans Tkinter callback Traceback (dernier appel en dernier): Fichier "C: \ Users \ Anaconda3 \ lib \ tkinter_ init_ .py", ligne 1702, dans appel renvoie self.func (* args) Fichier "
@henry: c'est parce que scroll
prend une valeur entière et "1.0" est une valeur flottante, le correctif est simple, il suffit de le convertir en entier. J'ai cependant édité mon message et l'ai corrigé. Je n'ai pas pu tester cela car je suis sur Macos. J'espère que cela fonctionnera maintenant.
Hmm .. comment changeriez-vous la taille de la fenêtre?
Tout comme vous modifiez la taille d'un widget avec les paramètres width
et height
, voir le code à la ligne 42 ScrollableImage (root, image = img, width = 200, hauteur = 200) .pack ()
Merci beaucoup pour votre patience et votre aide! J'apprécie beaucoup. Peut-être, si vous avez le temps, voudriez-vous jeter un œil à mon autre question: stackoverflow.com/questions/56056054/...
Pas de problème, et j'y reviendrai plus tard.