gyn

Win32下的Perl,无用的select,停滞的Tk,结束吧....

Tk实现带line number的text

关于 text 这个组件,说起来简单,其实却是又相当复杂,今天我从一个带 linum text 出发,管中窥豹,以期抛砖引玉。

使用 emacs 的大多会安装行号显示,便于 debug 时的定位,比较常用的便是 linum.el 。这里的 linum line number 的意思。现在我们来实现这种效果,以达到当发生输入、粘贴、删除或者退格事件时,左侧行号自动匹配实际文本行数。

linum.PNG

首先需要设置行号的显示方式,这是最基础但却是很重要的一个决定。倘若是在单 text 组件中使用 tag 实现 linum ,那么有两个问题。第一,无法保证 linum 的只读状态;第二,复制时会包含行号,大多数情况下这是多余的。这里我选择了两个组件的粘合,事实上是将两个 text 拼在一起,当然也可以使用 entry 或者 canvas ,只是前者比较方便,容易保持代码的一致性。在此之前,最好设置一个用于记录最后行号值的变量 linum ,初始化为 1

package require Tk

 

set linum 1

 

frame .f

text .f.linum -width 1 -bg gray -bd 0

.f.linum insert end "1"

.f.linum configure -state disable

text .f.content -bd 0

 

pack .f.linum -side left -expand 1 -fill y

pack .f.content -side left -expand 1 -fill both

pack .f

我们得到了如下图片显示的记事本,当然目前它还不能正常添加或删除行号,需要定义并绑定一系列过程。另外,随着行号的增加,应该相应设置左侧灰带的宽度来正常显示行号。

tk_linum_1.png

无论是因为何种文本编辑操作使得文本行数发生改变,在改变行号之前,我们都必须得到文本行的数量。这里有几种办法,比如 count 或者 index ,我们使用后者,顺便对 index 进行介绍。

proc linum {w} {

    return [expr int([$w index "end - 1c"])]

}

此处的 index 是“ end – 1c ”,表示文本的最后的前一个位置。事实上,这就是文本的实际最后位置,只不过因为 end 被定义为“ the character just after the last newline ”,一个不存在字符,所以必须在 end 的位置处再向前减去一个 character ,可以简写为“ - 1c ”。同样的,如果要得到待插入行的最后一个字符的位置,应使用“ insert lineend ”;向前一个字符就是“ insert lineend – 1c ”,如此类推。

现在要切实做一些绑定了,一般地我们使用回车和退格来进行换行,其中回车是必然转换为一个换行符的,而退格则在遇到换行符时才会通过一系列的操作实现换行。还是应该提一下,通过 ascii 码我们可以看到回车并不是换行,换行的码值是 10 ,而回车是 13 ,所以需要转换;而退格换行的行为,在实际中行数并不会立即发生变化,在退格时先增加一个退格符,再将该退格符连同上一个换行符一起删除。需要注意的是,文本永远在其最后保留一个换行符。

明白了这个细节,接下来的事情就好办了。由于我们还需要响应长按的情况,所以必须绑定是 KeyPress 过程,但无论是 KeyPress 还是 KeyRelease ,当遇到换行时 text 都会在之后做做一些以上描述的小手脚,所以真正的绑定处理过程必须发生在这些小手脚完成之后。这是一个矛盾,但并非不可调和。

after idle incrLinum

在绑定中,使用“ after idle ”的小技巧便可以轻松应对。它让 text 先干完想干的,一旦空下来就立即执行真正的处理过程。

除了回车和退格,还应该增加对一些常用的比如粘贴或删除操作的支持。对于粘贴,通常的快捷键是“ ctrl v ”,对应的事件是“ <Control-Key-v> ”,当然也可以是如 emacs 中的“ ctrl y ”。使用以下的形式可以方便地增加对事件的支持。

foreach keysum {

    <KeyPress-Return>

    <Control-Key-v>

} {

    bind .f.content $keysum {

after idle incrLinum

    }

}

点击下载代码 另外,添加比如语法着色也并非难事,只是肯定会相当复杂,以后再说了。

posted on 2009-05-02 07:45 gyn_tadao 阅读(681) 评论(0)  编辑 收藏 引用 所属分类: TclTk

只有注册用户登录后才能发表评论。
<2006年4月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

导航

统计

常用链接

留言簿(15)

随笔分类(126)

随笔档案(108)

相册

搜索

最新评论

阅读排行榜

评论排行榜