如何在 Tcl/Tk 中自动换行标签中的文本?
How to wrap text in label automatically in Tcl/Tk?
有没有人做过或知道如何自动 [label
] 换行?还是自我智能识别到达每行的末尾,即在边距的边缘,仅限于小部件本身?
代码:
package require Img
# Container
frame .fr -borderwidth 2 -bg white
# Text Variable
set description "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris"
# Thumbnail
image create photo pic -file /home/tc/webvideo/galinha_pitadinha/seu_lobato.jpg
button .fr.bt -relief flat -bg white -image pic
# Description
label .fr.lb -bg white -textvariable description -wraplength 250 -width 30 -justify left
pack .fr .fr.bt .fr.lb -side left -fill x -padx .5c -pady .5c
代码结果:
从程序上讲,我打算让它看起来像这样:
我要断句,还有上面的说明图
请注意,缺少正则表达式来搜索 第二行的末尾 并与末尾的小罐(省略号)结合。当然,隐藏其余文本。
将鼠标悬停在 label
小部件上时将显示所有文本:tooltip
我一直在想两个假设。他们是:
1) 显示文本变量
中"characters"的总量
tk_messageBox -message [string length $description]
2) 显示文本变量
中"words"的总量
tk_messageBox -message [llength $description]
我停在这里:
In this setting of the -wraplength 250
property, I have a variation of 10 words for every two lines.
Based on this, I can apply a condition and put the amount of word or character as a determining factor to only display up to the second line.
# If it were to quantify Characters and not words, this would be
if {[string length $description] < 40} {
pack [label .b -textvariable description -wraplength 250 -width 30 -justify left] -side top -fill x
}
或者比较一定数量的单词,在本例中是 10 个单词。如果为真,则执行正则表达式
的动作
# If it were to quantify words and not characters, this would be
if {[llength $description] <10} {
... RegExp code here ...
}
标签 小部件采用 -wraplength
option。它需要一个环绕宽度来应用任何形式以提供屏幕距离测量(例如,190
为 190 像素,5c
为 5 厘米)。
(很少使用)消息 小部件可以专注于尝试为其包含的文本获得特定的纵横比。
如果您愿意破坏性地更改正在显示的文本,您可以在脚本中进行省略号注入。
pack [label .l -textvar msg]
set msg "Lorem ipsum,\nfoo bar grill whatever to make this long"
proc trimWithEllipsis {msg width font {ellipsis ...}} {
set ew [font measure $font $ellipsis]
set out ""
foreach c [split $msg ""] {
if {[font measure $font $out$c] > $width} {
set oute ""
foreach c2 [split $out ""] {
if {[font measure $font $oute$c2$ellipsis] > $width} {
return $oute$ellipsis
}
append oute $c2
}
# failed to find ellipsis injection point??? keep going normally...
}
append out $c
}
return $msg
}
# How to apply the code
set msgLines {}
foreach line [split $msg "\n"] {
# 200 (pixels) was a good demonstration value on this system
lappend msgLines [trimWithEllipsis $line 200 [.l cget -font]]
}
set msg [join $msgLines "\n"]
我已经与其他 Tk 开发人员谈过话,我们一致认为这类事情应该是核心功能,尤其是因为它也可以很好地应用于其他小部件类型(尤其是条目和列表框).这应该成为核心功能的另一个原因是,这意味着包装的细节不会成为模型的一部分(即变量的内容/-message
属性),而是纯粹是一个视图问题。但它不可能制作 8.6 或更早版本。
我在黎明时编写的代码在我看来是一个可能的解决方案。但是,我还没有测试与 Tk library 相关的编码。我会做测试,以及任何消息,以防成功或失败。我会更新这个答案。
我在这里(在下面的这段代码中)基本上做的是创建一个文件作为指针,从那里我将开始找到我想在标签上显示的两行。按照源代码中包含的注释进行操作:
#!/usr/bin/env tclsh
# Opening a nonexistent file (empty)
set file [open "input.txt" w]
# Writing on it ..
puts $file "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris"
# Close. This saves a few bytes.
close $file
# Opening it again, now let's read.
set file [open "input.txt" r]
# Read me.
set read [read $file]
# Now I need to replace multiple spaces with '+' as a reference for
# we quantify and subsequently break the phrase into the variable at this point (+)
set add [string map -nocase {{ } {+}} $read]
# Just an index, indicator that starts counting the for loop
set count 0
for {set value 0} {$value<10} {incr value} {
# In this variable I will extract line-by-line
set number [lindex $add $count]
# Now I create a list
set data [list]
# It's time to break the text by the '+' signs, saving the result (a list of words) in the data variable
lappend data [split $number +]
# Just an index, indicator that starts counting the while loop
set indice 0
# Loop running until 10 words are exhausted
while {$indice<10} {
# Is this variable , wich show result
# shows us the words the loop went through until the set value ended: 10
set result [lindex $data 0 $indice]
# See them now on screen, detail!
# The variable phrase, which was once a single line, was broken and passed to the list.
# Thus, every word followed by its comma (,) and / or period (.)
# are in a single column, you will need to format them again to be displayed in "a single row"
# We enter the argument "-nonewline" getting all words extracted by on one line
# The space purposely placed in front of the variable "$ result"
# Is required to have space between words again
puts -nonewline "$result "
incr indice
}
incr count
puts ".."
break
}
close $file
结果输出:
打印屏幕
这里值得一提的是,我打包的机器(微机)里有,Tcl 8.4和8.5的包还没有8.6。这是我在 Tcl/Tk.
中的作品编程环境
But I did the code and ran the tests on this online platform, running Tcl 8.6.
我现在的关注点和工作是用 Tk 库调整上面的代码。
我的任务是捕获输出并检索它。全部在运行时。
我多次尝试将 put
命令的输出传递给另一个可以检索新内容的变量。
但不幸的是,我不知道如何成功。因为我是语言编程 Tcl 的新手。
因此,我使用 Shell Script Unix 和 Script Tcl 进行了捕获。查看部分:
这里恢复命令put
的输出:
set txt [exec cat ./output.txt]
此处输出:-textvariable txt
label .fr.lb -bg white -textvariable txt -wraplength 250 -width 30 -justify left
现在将代码放入包装器中 procedure
全部终止对 Tcl 脚本进程的调用并将其传输到 Bourn Shell 脚本,后者又 returns a window 与已经格式化的 label
文本。像这样:
proc test {} {
.. The code ..
put "output some text"
}
# invoke in file end
test
不多说,分析下结论
现在看结构
让我们将 puts
命令的输出重定向到外部文件 output.txt
。
我们必须创建 3 个文件,其中两个是 Tcl,另一个是 Bourne Shell。看:
test.tcl: 脚本 Tcl main
#!/usr/bin/env sh
# \
exec wish "[=11=]" "$@"
package require Img
set txt [exec cat ./output.txt]
# Container
frame .fr -borderwidth 2 -bg white
# Thumbnail
image create photo pic -file thumb.jpg
button .fr.bt -relief flat -bg white -image pic
# Description
label .fr.lb -bg white -textvariable txt -wraplength 250 -width 30 -justify left
# The help texts, as we said, stay in an array:
set subtitle(.fr.lb) [exec cat ./input.txt]
# The frame that will contain the help text itself:
frame .help -bd 1 -bg black
label .help.lab -wraplength 200 -width 30 -text "Texto da subtitle" -bg lightyellow -justify left
pack .help.lab
# Note that we do not materialize the frame as we do not want it to appear now.
# Now comes the most important part. When the mouse cursor enters a button, we should start the process of "Show in the future" the help frame.
bind .fr.lb <Enter> {+
set subtitle(win) %W
.help.lab config -text $subtitle(%W)
set subtitle(id) [after 500 place .help \
-x [expr %x + [winfo x %W]] \
-y [expr %y + [winfo y %W] + 20] ]
}
#
bind .fr.lb <Leave> {+
if [info exists subtitle(id)] {
after cancel $subtitle(id)
unset subtitle(id)
}
place forget .help
}
pack .fr .fr.bt .fr.lb -side left -fill x -padx .5c -pady .5c
test.sh: 调用脚本 test.tcl e 传输命令 put
的输出
#!/usr/bin/env sh
# \
exec tclsh "[=12=]" "$@"
set file [open "input.txt" w]
puts $file "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris"
close $file
proc test {} {
set file [open "input.txt" r]
set read [read $file]
set add [string map -nocase {{ } {+}} $read]
set value 0
for {set value 0} {$value<10} {incr value} {
set number [lindex $add $value]
set data [list]
lappend data [split $number +]
set indice 0
while {$indice<10} {
set result [lindex $data 0 $indice]
puts -nonewline "$result "
incr indice
}
incr value
puts ".."
break
}
close $file
}
# Invoke
test
main.tcl: Insert the out of command put in file output.txt
#!/usr/bin/env sh
# \
exec tclsh "[=13=]" "$@"
exec ./test.sh > ./output.txt
exec ./test.tcl
我不希望代码位于单独的文件中,但它组织得很好。
When using the code with the Tk library, the adaptation has been in parallel development .. which remains in the same way: That, being on the same plane, do not cut each other.
我会留下脚本和图片,以便从我的 Google 云端硬盘帐户下载 - Acess to get!
响应代码太长,因为它包含 tooltip
代码。
打印屏幕:
如果我现在或以后升级代码,我会 post 更改。感谢大家的贡献
有没有人做过或知道如何自动 [label
] 换行?还是自我智能识别到达每行的末尾,即在边距的边缘,仅限于小部件本身?
代码:
package require Img
# Container
frame .fr -borderwidth 2 -bg white
# Text Variable
set description "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris"
# Thumbnail
image create photo pic -file /home/tc/webvideo/galinha_pitadinha/seu_lobato.jpg
button .fr.bt -relief flat -bg white -image pic
# Description
label .fr.lb -bg white -textvariable description -wraplength 250 -width 30 -justify left
pack .fr .fr.bt .fr.lb -side left -fill x -padx .5c -pady .5c
代码结果:
从程序上讲,我打算让它看起来像这样:
我要断句,还有上面的说明图
请注意,缺少正则表达式来搜索 第二行的末尾 并与末尾的小罐(省略号)结合。当然,隐藏其余文本。
将鼠标悬停在 label
小部件上时将显示所有文本:tooltip
我一直在想两个假设。他们是:
1) 显示文本变量
中"characters"的总量tk_messageBox -message [string length $description]
2) 显示文本变量
中"words"的总量tk_messageBox -message [llength $description]
我停在这里:
In this setting of the
-wraplength 250
property, I have a variation of 10 words for every two lines. Based on this, I can apply a condition and put the amount of word or character as a determining factor to only display up to the second line.
# If it were to quantify Characters and not words, this would be
if {[string length $description] < 40} {
pack [label .b -textvariable description -wraplength 250 -width 30 -justify left] -side top -fill x
}
或者比较一定数量的单词,在本例中是 10 个单词。如果为真,则执行正则表达式
的动作 # If it were to quantify words and not characters, this would be
if {[llength $description] <10} {
... RegExp code here ...
}
标签 小部件采用 -wraplength
option。它需要一个环绕宽度来应用任何形式以提供屏幕距离测量(例如,190
为 190 像素,5c
为 5 厘米)。
(很少使用)消息 小部件可以专注于尝试为其包含的文本获得特定的纵横比。
如果您愿意破坏性地更改正在显示的文本,您可以在脚本中进行省略号注入。
pack [label .l -textvar msg]
set msg "Lorem ipsum,\nfoo bar grill whatever to make this long"
proc trimWithEllipsis {msg width font {ellipsis ...}} {
set ew [font measure $font $ellipsis]
set out ""
foreach c [split $msg ""] {
if {[font measure $font $out$c] > $width} {
set oute ""
foreach c2 [split $out ""] {
if {[font measure $font $oute$c2$ellipsis] > $width} {
return $oute$ellipsis
}
append oute $c2
}
# failed to find ellipsis injection point??? keep going normally...
}
append out $c
}
return $msg
}
# How to apply the code
set msgLines {}
foreach line [split $msg "\n"] {
# 200 (pixels) was a good demonstration value on this system
lappend msgLines [trimWithEllipsis $line 200 [.l cget -font]]
}
set msg [join $msgLines "\n"]
我已经与其他 Tk 开发人员谈过话,我们一致认为这类事情应该是核心功能,尤其是因为它也可以很好地应用于其他小部件类型(尤其是条目和列表框).这应该成为核心功能的另一个原因是,这意味着包装的细节不会成为模型的一部分(即变量的内容/-message
属性),而是纯粹是一个视图问题。但它不可能制作 8.6 或更早版本。
我在黎明时编写的代码在我看来是一个可能的解决方案。但是,我还没有测试与 Tk library 相关的编码。我会做测试,以及任何消息,以防成功或失败。我会更新这个答案。
我在这里(在下面的这段代码中)基本上做的是创建一个文件作为指针,从那里我将开始找到我想在标签上显示的两行。按照源代码中包含的注释进行操作:
#!/usr/bin/env tclsh
# Opening a nonexistent file (empty)
set file [open "input.txt" w]
# Writing on it ..
puts $file "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris"
# Close. This saves a few bytes.
close $file
# Opening it again, now let's read.
set file [open "input.txt" r]
# Read me.
set read [read $file]
# Now I need to replace multiple spaces with '+' as a reference for
# we quantify and subsequently break the phrase into the variable at this point (+)
set add [string map -nocase {{ } {+}} $read]
# Just an index, indicator that starts counting the for loop
set count 0
for {set value 0} {$value<10} {incr value} {
# In this variable I will extract line-by-line
set number [lindex $add $count]
# Now I create a list
set data [list]
# It's time to break the text by the '+' signs, saving the result (a list of words) in the data variable
lappend data [split $number +]
# Just an index, indicator that starts counting the while loop
set indice 0
# Loop running until 10 words are exhausted
while {$indice<10} {
# Is this variable , wich show result
# shows us the words the loop went through until the set value ended: 10
set result [lindex $data 0 $indice]
# See them now on screen, detail!
# The variable phrase, which was once a single line, was broken and passed to the list.
# Thus, every word followed by its comma (,) and / or period (.)
# are in a single column, you will need to format them again to be displayed in "a single row"
# We enter the argument "-nonewline" getting all words extracted by on one line
# The space purposely placed in front of the variable "$ result"
# Is required to have space between words again
puts -nonewline "$result "
incr indice
}
incr count
puts ".."
break
}
close $file
结果输出:
打印屏幕
这里值得一提的是,我打包的机器(微机)里有,Tcl 8.4和8.5的包还没有8.6。这是我在 Tcl/Tk.
中的作品编程环境But I did the code and ran the tests on this online platform, running Tcl 8.6.
我现在的关注点和工作是用 Tk 库调整上面的代码。
我的任务是捕获输出并检索它。全部在运行时。
我多次尝试将 put
命令的输出传递给另一个可以检索新内容的变量。
但不幸的是,我不知道如何成功。因为我是语言编程 Tcl 的新手。
因此,我使用 Shell Script Unix 和 Script Tcl 进行了捕获。查看部分:
这里恢复命令
put
的输出:
set txt [exec cat ./output.txt]
此处输出:-textvariable
txt
label .fr.lb -bg white -textvariable txt -wraplength 250 -width 30 -justify left
现在将代码放入包装器中 procedure
全部终止对 Tcl 脚本进程的调用并将其传输到 Bourn Shell 脚本,后者又 returns a window 与已经格式化的 label
文本。像这样:
proc test {} { .. The code .. put "output some text" } # invoke in file end test
不多说,分析下结论
现在看结构
让我们将 puts
命令的输出重定向到外部文件 output.txt
。
我们必须创建 3 个文件,其中两个是 Tcl,另一个是 Bourne Shell。看:
test.tcl: 脚本 Tcl main
#!/usr/bin/env sh
# \
exec wish "[=11=]" "$@"
package require Img
set txt [exec cat ./output.txt]
# Container
frame .fr -borderwidth 2 -bg white
# Thumbnail
image create photo pic -file thumb.jpg
button .fr.bt -relief flat -bg white -image pic
# Description
label .fr.lb -bg white -textvariable txt -wraplength 250 -width 30 -justify left
# The help texts, as we said, stay in an array:
set subtitle(.fr.lb) [exec cat ./input.txt]
# The frame that will contain the help text itself:
frame .help -bd 1 -bg black
label .help.lab -wraplength 200 -width 30 -text "Texto da subtitle" -bg lightyellow -justify left
pack .help.lab
# Note that we do not materialize the frame as we do not want it to appear now.
# Now comes the most important part. When the mouse cursor enters a button, we should start the process of "Show in the future" the help frame.
bind .fr.lb <Enter> {+
set subtitle(win) %W
.help.lab config -text $subtitle(%W)
set subtitle(id) [after 500 place .help \
-x [expr %x + [winfo x %W]] \
-y [expr %y + [winfo y %W] + 20] ]
}
#
bind .fr.lb <Leave> {+
if [info exists subtitle(id)] {
after cancel $subtitle(id)
unset subtitle(id)
}
place forget .help
}
pack .fr .fr.bt .fr.lb -side left -fill x -padx .5c -pady .5c
test.sh: 调用脚本 test.tcl e 传输命令 put
的输出#!/usr/bin/env sh
# \
exec tclsh "[=12=]" "$@"
set file [open "input.txt" w]
puts $file "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris"
close $file
proc test {} {
set file [open "input.txt" r]
set read [read $file]
set add [string map -nocase {{ } {+}} $read]
set value 0
for {set value 0} {$value<10} {incr value} {
set number [lindex $add $value]
set data [list]
lappend data [split $number +]
set indice 0
while {$indice<10} {
set result [lindex $data 0 $indice]
puts -nonewline "$result "
incr indice
}
incr value
puts ".."
break
}
close $file
}
# Invoke
test
main.tcl: Insert the out of command put in file output.txt
#!/usr/bin/env sh
# \
exec tclsh "[=13=]" "$@"
exec ./test.sh > ./output.txt
exec ./test.tcl
我不希望代码位于单独的文件中,但它组织得很好。
When using the code with the Tk library, the adaptation has been in parallel development .. which remains in the same way: That, being on the same plane, do not cut each other.
我会留下脚本和图片,以便从我的 Google 云端硬盘帐户下载 - Acess to get!
响应代码太长,因为它包含 tooltip
代码。
打印屏幕:
如果我现在或以后升级代码,我会 post 更改。感谢大家的贡献