【问题标题】:Implementing a node-based graphical interface?实现基于节点的图形界面?
【发布时间】:2018-04-30 08:07:04
【问题描述】:

我想实现一个节点接口,基本上是一个DAG,每个节点对其输入连接执行操作,并输出一些东西(您可以连接到另一个节点)

一些示例应用程序:


作为第一个目标,我想要一个只有 2 个节点的图形应用程序。一个“数字”,它简单地输出一个固定的数字,一个“加”节点,它接受两个输入并输出两者的总和。

到目前为止,正如人们所回答的那样,我对如何在代码中表示数据有一个粗略的了解,例如在 Python 的伪代码中:

class Number:
    def __init__(self, value):
        self.value = value

    def eval(self):
        return self.value

class Add:
    def __init__(self, input1, input2):
        self.input1 = input1
        self.input2 = input2

    def eval(self):
        return self.input1.eval() + self.input2.eval()


a = Number(20)
b = Number(72)

adder = Add(a, b)
print adder.eval()

我将如何围绕此包装自定义 GUI?类似下面的东西,但手绘的稍微少一点!

我会从哪里开始?我目前计划用 Objective-C/Cocoa 编写它,尽管我非常愿意接受其他语言的建议。

【问题讨论】:

    标签: python user-interface directed-graph


    【解决方案1】:

    我将从建模一些基本接口开始(在 OOP 意义上,而不是 GUI 意义上)。在我看来,您将拥有一个接受输入集合和单个输出的节点。您没有说明数据类型有多广泛,但您需要一些合适的方法来表示您的输入/输出。对于您的第一个目标,这可以是一个整数。

    在一些通用的 C 风格 OOP 语言中(希望它有意义):

    class Node<T> {
        Node<T>[] inputs;
        T eval();
    }
    
    class AdderNode extends Node<int> {
        int eval() {
            int accum = 0;
            for (inputs : i)
                accum += i.eval();
            return i;
        }
    }
    
    class ConstNode<int I> extends Node<int> {
        int eval() { return I; }
    }
    
    AdderNode a;
    a.inputs.add(ConstNode<2>());
    a.inputs.add(ConstNode<3>());
    a.eval();
    

    您可以通过将 int 替换为一些抽象类、泛型或接口来扩展此功能。当然,实际实现会因实际语言而异。

    【讨论】:

      【解决方案2】:

      我将从对有趣的操作进行建模开始。最终,您会将它们连接到一个 UI,但那是方向盘和油门踏板,而不是引擎。

      您尝试构建的内容与编程语言有很多共同点:变量、值、类型、表达式、求值等。许多比喻都是适用的,可能会提供一些指导。

      如果您使用的是 .NET 3.5,则可以选择 Expression Trees,它允许您在运行时表示和编译代码表达式。

      例如,为您的第一个目标建模:

      using System.Linq.Expressions;
      
      ConstantExpression theNumber2 = Expression.Constant(2);
      ConstantExpression theNumber3 = Expression.Constant(3);
      
      BinaryExpression add2And3 = Expression.Add(theNumber2, theNumber3);
      

      要调用表达式,我们需要用一个方法包装add2And3。这是通过 lambda 表达式完成的:

      Expression<Func<int>> add2And3Lambda = Expression.Lambda<Func<int>>(add2And3);
      

      Func&lt;int&gt; 表示不带参数并返回int 的方法。在 C# 中,add2And3Lambda 表示的代码将是:

      () => 2 + 3
      

      所以我们有一个表达式树,它的根是一个方法。因为方法是可调用的,我们可以将树编译成底层委托类型的实例:

      Func<int> add2And3Func = add2And3Lambda.Compile();
      

      现在我们可以调用我们构建的代码了:

      int theNumber5 = add2And3Func();
      

      支持 .NET 语言可用的每个表达式。

      想象图中的每个节点都有一个与之关联的Expression。这可能会让您了解表达式树的强大功能以及它们如何帮助您完成这项任务。

      【讨论】:

        【解决方案3】:

        所有节点系统的共同点是它们描述了一种函数式编程语言。一个函数接受多个参数并返回一个结果,无论它的设计目的是什么。一些例子:

        • 图形:模糊(图像、内核、半径)-> 图像

        • 数学:加(数字,数字)-> 数字

        • 关系:过滤器(表,谓词)-> 表

        基本上归结为 Func&lt;object[], object&gt; (C#) 之类的函数签名。

        您将面临如何使您的节点系统持久化的问题。你想让一个节点的结果只被另一个节点(树)或多个节点(图)用作参数吗?

        一棵树的例子,直接有一个子节点的参数:

        Add(
          Multiply(
            Constant(5),
            Constant(4)
          ),
          Multiply(
            Constant(5),
            Constant(3)
          )
        )
        

        图表示例,将所有节点存储在列表中,仅使用引用:

        A := Constant(5)
        B := Constant(4)
        C := Constant(3)
        
        D := Func(Multiply, A, B)
        E := Func(Multiply, A, C)
        
        F := Func(Add, D, E)
        

        【讨论】:

          【解决方案4】:

          我发现了一些关于在 Cocoa 中实现这样一个接口的有用信息:

          【讨论】:

            【解决方案5】:

            我在研究类似解决方案时偶然发现了这个线程。 最近在github上发现了一个不错的项目https://github.com/nodebox/nodebox 这似乎正是您正在寻找的。至少可以从项目中提取和采用编辑器组件。

            问候, 斯蒂芬

            【讨论】:

            • 欢迎来到 StackOverflow,感谢您的贡献,但不鼓励仅提供链接的答案。请查看answering guidelines。一个好的经验法则是在没有链接的情况下查看您的答案,如果它几乎没有价值,请考虑扩展。
            【解决方案6】:

            也许bwise 有兴趣?

            this page 的下半部分展示了一个使用 bwise 创建以两个数字作为输入的乘法块的示例。

            【讨论】:

              【解决方案7】:

              我实现了一个执行图,就像您在这个项目中描述的那样: GRSFramework

              源码可以在here找到。

              目前我正致力于在项目ExecutionGraph 中发布该系统的更好、更干净的版本。
              您可能也会感兴趣。

              还有来自 Google 的 TensorFlow 库,它实现了类似的系统 TensorFlow

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-03-25
                • 2018-10-31
                • 1970-01-01
                • 2013-03-25
                • 1970-01-01
                • 1970-01-01
                • 2021-09-12
                • 1970-01-01
                相关资源
                最近更新 更多