Найти - Пользователи
Полная версия: Tkinter, toplevel и потоки ЧЯДНТ?
Начало » GUI » Tkinter, toplevel и потоки ЧЯДНТ?
1 2
somaniac
Доброго времени суток!
Хочу сделать в приложении всплывающее окно с полем ввода. Приведенный ниже код работает, но есть одна неприятная особенность - при открытии toplevel-окна в совершенно произвольные моменты происходит подвисание программы. Открывается пустое окно у которого в заголовке написан числовой идентификатор и все вешается наглухо. Загрузка процессора не меняется. Использую ActiveState Python 2.5. Глюк проверялся на нескольких компах и везде проявляется одинаково. Что я делаю не так?

class EntryForm():
'''Форма ввода'''
def __init__(self, root = None, pict=''):
self.tl = Toplevel()
self.tl.title("Tst")
self._entry_val = ''
self.frame = Frame(self.tl)
self.frame.pack()
self.label = Label(self.tl, text="Ввод:", fg="red")
self.label.pack(side=TOP)
self.entry = Entry(self.tl)
self.entry.focus_set()
self.entry.pack(side = TOP)
self.entry.bind("<Return>", self.onEnter)

def onEnter(self, event):
'''Процедура вызываемая на
нажатие Enter в поле entry формы'''
self._entry_val = self.entry.get()
if self._entry_val == '':
self._entry_val = 'empty'
self.tl.destroy()
return self._entry_val

def getEntryVal(self):
'''Возвращает символы введенные
в поле entry формы'''
return self._entry_val

if __name__ == '__main__':

class App(Tk):
def __init__(self):
Tk.__init__(self)
self.btn = Button(self, text = "Нажми меня!")
self.btn.bind("<ButtonPress-1>", self.start)
self.btn.pack(side = TOP)

def visio(self):
self.tl = EntryForm()

def prepareThr(self):
print "prepareThr() begin"
for i in xrange(10):
self.visio()
txt = ''
while 1:
txt = self.tl.getEntryVal()
if txt != '':
break
time.sleep(0.1)
print txt
#del(self.tl)
print "prepareThr() end"

def start(self, event):
print "start() begin"
thr = threading.Thread(target = self.prepareThr, name = "thr").start()
print "start() end"

t = App()
t.mainloop()
somaniac
неужели никто не сталкивался с подобным?
igor.kaist
А что программа должна делать?
Данные между потоками лучше передавать через queue
DHT
Чтобы не подвисало нужно отобразить Toplevel с его виджетами до того как туда начнут добавлять данные потоки.
somaniac
Ну так проблема в том, что подвисания происходят случайным образом и даже в том случае если я просто создаю подряд несколько топлевел-окон и не дожидаюсь результатов ввода. Если же я заранее создаю окно и делаю ему withdraw, а потом в нужный момент вызываю deiconify, то подвисание происходит гарантированно на вызове deiconify
somaniac
igor.kaist
А что программа должна делать?
Данные между потоками лучше передавать через queue
Программа в потоке занимается довольно долгим перелопачиванием данных, но в некоторые моменты нужно скорректировать этот процесс вводом вариантов в сплывающем окне. т.е. практически вся функциональность всплывающего топлевел-окна описана в вышеприведенном примере
Griffon
Вообще не понятно что ссылается на первый созданный класс, после того как вы создали второй.
И не в этом ли проблема? Не знаю как ведёт себя питон в таком случае при созданном окне. Но если окно уничтожить, то скорее всего класс удалится сборщиком мусора. И соответственно произойдёт зацикливание в потоке. Или оба закроются по вводу во вторую форму.
Вот такое неуверенное предположение.

Может быть и зависания где-то на этом стыке?
somaniac
Griffon
Вообще не понятно что ссылается на первый созданный класс, после того как вы создали второй.
И не в этом ли проблема? Не знаю как ведёт себя питон в таком случае при созданном окне. Но если окно уничтожить, то скорее всего класс удалится сборщиком мусора. И соответственно произойдёт зацикливание в потоке. Или оба закроются по вводу во вторую форму.
Вот такое неуверенное предположение.

Может быть и зависания где-то на этом стыке?
Если выполнять del(self.tl) (в примере закомментирован), то поведение не меняется. И еще вызывает удивление тот момент, что если я вызываю deiconify для заранее созданного окна в основном классе, то без потока все работает замечательно, а вот если это сделать в потоке, то гарантированный “висяк”
Griffon
Так может в этом удалении и проблема? Стоит попробовать хранить ссылки на созданные классы в списке.
self.tl +=
В начале потока определять длину и проверять self.tl.ххххххх. В конце потока удалить из списка.

Или просто tl без self. :)

А вообще если это окно будет вызываться программой автоматически, то может такое получится что вылитит сразу десяток окон, а если юзер отойдёт от машины то вообще хана. То есть надо контролировать что бы окно всегда было одно, а необходимые события добавлялись в очередь.
somaniac
Griffon
Так может в этом удалении и проблема? Стоит попробовать хранить ссылки на созданные классы в списке.
self.tl +=
В начале потока определять длину и проверять self.tl.ххххххх. В конце потока удалить из списка.

Или просто tl без self. :)

А вообще если это окно будет вызываться программой автоматически, то может такое получится что вылитит сразу десяток окон, а если юзер отойдёт от машины то вообще хана. То есть надо контролировать что бы окно всегда было одно, а необходимые события добавлялись в очередь.
Я попробую, но кажется все же, что проблема не в этом, иногда подвисание происходит при создании первого окна (при вызове в prepareThr self.visio()).
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB