我想使用由 DOT(python 中的 pyDot)生成的图形作为交互式树结构 GUI 的基础,其中树中的每个节点都可以是小部件。
该树基本上是一个二进制莫尔斯电码树,它从顶部节点开始向下导航到所需的字母并选择它。他们要选择的节点应该是可突出显示的,并且应该能够根据用户输入更改其内容(字母)。
基本上,我希望将节点变成具有可调参数的全尺寸对象,这些参数会随着接口的使用而改变。谁能指出我正确的方向才能做到这一点?
我想使用由 DOT(python 中的 pyDot)生成的图形作为交互式树结构 GUI 的基础,其中树中的每个节点都可以是小部件。
该树基本上是一个二进制莫尔斯电码树,它从顶部节点开始向下导航到所需的字母并选择它。他们要选择的节点应该是可突出显示的,并且应该能够根据用户输入更改其内容(字母)。
基本上,我希望将节点变成具有可调参数的全尺寸对象,这些参数会随着接口的使用而改变。谁能指出我正确的方向才能做到这一点?
我从演示代码开始:http ://wiki.wxpython.org/AnotherTutorial#wx.TreeCtrl 。我添加了 build_tree、_build_tree_helper 和 build_conn_dict 方法。dot_parser 库中感兴趣的关键方法是 edge.get_source() 和 edge.get_destination() 用于制作“连接”字典。
点图存储在 dot_data 变量中。重要的是,点图不能循环;也就是说,它必须是生成树,否则 _build_tree_helper 方法将无限循环(并且在 TreeControl 中没有意义)。
我还必须根据https://github.com/nlhepler/pydot-py3/issues/1#issuecomment-15999052修补 dot_parser 以使其正常工作。
import wx
from dot_parser import parse_dot_data
class MyFrame(wx.Frame):
def __init__(self, parent, id, title, **kwargs):
self.parsed_dot = kwargs.pop("parsed_dot", None)
wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(450, 350))
hbox = wx.BoxSizer(wx.HORIZONTAL)
vbox = wx.BoxSizer(wx.VERTICAL)
panel1 = wx.Panel(self, -1)
panel2 = wx.Panel(self, -1)
self.tree = wx.TreeCtrl(panel1, 1, wx.DefaultPosition, (-1,-1), wx.TR_HAS_BUTTONS | wx.TR_LINES_AT_ROOT )
self.build_tree(self.tree)
self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=1)
self.display = wx.StaticText(panel2, -1, "",(10,10), style=wx.ALIGN_CENTRE)
vbox.Add(self.tree, 1, wx.EXPAND)
hbox.Add(panel1, 1, wx.EXPAND)
hbox.Add(panel2, 1, wx.EXPAND)
panel1.SetSizer(vbox)
self.SetSizer(hbox)
self.Centre()
def build_conn_dict(self):
conn_dict = {}
if(self.parsed_dot):
for edge in self.parsed_dot.get_edges():
conn_dict.setdefault(edge.get_source(), []).append(edge.get_destination())
return conn_dict
def build_tree(self, tree):
if(self.parsed_dot):
conn_dict = self.build_conn_dict()
outs = set(conn_dict.keys())
ins = reduce(lambda x, y: x | set(y), conn_dict.values(), set([]))
roots = list(outs - ins)
roots = dict([(root, tree.AddRoot(root)) for root in roots])
self._build_tree_helper(tree, conn_dict, roots)
def _build_tree_helper(self, tree, conn_dict = {}, roots = {}):
new_roots = {}
for root in roots:
if(conn_dict.has_key(root)):
for sub_root in conn_dict[root]:
new_roots[sub_root] = tree.AppendItem(roots[root], sub_root)
if(new_roots):
self._build_tree_helper(tree, conn_dict, new_roots)
def OnSelChanged(self, event):
item = event.GetItem()
self.display.SetLabel(self.tree.GetItemText(item))
child_text = self.tree.GetItemText(item)
parent_text = ""
try:
parent = self.tree.GetItemParent(item)
parent_text = self.tree.GetItemText(parent)
except wx._core.PyAssertionError:
pass
print "child: %s, parent: %s" % (child_text, parent_text)
class MyApp(wx.App):
def OnInit(self):
dot_data = \
'''
graph ""
{
label="(% (EXP (% (X) (% (X) (X)))) (EXP (SIN (X))))"
n039 ;
n039 [label="%"] ;
n039 -> n040 ;
n040 [label="EXP"] ;
n040 -> n041 ;
n041 [label="%"] ;
n041 -> n042 ;
n042 [label="X"] ;
n041 -> n043 ;
n043 [label="%"] ;
n043 -> n044 ;
n044 [label="X"] ;
n043 -> n045 ;
n045 [label="X"] ;
n039 -> n046 ;
n046 [label="EXP"] ;
n046 -> n047 ;
n047 [label="SIN"] ;
n047 -> n048 ;
n048 [label="X"] ;
}
'''
parsed_dot = parse_dot_data(dot_data)
frame = MyFrame(None, -1, "treectrl.py", parsed_dot = parsed_dot)
frame.Show(True)
self.SetTopWindow(frame)
return True
app = MyApp(0)
app.MainLoop()