我无法显示比大约30612像素高的图像(高度)。我已经读过画布的最大高度。我想获取源文件并将其扩展到90或100k像素的高度。相反,我已经看到建议画布可以缓冲,如果这是真的,我不知道如何实现它..任何帮助表示赞赏!
我正在使用我在Stack上发现的代码,它应该处理大图像,它确实没问题,但最终命中了cavas的高度限制。 Canvas Limit
from tkinter import *
from PIL import ImageTk
from PIL import *
Image.MAX_IMAGE_PIXELS = None
class ScrolledCanvas(Frame):
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.master.title("Spectrogram Viewer")
self.pack(expand=YES, fill=BOTH)
canv = Canvas(self, relief=SUNKEN)
canv.config(width=400, height=500)
# canv.config(scrollregion=(0,0,1000, 1000))
# canv.configure(scrollregion=canv.bbox('all'))
canv.config(highlightthickness=0)
sbarV = Scrollbar(self, orient=VERTICAL)
sbarH = Scrollbar(self, orient=HORIZONTAL)
sbarV.config(command=canv.yview)
sbarH.config(command=canv.xview)
canv.config(yscrollcommand=sbarV.set)
canv.config(xscrollcommand=sbarH.set)
sbarV.pack(side=RIGHT, fill=Y)
sbarH.pack(side=BOTTOM, fill=X)
canv.pack(side=LEFT, expand=YES, fill=BOTH)
self.im = Image.open("Test_3.tif")
width, height = self.im.size
canv.config(scrollregion=(0, 0, width, height))
self.im2 = ImageTk.PhotoImage(self.im)
self.imgtag = canv.create_image(0, 0, anchor="nw", image=self.im2)
ScrolledCanvas().mainloop()
答案 0 :(得分:0)
我试图从画布网格的显示中整理出更大的图像。看起来它可能会起作用,至少如果您只想显示一个大图像。我刚刚测试了一个小图像而没有注意记忆或速度或任何东西......
from tkinter import *
from scrframe import VerticalScrolledFrame
root = Tk()
tiles = VerticalScrolledFrame(root) # Scrolled frame
tiles.grid()
tw = 90 # Tile width
th = 110 # Tile height
rows = 4 # Number of tiles/row
cols = 4 # Number of tiles/column
tile_list = [] # List of image tiles
img = PhotoImage(file='pilner.png')
for r in range(rows):
col_list = []
for c in range(cols):
tile = Canvas(tiles.interior, highlightthickness=0, bg='tan1',
width=tw, height=th)
tile.create_image(-c*tw, -r*th, image=img, anchor ='nw')
tile.grid(row=r, column=c)
col_list.append(tile)
tile_list.append(col_list)
root.mainloop()
现在,滚动框架似乎会引发一些问题,但似乎也有解决方案。我尝试使用Python Tkinter scrollbar for frame中描述的VerticalScrolledFrame
,它运行正常。因为它只提供垂直滚动条,所以您必须自己实现水平滚动条。也许一些额外的功能,如滚动鼠标滚轮,键盘快捷键或其他功能将是有用的。
我从TKinter scrollable frame获得VerticalScrolledFrame
并为Python 3修改了它。
答案 1 :(得分:0)
这是我从几个来源提出的代码 - 感谢figbeam的所有帮助。此外,这不漂亮!!!!该按钮显示在Tkinter窗口的中央。如果你想修改它,请做。
from tkinter import *
from PIL import ImageTk as itk
from PIL import Image
import math
import numpy as np
Image.MAX_IMAGE_PIXELS = None #prevents the "photo bomb" warning from popping up. Have to have this for really large images.
#----------------------------------------------------------------------
# makes a simple window with a button right in the middle that let's you go "down" an image.
class MainWindow():
#----------------
def __init__(self, main):
# canvas for image
_, th, tw, rows, cols = self.getrowsandcols()
self.canvas = Canvas(main, width=tw, height=th)
self.canvas.grid(row=0, column=0)
# images
self.my_images = self.cropimages() # crop the really large image down into several smaller images and append to this list
self.my_image_number = 0 #
# set first image on canvas
self.image_on_canvas = self.canvas.create_image(0, 0, anchor = NW, image = self.my_images[self.my_image_number])
# button to change image
self.button = Button(main, text="DOWN", command=self.onDownButton)
self.button.grid(row=0, column=0)
#----------------
def getimage(self):
im = Image.open("Test_3.png") # import the image
im = im.convert("RGBA") # convert the image to color including the alpha channel (which is the transparency best I understand)
width, height = im.size # get the width and height
return width, height, im # return relevent variables/objects
def getrowsandcols(self):
width, height, im = self.getimage()
im = np.asarray(im) # Convert image to Numpy Array
tw = width # Tile width will equal the width of the image
th = int(math.ceil(height / 100)) # Tile height
rows = int(math.ceil(height / th)) # Number of tiles/row
cols = int(math.ceil(width / tw)) # Number of tiles/column
return im, th, tw, rows, cols #return selected variables
def cropimages(self):
self.my_images = [] # initialize list to hold Tkinter "PhotoImage objects"
im, th, tw, rows, cols = self.getrowsandcols() # pull in needed variables to crop the really long image
for r in range(rows): # loop row by row to crop all of the image
crop_im =im[r * th:((r * th) + th), 0:tw] # crop the image for the current row (r). (th) stands for tile height.
crop_im = Image.fromarray(crop_im) # convert the image from an Numpy Array to a PIL image.
crop_im = itk.PhotoImage(crop_im) # convert the PIL image to a Tkinter Photo Object (whatever that is)
self.my_images.append(crop_im) # Append the photo object to the list
crop_im = None
return self.my_images
def onDownButton(self):
# next image
self.my_image_number += 1 #every button pressed will
# return to first image
if self.my_image_number == len(self.my_images):
self.my_image_number = 0
# change image
self.canvas.itemconfig(self.image_on_canvas, image = self.my_images[self.my_image_number]) #attaches the image from the image list to the canvas
#----------------------------------------------------------------------
root = Tk()
MainWindow(root)
root.mainloop()