Уведомления

Группа в Telegram: @pythonsu

#1 Май 17, 2011 17:05:26

hea007
От:
Зарегистрирован: 2010-10-22
Сообщения: 4
Репутация: +  0  -
Профиль   Отправить e-mail  

Tkinter - отжать кнопку

А как сделать

ChooseOutDir()
таким, что бы он стал универсальным.
Возврашал
PATH
как параметр, т.е.
statusbar.config(text = dn)
вывести из состава функции



Офлайн

#2 Май 17, 2011 19:39:03

kublo
От:
Зарегистрирован: 2011-04-08
Сообщения: 31
Репутация: +  0  -
Профиль   Отправить e-mail  

Tkinter - отжать кнопку

Как то так ?

from Tkinter import *
import tkFileDialog

PATH = ""

def ChooseOutDir():
global PATH
PATH = tkFileDialog.askdirectory()

def PrintPATH():
statusbar.config(text = PATH)

root = Tk()
Button(text="Open File Dialog", command=ChooseOutDir).pack()
Button(text="Print PATH", command=PrintPATH).pack()
statusbar = Label(text="", bd=1, relief=SUNKEN, anchor=W)
statusbar.pack(side=BOTTOM, fill=X)
root.mainloop()



Офлайн

#3 Сен. 4, 2013 20:11:16

x-ray
Зарегистрирован: 2013-09-04
Сообщения: 9
Репутация: +  0  -
Профиль   Отправить e-mail  

Tkinter - отжать кнопку

А вот такое вам как?

#!/usr/bin/env python32
from tkinter import *
from tkinter.filedialog import askopenfilename
def ChooseFile(event):
a = askopenfilename()
root=Tk()
#простой способ - через параметр "command" - все нормально, кнопка не
#западает, а возвращается после нажатия обратно
outdirbtn=Button(root, text="Open File Dialog", command = askopenfilename)

# нажатием на кнопку правой клавишей мыши - тоже все О.К.
outdirbtn.bind("<Button-3>", ChooseFile)

# через фокус клавишей "Enter" - тоже все О.К.
outdirbtn.bind("<Return>", ChooseFile)

#а вот здесь странное поведение: при нажатии левой клавишей мыши
#кнопка после диалога выбора файла "западает", т.е. не возвращается в верхнее положение
# и остается "нажатой"
outdirbtn.bind("<Button-1>", ChooseFile)

outdirbtn.pack()
root.mainloop()

Кто знает - что это за странное реагирование виджета класса Button в результате разных способов нажатий кнопки?

Отредактировано x-ray (Сен. 4, 2013 20:14:39)

Офлайн

#4 Сен. 4, 2013 21:32:33

4kpt
От: Харьков
Зарегистрирован: 2010-11-03
Сообщения: 998
Репутация: +  63  -
Профиль   Отправить e-mail  

Tkinter - отжать кнопку

Вообще не понял, что Вы этим хотели сказать.
Все правильно работает. Разберитесь в потоке событий. Если хотите, чтобы кнопка “возвращалась” в исходное положение, то измените строку

outdirbtn.bind("<Button-1>", ChooseFile)

на

outdirbtn.bind("<ButtonRelease-1>", ChooseFile)

Можно еще использовать изменения порядка обработки событий добавлением строки

outdirbtn.bindtags(("Button", outdirbtn))

P.S. Эти две строки просто уносят в темные дали…

from tkinter import *
from tkinter.filedialog  import askopenfilename



Отредактировано 4kpt (Сен. 4, 2013 22:17:18)

Офлайн

#5 Сен. 4, 2013 22:39:18

x-ray
Зарегистрирован: 2013-09-04
Сообщения: 9
Репутация: +  0  -
Профиль   Отправить e-mail  

Tkinter - отжать кнопку

Благодарю за ответ! Вариант через <ButtonRelease-1> помог. Если можно - еще несколько вопросов:
1. А что Вас удивило в

