Есть ли способ захватить событие из виджета сфокусированного текста, прежде чем оно попадет в виджет? ⇐ Python

Программы на Python
Anonymous
Есть ли способ захватить событие из виджета сфокусированного текста, прежде чем оно попадет в виджет?

Сообщение Anonymous »

ПРОБЛЕМА:
Использование Python 2.7 Tkinter. У меня есть виджет «Текст с возможностью прокрутки в одном фрейме и холст с возможностью прокрутки в другом фрейме.
Я включил выделение текста в Текстовый виджет, но без ввода текста. Виджет «Текст» прекрасно прокручивается, если выделен текст (

Код: Выделить всё

TextВиджет 
находится в фокусе) или другие виджеты в фокусе.
Проблема заключается в том, что когда текст выделен, виджет «Текст» имеет фокус и захватывает < MouseWheel> и применяет Event к виджету Text в дополнение к виджету Canvas, который должен прокручиваться. Захват события с помощью виджетов с фокусом является неотъемлемым поведением Python 2.
(Обратите внимание: для краткости следующие фрагменты кода не включают стандартный код Tkinter, такой как привязка виджетов к сетке, как это есть это не часть вопроса.)

Код: Выделить всё

import Tkinter as tk

class MouseWheelConf:

# Note passing the widget and the scrollbar to these routines
# is to allow use of this convenience class for both widgets

def _on_mouse_wheel(self, event, widget, scrollbar):
#### Scroll the provided widget & scrollbar using Mousewheel event ####

def _bind_mouse_wheel(self, event, widget, scrollbar):
# Bind scrolling to Mousewheel event:
self.bind_all('',
lambda e: self._on_mouse_wheel(e, widget, scrollbar))

def _unbind_mouse_wheel(self):
# Unbind scrolling from Mousewheel event:
self.unbind_all('')

class ScrollableText(MouseWheelConf):
def __init__(self, master=None, text_conf={}, frame_conf={}):
# Initialize scrolling Text frame:
tk.Frame.__init__(self, master, **frame_conf)
self.text = tk.Text(self, **text_conf)

# Set up scrolling:
self.scrollbar = tk.Scrollbar(
self, orient='vertical',
command=lambda *e: self.text.yview(*e))
self.scrollbar.pack(side='right', fill='y')
self.text.config(yscrollcommand=lambda *e: self.scrollbar.set(*e))

# Apply scroll on enter and remove it when leave:
self.bind(
'',
lambda e: self._bind_mouse_wheel(e, self.text, self.scrollbar))
self.bind('', lambda e: self._unbind_mouse_wheel(e))

#### Grid all widgets here ####

class ScrollableCanvas(MouseWheelConf):
def __init__(self, master=None, canvas_conf={}, frame_conf={}, canvasframe_conf={}):
#### Standard scrolling canvas code goes here ####

Примечание. В Python 3 этой проблемы нет, но этот код работает в Python 3.
ВРЕМЕННОЕ РЕШЕНИЕ:
В настоящее время можно добавить копию тега sel (

Код: Выделить всё

sel_copy
), чтобы применить к выбранным границам текста в виджета «Текст», а затем, когда виджет «Текст», применить фокус к мастер виджета «Текст» () и немедленно применить тег sel_copy к выделенному тексту (теряя выделенные области текста).

Код: Выделить всё

class MouseWheelConf:
#### PRIOR CODE GOES HERE ####

# Only change is to unbind method:
def _unbind_mouse_wheel(self, event, widget):
#### PRIOR CODE GOES HERE ####

# Change focus to Text master on Leave event:
if 'text' in widget._name:
# If Text is focused on Leave, change focus to Frame (master)
# (this removes 'sel' tag from Text widget!)
if self.focus_get() == widget:
widget.master.focus()

class ScrollableText(MouseWheelConf):
def __init__(self, master=None, text_conf={}, frame_conf={}):
#### PRIOR CODE GOES HERE ####

# Change the Leave binding to include the widget:
self.bind(
'',
lambda e: self._unbind_mouse_wheel(e, self.text))

# Workaround:
self._create_sel_copy()
self.text.bind(
'', lambda e: self._apply_sel_copy(self.text, e))
self.bind('', lambda e: self._remove_sel_copy(self.text, e))
self.text.bind(
'', lambda e: self._remove_sel_copy(self.text, e))

def _create_sel_copy(self):
#### Create copy of sel tag named 'sel_copy' here ####

def _apply_sel_copy(self, widget, *event):
# Apply sel tag copy copy when sel removed:
if widget.tag_ranges("sel"):
widget.tag_add("sel_copy", *widget.tag_ranges("sel"))

def _remove_sel_copy(self, widget, *event):
# Remove sel tag copy manually:
widget.tag_remove("sel_copy", '1.0', 'end')

ВОПРОС:
Есть ли лучший способ сделать это ? Могу ли я перехватить событие до того, как оно достигнет выделенного виджета «Текст»? Или это лучшее, что я могу сделать, — подражать тому поведению, которого я хочу?

Подробнее здесь: https://stackoverflow.com/questions/790 ... s-to-widge

Вернуться в «Python»