Как заставить Tkinter pack_forget работать только с уникальными объектами - PullRequest
0 голосов
/ 21 января 2012

Ubuntu Linux 11.04 / Python 2.7 / Tkinter

Я новичок в Python GUI, и у меня возникают проблемы с исчезновением и повторным появлением отдельных объектов. pack_forget вроде как работает для меня, но то, как я это делаю, заставляет все объекты мигать, когда мне нужен только один объект за раз. В приведенном ниже примере, приведенном ниже, я пытаюсь заставить объект «а» появляться, а затем исчезать, а затем делать то же самое для объекта «б».

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

from Tkinter import *
import time

class Box:
    def __init__(self, canvas):
            self.canvas = canvas
    def type(self, type):
        if type == "1":
            self.if = self.canvas.create_rectangle(0, 0, 50, 50, fill="red")
        elif type == "2":
            self.if = self.canvas.create_rectangle(50, 50, 100, 100, fill="blue")
    def hide(self):
        self.canvas.pack_forget()
        self.canvas.update_idletasks()
        root.update()
    def unhide(self):
        self.canvas.pack()
        self.canvas.update_idletasks()
        root.update()

root = Tk()
frame = Frame(root)
frame.pack()
canvas = Canvas(frame, width=500, height=200)
canvas.pack()
root.update()

a = Box(canvas)
a.type("1")
b = Box(canvas)
b.type("2")

a.unhide()
time.sleep(.5)
a.hide()
time.sleep(1)

b.unhide()
time.sleep(.5)
b.hide()
time.sleep(1)

1 Ответ

3 голосов
/ 22 января 2012

В вашем коде много неправильного или любопытного. Во-первых, вы никогда не должны вызывать sleep в программе, которая имеет цикл обработки событий. Когда вы звоните, вся ваша программа будет зависать. Если вы хотите, чтобы что-то произошло после определенного периода времени, используйте метод after, чтобы запланировать выполнение функции в будущем.

Во-вторых, нет смысла звонить root.update после звонка self.canvas.update_idletasks. Например, предположим, что это каменное правило, которое никогда не следует называть update. Можно позвонить update, если вы знаете последствия этого, но так как вы только учитесь и не знаете, предположите, что это опасно называть. Кроме того, update выполняет ту же работу, что и update_idletasks и более, поэтому, если вы решите вызвать обновление, вызов update_idletasks не требуется.

Что касается вашей реальной проблемы. Похоже, вы хотите создать два отдельных объекта «Box» и хотите скрыть и показать их независимо (?). Однако оба поля представляют собой прямоугольники, которые нарисованы на одном и том же холсте. Когда вы вызываете pack_forget, это влияет на весь холст, поэтому оба этих объекта исчезают, а затем снова появляются.

Не ясно, каково ваше намерение. Если каждый экземпляр «Box» является просто прямоугольником на холсте, вы не хотите использовать pack_forget, потому что это работает с виджетами, а не с объектами холста.

Если вы хотите, чтобы прямоугольники появлялись и исчезали, у вас есть несколько вариантов. Вы можете уничтожать и воссоздавать их каждый раз, или вы можете использовать метод canvas move или coords, чтобы переместить элемент в невидимую часть холста. Вы также можете управлять порядком наложения, чтобы поднять или опустить объект выше или ниже любого или всех других объектов.

Вот краткий пример, который использует способ перемещения предметов за пределы видимой области холста.

from Tkinter import *
import time

class Box:
    def __init__(self, canvas, type):
        self.canvas = canvas
        if type == "1":
            self.rect = canvas.create_rectangle(0, 0, 50, 50, fill="red")
        elif type == "2":
            self.rect = canvas.create_rectangle(50, 50, 100, 100, fill="blue")
        self.coords = canvas.coords(canvas, self.rect)

    def hide(self):
        # remember where this object was
        self.coords = canvas.coords(self.rect)
        # move it to an invisible part of the canvas
        self.canvas.move(self.rect, -1000, -1000)
    def unhide(self):
        # restore it to where it was
        self.canvas.coords(self.rect, *self.coords)

root = Tk()
frame = Frame(root)
frame.pack()
canvas = Canvas(frame, width=500, height=200)
canvas.pack()

a = Box(canvas, type="1")
b = Box(canvas, type="2")

root.after(1000, a.hide)
root.after(2000, a.unhide)
root.after(3000, b.hide)
root.after(4000, b.unhide)

root.mainloop()

Наконец, если вы действительно хотите, чтобы объект непрерывно мигал, вы можете использовать метод hide для автоматического вызова метода unhide и наоборот:

    def hide(self):
        # remember where this object was
        self.coords = canvas.coords(self.rect)
        # move it to an invisible part of the canvas
        self.canvas.move(self.rect, -1000, -1000)
        # unhide after a second
        self.canvas.after(1000, self.unhide)

    def unhide(self):
        # restore it to where it was
        self.canvas.coords(self.rect, *self.coords)
        # re-hide after a second
        self.canvas.after(1000, self.hide)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...