Texicans
Texicans

Reputation: 75

How to draw arrow at begining of label end

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

Answers (1)

Bryan Oakley
Bryan Oakley

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

Related Questions