python - 在 Python tkinter 中,Text 小部件的 yscrollcommand 无法按预期工作
问题描述
我正在用 Python 构建一个 Tkinter 应用程序,我想为用户添加一个 Text 小部件以添加评论,同时在每个评论旁边放置数字。我使用第二个小文本小部件添加数字,并按照此问题中的建议使两个小部件一起滚动,以使数字保持正确的位置。
问题是,当文本的高度超过小部件的高度并且滚动条应该“跟随”以显示插入索引时,我会得到一个意外的行为,每次我输入一个滚动条交替上下移动新字符。
每次输入新字符时,我都会监视yscrollcommand的值,它们遵循以下顺序,而我在同一行中编写,最后一个在小部件的低端:
f/l: 0.0 0.9732142857142857
---
f/l: 0.026785714285714284 1.0
---
f/l: 0.0 0.9732142857142857
---
f/l: 0.026785714285714284 1.0
---
f/l: 0.0 0.9732142857142857
---
f/l: 0.026785714285714284 1.0
---
f/l: 0.0 0.9732142857142857
---
f/l: 0.026785714285714284 1.0
以下是相关代码:
from tkinter import *
from tkinter.ttk import *
class MyApp(Frame):
def __init__(self, parent, *args, **kwargs):
Frame.__init__(self, parent)
self.pack()
self.parent = parent
self.action_frame = Frame(self, name="action")
self.vis_frame = Panedwindow(self.action_frame, orient=HORIZONTAL)
self.action_frame.pack(fill=BOTH, expand=YES)
self.vis_frame.pack(fill=BOTH, expand=YES)
fr = LabelFrame(self.vis_frame, text="Comments")
fr1 = LabelFrame(self.vis_frame, text="Draft")
self.text = Text(fr)
self.lbl_fr = Text(fr, width=4, state=DISABLED, background="SystemMenu")
self.scrl = Scrollbar(fr, orient=VERTICAL)
Button(fr, text="Submit", command=self.submit).pack(side=BOTTOM)
self.scrl.pack(side=RIGHT, fill=Y)
self.text.pack(side=RIGHT, fill=BOTH)
self.lbl_fr.pack(side=RIGHT, fill=Y)
self.scrl.configure(command=self.__scrollBoth)
self.text.configure(yscrollcommand=self.__updateScroll)
self.lbl_fr.configure(yscrollcommand=self.__updateScroll)
self.vis_frame.add(fr1, weight=1)
self.vis_frame.add(fr)
bindtags = list(self.text.bindtags())
bindtags.insert(2, "custom")
self.text.bindtags(tuple(bindtags))
self.text.bind_class("custom", "<Return>", self.lbls)
self.text.bind_class("custom", "<Key>", self.lbls)
self.text.bind_class("custom", "<BackSpace>", self.lbls)
self.text.bind_class("custom", "<Delete>", self.lbls)
self.cur = self.lbl_fr.index(INSERT)
def lbls(self, e=None):
self.text.see("{}+1c".format(INSERT))
self.lbl_fr["state"] = NORMAL
self.lbl_fr.delete("0.0", END)
i = "1.0"
while True:
if i == self.text.index(END):
break
linenum = str(i).split(".")[0]
if i[:-2] == self.text.index(INSERT).split(".")[0]:
self.cur = self.lbl_fr.index(INSERT)
what = "{}.\n".format(linenum)
self.lbl_fr.insert(INSERT, what)
for j in range(len(self.text.get(i, i+"+1l-1c"))//self.text.cget("width")):
if i[:-2] == self.text.index(INSERT).split(".")[0]:
if j+1 == int(self.text.index(INSERT).split(".")[1]) // self.text.cget("width"):
self.cur = self.lbl_fr.index(INSERT)
self.lbl_fr.insert(INSERT, " \n")
i = self.text.index("{}+1l".format(i))
self.lbl_fr.delete(INSERT+"-1c", INSERT+" lineend")
self.lbl_fr["state"] = DISABLED
print("---------------------------")
# print("--->", self.cur)
def __scrollBoth(self, act, pos, type=None):
self.text.yview_moveto(pos)
self.lbl_fr.yview_moveto(pos)
print("pos: ", pos)
def __updateScroll(self, first, last, type=None):
self.text.yview_moveto(first)
self.lbl_fr.yview_moveto(first)
self.scrl.set(first, last)
# self.text.see(INSERT)
# self.lbl_fr.see(self.cur)
print("f/l: ", first, last)
def submit(self):
pass
if __name__ == "__main__":
root = Tk()
MyApp(root)
root.mainloop()
有没有人碰巧有任何类似的问题,或者可能知道为什么会发生这种情况?我尝试了一种解决方法,方法是在__updateScroll方法中添加两个注释行,以明确地将两个小部件放在INSERT所在的任何位置(self.cur变量始终使用 lbl_fr Text 小部件中 INSERT 标签的相应位置进行更新),但这当然不是一个完美的解决方案,因为在不更改INSERT的情况下滚动小部件时它无法正常工作。
解决方案
推荐阅读
- serialization - 如何序列化不可变结构
- spring-boot - 拦截骆驼@Consume
- django - 如何在 django 表单中抛出一条消息,它不会更改 UpdateView 中表单中的数据
- html - 如何调整文本的宽度并将其放在帖子(视觉)编辑器的中心?
- javascript - 如何使用javascript从json表中按键过滤数组
- sql - 更新查询的执行时间过长
- php - 忽略多个搜索请求中的重音
- python - 如何模拟点击元素?
- asp.net-core - 从 HttpContext 中提取自定义对象
- kubernetes - 每当 pod 被调度或未调度时,如何在 kubernetes 节点(不在容器内)上运行操作?