gpt4 book ai didi

具有自动和自定义滚动功能的 Python Tkinter 文本小部件

转载 作者:太空狗 更新时间:2023-10-30 00:00:16 25 4
gpt4 key购买 nike

我编写了一个简单的基于 Tkinter 的 Python 应用程序,该应用程序从串行连接读取文本并将其添加到窗口,特别是窗口化的文本。

经过大量调整和一些非常奇怪的异常后,这有效。然后我通过这样做添加了自动滚动:

self.text.insert(END, str(parsed_line))
self.text.yview(END)

这些行在线程中运行。线程在从串行连接读取时阻塞,拆分行,然后将所有行添加到小部件。

这也行。然后我想允许用户滚动,这应该禁用自动滚动,直到用户滚动回底部。

我找到了 Stop Text widget from scrolling when content is changed这似乎是相关的。特别是,我尝试了 DuckAssasin 评论中的代码:

if self.myWidgetScrollbar.get() == 1.0:
self.myWidget.yview(END)

我还尝试了 .get()[1] 这实际上是我想要的元素(底部位置)。但是,这会崩溃并出现以下异常:

Traceback (most recent call last):
File "transformer-gui.py", line 119, in run
pos = self.scrollbar.get()[1]
File "C:\Python26\lib\lib-tk\Tkinter.py", line 2809, in get
return self._getdoubles(self.tk.call(self._w, 'get'))
File "C:\Python26\lib\lib-tk\Tkinter.py", line 1028, in _getdoubles
return tuple(map(getdouble, self.tk.splitlist(string)))
ValueError: invalid literal for float(): None

似乎 tkinter 某处返回 None 然后被解析为 float 。我在某处读到,例如如果请求的位置不可见,则文本 widged 的​​索引方法有时会返回 None。

希望有人能帮我解决这个问题!

[编辑]

好的,我已经组装了一个演示脚本,可以在我的 Win XP 机器上重现这个问题:

import re,sys,time
from Tkinter import *
import Tkinter
import threading
import traceback


class ReaderThread(threading.Thread):
def __init__(self, text, scrollbar):
print "Thread init"
threading.Thread.__init__(self)
self.text = text
self.scrollbar = scrollbar
self.running = True

def stop(self):
print "Stopping thread"
running = False

def run(self):
print "Thread started"
time.sleep(5)
i = 1
try:
while(self.running):
# emulating delay when reading from serial interface
time.sleep(0.05)
line = "the quick brown fox jumps over the lazy dog\n"

curIndex = "1.0"
lowerEdge = 1.0
pos = 1.0

# get cur position
pos = self.scrollbar.get()[1]

# Disable scrollbar
self.text.configure(yscrollcommand=None, state=NORMAL)

# Add to text window
self.text.insert(END, str(line))
startIndex = repr(i) + ".0"
curIndex = repr(i) + ".end"

# Perform colorization
if i % 6 == 0:
self.text.tag_add("warn", startIndex, curIndex)
elif i % 6 == 1:
self.text.tag_add("debug", startIndex, curIndex)
elif i % 6 == 2:
self.text.tag_add("info", startIndex, curIndex)
elif i % 6 == 3:
self.text.tag_add("error", startIndex, curIndex)
elif i % 6 == 4:
self.text.tag_add("fatal", startIndex, curIndex)
i = i + 1

# Enable scrollbar
self.text.configure(yscrollcommand=self.scrollbar.set, state=DISABLED)

# Auto scroll down to the end if scroll bar was at the bottom before
# Otherwise allow customer scrolling

if pos == 1.0:
self.text.yview(END)

#if(lowerEdge == 1.0):
# print "is lower edge!"
#self.text.see(curIndex)
#else:
# print "Customer scrolling", lowerEdge

# Get current scrollbar position before inserting
#(upperEdge, lowerEdge) = self.scrollbar.get()
#print upperEdge, lowerEdge

#self.text.update_idletasks()
except Exception as e:
traceback.print_exc(file=sys.stdout)
print "Exception in receiver thread, stopping..."
pass
print "Thread stopped"


class Transformer:
def __init__(self):
pass

def start(self):
"""starts to read linewise from self.in_stream and parses the read lines"""
count = 1
root = Tk()
root.title("Tkinter Auto-Scrolling Test")
topPane = PanedWindow(root, orient=HORIZONTAL)
topPane.pack(side=TOP, fill=X)
lowerPane = PanedWindow(root, orient=VERTICAL)

scrollbar = Scrollbar(root)
scrollbar.pack(side=RIGHT, fill=Y)
text = Text(wrap=WORD, yscrollcommand=scrollbar.set)
scrollbar.config(command=text.yview)
# Color definition for log levels
text.tag_config("debug",foreground="gray50")
text.tag_config("info",foreground="green")
text.tag_config("warn",foreground="orange")
text.tag_config("error",foreground="red")
text.tag_config("fatal",foreground="#8B008B")
# set default color
text.config(background="black", foreground="gray");
text.pack(expand=YES, fill=BOTH)

