如何用NLTK同时可视化歧义句的两种句法结构?
同时可视化NLTK中的两个句法树
你遇到的问题其实是因为NLTK的tree.draw()方法默认会创建一个独立的Tkinter窗口,要是连续调用两次draw(),第一个窗口会阻塞程序直到你关闭它,才会弹出第二个窗口——甚至可能因为多个Tkinter主窗口实例冲突,最终只显示最后一个结构。要同时展示两种歧义句法树,我们可以把它们放在同一个窗口的不同区域,或者创建两个并列的子窗口,下面是两种可行的解决方案:
方法1:将两个树放在同一个窗口中
这种方法会创建一个主窗口,把两个句法树分别放在左右两侧,方便直观对比两种歧义结构:
import tkinter as tk from nltk.tree import Tree import nltk.draw.tree # 解析你的两个句法树字符串 tree_str1 = "(S (NP I) (VP (V shot) (NP (Det an) (N elephant) (PP (P in) (NP (Det my) (N pajamas))))))" tree_str2 = "(S (NP I) (VP (VP (V shot) (NP (Det an) (N elephant))) (PP (P in) (NP (Det my) (N pajamas)))))" tree1 = Tree.fromstring(tree_str1) tree2 = Tree.fromstring(tree_str2) # 创建主窗口 root = tk.Tk() root.title("歧义句两种句法结构对比") # 创建两个框架分别放置两棵树 left_frame = tk.Frame(root, padx=20, pady=20) left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) right_frame = tk.Frame(root, padx=20, pady=20) right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True) # 为每个树创建TreeWidget并添加到对应框架 tree_widget_left = nltk.draw.tree.TreeWidget(left_frame, tree1) tree_widget_left.pack(fill=tk.BOTH, expand=True) tree_widget_right = nltk.draw.tree.TreeWidget(right_frame, tree2) tree_widget_right.pack(fill=tk.BOTH, expand=True) # 启动窗口主循环 root.mainloop()
方法2:创建两个独立的并列窗口
如果你更倾向于用两个分开的窗口(比如方便拖动、放大对比),可以用Toplevel子窗口实现:
import tkinter as tk from nltk.tree import Tree import nltk.draw.tree # 解析句法树 tree_str1 = "(S (NP I) (VP (V shot) (NP (Det an) (N elephant) (PP (P in) (NP (Det my) (N pajamas))))))" tree_str2 = "(S (NP I) (VP (VP (V shot) (NP (Det an) (N elephant))) (PP (P in) (NP (Det my) (N pajamas)))))" tree1 = Tree.fromstring(tree_str1) tree2 = Tree.fromstring(tree_str2) # 创建主窗口并隐藏(我们用子窗口显示树) root = tk.Tk() root.withdraw() # 第一个子窗口:大象穿着睡衣的结构 win1 = tk.Toplevel(root) win1.title("结构1:Elephant in pajamas") tree_widget1 = nltk.draw.tree.TreeWidget(win1, tree1) tree_widget1.pack(padx=10, pady=10) # 第二个子窗口:我穿着睡衣的结构 win2 = tk.Toplevel(root) win2.title("结构2:I in pajamas") tree_widget2 = nltk.draw.tree.TreeWidget(win2, tree2) tree_widget2.pack(padx=10, pady=10) root.mainloop()
为什么之前只显示第二个结构?
当你连续调用tree1.draw()和tree2.draw()时,第一个draw()会创建一个Tkinter主窗口,程序会阻塞在这个窗口的主循环里——直到你关闭它,才会执行第二个draw()。但Tkinter不推荐同时创建多个主Tk()实例,这可能导致资源冲突,最终只显示最后一个窗口。上面的方法通过复用一个主窗口或使用子窗口,完美避免了这个问题。
内容的提问来源于stack exchange,提问作者Thiago Pires
相关产品推荐
相关产品推荐

