def reset_workspace(self): c = self._workspace.canvas() fontsize = int(self._size.get()) node_font = ("helvetica", -(fontsize + 4), "bold") leaf_font = ("helvetica", -(fontsize + 2)) # Remove the old tree if self._tree is not None: self._workspace.remove_widget(self._tree) # The root of the tree. start = self._grammar.start().symbol() rootnode = TextWidget(c, start, font=node_font, draggable=1) # The leaves of the tree. leaves = [] for word in self._text: leaves.append(TextWidget(c, word, font=leaf_font, draggable=1)) # Put it all together into one tree self._tree = TreeSegmentWidget(c, rootnode, leaves, color="white") # Add it to the workspace. self._workspace.add_widget(self._tree) # Move the leaves to the bottom of the workspace. for leaf in leaves: leaf.move(0, 100)
def _init_canvas(self, parent): self._cframe = CanvasFrame(parent, background='white', width=525, closeenough=10, border=2, relief='sunken') self._cframe.pack(expand=1, fill='both', side='top', pady=2) canvas = self._canvas = self._cframe.canvas() self._stackwidgets = [] self._rtextwidgets = [] self._titlebar = canvas.create_rectangle(0, 0, 0, 0, fill='#c0f0f0', outline='black') self._exprline = canvas.create_line(0, 0, 0, 0, dash='.') self._stacktop = canvas.create_line(0, 0, 0, 0, fill='#408080') size = self._size.get() + 4 self._stacklabel = TextWidget(canvas, 'Stack', color='#004040', font=self._boldfont) self._rtextlabel = TextWidget(canvas, 'Remaining Text', color='#004040', font=self._boldfont) self._cframe.add_widget(self._stacklabel) self._cframe.add_widget(self._rtextlabel)
def _init_canvas(self, parent): self._cframe = CanvasFrame( parent, background="white", width=525, closeenough=10, border=2, relief="sunken", ) self._cframe.pack(expand=1, fill="both", side="top", pady=2) canvas = self._canvas = self._cframe.canvas() self._stackwidgets = [] self._rtextwidgets = [] self._titlebar = canvas.create_rectangle( 0, 0, 0, 0, fill="#c0f0f0", outline="black" ) self._exprline = canvas.create_line(0, 0, 0, 0, dash=".") self._stacktop = canvas.create_line(0, 0, 0, 0, fill="#408080") size = self._size.get() + 4 self._stacklabel = TextWidget( canvas, "Stack", color="#004040", font=self._boldfont ) self._rtextlabel = TextWidget( canvas, "Remaining Text", color="#004040", font=self._boldfont ) self._cframe.add_widget(self._stacklabel) self._cframe.add_widget(self._rtextlabel)
def _animate_reduce_frame(self, frame, widgets, dy): if frame > 0: self._animating_lock = 1 for widget in widgets: widget.move(0, dy) self._top.after(10, self._animate_reduce_frame, frame - 1, widgets, dy) else: del self._stackwidgets[-len(widgets):] for widget in widgets: self._cframe.remove_widget(widget) tok = self._parser.stack()[-1] if not isinstance(tok, Tree): raise ValueError() label = TextWidget(self._canvas, str(tok.label()), color='#006060', font=self._boldfont) widget = TreeSegmentWidget(self._canvas, label, widgets, width=2) (x1, y1, x2, y2) = self._stacklabel.bbox() y = y2 - y1 + 10 if not self._stackwidgets: x = 5 else: x = self._stackwidgets[-1].bbox()[2] + 10 self._cframe.add_widget(widget, x, y) self._stackwidgets.append(widget) # Display the available productions. self._draw_stack_top(widget) self._highlight_productions() # # Delete the old widgets.. # del self._stackwidgets[-len(widgets):] # for widget in widgets: # self._cframe.destroy_widget(widget) # # # Make a new one. # tok = self._parser.stack()[-1] # if isinstance(tok, Tree): # attribs = {'tree_color': '#4080a0', 'tree_width': 2, # 'node_font': bold, 'node_color': '#006060', # 'leaf_color': '#006060', 'leaf_font':self._font} # widget = tree_to_treesegment(self._canvas, tok.type(), # **attribs) # widget.node()['color'] = '#000000' # else: # widget = TextWidget(self._canvas, tok.type(), # color='#000000', font=self._font) # widget.bind_click(self._popup_reduce) # (x1, y1, x2, y2) = self._stacklabel.bbox() # y = y2-y1+10 # if not self._stackwidgets: x = 5 # else: x = self._stackwidgets[-1].bbox()[2] + 10 # self._cframe.add_widget(widget, x, y) # self._stackwidgets.append(widget) # self._redraw() self._animating_lock = 0
def _redraw(self): canvas = self._canvas # Delete the old tree, widgets, etc. if self._tree is not None: self._cframe.destroy_widget(self._tree) for twidget in self._textwidgets: self._cframe.destroy_widget(twidget) if self._textline is not None: self._canvas.delete(self._textline) # Draw the tree. helv = ('helvetica', -self._size.get()) bold = ('helvetica', -self._size.get(), 'bold') attribs = { 'tree_color': '#000000', 'tree_width': 2, 'node_font': bold, 'leaf_font': helv, } tree = self._parser.tree() self._tree = tree_to_treesegment(canvas, tree, **attribs) self._cframe.add_widget(self._tree, 30, 5) # Draw the text. helv = ('helvetica', -self._size.get()) bottom = y = self._cframe.scrollregion()[3] self._textwidgets = [ TextWidget(canvas, word, font=self._font) for word in self._sent ] for twidget in self._textwidgets: self._cframe.add_widget(twidget, 0, 0) twidget.move(0, bottom - twidget.bbox()[3] - 5) y = min(y, twidget.bbox()[1]) # Draw a line over the text, to separate it from the tree. self._textline = canvas.create_line(-5000, y - 5, 5000, y - 5, dash='.') # Highlight appropriate nodes. self._highlight_nodes() self._highlight_prodlist() # Make sure the text lines up. self._position_text()
def word_to_widget(s, canvas, basefont='helvetica', fontsize=12, color='black', bold=False): """ Parse a node or leaf substring from a tree string, and return a corresponding widget. """ textwidgets = [] # Convert each piece of the word to a widget. for (italic, subscript, text) in parse_word(s): if not text: continue # Strip remaining backslashes text = re.sub(r'\\(.)', r'\1', text) # Decide on a font size = fontsize if subscript: size = size * 2 / 3 slant = italic and 'italic' or 'roman' weight = bold and 'bold' or 'normal' font = tkinter.font.Font(family=basefont, size=size, weight=weight, slant=slant) # Create the widget. textwidgets.append(TextWidget(canvas, text, font=font, color=color)) global metrics metrics[basefont, size, weight, slant] = font.metrics() # If there's only one widget, return it; otherwise, use a # sequencewidget to join them. Use align=bottom to make # subscripting work. if len(textwidgets) == 0: w = SpaceWidget(canvas, 1, 1) w.set_width(0) w.set_height(0) return w if len(textwidgets) == 1: return textwidgets[0] else: return SequenceWidget(canvas, align='bottom', space=-2, *textwidgets)
def draw_one_tree(strtree, draw_file): cf = CanvasFrame() t = Tree.fromstring(strtree) tc = TreeWidget(cf.canvas(), t, draggable=1) cf.add_widget(tc, 1200, 0) # (10,10) offsets # edus 文本 edus_txt = "" c = cf.canvas() edu_path = RAW_TXT + "/" + draw_file.split("/")[2].split( ".")[0] + ".out.edu" with open(edu_path, "r") as f: for line in f: edus_txt += line edus_txt = TextWidget(c, edus_txt, draggable=1) cf.add_widget(edus_txt, 1400, 0) user_choice = input("直接打印(a) or 存到文件(b): ") if user_choice == "a": cf.mainloop() else: cf.print_to_file(draw_file) cf.destroy()
def _redraw(self): scrollregion = self._canvas['scrollregion'].split() (cx1, cy1, cx2, cy2) = [int(c) for c in scrollregion] # Delete the old stack & rtext widgets. for stackwidget in self._stackwidgets: self._cframe.destroy_widget(stackwidget) self._stackwidgets = [] for rtextwidget in self._rtextwidgets: self._cframe.destroy_widget(rtextwidget) self._rtextwidgets = [] # Position the titlebar & exprline (x1, y1, x2, y2) = self._stacklabel.bbox() y = y2 - y1 + 10 self._canvas.coords(self._titlebar, -5000, 0, 5000, y - 4) self._canvas.coords(self._exprline, 0, y * 2 - 10, 5000, y * 2 - 10) # Position the titlebar labels.. (x1, y1, x2, y2) = self._stacklabel.bbox() self._stacklabel.move(5 - x1, 3 - y1) (x1, y1, x2, y2) = self._rtextlabel.bbox() self._rtextlabel.move(cx2 - x2 - 5, 3 - y1) # Draw the stack. stackx = 5 for tok in self._parser.stack(): if isinstance(tok, Tree): attribs = { 'tree_color': '#4080a0', 'tree_width': 2, 'node_font': self._boldfont, 'node_color': '#006060', 'leaf_color': '#006060', 'leaf_font': self._font } widget = tree_to_treesegment(self._canvas, tok, **attribs) widget.label()['color'] = '#000000' else: widget = TextWidget(self._canvas, tok, color='#000000', font=self._font) widget.bind_click(self._popup_reduce) self._stackwidgets.append(widget) self._cframe.add_widget(widget, stackx, y) stackx = widget.bbox()[2] + 10 # Draw the remaining text. rtextwidth = 0 for tok in self._parser.remaining_text(): widget = TextWidget(self._canvas, tok, color='#000000', font=self._font) self._rtextwidgets.append(widget) self._cframe.add_widget(widget, rtextwidth, y) rtextwidth = widget.bbox()[2] + 4 # Allow enough room to shift the next token (for animations) if len(self._rtextwidgets) > 0: stackx += self._rtextwidgets[0].width() # Move the remaining text to the correct location (keep it # right-justified, when possible); and move the remaining text # label, if necessary. stackx = max(stackx, self._stacklabel.width() + 25) rlabelwidth = self._rtextlabel.width() + 10 if stackx >= cx2 - max(rtextwidth, rlabelwidth): cx2 = stackx + max(rtextwidth, rlabelwidth) for rtextwidget in self._rtextwidgets: rtextwidget.move(4 + cx2 - rtextwidth, 0) self._rtextlabel.move(cx2 - self._rtextlabel.bbox()[2] - 5, 0) midx = (stackx + cx2 - max(rtextwidth, rlabelwidth)) / 2 self._canvas.coords(self._stacktop, midx, 0, midx, 5000) (x1, y1, x2, y2) = self._stacklabel.bbox() # Set up binding to allow them to shift a token by dragging it. if len(self._rtextwidgets) > 0: def drag_shift(widget, midx=midx, self=self): if widget.bbox()[0] < midx: self.shift() else: self._redraw() self._rtextwidgets[0].bind_drag(drag_shift) self._rtextwidgets[0].bind_click(self.shift) # Draw the stack top. self._highlight_productions()
def ovalit(canvas, text): return OvalWidget(canvas, TextWidget(canvas, text), fill='cyan')
def boxit(canvas, text): big = ('helvetica', -16, 'bold') return BoxWidget(canvas, TextWidget(canvas, text, font=big), fill='green')
def demo(): import random def fill(cw): cw['fill'] = '#%06d' % random.randint(0, 999999) cf = CanvasFrame(width=550, height=450, closeenough=2) t = Tree(''' (S (NP the very big cat) (VP (Adv sorta) (V saw) (NP (Det the) (N dog))))''') tc = TreeWidget(cf.canvas(), t, draggable=1, node_font=('helvetica', -14, 'bold'), leaf_font=('helvetica', -12, 'italic'), roof_fill='white', roof_color='black', leaf_color='green4', node_color='blue2') cf.add_widget(tc, 10, 10) def boxit(canvas, text): big = ('helvetica', -16, 'bold') return BoxWidget(canvas, TextWidget(canvas, text, font=big), fill='green') def ovalit(canvas, text): return OvalWidget(canvas, TextWidget(canvas, text), fill='cyan') treetok = Tree('(S (NP this tree) (VP (V is) (AdjP shapeable)))') tc2 = TreeWidget(cf.canvas(), treetok, boxit, ovalit, shapeable=1) def color(node): node['color'] = '#%04d00' % random.randint(0, 9999) def color2(treeseg): treeseg.label()['fill'] = '#%06d' % random.randint(0, 9999) treeseg.label().child()['color'] = 'white' tc.bind_click_trees(tc.toggle_collapsed) tc2.bind_click_trees(tc2.toggle_collapsed) tc.bind_click_nodes(color, 3) tc2.expanded_tree(1).bind_click(color2, 3) tc2.expanded_tree().bind_click(color2, 3) paren = ParenWidget(cf.canvas(), tc2) cf.add_widget(paren, tc.bbox()[2] + 10, 10) tree3 = Tree(''' (S (NP this tree) (AUX was) (VP (V built) (PP (P with) (NP (N tree_to_treesegment)))))''') tc3 = tree_to_treesegment(cf.canvas(), tree3, tree_color='green4', tree_xspace=2, tree_width=2) tc3['draggable'] = 1 cf.add_widget(tc3, 10, tc.bbox()[3] + 10) def orientswitch(treewidget): if treewidget['orientation'] == 'horizontal': treewidget.expanded_tree(1, 1).subtrees()[0].set_text('vertical') treewidget.collapsed_tree(1, 1).subtrees()[0].set_text('vertical') treewidget.collapsed_tree(1).subtrees()[1].set_text('vertical') treewidget.collapsed_tree().subtrees()[3].set_text('vertical') treewidget['orientation'] = 'vertical' else: treewidget.expanded_tree(1, 1).subtrees()[0].set_text('horizontal') treewidget.collapsed_tree(1, 1).subtrees()[0].set_text('horizontal') treewidget.collapsed_tree(1).subtrees()[1].set_text('horizontal') treewidget.collapsed_tree().subtrees()[3].set_text('horizontal') treewidget['orientation'] = 'horizontal' text = """ Try clicking, right clicking, and dragging different elements of each of the trees. The top-left tree is a TreeWidget built from a Tree. The top-right is a TreeWidget built from a Tree, using non-default widget constructors for the nodes & leaves (BoxWidget and OvalWidget). The bottom-left tree is built from tree_to_treesegment.""" twidget = TextWidget(cf.canvas(), text.strip()) textbox = BoxWidget(cf.canvas(), twidget, fill='white', draggable=1) cf.add_widget(textbox, tc3.bbox()[2] + 10, tc2.bbox()[3] + 10) tree4 = Tree('(S (NP this tree) (VP (V is) (Adj horizontal)))') tc4 = TreeWidget(cf.canvas(), tree4, draggable=1, line_color='brown2', roof_color='brown2', node_font=('helvetica', -12, 'bold'), node_color='brown4', orientation='horizontal') tc4.manage() cf.add_widget(tc4, tc3.bbox()[2] + 10, textbox.bbox()[3] + 10) tc4.bind_click(orientswitch) tc4.bind_click_trees(tc4.toggle_collapsed, 3) # Run mainloop cf.mainloop()
def boxit(canvas, text): big = ("helvetica", -16, "bold") return BoxWidget(canvas, TextWidget(canvas, text, font=big), fill="green")
def demo(): import random def fill(cw): cw["fill"] = "#%06d" % random.randint(0, 999999) cf = CanvasFrame(width=550, height=450, closeenough=2) t = Tree.fromstring(""" (S (NP the very big cat) (VP (Adv sorta) (V saw) (NP (Det the) (N dog))))""") tc = TreeWidget( cf.canvas(), t, draggable=1, node_font=("helvetica", -14, "bold"), leaf_font=("helvetica", -12, "italic"), roof_fill="white", roof_color="black", leaf_color="green4", node_color="blue2", ) cf.add_widget(tc, 10, 10) def boxit(canvas, text): big = ("helvetica", -16, "bold") return BoxWidget(canvas, TextWidget(canvas, text, font=big), fill="green") def ovalit(canvas, text): return OvalWidget(canvas, TextWidget(canvas, text), fill="cyan") treetok = Tree.fromstring( "(S (NP this tree) (VP (V is) (AdjP shapeable)))") tc2 = TreeWidget(cf.canvas(), treetok, boxit, ovalit, shapeable=1) def color(node): node["color"] = "#%04d00" % random.randint(0, 9999) def color2(treeseg): treeseg.label()["fill"] = "#%06d" % random.randint(0, 9999) treeseg.label().child()["color"] = "white" tc.bind_click_trees(tc.toggle_collapsed) tc2.bind_click_trees(tc2.toggle_collapsed) tc.bind_click_nodes(color, 3) tc2.expanded_tree(1).bind_click(color2, 3) tc2.expanded_tree().bind_click(color2, 3) paren = ParenWidget(cf.canvas(), tc2) cf.add_widget(paren, tc.bbox()[2] + 10, 10) tree3 = Tree.fromstring(""" (S (NP this tree) (AUX was) (VP (V built) (PP (P with) (NP (N tree_to_treesegment)))))""") tc3 = tree_to_treesegment(cf.canvas(), tree3, tree_color="green4", tree_xspace=2, tree_width=2) tc3["draggable"] = 1 cf.add_widget(tc3, 10, tc.bbox()[3] + 10) def orientswitch(treewidget): if treewidget["orientation"] == "horizontal": treewidget.expanded_tree(1, 1).subtrees()[0].set_text("vertical") treewidget.collapsed_tree(1, 1).subtrees()[0].set_text("vertical") treewidget.collapsed_tree(1).subtrees()[1].set_text("vertical") treewidget.collapsed_tree().subtrees()[3].set_text("vertical") treewidget["orientation"] = "vertical" else: treewidget.expanded_tree(1, 1).subtrees()[0].set_text("horizontal") treewidget.collapsed_tree(1, 1).subtrees()[0].set_text("horizontal") treewidget.collapsed_tree(1).subtrees()[1].set_text("horizontal") treewidget.collapsed_tree().subtrees()[3].set_text("horizontal") treewidget["orientation"] = "horizontal" text = """ Try clicking, right clicking, and dragging different elements of each of the trees. The top-left tree is a TreeWidget built from a Tree. The top-right is a TreeWidget built from a Tree, using non-default widget constructors for the nodes & leaves (BoxWidget and OvalWidget). The bottom-left tree is built from tree_to_treesegment.""" twidget = TextWidget(cf.canvas(), text.strip()) textbox = BoxWidget(cf.canvas(), twidget, fill="white", draggable=1) cf.add_widget(textbox, tc3.bbox()[2] + 10, tc2.bbox()[3] + 10) tree4 = Tree.fromstring("(S (NP this tree) (VP (V is) (Adj horizontal)))") tc4 = TreeWidget( cf.canvas(), tree4, draggable=1, line_color="brown2", roof_color="brown2", node_font=("helvetica", -12, "bold"), node_color="brown4", orientation="horizontal", ) tc4.manage() cf.add_widget(tc4, tc3.bbox()[2] + 10, textbox.bbox()[3] + 10) tc4.bind_click(orientswitch) tc4.bind_click_trees(tc4.toggle_collapsed, 3) # Run mainloop cf.mainloop()