[Tutor] Tkinter draw line segments

Peter Otten __peter__ at web.de
Wed Mar 30 11:27:51 EDT 2022


On 30/03/2022 08:35, Phil wrote:
> The segment table contains the start and end points of lines to be drawn
> on the canvas.
>
>          seg = {0: (20, 20, 40, 20),
>                 1: (44, 24, 44, 44),
>                 2: (44, 48, 44, 68),
>                 3: (20, 72, 40, 72),
>                 4: (16, 48, 16, 68),
>                 5: (16, 24, 16, 44),
>                 6: (20, 46, 40, 46),
>                }
>
> Say I want to draw segments 1 and 2.
>
>          num = {1: (seg[1], seg[2])}
>
> The following will draw all of the segments correctly.
>
>          for i in range(7):
>              self.canvas.create_line(seg[i], width=4, fill="green")
>
> What I haven't sorted out is how to draw segments 1 and 2 without having
> two draw statements. The following does draw the two segments but
> without the break between them.
>
>          self.canvas.create_line(num[1], width=4, fill="green")
>
> What I'm trying to come up with is a table entry that tells the draw
> routine how many draw statements there are, one for each segment. No
> doubt I'm making this more complicated than it needs to be.
>
> One way around this is to draw all of the segments in two colours. In
> the above case I would draw segments 1 and 2 green and the remainder
> black. That way I'd only need one draw statement in a for loop with a
> variable fill colour. This would work perfectly on a black background
> but it seems like an amateurish solution.
>

I'd go about it a bit differently. When you draw all segments separately
you can remember them by their ids. To display the desired digits you
can hide/display segments as needed. A complete example:

import tkinter as tk

segments = [
     (20, 20, 40, 20),
     (44, 24, 44, 44),
     (44, 48, 44, 68),
     (20, 72, 40, 72),
     (16, 48, 16, 68),
     (16, 24, 16, 44),
     (20, 46, 40, 46),
]

segment_states = [
     (1, 1, 1, 1, 1, 1, 0),  # 0
     (0, 1, 1, 0, 0, 0, 0),  # 1
     (1, 1, 0, 1, 1, 0, 1),  # 2
     (1, 1, 1, 1, 0, 0, 1),  # 3
     (0, 1, 1, 0, 0, 1, 1),  # 4
     (1, 0, 1, 1, 0, 1, 1),  # 5
     (0, 0, 1, 1, 1, 1, 1),  # 6
     (1, 1, 1, 0, 0, 0, 0),  # 7
     (1, 1, 1, 1, 1, 1, 1),  # 8
     (1, 1, 1, 0, 0, 1, 1),  # 9
]


class Demo:
     def __init__(self):
         self.root = tk.Tk()

         self.label = tk.Label(
             self.root,
             text="Hit digit key to display corresponding number"
         )
         self.label.pack()

         self.canvas = tk.Canvas(self.root, width=100, height=100)
         self.canvas.pack()

         self.segment_ids = []
         self.draw_segments()
         for c in "0123456789":
             self.root.bind(
                 c,
                 lambda event, n=int(c): self.set_segments(
                     segment_states[n]
                 )
             )

     def draw_segments(self):
         for segment in segments:
             self.segment_ids.append(
                 self.canvas.create_line(segment, width=4, fill="green")
             )

     def set_segments(self, states):
         for seg_id, on in zip(self.segment_ids, states):
             self.canvas.itemconfigure(
                 seg_id, state=tk.NORMAL if on else tk.HIDDEN
             )

     def mainloop(self):
         self.root.mainloop()


if __name__ == "__main__":
     demo = Demo()
     demo.mainloop()



More information about the Tutor mailing list