from tkinter import *
from tkinter.filedialog  import askopenfilename
если нет хотя бы одной из строк - у меня питон ругается…
если нет первой - NameError: name ‘Tk’ is not defined
если нет второй - NameError: name ‘askopenfilename’ is not defined

2. Почему такое поведение только на левой кнопке мыши? У меня нет подробной спецификации…

Офлайн

#6 Сен. 4, 2013 23:29:21

4kpt
От: Харьков
Зарегистрирован: 2010-11-03
Сообщения: 998
Репутация: +  63  -
Профиль   Отправить e-mail  

Tkinter - отжать кнопку

Исправлю Ваш код.

#!/usr/bin/env python32
#
import tkinter
#
def ChooseFile(): 
	file_ = tkinter.filedialog.askopenfilename()
#
root = tkinter.Tk()
outdirbtn = tkinter.Button(root, text="Open File Dialog", command = ChoiseFile)
outdirbtn.pack()
#
root.mainloop()

У Вас двойное импортирование. Вы импортируете сначала tkinter и все ссылки на объекты добавляете в пространство имен. Потом опять импортируете tkinter и добавляете в пространство имен ссылку на объект askopenfilename. Зачем?

P.S. Старайтесь не использовать инструкцию from tkinter import *. Это приводит к ошибкам, которые трудно отследить и исправить. Ошибки, связанные с замещением ссылок на объекты в одном пространстве имен. Лучше явное указание (см. пример выше).



Отредактировано 4kpt (Сен. 4, 2013 23:32:05)

Офлайн

#7 Сен. 4, 2013 23:47:11

4kpt
От: Харьков
Зарегистрирован: 2010-11-03
Сообщения: 998
Репутация: +  63  -
Профиль   Отправить e-mail  

Tkinter - отжать кнопку

x-ray
2. Почему такое поведение только на левой кнопке мыши? У меня нет подробной спецификации…

Да она и не нужна. Смотрите сами.
Как должна реагировать кнопка на событие нажатия левой клавиши мышки? Правильно - придавиться. А что она должна сделать, когда вы отпустите кнопку мыши? Правильно - отжаться (или принять первоначальное состояние). Опишем эти события:

ButtonPress - 1 : Придавиться
ButtonRelease - 1 : Отжаться

Теперь Ваш случай. Вы вешаете событие ButtonPress - 1 и при его проишествии выполняете свой код. При этом кнопка теряет контроль над потоком событий, так как он переходит к другому виджету (в Вашем случае окну выбора файла). ButtonRelease - 1 происходит уже вне потока событий кнопки так как вы отпускаете кнопку, чтобы перейти к выбору файла. Она о нем ничего не знает, так как одеяло на себя перетянуло окно выбора файла. В новом потоке Вы клацаете любыми клавишами и все эти манипуляции остаются для кнопки неизвестными. Для нее известно только окончание действия события (окончания выбора файла). Формально кнопка никогда так и не узает про событие ButtonRelease - 1. И какое состояние у кнопки после события ButtonPress - 1, которое для нее стало последним. Вот тут мы и получаем состояние – Придавиться –.

P.S. Извините, но сложно пояснить проще. Надеюсь понятно :)



Отредактировано 4kpt (Сен. 5, 2013 00:14:58)

Офлайн

#8 Сен. 5, 2013 20:06:00

x-ray
Зарегистрирован: 2013-09-04
Сообщения: 9
Репутация: +  0  -
Профиль   Отправить e-mail  

Tkinter - отжать кнопку

Еще раз благодарю за объяснение, все достаточно подробно и понятно (Вам бы книги по питону писать). Если можно - еще пара вопросов (как говорится - раз пошла такая пьянка…. )))
- в объяснении указаны 2 события ButtonPress - 1 и ButtonRelease - 1, но вместо ButtonPress-1 я использовал Button-1, но может это и не столь важно..
- и все-таки почему так реагирует только левая кнопка мыши, а с правой (да и с “Enter” тоже) - проблем нет? Ну это так - для расширения кругозора….