lowerPane.add(text)
lowerPane.pack(expand=YES, fill=BOTH)

t = ReaderThread(text, scrollbar)
print "Starting thread"
t.start()

try:
root.mainloop()
except Exception as e:
print "Exception in window manager: ", e

t.stop()
t.join()


if __name__ == "__main__":
try:
trans = Transformer()
trans.start()
except Exception as e:
print "Error: ", e
sys.exit(1)

我让这个 scipt 运行并开始上下滚动,一段时间后我得到很多不同的异常,例如:

.\source\testtools\device-log-transformer>python tkinter-autoscroll.py
Thread init
Starting thread
Thread started
Traceback (most recent call last):
File "tkinter-autoscroll.py", line 59, in run
self.text.configure(yscrollcommand=self.scrollbar.set, state=DISABLED)
File "C:\Python26\lib\lib-tk\Tkinter.py", line 1202, in configure
Stopping thread
return self._configure('configure', cnf, kw)
File "C:\Python26\lib\lib-tk\Tkinter.py", line 1193, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
TclError: invalid command name ".14762592"
Exception in receiver thread, stopping...
Thread stopped

.\source\testtools\device-log-transformer>python tkinter-autoscroll.py
Thread init
Starting thread
Thread started
Stopping thread
Traceback (most recent call last):
File "tkinter-autoscroll.py", line 35, in run
pos = self.scrollbar.get()[1]
File "C:\Python26\lib\lib-tk\Tkinter.py", line 2809, in get
return self._getdoubles(self.tk.call(self._w, 'get'))
TclError: invalid command name ".14762512"
Exception in receiver thread, stopping...
Thread stopped

.\source\testtools\device-log-transformer>python tkinter-autoscroll.py
Thread init
Starting thread
Thread started
Traceback (most recent call last):
File "tkinter-autoscroll.py", line 65, in run
self.text.yview(END)
File "C:\Python26\lib\lib-tk\Tkinter.py", line 3156, in yview
self.tk.call((self._w, 'yview') + what)
Stopping threadTclError: invalid command name ".14762592"

Exception in receiver thread, stopping...
Thread stopped

.\source\testtools\device-log-transformer>python tkinter-autoscroll.py
Thread init
Starting thread
Thread started
Traceback (most recent call last):
File "tkinter-autoscroll.py", line 35, in run
pos = self.scrollbar.get()[1]
File "C:\Python26\lib\lib-tk\Tkinter.py", line 2809, in get
return self._getdoubles(self.tk.call(self._w, 'get'))
File "C:\Python26\lib\lib-tk\Tkinter.py", line 1028, in _getdoubles
return tuple(map(getdouble, self.tk.splitlist(string)))
ValueError: invalid literal for float(): None
Exception in receiver thread, stopping...
Thread stopped
Stopping thread

.\source\testtools\device-log-transformer>python tkinter-autoscroll.py
Thread init
Starting thread
Thread started
Traceback (most recent call last):
File "tkinter-autoscroll.py", line 53, in run
self.text.tag_add("error", startIndex, curIndex)
File "C:\Python26\lib\lib-tk\Tkinter.py", line 3057, in tag_add
(self._w, 'tag', 'add', tagName, index1) + args)
TclError: bad option "261.0": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, pe
er, replace, scan, search, see, tag, window, xview, or yview
Exception in receiver thread, stopping...
Thread stopped

我希望这能帮助你帮助我:)

谢谢,

/J

最佳答案

很难说到底发生了什么,但您是否考虑过使用队列?

from Tkinter import *
import time, Queue, thread

def simulate_input(queue):
for i in range(100):
info = time.time()
queue.put(info)
time.sleep(0.5)

class Demo:
def __init__(self, root, dataQueue):
self.root = root
self.dataQueue = dataQueue

self.text = Text(self.root, height=10)
self.scroller = Scrollbar(self.root, command=self.text.yview)
self.text.config(yscrollcommand=self.scroller.set)
self.text.tag_config('newline', background='green')
self.scroller.pack(side='right', fill='y')
self.text.pack(fill='both', expand=1)

self.root.after_idle(self.poll)

def poll(self):
try:
data = self.dataQueue.get_nowait()
except Queue.Empty:
pass
else:
self.text.tag_remove('newline', '1.0', 'end')
position = self.scroller.get()
self.text.insert('end', '%s\n' %(data), 'newline')
if (position[1] == 1.0):
self.text.see('end')
self.root.after(1000, self.poll)

q = Queue.Queue()
root = Tk()
app = Demo(root, q)

worker = thread.start_new_thread(simulate_input, (q,))
root.mainloop()

关于具有自动和自定义滚动功能的 Python Tkinter 文本小部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8850329/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com