以下代码生成一个带有图像的漂亮Canvas,我可以在它上面绘制一个正方形。然而: a)我无法让Canvas不滚动。 b)我只希望图像显示而不是其他任何东西,并且无法正确显示尺寸
正如您将看到的,我甚至试图停止滚动但它不能一直工作。此外,即使我将三个(根,画布和图像)的大小设置为相同,图像也永远不会与Canvas和窗口完全对齐。
这是代码(部分取自另一个示例,其中一些部分被注释掉):
try:
from PIL import Image
except ImportError:
import Image
from PIL import ImageTk
try:
import Tkinter as tk # Python2
except ImportError:
import tkinter as tk # Python3s
import Tkinter
from Tkinter import *
import PIL as PILAll
class ExampleApp(Frame):
def __init__(self,master):
Frame.__init__(self,master=None)
self.x = 0
self.y = 0
self.canvas = Canvas(self, cursor="cross", width=640, height=480, confine=True, scrollregion=(10, 10, 10, 10), relief="groove", bg="blue")# and I have experimented with a few other options
#self.sbarv=Scrollbar(self,orient=VERTICAL)
#self.sbarh=Scrollbar(self,orient=HORIZONTAL)
#self.sbarv.config(command=self.canvas.yview)
#self.sbarh.config(command=self.canvas.xview)
self.canvas.config()#yscrollcommand=self.sbarv.set)
self.canvas.config()#xscrollcommand=self.sbarh.set)
self.canvas.config(scrollregion=self.canvas.bbox(ALL))
self.canvas.grid(row=0,column=0,sticky=N+S+E+W)
#self.sbarv.grid(row=0,column=1,stick=N+S)
#self.sbarh.grid(row=1,column=0,sticky=E+W)
self.canvas.bind("<ButtonPress-1>", self.on_button_press)
self.canvas.bind("<B1-Motion>", self.on_move_press)
self.canvas.bind("<ButtonRelease-1>", self.on_button_release)
self.canvas.bind("<Leave>", self.on_button_leave)
self.canvas.bind("<Enter>", self.on_button_enter)
self.canvas.bind("<Double-Button-1>", self.on_double_click)
self.canvas.create_line(0, 0, 200, 100)
self.canvas.create_line(0, 100, 200, 0, fill="red", dash=(4, 4))
self.canvas.create_rectangle(50, 25, 150, 75, fill="blue")
self.rect = None
self.text = None
self.start_x = None
self.start_y = None
self.im = PILAll.Image.open("../../" + "image6.JPG")
self.wazil,self.lard=self.im.size
self.canvas.config() #scrollregion=(0,0,self.wazil,self.lard))
self.tk_im = ImageTk.PhotoImage(self.im)
self.canvas.create_image(0,0,anchor="nw",image=self.tk_im)
out_of_scope = 1
def on_button_leave(self, event):
self.out_of_scope = 2
print "out_of_scope....", self.out_of_scope
def on_button_enter(self, event):
print("entering...")
self.out_of_scope = 1
def on_double_click(self, event):
print("double click")
def on_button_press(self, event):
# save mouse drag start position
self.start_x = self.canvas.canvasx(event.x)
self.start_y = self.canvas.canvasy(event.y)
# create rectangle if not yet exist
if not self.rect:
if self.out_of_scope == 1:
self.rect = self.canvas.create_rectangle(self.x, self.y, 1, 1, outline='blue', fill='yellow') #since it's only created once it always remains at the bottom
def get_out_of_scope(self, x, y):
return self.out_of_scope
def on_move_press(self, event):
curX = self.canvas.canvasx(event.x)
curY = self.canvas.canvasy(event.y)
var=self.get_out_of_scope(event.x, event.y)
print(var, event.x, event.y)
if var == 1:
w, h = self.canvas.winfo_width(), self.canvas.winfo_height()
if event.x > 0.9*w:
self.canvas.xview_scroll(1, 'units')
elif event.x < 0.1*w:
self.canvas.xview_scroll(-1, 'units')
if event.y > 0.9*h:
self.canvas.yview_scroll(1, 'units')
elif event.y < 0.1*h:
self.canvas.yview_scroll(-1, 'units')
# expand rectangle as you drag the mouse
self.canvas.coords(self.rect, self.start_x, self.start_y, curX, curY)
def on_button_release(self, event):
print(event.x, event.y)
pass
root=Tk()
root.geometry("640x480")
app = ExampleApp(root)
app.grid()
root.mainloop()
答案 0 :(得分:1)
我认为您的代码会因reviewed而受益,但我会尝试将自己限制在这个问题上......
如果canvas
需要与图片大小相同,为什么用width=640, height=480
构建它?你可以进一步计算出图像的宽度和高度:
self.im = PILAll.Image.open("../../" + "image6.JPG")
self.wazil,self.lard=self.im.size
(有趣的变量名称选择btw)所以,如果self.wazil
和self.lard
代表图像的宽度和高度,为什么不让它成为画布的宽度和高度?
self.im = PILAll.Image.open("../../" + "image6.JPG")
self.wazil,self.lard=self.im.size
self.canvas = Canvas(self, width=self.wazil, height=self.lard) #, ...)
然后画布将是正确的大小,但根窗口仍然强制自己 640x480 :
root.geometry("640x480")
但由于小部件会自动扩展到内容,您只需对该行进行注释,它的大小应该正确。
#root.geometry("640x480")
我应该注意到,我正在经历一些非常奇怪的行为,关于图像的位置是3像素太高,左边3像素,用图像绘制图像:
self.canvas.create_image(3,3,anchor="nw",image=self.tk_im)
为我修好了,但我不知道为什么......
至于滚动,您删除了有关滚动条的部分,但是您在on_move_press
中留下了这些内容:
w, h = self.canvas.winfo_width(), self.canvas.winfo_height()
if event.x > 0.9*w:
self.canvas.xview_scroll(1, 'units')
elif event.x < 0.1*w:
self.canvas.xview_scroll(-1, 'units')
if event.y > 0.9*h:
self.canvas.yview_scroll(1, 'units')
elif event.y < 0.1*h:
self.canvas.yview_scroll(-1, 'units')
这是偶尔滚动画布的代码部分(当我尝试调整窗口大小时发生),所以你可以再次对该部分进行评论,它不应该再滚动。
最后一个与问题无关的注释,你有:
def __init__(self,master):
Frame.__init__(self,master=None)
但我很确定你的意思是:
def __init__(self,master=None):
Frame.__init__(self,master)
因为您需要主参数的第一种方式,但不要将其传递给Frame.__init__
。当Frame.__init__
收到None
的主文件时,它只使用Tk
实例,在您的情况下是相同的,但如果您使用任何其他主文件,则会导致非常奇怪的问题。