Создание множества фигур на холсте tkinter, которые можно изменить позже - PullRequest
0 голосов
/ 24 сентября 2019

Я хочу сделать несколько геометрических единиц и повторить их, как 100 раз на моем холсте.Тем не менее, я должен быть в состоянии изменить каждый юнит после того, как он нарисован.

Я думал обернуть код, чтобы нарисовать единицу (прямо сейчас 4 дуги), в один метод и вызывать этот метод много раз.Но тогда я не могу получить доступ к первой дуге и т. Д.

def box(coords):
    arc_one = canvas.create_arc(coords, start=0, extent=90, outline="white", style="arc", tag=1)

    arc_two = canvas.create_arc(coords, start=90, extent=90, outline="white", style="arc", tag=2)

    arc_three = canvas.create_arc(coords, start=180, extent=90, outline="white", style="arc", tag=3)

    arc_four = canvas.create_arc(coords, start=270, extent=90, outline="white", style="arc", tag=4)

^ идея, но тогда я не могу получить доступ к arc_one позже

В настоящее время у меня есть:

import tkinter as tk
import time

root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200, bg='black')
canvas.pack(fill="both", expand=True)

# direction will be dynamic later
direction='RIGHT'

# motion will be dynamic later
motion='FULLMOON'

# each bounding box is 100 x 100
# coordinates are (x,y) of upper left corner, and then (x,y) of lower left corner

coords = (100, 50, 200, 150)

# use box width to later move around
box_width = coords[2] - coords[0]

# use arc width for width of 1 component
# 4 components in 1 box
arc_width = box_width/2

arc_one = canvas.create_arc(coords, start=0, extent=90, outline="white", style="arc",tag=1)

arc_two = canvas.create_arc(coords, start=90, extent=90, outline="white", style="arc",tag=2)

arc_three = canvas.create_arc(coords, start=180, extent=90, outline="white", style="arc",tag=3)

arc_four = canvas.create_arc(coords, start=270, extent=90, outline="white", style="arc",tag=4)

'''
I want to just bundle arcs one to four into a single method, and call it with new coordinates to create many new 
circles. 

However, I won't be able to call each arc later if I do so.
'''

# second bounding box to the right
coords_2 = (100 + 100, 50, 200 + 100, 150)

arc_five = canvas.create_arc(coords_2, start=0, extent=90, outline="white", style="arc",tag=1)

arc_six = canvas.create_arc(coords_2, start=90, extent=90, outline="white", style="arc",tag=2)

arc_seven = canvas.create_arc(coords_2, start=180, extent=90, outline="white", style="arc",tag=3)

arc_eight = canvas.create_arc(coords_2, start=270, extent=90, outline="white", style="arc",tag=4)


def bold(event):
    id = event.widget.find_closest(event.x,event.y)[0]
    canvas.itemconfigure(id,width=2.5)
    canvas.update()
    time.sleep(.5)

    if direction == 'RIGHT' and motion == 'FULLMOON':
#         while there are no more new widgets
        while (id != event.widget.find_closest(event.x + arc_width, event.y)[0]):
    #         move cursor to the right
            event.x += arc_width
            id = event.widget.find_closest(event.x, event.y)[0]
            canvas.itemconfigure(id, width=2.5)
            canvas.update()
            time.sleep(.5)


canvas.tag_bind(arc_one,"<Button-1>", bold)
canvas.tag_bind(arc_two,"<Button-1>", bold)
canvas.tag_bind(arc_three,"<Button-1>", bold)
canvas.tag_bind(arc_four,"<Button-1>", bold)

canvas.tag_bind(arc_five,"<Button-1>", bold)
canvas.tag_bind(arc_six,"<Button-1>", bold)
canvas.tag_bind(arc_seven,"<Button-1>", bold)
canvas.tag_bind(arc_eight,"<Button-1>", bold)


root.mainloop()

1 Ответ

1 голос
/ 24 сентября 2019

Я рекомендую изменить box на класс.Это значительно облегчит обработку каждого «ящика» как объекта, и каждый объект будет иметь пространство имен для хранения своих собственных метаданных.Это именно тот тип проблемных классов, которые предназначены для решения.

В следующем примере каждая дуга в «прямоугольнике» получает два тега.Один из них - "arc" на случай, если вы захотите изменить все дуги всех блоков одновременно, а один - тег, уникальный для каждого блока, для настройки всех дуг одновременно для одного блока.

Кроме того, идентификаторы холста каждой отдельной дуги сохраняются в массиве.При этом вы можете настроить любую отдельную дугу для любого отдельного «ящика».

class Box():
    def __init__(self, canvas, coords):
        self.canvas = canvas
        self.tag = "box-{}".format(id(self))
        tags = ("arc", self.tag)
        self.arcs = [
            canvas.create_arc(coords, start=0, extent=90, style="arc", tags=tags),
            canvas.create_arc(coords, start=90, extent=90, style="arc", tags=tags),
            canvas.create_arc(coords, start=180, extent=90, style="arc", tags=tags),
            canvas.create_arc(coords, start=270, extent=90, style="arc", tags=tags),
    ]

Пример использования:

box1 = Box(canvas, (100, 50, 200, 150))
box2 = Box(canvas, (100 + 100, 50, 200 + 100, 150))

Чтобы изменить все дуги глобально, вы можете настроить «дугу»"tag:

canvas.itemconfigure("arc", width=5, fill="yellow")

Чтобы изменить один блок, используйте тег для этого блока:

canvas.itemconfigure(box1.tag, outline='red')

Чтобы изменить одну дугу для одного блока, используйте индекс этой дугидля этого поля

canvas.itemconfigure(box2.arcs[0], outline="green")

Если вы выполните все вышеперечисленное, конечный результат будет выглядеть следующим образом, где:

  • желтый представляет изменения, которые мы внесли ввсе дуги,
  • красный представляет изменения, которые мы внесли в box1, а
  • зеленый представляет изменения, которые мы внесли в одну дугу в box2

window screenshot

Если вы хотите иметь возможность нажимать на любую отдельную дугу, вам нужно иметь только один оператор связывания для тега "arc":

canvas.tag_bind("arc", "<Button-1>", bold)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...