CombBox中的Tcl / Tk LstBox宽度 [英] Tcl/Tk LstBox width in CombBox
问题描述
如何在组合框中配置列表框组件的宽度,使其适合最长的条目?
小部件宽度本身(入口组件)可以很短,但是我正在寻找一种方法来配置列表框组件以使其比入口更宽...
How can I configure the listbox component width in a combobox, so that it will fit to longest entry? The widget width itself (the entry component) can be short, but I'm looking for a way to configure the listbox component to be wider than the entry...
推荐答案
这是可能的,但并非没有一点黑客;)
This is possible, but not without a bit of hacking ;)
您可以在以下位置找到combobox的实现 combobox.tcl
(在我的情况下为 /usr/share/tcltk/tk8.5/ttk/combobox.tcl
。在那里,您看到是否有组合框
You can find the implementation of combobox in combobox.tcl
(in my case /usr/share/tcltk/tk8.5/ttk/combobox.tcl
. There you see that if you have a combobox
set cb [ttk::combobox .cb -state readonly]
并调用它,它会创建以下内部窗口小部件结构:
and invoke it, it creates the following internal widget structure:
$cb.popdown.f.l
popdown
是单击组合框, f
框架和 l
包含值的实际列表框。要适应最长的条目,您需要修改 popdown
顶层的几何。
popdown
is the toplevel that pops down if you click the combobox, f
a frame, and l
the actual listbox which contains your values. To fit the longest entry you need to modify the geometry of the popdown
toplevel.
我们尝试这样做通过将一个调整大小的脚本绑定到组合框上的 ButtonPress
事件,但是,这不起作用,因为默认情况下,绑定是按以下顺序处理的(输出 puts [bindtags $ cb]
):
We try to do so by binding a resize script to theButtonPress
event on the combobox, however, this does not work because by default the bindings are handled in the following order (output of puts [bindtags $cb]
):
.cb TCombobox . all
所以首先是小部件上的事件( .cb
)被处理,然后是类( TCombobox
)上的事件,然后是顶级事件()。
),最后是绑定到所有小部件的事件。
的意思是,当我们单击组合框时,首先执行了我们的调整大小脚本,但随后确实存在 popdown
顶级,因为它只会被创建在处理类事件时。
So first the events on the widget (.cb
) are handled, then the events on the class (TCombobox
), and then on the toplevel (.
) and finally the events that are bound to all widgets.
What this means is that when we click the combobox, first our resize script is executed, but then the popdown
toplevel does exist yet, because it will only be created when handling the class event.
解决方案是为小部件和类切换事件处理顺序:
The solution is to switch the event handling order for the widget and class:
bindtags $cb [list TCombobox $cb . all]
现在应该可以了!下面是一个最小的概念证明:
Now it should be working! Below a minimal proof of concept:
package require Tk
wm title . "Combobox Listbox resize"
wm geometry . "150x40"
grid columnconfigure . 0 -weight 1
set cb [ttk::combobox .cb -width 20 -state readonly]
grid $cb -row 1 -column 0
set cmd "$cb configure -values {abarsdhresntdaenstdsnthret erstihre reshterhstierht}"
$cb configure -postcommand $cmd
bind $cb <ButtonPress> changeGeomPopdown
bindtags $cb [list TCombobox $cb . all]
proc changeGeomPopdown { } {
global cb
scan [wm geometry $cb.popdown] "%dx%d+%d+%d" w h x y
wm geometry $cb.popdown "300x${h}+${x}+${y}"
}
要获得所需的宽度,您需要询问列表框的字体[1]:
To get the desired width you need to ask for the font of the listbox [1]:
$cb.popdown.f.l cget -font
然后使用在每个字符串上使用 font measure
命令([2])确定适合所有条目的像素。不要忘记添加一些填充以使外观更好,并确保滚动条不会与您的文本重叠。
Then use the font measure
command ([2]) on every string to determine the pixels you need to fit all entries. Don't forget to add a bit of padding to for a better look and to make sure the scrollbar doesn't overlap with your text.
注意:避免使用各种讨厌的东西,请在尝试修改内部小部件结构之前确保其正确, ttk :: combobox
的实现可能会更改,然后您的程序
NB: To avoid all kind of nasty stuff please make sure that this internal widget structure is in place before you try to modify it, the implementation of ttk::combobox
might change and then your program won't work anymore!
[1] http://www.tcl.tk/man/tcl8.5/TkCmd/listbox.htm#M16
[2] http:// www.tcl.tk/man/tcl8.5/TkCmd/font.htm#M10
这篇关于CombBox中的Tcl / Tk LstBox宽度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!