在输入框中显示文件名的尾部

时间:2013-06-21 08:48:34

标签: tcl tk

我经常发现自己使用ttk :: entry小部件编写Tk对话框来提示输入文件名。我将用户的最后一个输入保存到这样的对话框,并在下次显示时将其显示为默认值。

在我填充小部件之后,如果完整文件名长于输入框,那么它将显示最左边的几个字符,这些字符通常是文件名中不太有趣的部分,我宁愿显示最右边的字符

我发现尝试立即使用$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

第5行(?)没有after 1000没有错误,也没有效果。如果我尝试after 10,则无效。如果我遗漏after n并执行update idletasks; $ent xview moveto 1.0则无效。

“无效”意味着对话框显示“快速棕色狐狸跳跃”,字符串的其余部分被隐藏。使用上面的代码,它最初显示,但在一秒钟之后(正如预期的那样,确实如编码),它会切换到显示“跳过懒狗”,其余的隐藏。用户不希望能够看到未滚动的文本,但除了选择等待的魔术毫秒数之外,我无法弄清楚如何避免它。

2 个答案:

答案 0 :(得分: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。

答案 1 :(得分:1)

这是一个非常棘手的问题,远远超过最初看起来的问题。问题在于它需要处理相当多的空闲事件(这需要一个不确定但非零的时间)才能足够理解内容以显示数据结束,并且此处理发生< em>在之后为这类事件绑定的常见事件(<Map><Configure>)。

[编辑]:事实证明,你需要做的是将调整推迟到绘图过程后期真正的观察位置,到<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用于此目的)。