我想用一些文本项填充画布小部件并突出显示这些文本的部分内容(想想在画布的所有文本项中突出显示搜索短语)。
当然,可以将单个文本拆分为突出显示和非突出显示的部分,并为这些部分添加单独的文本项,例如
#!/usr/bin/env wish
proc _drawText {canvas x y text highlighted} {
if {$text != {}} {
set cmd [list $canvas create text $x $y -anchor nw -text $text]
if {$highlighted == "1"} {
lappend cmd -fill red
}
set t [{*}$cmd]
# advance x to the bbox' right side
set x [lindex [$canvas bbox $t] 2]
# adjust x, because the bbox seems to be 1 pixel too wide :(
incr x -1
}
return $x
}
proc addText {canvas x y text {highlightedChars {}}} {
set highlighted "0"
set chars ""
foreach c [split $text {}] h [split $highlightedChars {}] {
if {$h != $highlighted} {
set x [_drawText $canvas $x $y $chars $highlighted]
set highlighted $h
set chars ""
}
append chars $c
}
_drawText $canvas $x $y $chars $highlighted
}
canvas .c
pack .c -expand 1 -fill both
# add "some example text" and highlight the two occurrences of "ex"
addText .c 0 0 \
"some example text" \
"00000110000000110"
这是一种非常有限的方法( - >仅适用于nw
锚定文本,必须手动执行换行等等),所以我想知道是否有更好的方法可以做那。有什么想法吗?
答案 0 :(得分:2)
首先,文本窗口小部件可能更适合您所描述的问题 ,因为它支持更复杂的文本标记。画布仅支持单个项目的单个选定范围,听起来它们不会为您正在进行的更复杂的事情提供大量支持。画布对于文本小部件同样复杂,但是将其复杂性集中在其他地方;要对它们进行复杂的文本显示,你必须做相当多的脚本编写。
但是,您可以相当容易地找出文本的位置。首先,(只要文本没有旋转),您可以忽略锚点和锚定控件,只使用整个边界框。其次,要处理多行文本,你需要知道对齐规则,但实际上只是说如何将每一行水平放置在边界框的子部分中。
第三,由于画布文本项目只有一种字体,因此您可以在font measure
和font metrics
的帮助下轻松完成文本计算。使用font measure
命令可以确定文本在特定字体中的宽度,而不在屏幕上显示(如果文本中没有换行符)。 font metrics
命令可让您找出-linespace
对字体的影响,即行之间应有多少空间,以及-ascent
和-descent
是什么(线的顶部和底部相对于文本的基线)。这些命令调用与Tk用于实际显示文本的完全相同的字体引擎;您不需要对您正在使用的字体的大小和形状进行硬编码。
令人惊讶的是,没有简单的机制将项目索引转换为画布坐标对。