Prefuse Toolkit: динамическое добавление узлов и ребер - PullRequest
4 голосов
/ 02 февраля 2009

У кого-нибудь есть опыт работы с инструментарием prefuse graph? Можно ли изменить уже отображенный график, т.е. добавить / удалить узлы и / или ребра и правильно ли настроить дисплей?

Например, prefuse поставляется с примером, который визуализирует сеть друзей:

http://prefuse.org/doc/manual/introduction/example/Example.java

Я хотел бы сделать что-то вроде этого:

// -- 7. add new nodes on the fly -------------------------------------
new Timer(2000, new ActionListener() {
    private Node oldNode = graph.nodes().next(); // init with random node

    public void actionPerformed(ActionEvent e) {
        // insert new node //
        Node newNode = graph.addNode();

        // insert new edge //
        graph.addEdge(oldNode, newNode);

        // remember node for next call //
        oldNode = newNode;
    }
}).start();

Но, похоже, это не работает. Есть намеки?

Ответы [ 4 ]

7 голосов
/ 03 февраля 2009

Вы должны знать несколько слоев префузии:

  • Данные
  • Визуализация
  • Дисплей

Короче говоря, три слоя можно связать следующим образом:

Graph graph = new Graph(eg. yourXML_file);
Visualization viz = new Visualization();
viz.add(GRAPH, graph);
Display disp = new Display();
disp.setVisualization(viz);

Отображение - это графический компонент, который обычно добавляется на панель.

Здесь вы изменяете только слой данных.

Node newNode = graph.addNode();
graph.addEdge(oldNode, newNode);

Теперь вам нужно обновить визуальный слой:

viz.run("repaint");

Необходимо определить действие repaint .

ActionList repaint = new ActionList();
repaint.add(new RepaintAction());
viz.putAction("repaint", repaint);

Я действительно советую вам прочитать prefuse doc . И вы можете найти много ресурсов на официальном форуме

По крайней мере, я могу вам сказать, что на данный момент prefuse не очень эффективен для обновления живого графика.

Но этого должно быть недостаточно, так как вы изменили структуру графа, вы должны восстановить ее в визуализации (то есть пересчитать размещение узлов и т. Д.). В вашем примере кода уже определены два действия. Запустите их в конце вашего действия.

viz.run("color");
viz.run("layout");

Этот метод не очень эффективен, потому что он добавляет много вычислений каждый раз, когда вы добавляете узел, но на данный момент нет других с prefuse.

6 голосов
/ 06 февраля 2009

Как указывалось в моем другом посте, причина, по которой новые узлы и ребра не видны в исходном примере, заключается в том, что цвета и т. Д. Для узлов установлены неправильно. Один из способов исправить это - явно вызвать vis.run («color»); всякий раз, когда был добавлен узел или ребро.

В качестве альтернативы, мы можем гарантировать, что действие color всегда выполняется, инициализируя ActionList, к которому мы его добавляем (называемый «color» в исходном примере), немного по-другому:

вместо

ActionList color = new ActionList();

мы могли бы написать

ActionList color = new ActionList(Activity.INFINITY);

Это позволяет бесконечно долго выполнять список действий, так что новые узлы / ребра будут автоматически инициализироваться для их визуального вида.

Однако мне неясно, будет ли это на самом деле предпочтительным методом - для таких вещей, как действие динамического макета (например, ForceDirectedLayout), такое объявление имеет смысл, но для цветов мне кажется, что постоянно работающая раскраска действие в основном накладное.

Таким образом, возможно, лучшим решением было бы опубликованное ранее решение, состоящее в том, чтобы просто выполнить действие «color» явно (но только один раз) всякий раз, когда граф расширяется ...

2 голосов
/ 06 февраля 2009

Хорошо, немного покопавшись в префузионных источниках, теперь я лучше понимаю, как все работает под капотом. Я обнаружил, что на самом деле новые узлы, которые я создаю с помощью приведенного выше кода, не только правильно добавляются в граф, но и визуализация принимает это к сведению!

Таким образом, в отличие от Джерома, нет необходимости явно вызывать vis.run ("layout").

Причина, по которой я думал, что узлы не были добавлены правильно, заключалась в том, что они нарисованы с белым фоном, границей и цветом текста - на белом фоне, то есть. Не удивительно, что их немного трудно обнаружить.

Чтобы исправить это, нужно вызвать цветовое действие после вставки нового узла, например:

// insert new edge //
graph.addEdge(oldNode, newNode);
vis.run("color"); // <- this is new

(Обратите внимание, что это действие определено далее в коде Example.jar в разделе // - 4.)

И последнее, в чем я сейчас не уверен, так это то, заставит ли вызов этого действия префузию снова пройти по всем узлам графа и установить их цвет - для очень больших графов, что, конечно, нежелательно.

0 голосов
/ 02 февраля 2009

Вы должны указать контейнеру управления ('d', в example.java) перерисоваться. Вызывать invalidate () должно быть достаточно (хотя и не уверен).

В любом случае, это может вам помочь.

...