Reputation: 75
I want to draw an arrow which begin when a label is ending. I have written some code: ` import Tkinter as tk
from Tkinter import *
methods=["m1","m2"]
results=["r1","r2"]
pos_x_of_image=100
pos_y_of_image=150
frame_size_x=850
frame_size_y=550
def main():
root = Tk()
canvas=Canvas(root)
canvas.config(width=frame_size_x, height=frame_size_y)
root.title("window")
root.geometry('%dx%d'%(frame_size_x,frame_size_y))
for i in range(0,len(methods)):
create_label(canvas, methods[i], pos_x_of_image+100, 50 +i*int(frame_size_y/int(len(methods))))
create_arrow(canvas, pos_x_of_image, pos_y_of_image+50, pos_x_of_image+100, 60 +i*int(frame_size_y/int(len(methods))))
for j in range(0,2):
if j==0:
create_label(canvas, methods[i], pos_x_of_image+170+4*int(len(methods[i])), 30 +j*40+i*int(frame_size_y/int(len(methods))))
create_arrow(canvas,label_width ,label_height , pos_x_of_image+170+4*int(len(methods[i])), 40 +j*40+i*int(frame_size_y/int(len(methods))))
if j==1:
create_label(canvas, results[j], pos_x_of_image+170+4*int(len(methods[i])), 30 +j*40+i*int(frame_size_y/int(len(methods))))
create_arrow(canvas,label_width ,label_height, pos_x_of_image+170+4*int(len(methods[i])), 30 +j*40+i*int(frame_size_y/int(len(methods))))
canvas.pack()
root.mainloop()
def create_arrow(canvas,x_start,y_start,x_finish,y_finish):
id = canvas.create_line(x_start,y_start,x_finish,y_finish,arrow=tk.LAST)
def create_label(canvas,method,x_start,y_start):
w=Label(canvas,text=method)
w.place(x=x_start,y=y_start)
return w
if __name__ == '__main__':
main()
The problem is with line create_arrow(canvas,label_width ,label_height, pos_x_of_image+170+4*int(len(methods[i])), 30 +j*40+i*int(frame_size_y/int(len(methods))))
, because I do not know how to get label width and heigth.
Upvotes: 0
Views: 699
Reputation: 386352
The problem you are facing is that the width of a widget is indeterminate until it is actually drawn, since the width can be affected by how it is added to a window.
In your case, however, you can compute the width and height by forcing an update. For example, change the code where you create the label and arrow to be this:
l = create_label(...)
canvas.update()
label_width = l.winfo_width()
label_height = l.winfo_height()
create_arrow(canvas,label_width ,label_height, ...)
If you don't like having to force an update, there are other things you can do. For example, you can use a text object on the canvas rather than a label widget:
l = create_label(...)
bbox = canvas.bbox(l)
label_width = bbox[2]-bbox[0]
label_height = bbox[3]-bbox[1]
...
def create_label(canvas,method,x_start,y_start):
w = canvas.create_text(x_start, y_start, text=method, anchor="nw")
return w
...
This second method is much preferable, since objects added to a canvas with place
will not scroll along with canvas objects.
Upvotes: 1