我刚刚为我的日志控制台添加了一些不错的格式,根据消息类型,消息前缀的颜色不同:
为了做到这一点,我使用了标签(tag_config()
)和Font()
来使事情变得粗体:
from tkinter import font, Tk, END
from tkinter.scrolledtext import ScrolledText
def log_info(msg, widget):
log(msg, "info", widget)
def log_error(msg, widget):
log(msg, "error", widget)
def log_warn(msg, widget):
log(msg, "warn", widget)
def log(msg, type, widget):
msg_prefix = font.Font(widget, widget.cget("font"))
msg_prefix.configure(weight="bold")
if type == "info":
widget.insert(END, "INFO: ", "info")
widget.insert(END, msg + "\n")
elif type == "error":
widget.insert(END, "ERROR: ", "error")
widget.insert(END, msg + "\n")
elif type == "warn":
widget.insert(END, "WARNING: ", "warn")
widget.insert(END, msg + "\n")
else:
print("Unknown type of log message. Available types are 'info', 'error' and 'warn'")
widget.tag_config("info", font=msg_prefix)
widget.tag_config("error", foreground="red", font=msg_prefix)
widget.tag_config("warn", foreground="orange", font=msg_prefix)
window = Tk()
window.geometry('970x45')
box = ScrolledText(window, width=70, height=7)
box.pack()
log_info("This is an information log message", box)
log_error("This is an error log message", box)
log_warn("This is a warning log message", box)
window.mainloop()
但是我很难在这个控制台所在的选项卡中添加类似的功能。每次在控制台中记录错误日志消息时,它所在的选项卡都会更新,以显示当前记录的错误数:
但是我想让(4)
(来自上面的屏幕截图)用红色着色。我无法找到标签标签的字体格式:
原因:我发现日志记录控制台经常被忽略,因为我的小部件中的其他选项卡是交互发生的地方。由于我希望保持分离以防止在屏幕上聚集太多东西,同时我试图以非侵入方式通知用户发生了错误(其他类型的日志消息是不那么重要。)
答案 0 :(得分:2)
如果您正在使用ttk.Notebook,答案是您只能使用样式为所有选项卡配置标签文本样式。所以你可以让所有标签前景红...
nb = ttk.Notebook(master, style='TNotebook')
...
style = ttk.Style()
# This will change the foreground color of ALL tabs to red.
style.configure('TNotebook.Tab', foreground='red')
您还可以使用选项卡compound
选项,该选项可让您在选项卡上放置文本和图像。您可以单独更改给定选项卡上的文本或图像。但要做你要求的,你的'(4)'必须是一个图像,这意味着您必须等待加载许多预先存在的图像,具体取决于您预期的错误数量。
答案 1 :(得分:1)
不,从头开始是不可能的,因为ttk小部件的外观很大程度上取决于使用中的主题和/或平台 - 如果没有跳转到tk
环境/难以保持所需的布局,很难实现。 / p>
但你的问题真的很感兴趣,所以我试着自己实现这个功能。
首先,您需要知道,每个小部件都有layout structure,由元素层次结构表示。
在我的Win
计算机上,默认主题为vista
,Tab
的布局为:
>>> s = ttk.Style()
>>> print(s.layout('TNotebook.Tab'))
# formatted result, actual result is one-line string
[('Notebook.tab', {
'children': [(
'Notebook.padding', {
'children': [(
'Notebook.focus', {
'children': [(
'Notebook.label', {
'sticky': '',
'side': 'top'
})],
'sticky': 'nswe',
'side': 'top'
})],
'sticky': 'nswe',
'side': 'top'
})],
'sticky': 'nswe'
})]
如您所见 - 有一个Notebook.label
元素。这些元素处理所有选项:
>>> print(s.element_options('Notebook.label'))
('-compound', '-space', '-text', '-font', '-foreground', '-underline', '-width', '-anchor', '-justify', '-wraplength', '-embossed', '-image', '-stipple', '-background')
就是这样 - 你不能在标签内部分地格式化文本,因为-font
或-foreground
选项适用于整个字符串。
但是,如果我们使用其他标签/文字更改此布局结构会怎么样? 这看起来是个好主意,我们可以使用第一个文本作为标题标题,第二个文本用于计数器!
s = ttk.Style()
s.configure('SOExample.TNotebook')
s.layout('SOExample.TNotebook.Tab', [('Notebook.tab', {
'sticky': 'nswe',
'children': [(
'Notebook.padding', {
'sticky': 'nswe',
'children': [(
'Notebook.focus', {
'sticky': 'nswe',
'children': [(
'Notebook.label', {
'sticky': '',
'side': 'left'
}), (
'Notebook.text', {
'sticky': '',
'side': 'right'
})],
'side': 'top'
})],
'side': 'top'
})]})])
不幸的是,显然,它不会起作用,因为两个元素对相同的选项做出反应(text
,font
等等。
根据文档here:
元素选项的值取自:
包含该小部件的小部件中具有相同名称和类型的选项 元件;
由样式图和当前状态指定的动态设置;
style configure指定的默认设置;或
元素内置的选项默认值。
但是,我认为可以将第二个text
选项“映射”为text2
用于Tab,但是如果有自己的Python,则看起来不可能完成任务!
很长的答案是尝试实现这样的功能,这导致另一个问题“如何向自定义类窗口小部件添加选项并将它们绑定到元素选项”。更严格的解决方案是使用标签的compound
行为,因为您可以将任何int
转换为图像/ 64编码的图像字符串,但已经提到了此选项。
答案 2 :(得分:0)
我会将您的日志窗口声明为LogWindow类的实例。这可能不是完美的Python,但你明白了。您也可以移动tag_config
命令。 __log
成为私有方法,因此不需要严格的数据检查。
class LogWindow:
def __init__(self):
window = Tk()
window.geometry('970x45')
self.widget = ScrolledText(window, width=70, height=7)
self.widget.pack()
def info(msg):
self.widget.insert(END, "INFO: ", "info")
__log(msg, "info")
def error(msg, widget):
self.widget.insert(END, "ERROR: ", "error")
__log(msg, "error")
def warn(msg):
self.widget.insert(END, "WARNING: ", "warn")
__log(msg, "warn")
def __log(msg, type):
msg_prefix = font.Font(self.widget, widget.cget("font"))
msg_prefix.configure(weight="bold")
self.widget.insert(END, msg + "\n")
self.widget.tag_config("info", font=msg_prefix)
self.widget.tag_config("error", foreground="red", font=msg_prefix)
self.widget.tag_config("warn", foreground="orange", font=msg_prefix)
log = LogWindow();
log.info("This is an information log message")
log.error("This is an error log message")