Найти - Пользователи
Полная версия: Tkinter виджет Text "выбрать все"
Начало » GUI » Tkinter виджет Text "выбрать все"
1 2 3
moskitos80
Всем доброго времени суток. При изучении библиотеки tkinter (Python 3*) столкнулся с непонятным мне поведением.
Первое, когда я пытался реализовать функционал “выбрать все” по нажатию клавиш Ctrl+a:

from tkinter import *
root = Tk()
text = Text(root)
text.pack(expand=YES, fill=BOTH)
def select_all(e):
    e.widget.tag_add(SEL, '1.0', END)
text.bind('<Control-a>', select_all)
root.mainloop()

Первая же ссылка впоиске гугла по запросу: http://stackoverflow.com/questions/5870561/re-binding-select-all-in-text-widget
где из второго ответа я понял что нужно либо использовать …bind_class но это не есть гуд т.к. определит поведение для всех виджетов класса; либо можно вернуть из обработчика события строку ‘break’ я сделал второе и о чудо - оно заработало:

from tkinter import *
root = Tk()
text = Text(root)
text.pack(expand=YES, fill=BOTH)
def select_all(e):
    e.widget.tag_add(SEL, '1.0', END)
    return 'break'    # ЭТО ДАЛО НУЖНЫЙ ЭФФЕКТ!
text.bind('<Control-a>', select_all)
root.mainloop()

Второе, когда я делал поиск слова по виджету Text у меня получались странные глюки при находжении нужного слова оно должно выделиться и если оно за пределами экрана должна произвестись прокрутка. Но это происходило через раз! Я решил ради интереса добавить в обработчик return ‘break’ - и оно заработало!

from tkinter import *
from tkinter.simpledialog import *

root = Tk()
text = Text(root)
text.pack(expand=YES, fill=BOTH)
def find_text(e):
    target = askstring('Find text', 'Search String?')
    if target:
        where = e.widget.search(target, INSERT, END)
        if where:
            print(where)
            pastit = where + ('+%dc' % len(target))
            e.widget.tag_remove(SEL, '1.0', END)
            e.widget.tag_add(SEL, where, pastit)
            e.widget.mark_set(INSERT, pastit)
            e.widget.see(INSERT)
            e.widget.focus()
    return 'break'    # РЕШИЛО ПРОБЛЕМУ!!!
text.bind('<Control-f>', find_text)
root.mainloop()

Там же на stackoverflow была приведена ссылка: http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm где поясняются какие то моменты при работе с событиями, и поиск по странице по слову ‘break’ указал мне на нужный параграф. Там даже примеры кода даются. Но у меня не очень хорошо с английским и я как не бился не смог понять толком о чём там говорится. Объясните пожалуйста, кто “в теме” что тут вообще происходит? Почему return ‘break’ - решило обе проблемы?
4kpt_III
Кучу лет уже работаю с tkinter, но никогда такого не видел. Попробуйте просто вернуть None или приведите полный код, чтобы можно было протестировать.

moskitos80
Первое, когда я пытался реализовать функционал “выбрать все” по нажатию клавиш Ctrl+a:

Приведите код и что было не так. Очень и очень сумбурно.

P.S. У меня никаких проблем с выделением не было. Правда я не маркировал текст тегами (не было таких задач). Такой подход к обработке события мне кажется сомнительным, если честно… Понятие “всплывание” события здесь хоть и есть, но не такой как в jquery.
terabayt
4kpt_III
или приведите полный код, чтобы можно было протестировать
from Tkinter import *
root = Tk()
text = Text(root)
text.pack(expand=YES, fill=BOTH)
def find_text(e):
    target = "a" # текст который нужно найти
    if target:
        where = e.widget.search(target, INSERT, END)
        if where:
            print(where)
            pastit = where + ('+%dc' % len(target))
            e.widget.tag_remove(SEL, '1.0', END)
            e.widget.tag_add(SEL, where, pastit)
            e.widget.mark_set(INSERT, pastit)
            e.widget.see(INSERT)
            e.widget.focus()
    return 'break'    # РЕШИЛО ПРОБЛЕМУ!!!
text.bind('<Control-f>', find_text)
root.mainloop()
вот пример
http://dmych.org/post/1351354709
moskitos80
4kpt_III
Кучу лет уже работаю с tkinter, но никогда такого не видел. Попробуйте просто вернуть None или приведите полный код, чтобы можно было протестировать.

Я же привел примеры кода. Можно запустить и проверить. Вот это не работает:

from tkinter import *
root = Tk()
text = Text(root)
text.pack(expand=YES, fill=BOTH)
def select_all(e):
    e.widget.tag_add(SEL, '1.0', END)
text.bind('<Control-a>', select_all)
root.mainloop()

А вот так работает (я привел комментарий там где добавил код):

from tkinter import *
root = Tk()
text = Text(root)
text.pack(expand=YES, fill=BOTH)
def select_all(e):
    e.widget.tag_add(SEL, '1.0', END)
    return 'break'    # ЭТО ДАЛО НУЖНЫЙ ЭФФЕКТ!
text.bind('<Control-a>', select_all)
root.mainloop()
4kpt_III
Все правильно работает…

break не нужен

P.S. Подсказка. Поменяйте <Control-a> на <Control-m>…

P.S.S. Тут имеет место дележка вызванного события.
moskitos80
4kpt_III
P.S.S. Тут имеет место дележка вызванного события.
Вот! Вот про это можно по подробнее? Именно этот момент я смутно представляю себе и хочу разобраться. Я предполагал, точнее все что я смог понять со своим плохим английским на иностранных сайтах это то, что после моего обработчика вызываются какие то еще обработчики. Но я же не вешал больше ни каких обработчиков. Делаю вывод, что библиотека вызывает какие то свои обработчики т.н. действия по-умолчанию, а возвращение строки ‘break’ предотвращает их выполнение. Но что это за обработчики по умолчанию? И для чего они нужны? Зачем они сделаны? Можно пожалуйста подробнее рассказать?
4kpt_III
Объясню. Но с одним условием. Никогда больше вы не будете использовать конструкцию

from tkinter import*

Договорились?
moskitos80
4kpt_III
Никогда больше вы не будете использовать конструкцию… Договорились?
Без проблем. Я её использую только в учебных целях. Я представляю все плюсы и минусы этой конструкции. В реальном коде я себе такого не позволю
4kpt_III
Тогда держите. Этот код ответит Вам на все вопросы.

import Tkinter
#
root = Tkinter.Tk()
#
#
def call(who):
    print who
#
but = Tkinter.Button(root, text="ops", width=30, height=3)
but.bind("<Button-1>", lambda e: call("but"))
but.pack()
root.bind_class("Button", "<Button-1>", lambda e: call("class"))
root.bind("<Button-1>", lambda e: call("root"))
root.bind_all("<Button-1>", lambda e: call("all"))
#
root.mainloop()
moskitos80
Да-да этот код я понимаю. В вашем примере на одно событие явно “повешено” несколько обработчиков и событие “всплывает” через них всех. Но в моей то ситуации:

import tkinter as tk
#
root = tk.Tk()
text = tk.Text(root)
text.pack(expand=tk.YES, fill=tk.BOTH)
#
def select_all(e):
    e.widget.tag_add(tk.SEL, '1.0', tk.END)
#
text.bind('<Control-a>', select_all)
root.mainloop()

на событие <Control-a> “повешен” только один, мой обработчик!? А почему тогда происходит вызов каких то еще обработчиков?
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