Python tkinter 使用箭头键同时滚动两个 TEXT 组件

0 投票
1 回答
1238 浏览
提问于 2025-04-18 14:39

我正在制作一个图形用户界面(GUI),里面有两个文本框。(其实里面还有很多其他东西,但为了这个问题,我们就只讨论这两个文本框。)我想要实现的是,当我用箭头键滚动一个文本框的时候,另一个文本框也能同时滚动。我已经通过滚动条实现了这个功能(代码里没有显示滚动条),但用箭头键却没能做到。我希望两个文本框在使用箭头键时能有正常的行为。也就是说,当我滚动到可见文本的底部时,它会继续向下滚动,但如果我向上滚动,文本不会移动,只是光标会移动。就像任何普通的文本编辑器一样。那么,我该怎么实现这个功能呢?下面是我的代码片段。

#create Text widgets

descriptionTextField = Text(mainframe, width=40, height=10)
descriptionTextField.grid(column=2, row=5, sticky=(W))
descriptionTextField.bind("<Down>", OnEntryDown)
descriptionTextField.bind("<Up>", OnEntryUp)

pnTextField = Text(mainframe, width=40, height=10)
pnTextField.grid(column=3, row=5, sticky=(W))
pnTextField.bind("<Down>", OnEntryDown)
pnTextField.bind("<Up>", OnEntryUp)

#here are what I have for code that **DOESN'T** do what I want.
def OnEntryDown(event):
    descriptionTextField.yview_scroll(1,"units")
    pnTextField.yview_scroll(1,"units")

def OnEntryUp(event):
    descriptionTextField.yview_scroll(-1,"units")
    pnTextField.yview_scroll(-1,"units")

必须有一种方法可以判断下一个箭头键的动作是否会超过可见区域(在这个例子中是10),然后再进行滚动,否则就只移动光标。

注意:我无法在上面的代码中显示向上“< Up >”和向下“< Down >”箭头的代码,但相信我,它们确实在里面。

1 个回答

1

与其试图复制箭头键的功能,不如在按键处理完后,让两个窗口的内容同步(也就是说,把一个窗口的视图设置成和另一个窗口一样)。如果你想的话,也可以同时移动插入光标。这种方法只有在两个窗口的行数相同的情况下才能奏效。

虽然正确的做法是调整绑定标签,这样可以在类绑定之后创建一个新的绑定,但你可以通过了解tkinter是如何处理按键按下事件的,来避免这种复杂性。这意味着你可以添加对按键释放事件的绑定。不过这样会有一点延迟。

效果大概是这样的:

descriptionTextField("<KeyRelease-Up>", OnArrow)
descriptionTextField("<KeyRelease-Down>", OnArrow)
pnTextField("<KeyRelease-Up>", OnArrow)
pnTextField("<KeyRelease-Down>", OnArrow)
...
def OnArrow(event):
    widget = event.widget
    other = pnTextField if widget == descriptionTextField else descriptionTextField
    other.yview_moveto(widget.yview()[0])
    other.mark_set("insert", widget.index("insert"))

使用绑定标签可以消除延迟。你可以这样设置:

   for widget in (descriptionTextField, pnTextField):
        bindtags = list(widget.bindtags())
        bindtags.insert(2, "custom")
        widget.bindtags(tuple(bindtags))

        widget.bind_class("custom", "<Up>", OnArrow)
        widget.bind_class("custom", "<Down>", OnArrow)

撰写回答