我想做一个能够在Text Widget中“记录”文本的类。其他应用程序可以使用此类将日志发送和显示到文本小部件。
class TraceConsole():
def __init__(self):
# Init the main GUI window
self._logFrame = Tk.Frame()
self._log = Tk.Text(self._logFrame, wrap=Tk.NONE, setgrid=True)
self._scrollb = Tk.Scrollbar(self._logFrame, orient=Tk.VERTICAL)
self._scrollb.config(command = self._log.yview)
self._log.config(yscrollcommand = self._scrollb.set)
# Grid & Pack
self._log.grid(column=0, row=0)
self._scrollb.grid(column=1, row=0, sticky=Tk.S+Tk.N)
self._logFrame.pack()
def log(self, msg, level=None):
# Write on GUI
self._log.insert('end', msg + '\n')
def exitWindow(self):
# Exit the GUI window and close log file
print('exit..')
用法例子:
t = TraceConsole()
t.log('hello world!')
我现在的问题是我不知道把主循环放在哪里。此记录器必须“在后台”运行,并且可以随时写入日志,直到窗口关闭。
答案 0 :(得分:2)
我在这方面有点挣扎,但在这里的建议上融合了:
我在下面有一个例子,我用它来阐明使用Tkinter记录到GUI控件的概念。下面的示例根据您的要求记录到文本控件,但您可以通过将类MyHandlerText
替换/复制到其他处理程序类(如MyHandlerLabel
,MyHandlerListbox
),将日志消息发送到其他GUI组件,等(为处理程序类选择自己的名称)。然后,您将拥有一个感兴趣的各种GUI控件的处理程序。大" a-ha"我的时刻是python.org鼓励的模块级getLogger
概念。
import Tkinter
import logging
import datetime
# this item "module_logger" is visible only in this module,
# (but you can also reference this getLogger instance from other modules and other threads by passing the same argument name...allowing you to share and isolate loggers as desired)
# ...so it is module-level logging and it takes the name of this module (by using __name__)
# recommended per https://docs.python.org/2/library/logging.html
module_logger = logging.getLogger(__name__)
class simpleapp_tk(Tkinter.Tk):
def __init__(self,parent):
Tkinter.Tk.__init__(self,parent)
self.parent = parent
self.grid()
self.mybutton = Tkinter.Button(self, text="ClickMe")
self.mybutton.grid(column=0,row=0,sticky='EW')
self.mybutton.bind("<ButtonRelease-1>", self.button_callback)
self.mytext = Tkinter.Text(self, state="disabled")
self.mytext.grid(column=0, row=1)
def button_callback(self, event):
now = datetime.datetime.now()
module_logger.info(now)
class MyHandlerText(logging.StreamHandler):
def __init__(self, textctrl):
logging.StreamHandler.__init__(self) # initialize parent
self.textctrl = textctrl
def emit(self, record):
msg = self.format(record)
self.textctrl.config(state="normal")
self.textctrl.insert("end", msg + "\n")
self.flush()
self.textctrl.config(state="disabled")
if __name__ == "__main__":
# create Tk object instance
app = simpleapp_tk(None)
app.title('my application')
# setup logging handlers using the Tk instance created above
# the pattern below can be used in other threads...
# ...to allow other thread to send msgs to the gui
# in this example, we set up two handlers just for demonstration (you could add a fileHandler, etc)
stderrHandler = logging.StreamHandler() # no arguments => stderr
module_logger.addHandler(stderrHandler)
guiHandler = MyHandlerText(app.mytext)
module_logger.addHandler(guiHandler)
module_logger.setLevel(logging.INFO)
module_logger.info("from main")
# start Tk
app.mainloop()
答案 1 :(得分:0)
在这种情况下,您已经创建了一个将在应用程序中使用的组件。将在该应用程序中调用mainloop,它们将写入您的日志窗口小部件。
您可以使用类似
之类的内容添加一些简单的用法示例(例如您提供的示例)和/或在与TraceConsole相同的python文件中进行测试if __name__ == '__main__':
m = tkinter.Tk()
t = TraceConsole()
t.log('hello world!')
m.mainloop()
我通常会这样做,所以我可以在将tkinter组件合并到我的应用程序之前自行测试它。