在
python-3.x
和 tkinter
GUI 中,我开发了一个带有常规简单窗口的程序。
我想在程序窗口上显示保存在名为 markdownText
的字符串中的
markdown格式字符串:
markdownText='_italic_ or **bold**'
期望的输出是:
斜体或粗体
有什么解决办法吗?
我只是在寻找类似的解决方案,而且确实似乎没有一个用于Python、TkInter和markdown组合的默认模块/类/库。然而,继续搜索发现了以下选项:
换句话说,如果您愿意使用转换为 html 的中间步骤,这可能是您在 tkinter GUI 中显示 Markdown 字符串的可行途径。
如果你不想要holroy的伟大建议转换为html并显示它,而只想要markdown进行基本格式化,你可以编写一个基本的markdown解析器。
但是,如果您想要完整的 Markdown 支持,请使用真正的解析器,例如 marko 或 python-markdown 并弄清楚如何遍历文档以将每个项目添加到
tk.Text
。
否则,看看:
import re
import tkinter as tk
import tkinter.font as tkFont
class SimpleMarkdownText(tk.Text):
"""
Really basic Markdown display. Thanks to Bryan Oakley's RichText:
https://stackoverflow.com/a/63105641/79125
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
default_font = tkFont.nametofont(self.cget("font"))
em = default_font.measure("m")
default_size = default_font.cget("size")
bold_font = tkFont.Font(**default_font.configure())
italic_font = tkFont.Font(**default_font.configure())
bold_font.configure(weight="bold")
italic_font.configure(slant="italic")
# Small subset of markdown. Just enough to make text look nice.
self.tag_configure("**", font=bold_font)
self.tag_configure("*", font=italic_font)
self.tag_configure("_", font=italic_font)
self.tag_chars = "*_"
self.tag_char_re = re.compile(r"[*_]")
max_heading = 3
for i in range(1, max_heading + 1):
header_font = tkFont.Font(**default_font.configure())
header_font.configure(size=int(default_size * i + 3), weight="bold")
self.tag_configure(
"#" * (max_heading - i), font=header_font, spacing3=default_size
)
lmargin2 = em + default_font.measure("\u2022 ")
self.tag_configure("bullet", lmargin1=em, lmargin2=lmargin2)
lmargin2 = em + default_font.measure("1. ")
self.tag_configure("numbered", lmargin1=em, lmargin2=lmargin2)
self.numbered_index = 1
def insert_bullet(self, position, text):
self.insert(position, f"\u2022 {text}", "bullet")
def insert_numbered(self, position, text):
self.insert(position, f"{self.numbered_index}. {text}", "numbered")
self.numbered_index += 1
def insert_markdown(self, mkd_text):
"""A very basic markdown parser.
Helpful to easily set formatted text in tk. If you want actual markdown
support then use a real parser.
"""
for line in mkd_text.split("\n"):
if line == "":
# Blank lines reset numbering
self.numbered_index = 1
self.insert("end", line)
elif line.startswith("#"):
tag = re.match(r"(#+) (.*)", line)
line = tag.group(2)
self.insert("end", line, tag.group(1))
elif line.startswith("* "):
line = line[2:]
self.insert_bullet("end", line)
elif line.startswith("1. "):
line = line[2:]
self.insert_numbered("end", line)
elif not self.tag_char_re.search(line):
self.insert("end", line)
else:
tag = None
accumulated = []
skip_next = False
for i, c in enumerate(line):
if skip_next:
skip_next = False
continue
if c in self.tag_chars and (not tag or c == tag[0]):
if tag:
self.insert("end", "".join(accumulated), tag)
accumulated = []
tag = None
else:
self.insert("end", "".join(accumulated))
accumulated = []
tag = c
next_i = i + 1
if len(line) > next_i and line[next_i] == tag:
tag = line[i : next_i + 1]
skip_next = True
else:
accumulated.append(c)
self.insert("end", "".join(accumulated), tag)
self.insert("end", "\n")
def run_rich_edit():
root = tk.Tk()
default_font = tkFont.nametofont("TkDefaultFont")
default_font.configure(size=12)
text = SimpleMarkdownText(root, width=45, height=22, font=default_font)
text.pack(fill="both", expand=True)
text.insert_markdown(
"""
# Rich Text Example
Hello, world
This line **has bold** text.
This line _has italicized_ text. Also *italics* using asterisks.
Text _with italics **and bold** does_ not work.
## Sub Heading
This is a more interesting line with _some_ italics, but also **some bold text**.
* Create a list
* With bullets
1. Create a list
1. Or numbers
1. Use blank lines
1. to restart numbering
"""
)
root.mainloop()
if __name__ == "__main__":
run_rich_edit()
您可以看到有很多限制:没有斜体+粗体的组合,没有文字换行。但对于显示大块文本来说似乎要好得多。