Уведомления

Группа в Telegram: @pythonsu

#1 Авг. 9, 2015 16:08:05

vanvanov
Зарегистрирован: 2013-03-31
Сообщения: 252
Репутация: +  4  -
Профиль   Отправить e-mail  

Tkinter и выход из цикла

Привет всем.

Есть код, отслеживающий буфер обмена. Реализован так (образец):

#!/usr/bin/python3
import tkinter as tk
import sys
from time import sleep
lev_crit='CRITICAL'
def log(func='MAIN',lev_crit='CRITICAL',cur_mes='Сообщение'):
	print(func,':',lev_crit,':',cur_mes)
def clipboard_copy(line='Сообщение'):
	root.clipboard_clear()
	root.clipboard_append(line)
def clipboard_paste():
	return root.clipboard_get()
	
def watch_clipboard():
	cur_func=sys._getframe().f_code.co_name
	root.withdraw()
	old_clipboard=clipboard_paste()
	while True:
		log(cur_func,lev_crit,'Ожидание изменения буфера...')
		sleep(1)
		new_clipboard=clipboard_paste()
		log(cur_func,lev_crit,'Новый буфер: "%s"' % str(new_clipboard))
		if old_clipboard!=new_clipboard:
			root.deiconify()
			break
root=tk.Tk()
#clipboard_copy('lamer')
watch_clipboard()
root.mainloop()
Почему, если раскомментировать clipboard_copy, выхода из цикла не происходит, а Tkinter считает, что буфер обмена не изменен?

P.S. Я слышал, что time.sleep() лучше не использовать в циклах с tkinter, но комментирование sleep проблему не решает. Версия Python: 3.4.2.

Отредактировано vanvanov (Авг. 9, 2015 16:08:57)

Офлайн

#2 Авг. 9, 2015 17:48:02

4kpt_III
Зарегистрирован: 2014-12-22
Сообщения: 999
Репутация: +  39  -
Профиль   Отправить e-mail  

Tkinter и выход из цикла

Ожидание нужно запускать через .after().

Офлайн

#3 Авг. 9, 2015 23:08:08

vanvanov
Зарегистрирован: 2013-03-31
Сообщения: 252
Репутация: +  4  -
Профиль   Отправить e-mail  

Tkinter и выход из цикла

4kpt_III
Ожидание нужно запускать через .after().
Как оказывается, в процедуру получения буфера надо вставить root.update(). after() тут имхо ни при чем (см. мое замечание про sleep).

Офлайн

#4 Авг. 9, 2015 23:54:03

JOHN_16
От: Россия, Петропавловск-Камчатск
Зарегистрирован: 2010-03-22
Сообщения: 3292
Репутация: +  221  -
Профиль   Отправить e-mail  

Tkinter и выход из цикла

vanvanov
надо вставить root.update()
ОС linux ? Если да, то есть некоторая вероятность что на Windows работать не будет. Как то напарывался вот на такое поведение.



_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com

Офлайн

#5 Авг. 10, 2015 14:29:50

4kpt_III
Зарегистрирован: 2014-12-22
Сообщения: 999
Репутация: +  39  -
Профиль   Отправить e-mail  

Tkinter и выход из цикла

vanvanov
.update() нужно делать везде, где происходит обновление. Это даже не обсуждается.
.update_idletask() - везде, где необходимы точные размеры виджетов, которые явно не задавались.
.after() - это механизм отложенного ожидания. Его можно повесить рекурсивно на какую-то функцию и она будет вызываться с каким-то интервалом. Это правильный подход. sleep() - блокирующая функция - это неправильный подход. И я не говорил, что он “причем” к Вашей проблеме. Я не пользуюсь 3.Х поэтому повторить Ваш код не смогу, в результате сделал очевидное для меня замечание. Вот такие вот дела…

Отредактировано 4kpt_III (Авг. 10, 2015 14:30:25)

Офлайн

#6 Авг. 10, 2015 14:31:29

4kpt_III
Зарегистрирован: 2014-12-22
Сообщения: 999
Репутация: +  39  -
Профиль   Отправить e-mail  

Tkinter и выход из цикла

JOHN_16
На винде должно работать. Ну на ХР точно работает, про остальные не знаю.

Офлайн

#7 Авг. 10, 2015 14:48:52

vanvanov
Зарегистрирован: 2013-03-31
Сообщения: 252
Репутация: +  4  -
Профиль   Отправить e-mail  

Tkinter и выход из цикла

4kpt_III
vanvanov.update() нужно делать везде, где происходит обновление. Это даже не обсуждается.
Спасибо за разъяснение. Я просто не знал, что копирование в буфер считается обновлением.

Офлайн

#8 Авг. 10, 2015 15:16:08

vanvanov
Зарегистрирован: 2013-03-31
Сообщения: 252
Репутация: +  4  -
Профиль   Отправить e-mail  

Tkinter и выход из цикла

JOHN_16
ОС linux ? Если да, то есть некоторая вероятность что на Windows работать не будет. Как то напарывался вот на такое поведение.
Сегодня потестил на винде, работает. Кстати, если Вы программируете под Windows, можете объяснить, почему этот код не работает как нужно:
#!/usr/bin/python3
import tkinter as tk
text=[]
for i in range(100):
	text.append('Sample text here %d' % i)
text='\n'.join(text)
root=tk.Tk()
root.geometry('640x480')
frame=tk.Frame(root)
frame.pack(expand=1,fill='both')
scrollbar=tk.Scrollbar(frame,jump=1)
scrollbar.pack(side='right',fill='y')
txt=tk.Text(frame,wrap='word',yscrollcommand=scrollbar.set)
txt.pack(expand=1,fill='both')
scrollbar.config(command=txt.yview)
txt.insert('1.0',text)
txt.focus_set()
root.mainloop()
Вопрос конкретно про параметр jump=1. При jump=0 прокрутка скроллбара должна быть плавной, при jump=1 скроллбар должен прокручиваться только после того, как пользователь отпустил левую кнопку мыши. На Linux работает так, как задумано, на Windows - работает плавно, как будто jump=0. На Windows Python 3.3.5.

Офлайн

#9 Авг. 10, 2015 19:46:08

4kpt_III
Зарегистрирован: 2014-12-22
Сообщения: 999
Репутация: +  39  -
Профиль   Отправить e-mail  

Tkinter и выход из цикла

vanvanov
Интерфейсы и реализация tcl/tk могут просто не совпадать для этих двух систем. Если присмотреться, то в tkinter существует много команд, которые выполняются на nix и никак не повторяются на windows. При этом существует также набор команд, которые аналогичным образом отрабатываю на windows и не имеют никаких аналогов на nix. Поэтому ожидать 100% повторения поведения не приходится…

Отредактировано 4kpt_III (Авг. 10, 2015 22:11:26)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version