Сопровождение заказов в Ткинтере - PullRequest
3 голосов
/ 06 марта 2012

Есть ли способ поддерживать последовательный порядок наложения виджетов (особенно изображений) изнутри Tkinter?Например, у меня может быть два прямоугольника, два треугольника и круг в одном месте на холсте.Круг перемещается туда, где была нажата последняя кнопка мыши, но я всегда хочу, чтобы она была нарисована поверх прямоугольников и позади треугольников.Поведение по умолчанию, конечно, заключается в том, чтобы поместить последний нарисованный объект в заданное место сверху.

До сих пор я нашел только методы lift () и lower () для решения проблемы стекирования в Tkinter.Теоретически я мог бы делать некоторые беспорядочные проверки при каждом повторном рисовании, чтобы увидеть, существуют ли треугольники в месте назначения, и выполнить некоторые функции lift () / lower () для каждой фигуры, пока все не будет так, как я хочу, но это кажется абсурдным решением.Я ожидал, что на объектах холста будет какая-то переменная «layer», поэтому он будет пассивно помнить, что элементы уровня 3 всегда должны быть позади элементов уровня 1.

Я прошу прощения, если есть простой метод для решениямоя проблема, но пока все мои поиски были безрезультатны.Буду благодарен за любой вклад!

1 Ответ

6 голосов
/ 06 марта 2012

Пометьте все треугольники «треугольником», все прямоугольники «прямоугольником» и все круги «окружностью». Затем вы можете использовать метод lift или lower, чтобы поднять или опустить все треугольники, круги или прямоугольники одновременно. Это займет всего пару утверждений и произойдет в мгновение ока, даже если у вас есть тысячи предметов.

Поскольку вы спрашивали о встроенном механизме слоя: у tk такого нет, но его действительно легко добавить, все инструменты есть. Таким образом, вместо разбрызгивания команд lift или lower повсюду, все ваши рисунки проходят через специальную команду, которая обрабатывает наслоение для вас.

Например, вот пример команды, которая принимает номер слоя и удостоверяется, что все, что она рисует, находится на этом слое:

def add_to_layer(self, layer, command, coords, **kwargs):
    layer_tag = "layer %s" % layer
    if layer_tag not in self._layers: self._layers.append(layer_tag)
    tags = kwargs.setdefault("tags", [])
    tags.append(layer_tag)
    item_id = command(coords, **kwargs)
    self._adjust_layers()
    return item_id

def _adjust_layers(self):
    for layer in sorted(self._layers):
        self.canvas.lift(layer)

Тогда вы бы назвали это так:

# draw a circle on layer 1:
self.add_to_layer(1, self.canvas.create_oval, (x0,y0,x1,y1), outline="red")
# draw a square on layer 2:
self.add_to_layer(2, self.canvas.create_rectangle, (x0,y0,x1,y1), fill="blue")

Есть много других способов сделать то же самое, вышеизложенное - просто быстрый и грязный пример с моей головы (и он не гарантирован на 100% правильный, но я думаю, что это иллюстрирует суть).

Основная идея состоит в том, что создание всех объектов проходит через одну функцию, которая может регулировать порядок наложения при каждом создании элемента. Таким образом, вам нужно только добавить эти команды подъема / опускания в одном месте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...