Офлайн

#9 Сен. 5, 2013 21:02:10

4kpt
От: Харьков
Зарегистрирован: 2010-11-03
Сообщения: 998
Репутация: +  63  -
Профиль   Отправить e-mail  

Tkinter - отжать кнопку

x-ray
в объяснении указаны 2 события ButtonPress - 1 и ButtonRelease - 1, но вместо ButtonPress-1 я использовал Button-1, но может это и не столь важно.

Не важно. Вы правы. Это просто развернутое название. Можно использовать даже вместо “<ButtonPress - 1>” просто “<1>”, но это плохой тон.

x-ray
- и все-таки почему так реагирует только левая кнопка мыши, а с правой (да и с “Enter” тоже) - проблем нет? Ну это так - для расширения кругозора….

Сейчас расширим :)
Так… На другие клавиши у виджета Button не заложено никаких реакций. Если Вы будете внимательно следить за поведением кнопки при нажатии того-же “Return”, то она никак не реагирует (не придавливается и не отдавливается), т.е. эта реакция не заложена изначально в виджет и он ее возникновение не перехватывает и, соответственно, свой статус не меняет. Перехватчик Вы пишите сами методом bind. Это как написать

outdirbtn.bind("<a>", press)

Событие будет вызвано, функция обработчик будет выполнена, но вот виджет никак не отреагирует.
Фактические реакции виджета можно узнать через механизм command. Для кнопки - это пробел и левая клавиша мышки. Все остальные реакции приходится писать самому. Ручками так сказать.

P.S. У меня был клиент, которому было принципиально, чтобы при нажатии на кнопки при фокусе можно было нажимать “Return” и оно работало. Пришлось писать обертку для bind, которая отслеживала бы события и реагировала на них соответственно. Было достаточно весело :(

P.S.S. Кстати, можно подавить рекацию виджета на любое событие…

P.S.S.S. Я преподаватель :)



Отредактировано 4kpt (Сен. 5, 2013 21:09:51)

Офлайн

#10 Сен. 5, 2013 22:11:24

x-ray
Зарегистрирован: 2013-09-04
Сообщения: 9
Репутация: +  0  -
Профиль   Отправить e-mail  

Tkinter - отжать кнопку

Вот теперь я полностью разобрался, огромное спасибо! Предпочитаю понимать процесс, а не тупо копировать чужие решения….
Ну если я Вас не очень “достал” своими вопросами - по-поводу использования вариантов import tkinter или from tkinter import * - в разных источниках я видел оба способа, причем достаточно известных авторов по питону, например в книге Саммерфилда “Программирование на Python 3” в главах по GUI на питоне используется вариант import tkinter, ну и соотвественно приставка tkinter в коде, а Марк Лутц в “Программирование на Python том-1” предлагается вариант, from tkinter import * , код не загружен приставкой tkinter к классам-объектам. Также и сети - на разных ресурсах используют оба варианта. Как по-вашему - что лучше и почему достаточно известные источники по-разному это делают? Причем способ, где, как Вы говорили, происходит двойное импортирование (с перечислением типа from tkinter.filedialog import askopenfilename) я взял именно у Лутца…

P.S. А насчет клиента - так ведь он реально прав в том случае! Сам предпочитаю работать больше с клавиатурой (быстрее и удобнее), даже немного освоил “слепой” метод. Поэтому не понимаю интерфейсов программ, на которых работают только мышью, очень неудобно! Вот и делаю для себя и друзей оба варианта нажатия на кнопки.

P.S. А ведь никогда раньше не замечал, что Enter-ом кнопка работает но эффекта нажатия нет!

Отредактировано x-ray (Сен. 5, 2013 22:20:25)

Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version