2013-06-21 3 views
2

Я регулярно нахожу себя в диалоговом окне Tk, используя ttk :: entry widgets для запроса имени файла. Я сохраняю последний вход пользователя в таком диалоговом окне и отображаю его как значение по умолчанию при следующем его отображении.Отобразить хвост имени файла в поле ввода

После того, как я заполнил виджет, если полное имя файла больше, чем поле ввода, тогда оно отобразит самые левые несколько символов, которые, как правило, являются менее интересной частью имени файла, и я предпочел бы, чтобы он отображался справа персонажи.

Я обнаружил, что попытка использовать $entryWidget xview сразу не работал очень хорошо - это не сделал ничего, что я предполагаю, был из-за какого-то состояния гонки - так что я принял к написанию

after $N $entryWidget xview moveto 1.0 

Есть ли лучше путь, а если нет, то какой хороший выбор для N? Мне не нравятся магические числа, и, насколько я помню, after 0 не работал должным образом, и after idle.

Вот пример, демонстрирующий проблему

package require Tk 

set ent [ttk::entry .ent] 
pack $ent -fill both -expand yes 

$ent insert end "The quick brown fox jumps over the lazy dog" 
after 1000 $ent xview moveto 1.0 

set btn [ttk::button .btn -text Dismiss -command exit] 
pack $btn -fill both -expand yes 

Без after 1000 в строке 5 (?) Нет ошибок, и никакого эффекта. Если я попробую after 10, эффекта не будет. Если я оставлю after n и сделаю update idletasks; $ent xview moveto 1.0, эффект не будет.

«Без эффекта» означает, что в диалоговом окне отображается «Быстрые коричневые прыжки лисицы», остальная часть строки скрыта. С кодом, как указано выше, он отображает это первоначально, но через секунду (как и ожидалось, действительно, как закодирован) он переключается на отображение «перепрыгивает через ленивую собаку», а остальное скрывается. Это нежелательно для пользователя, чтобы он мог видеть незашифрованный текст, но я не могу решить, как избежать его, кроме как выбрав волшебное число миллисекунд, чтобы подождать.

+0

+1 Увлекательная проблема. Кажется, что не работает ни привязка к '', ни' ''. –

ответ

1

Это очень сложная проблема, гораздо больше, чем кажется на первый взгляд. Проблема заключается в том, что для обработки содержимого довольно много незанятых событий (которые принимают неопределенное, но ненулевое количество времени) для содержания, которое должно быть понято для отображения конца данных, и эта обработка происходит после обычные события, которые вы связываете для такого рода вещей (<Map> и <Configure>).

[EDIT]: Оказывается, что вам нужно сделать, это отложить корректировку на месте просмотра действительно в конце процесса рисования на <Expose> событие, которое когда оконная система запрашивает вещи на самом деле будет отображаться на экране.(Есть сложная серия событий, которые хореографированы, чтобы фактически доставить окно на экран, при этом <Map> будет уведомлять, что окно должно появиться, <Configure> будет уведомлять об изменении размера окна и <Expose> запрос на на самом деле сделать что-то)

set ent [ttk::entry .ent] 
pack $ent -fill both -expand yes 
$ent insert end "The quick brown fox jumps over the lazy dog" 

bind $ent <Expose> { 
    # IMPORTANT! Unregister this event handler! 
    bind %W <Expose> {} 
    # Reposition the view on the content 
    %W xview [%W index end] 
} 

set btn [ttk::button .btn -text "Dismiss" -command exit] 
pack $btn -fill both -expand yes 

хитрым бит, что мы хотим действовать в ответ на только первый<Expose> события, а не каждый (как довольно много доставляется в течение срока службы приложения. есть также встроенный обработчик для этого события на низком уровне реализации приложения, которое фактически выполняет двойной буферизированный чертеж). Это означает, что нам нужно включить отмену регистрации (иначе окно будет «прибито до конца»).

Этот код работает только с содержимым, размещенным до первого появления окна. Чтобы переместить его после этого, вызовите ttk::entry::See $ent end (это то, что использует ttk :: entry binding implementation scripts).

+0

Спасибо Донал. @Glenn Jackman выкопал существующий отчет об ошибке для этого. – nurdglaw

+0

Странно. Это отлично работает, если я копирую и вставляю его в оболочку желаний, но если я сохраню файл и отправлю его из оболочки желания, это не так. Я предполагаю, что это является следствием «довольно много» праздных событий, различающихся в двух случаях. Кажется, мне нужно вернуться к моим магическим номерам. – nurdglaw

+0

@nurdglaw Ugh. Позвольте мне немного поэкспериментировать ... –

1

end является действительным index, так что можно сказать

$entryWidget xview end 

В зависимости, если ваша запись виджет не только для чтения или неактивное состояние, вы можете:

bind $entryWidget <FocusOut> {%W xview end} 

Я удивлен .ent xview end возвращает ошибку. Это работает для меня:

$ tclsh 
% package req Tk 
8.5.10 
% entry .e 
.e 
% pack .e 
% .e conf -textvar foo 
% set foo {qpowieurpoqwyerpiqyweritqywpeityqwpeitrqiweyrioqwter1234} 
qpowieurpoqwyerpiqyweritqywpeityqwpeitrqiweyrioqwter1234 
% .e xview end 

Виджет ввода отображает 1234 в конце.

+0

Спасибо за подсказку 'moveto end'. Я обеспокоен тем, как разумно отображать последний выбор пользователя и как быстро запускать команду '$ entryWidget xview' после того, как я заполнил виджет. Я отредактирую свой вопрос, чтобы уточнить. – nurdglaw

+0

Я только что попробовал 'xview end', но с ошибкой« ожидаемое целое число », но получил« конец ». 'xview mmoveto end' терпит неудачу с' ожидаемым числом с плавающей запятой, но получил «конец» '. Я использую ActiveTcl 8.6.0 на WIndows XP – nurdglaw

+0

Зачем вам нужно откладывать? Почему бы не установить xview сразу после его заполнения? Это странная ошибка, пожалуйста, покажите полную команду, которую вы использовали. –

Смежные вопросы