Tkinter Canvas带滚动条显示图片触发TypeError错误,请求技术排查帮助
Let's break down the problems in your code and fix them one by one:
1. Direct Cause of the Latest TypeError
The line canvas.config(self.image_on_canvas) is the source of your TypeError: object of type 'int' has no len() error.
self.image_on_canvasis an integer ID returned bycanvas.create_image(), which identifies the image item on the canvas.- The
canvas.config()method is meant to set properties of the canvas itself (like size or scroll commands), not modify individual items on it. Passing an integer ID here makes no sense to Tkinter.
Fix: Delete this line entirely—it's unnecessary for your current code.
2. Preventing Image Disappearance (Garbage Collection Issue)
You're creating img2 = ImageTk.PhotoImage(img) as a local variable inside your loop. Tkinter PhotoImages are prone to being garbage collected if there's no persistent reference to them, which would make your image vanish after the function runs.
Fix: Store the PhotoImage as an instance variable to keep it alive:
img2 = ImageTk.PhotoImage(img) self.canvas_img = img2 # Keep reference to avoid garbage collection self.image_on_canvas = canvas.create_image(0, 0, anchor="nw", image=img2)
3. Avoiding Duplicate UI Elements
Your for database_visuales2 in db_rows: loop will create multiple frames, buttons, and canvases if your query returns more than one row (which it shouldn't, since you're querying by ID_IMAGEN_VISUAL). To prevent overlapping UI elements, add a break after processing the first row:
for database_visuales2 in db_rows: # ... all your existing code for this iteration ... break # Exit loop after first row (since ID should be unique)
Corrected Code Snippet
Here's the revised section of your function with all fixes applied:
def visualizar_imagen_consulta(self): try: self.tree3.item(self.tree3.selection())['values'][0] except IndexError as e: messagebox.showinfo("A T E N C I O N ! ! !", "Selecciones una consulta, por favor!") return self.windows_fichas_consulta2 = Toplevel() self.windows_fichas_consulta2.transient(self.windows_consulta1) self.windows_fichas_consulta2.resizable(width=False, height=False) self.windows_fichas_consulta2.geometry("655x600+700+0") query = 'SELECT * FROM visuales WHERE ID_IMAGEN_VISUAL = ?' parameters = (self.miid_nombre_imagen.get(), ) db_rows = self.run_query(query, parameters) for database_visuales2 in db_rows: self.midescripcion_imagen.set(database_visuales2[4]) self.tarjeta_ficha_consulta1="/oftica/visuales/" + self.miid_nombre_imagen.get() # Frame for menu self.frame200 = LabelFrame(self.windows_fichas_consulta2, text = '', foreground = 'darkgreen', font = ('arial', 16, 'bold'), background='lightcyan2') self.frame200.place(x=70, y=510) Button(self.frame200, text = ' Escuchar', command = self.voz_imagen_consulta, background="cyan4", image=self.photo_tarjeta_speaker, compound="left", height = 30, width = 150, foreground = 'black', font = ('arial', 12, 'bold')).grid(row = 1, column = 0, columnspan = 1, sticky = W + E, pady=5, padx=5) Button(self.frame200, text = ' Zoom', command = self.zoom_imagen_consulta2, background="cyan4", image=self.photo_zoom, compound="left", height = 30, width = 150, foreground = 'black', font = ('arial', 12, 'bold')).grid(row = 1, column = 1, columnspan = 1, sticky = W + E, pady=5, padx=5) Button(self.frame200, text = ' Volver', command = lambda : self.windows_fichas_consulta2.destroy(), background="seaGreen3", image=self.photo_volver_consulta, compound="left", height = 30, width = 150, foreground = 'black', font = ('arial', 12, 'bold')).grid(row = 1, column = 2, columnspan = 1, sticky = W + E, pady=5, padx=5) Label(self.frame200, text = '' + self.midescripcion_imagen.get(), font = ('arial', 12, 'bold'), background='lightcyan2').grid(row = 0, column = 0, columnspan = 5, sticky = W + E, pady=5, padx=5) img_frame = tk.Frame(self.windows_fichas_consulta2, height=400, width=600, bg='#faf0e6') img_frame.pack() canvas = tk.Canvas (img_frame, height=400, width=600, bg='#faf0e6', relief=tk.SUNKEN) sbarV = tk.Scrollbar(img_frame, orient=tk.VERTICAL, command=canvas.yview) sbarH = tk.Scrollbar(img_frame, orient=tk.HORIZONTAL, command=canvas.xview) sbarV.pack(side=tk.RIGHT, fill=tk.Y) sbarH.pack(side=tk.BOTTOM, fill=tk.X) canvas.config(yscrollcommand=sbarV.set) canvas.config(xscrollcommand=sbarH.set) canvas.pack(side=tk.LEFT, expand=True, fill=tk.BOTH) img = Image.open(self.tarjeta_ficha_consulta1) width, height = img.size canvas.config(scrollregion=(0, 0, width, height)) img2 = ImageTk.PhotoImage(img) self.canvas_img = img2 # Persist reference to avoid garbage collection self.image_on_canvas = canvas.create_image(0, 0, anchor="nw", image=img2) break # Stop after first row (ID should be unique)
Notes on the Previous item configure Error
That error occurred because you likely tried calling canvas.itemconfigure() without passing the required item ID (the first argument). If you ever need to modify the image later (like for zooming), you'd use:
canvas.itemconfigure(self.image_on_canvas, image=new_photo_image)
Just make sure you pass the item ID first, then the properties to change.
内容的提问来源于stack exchange,提问作者Juan carlos Pantoja

