Показать график графового потока на панели Javafx

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

Мой код находится в следующей функции:

    void cargaGrafico() {
        SingleGraph graph = aula.getSociogramas().get(currentSocio).getRelaPos().getGraph();
        FxViewer v = new FxViewer(graph,FxViewer.ThreadingModel.GRAPH_IN_GUI_THREAD);
        v.enableAutoLayout();
        FxViewPanel panel = (FxViewPanel)v.addDefaultView(false, new FxGraphRenderer());
        spGraficos.getChildren().add(panel);
    }

где spGraficos — это StackPane javafx. Когда я запускаю код, я получаю на панели очень маленький график, не интерактивный, и кажется, что график выполняется в другом потоке, потому что я получаю следующее исключение:

Exception in thread "Thread-2" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-2
    at javafx.graphics@22-ea/com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:294)
    at javafx.graphics@22-ea/com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:475)
    at javafx.graphics@22-ea/javafx.animation.Animation.play(Animation.java:990)
    at [email protected]/org.graphstream.ui.fx_viewer.FxViewer.lambda$init$1(FxViewer.java:220)
    at java.base/java.lang.Thread.run(Thread.java:1570)e here

Я также искал список рассылки Graphstream, но, похоже, его уже нет в живых. Заранее спасибо!

Это минимальный воспроизводимый пример: В Intellij Idea я начинаю новый проект javafx, только с кнопкой и панелью привязки. Когда я нажимаю кнопку, граф графового потока заполняется, и его следует поместить в панель привязки. Результат тот же, маленький график и то же исключение. Код: ПриветПриложение.java

package com.probags.probags;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
        Scene scene = new Scene(fxmlLoader.load(), 820, 950);
        stage.setTitle("Hello!");
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        System.setProperty("org.graphstream.ui", "javafx");
        launch();
    }
}

Приветконтроллер.java

package com.probags.probags;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import org.graphstream.graph.Graph;
import org.graphstream.graph.implementations.SingleGraph;
import org.graphstream.ui.fx_viewer.FxViewPanel;
import org.graphstream.ui.fx_viewer.FxViewer;
import org.graphstream.ui.javafx.FxGraphRenderer;

public class HelloController {

    @FXML
    private AnchorPane apGraph;
    @FXML
    private Label welcomeText;
    private Graph graph = new SingleGraph("Test");
    @FXML
    void onHelloButtonClick(ActionEvent event) {
        populateGraph();
        FxViewer v = new FxViewer(graph,FxViewer.ThreadingModel.GRAPH_IN_GUI_THREAD);
        v.enableAutoLayout();
        FxViewPanel panel = (FxViewPanel)v.addDefaultView(false, new FxGraphRenderer());
        apGraph.getChildren().add(panel);
    }

    void populateGraph() {
        graph.addNode("A" );
        graph.addNode("B" );
        graph.addNode("C" );
        graph.addEdge("AB", "A", "B");
        graph.addEdge("BC", "B", "C");
        graph.addEdge("CA", "C", "A");
    }

}

модуль-info.java

module com.probags.probags {
    requires javafx.controls;
    requires javafx.fxml;
    requires gs.core;
    requires gs.ui.javafx;


    opens com.probags.probags to javafx.fxml;
    exports com.probags.probags;
}

Я использую gs.core и gs.ui.javafx 2.0, включенные в структуру проекта Intellij Idea от Maven.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
65
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Проблемы с вашим кодом

Я не знаю граф-стрима, но у вас есть ThreadingModel.GRAPH_IN_GUI_THREAD. И трассировка стека показывает, что вы не находитесь в потоке графического интерфейса. Чтобы запустить код в потоке графического интерфейса (JavaFX), используйте Platform.runLater. Поскольку графический поток, похоже, полагается на некоторый код Swing для некоторых операций, я не знаю, означает ли контекст этого, что поток графического интерфейса должен быть потоком JavaFX или потоком AWT. Если у вас по-прежнему возникают проблемы, предоставьте минимальный воспроизводимый пример.

Я попробовал использовать образец учебного приложения GraphStream JavaFX, и он у меня сработал нормально (JavaFX 22.0.2, Java 21, OS X 14.5 — Intel). Я использовал модель потоков по умолчанию из примера кода FxViewer.ThreadingModel.GRAPH_IN_ANOTHER_THREAD.

Рабочий пример

Я попробовал создать проект по инструкции https://github.com/graphstream/gs-ui-javafx/tree/master.

Используемый значок был взят отсюда:

Код диаграммы был взят и изменен отсюда:

Изменения были незначительными: они касались загрузки ресурсов для значка, чтобы он работал в модульной среде, очистки для использования lamdas, удаления неиспользуемого кода и установки документированного системного свойства для маршрутизации графического потока через JavaFX.

Информацию об авторских правах смотрите в исходной ссылке.

Выход

Пример кода выводит 4 графика, здесь я показываю только один. Это довольно уродливый результат. Я не уверен, так ли это должно выглядеть, но именно это он и создал.

Источник

package org.example.graphstream;

import org.graphstream.graph.Edge;
import org.graphstream.graph.Graph;
import org.graphstream.graph.Node;
import org.graphstream.graph.implementations.MultiGraph;
import org.graphstream.ui.fx_viewer.FxDefaultView;
import org.graphstream.ui.fx_viewer.FxViewer;
import org.graphstream.ui.view.Viewer;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.stage.Stage;

import java.util.Objects;

public class TutorialDiagrams extends Application {
    public static final String URL_IMAGE = Objects.requireNonNull(TutorialDiagrams.class.getResource("/org/graphstream/ui/viewer_fx/test/data/icon.png")).toString();
    
    public static void main(String[] args) {
        System.setProperty("org.graphstream.ui", "javafx");
        launch(args);
    }

    public void start(Stage primaryStage) {
        Scene scene1 = diagram1("diagram1", styleSheet1);
        Scene scene2 = diagram1b("diagram1b", styleSheet1);
        Scene scene3 = diagram2("diagram2", styleSheet1);
        Scene scene4 = diagram3("diagram3", styleSheet2);
        
        primaryStage.setScene(scene1);
        primaryStage.setOnCloseRequest(t -> Platform.exit());
        primaryStage.show();
        
        Stage stage2 = new Stage();
        stage2.setX(primaryStage.getX() + primaryStage.getWidth());
        stage2.setY(primaryStage.getY());
        stage2.setScene(scene2);
        stage2.setOnCloseRequest(t -> Platform.exit());
        stage2.show();
        
        Stage stage3 = new Stage();
        stage3.setX(primaryStage.getX());
        stage3.setY(primaryStage.getY() + primaryStage.getY());
        stage3.setScene(scene3);
        stage3.setOnCloseRequest(t -> Platform.exit());
        stage3.show();
        
        Stage stage4 = new Stage();
        stage4.setX(primaryStage.getX() + primaryStage.getWidth());
        stage4.setY(primaryStage.getY() + primaryStage.getY());
        stage4.setScene(scene4);
        stage4.setOnCloseRequest(t -> Platform.exit());
        stage4.show();
    }
    
    public Scene diagram(Graph graph, String style, String title, int width, int height) {
         graph.setAttribute("ui.quality");
         graph.setAttribute("ui.antialias");
         graph.setAttribute("ui.stylesheet", style);
         
         graph.setAttribute("ui.screenshot", title+".png");
         
         Viewer viewer = new FxViewer( graph, FxViewer.ThreadingModel.GRAPH_IN_ANOTHER_THREAD );
         FxDefaultView view = (FxDefaultView) viewer.addDefaultView(true);
         view.resize(width, height);

        return new Scene(view, width, height, true, SceneAntialiasing.DISABLED);
    }
    
    public Scene diagram1(String title, String styleSheet) {
        MultiGraph graph = new MultiGraph(title);
        Scene s = diagram(graph, styleSheet, title, 500, 250);
        
        Node G = graph.addNode("Graph");
        Node V = graph.addNode("Viewer");
        Edge E = graph.addEdge("G->V", "Graph", "Viewer", true);
        
        G.setAttribute("xyz", new double[] {0, 0, 0});
        V.setAttribute("xyz", new double[] {1, 0, 0});
        G.setAttribute("ui.label", "Graph");
        V.setAttribute("ui.label", "Viewer");
        
        return s ;
    }
    
    public Scene diagram1b(String title, String styleSheet) {
        MultiGraph graph = new MultiGraph(title);
        Scene s = diagram(graph, styleSheet, title, 500, 370);
        
        Node G = graph.addNode("Graph");
        Node V = graph.addNode("Viewer");
        Node B1 = graph.addNode("bidon1");
        Node B2 = graph.addNode("bidon2");
        
        graph.addEdge("G->bidon1", "Graph", "bidon1", true);
        graph.addEdge("bidon1->V", "bidon1", "Viewer", true);
        graph.addEdge("V->bidon2", "Viewer", "bidon2", true);
        graph.addEdge("bidon2->G", "bidon2", "Graph", true);
        
        G.setAttribute("xyz", new double[]{0, 0, 0});
        B1.setAttribute("xyz", new double[]{0, 0.5, 0});
        V.setAttribute("xyz", new double[]{1, 0.5, 0});
        B2.setAttribute("xyz", new double[]{1, 0, 0});
        G.setAttribute("ui.label", "Graph");
        V.setAttribute("ui.label", "Viewer");
        B1.setAttribute("ui.class", "invisible");
        B2.setAttribute("ui.class", "invisible");
        
        return s;
    }
    
    public Scene diagram2(String title, String styleSheet) {
        MultiGraph graph = new MultiGraph(title);
        Scene s = diagram(graph, styleSheet, title, 500, 250);
        
        Node G = graph.addNode("Graph");
        Node P = graph.addNode("Pipe");
        Node V = graph.addNode("Viewer");
                
        graph.addEdge("G->P", "Graph", "Pipe", true);
        graph.addEdge("P->V", "Pipe", "Viewer", true);
         
        G.setAttribute("xyz", new double[] {0, 0, 0});
        P.setAttribute("xyz", new double[] {1, 0, 0});
        V.setAttribute("xyz", new double[] {2, 0, 0});
        G.setAttribute("ui.label", "Graph");
        P.setAttribute("ui.label", "Pipe");
        V.setAttribute("ui.label", "Viewer");
        
        return s;
    }
    
    public Scene diagram3(String title, String styleSheet) {
        MultiGraph graph = new MultiGraph(title);
        Scene s = diagram(graph, styleSheet, title, 800, 500);
        
        Node G = graph.addNode("Graph");
        Node V = graph.addNode("Viewer");
        Node P1 = graph.addNode("GtoV");
        Node P2 = graph.addNode("VtoG");
        graph.addEdge("G->GtoV", "Graph", "GtoV", true);
        graph.addEdge("GtoV->V", "GtoV", "Viewer", true);
        graph.addEdge("VtoG<-V", "Viewer", "VtoG", true);
        graph.addEdge("G<-VtoG", "VtoG", "Graph", true);
                
        G.setAttribute("ui.label", "Graph");
        P1.setAttribute("ui.label", "Pipe");
        P2.setAttribute("ui.label", "ViewerPipe");
        V.setAttribute("ui.label", "Viewer");
            
        G.setAttribute("xyz", new double[] {-2,  0, 0});
        P1.setAttribute("xyz", new double[] {-1,  1.4, 0});
        P2.setAttribute("xyz", new double[] { 1, -1.4, 0});
        V.setAttribute("xyz", new double[] { 2,  0, 0});
        
        return s;
    }
    
    public String styleSheet1 = 
            "graph {"+
            "   padding: 90px;"+
            "}"+
            "node {"+
            "   size: 128px;"+
            "   shape: box;"+
            "   fill-mode: image-scaled;"+
            "   fill-image: url('"+URL_IMAGE+"');"+
            "   text-alignment: under;"+
            "   text-color: #DDD;"+
            "   text-background-mode: rounded-box;"+
            "   text-background-color: #333;"+
            "   text-padding: 4px;"+
            "}"+
            "node#Pipe {"+
            "   fill-image: url('"+URL_IMAGE+"');"+
            "}"+
            "node#Viewer {"+
            "   fill-image: url('"+URL_IMAGE+"');"+
            "}"+
            "node.invisible {"+
            "   fill-mode: plain;"+
            "   fill-color: #0000;"+
            "}"+
            "edge {"+
            "   size: 4px;"+
            "   fill-color: #979797;"+
            "   arrow-shape: none;"+
            "}";
    
    public String styleSheet2 = 
        "graph {"+
        "   padding: 90px;"+
        "}"+
        "node {"+
        "   size: 128px;"+
        "   shape: box;"+
        "   fill-mode: image-scaled;"+
        "   fill-image: url('"+URL_IMAGE+"');"+
        "   text-alignment: under;"+
        "   text-color: #DDD;"+
        "   text-background-mode: rounded-box;"+
        "   text-background-color: #333;"+
        "   text-padding: 4px;"+
        "}"+
        "node#Graph {"+
        "   fill-image: url('"+URL_IMAGE+"');"+
        "}"+
        "node#Viewer {"+
        "   fill-image: url('"+URL_IMAGE+"');"+
        "}"+
        "node#VtoG {"+
        "   fill-image: url('"+URL_IMAGE+"');"+
        "}"+
        "edge {"+
        "   size: 4px;"+
        "   fill-color: #979797;"+
        "   shape: L-square-line;"+
        "   arrow-size: 25px, 10px;"+
        "   arrow-shape: none;"+
        "}";
}

модуль-info.java

module org.example.graphstream {
    requires javafx.controls;
    requires javafx.swing;

    requires gs.core;
    requires gs.ui.javafx;

    exports org.example.graphstream;
}

pom.xml

<?xml version = "1.0" encoding = "UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0"
         xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>graph-stream</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>graph-stream</name>

    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>22.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-swing</artifactId>
            <version>22.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.graphstream</groupId>
            <artifactId>gs-core</artifactId>
            <version>2.0</version>
        </dependency>

        <dependency>
            <groupId>org.graphstream</groupId>
            <artifactId>gs-ui-javafx</artifactId>
            <version>2.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <source>21</source>
                    <target>21</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Пример стиля FXML

pom.xml

То же, что и выше, просто добавьте следующую зависимость.

<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-fxml</artifactId>
    <version>22.0.2</version>
</dependency>

привет-view.fxml

<?xml version = "1.0" encoding = "UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.VBox?>

<VBox fx:id = "apGraph" xmlns = "http://javafx.com/javafx/19" xmlns:fx = "http://javafx.com/fxml/1"
      fx:controller = "org.example.graphstream.HelloController">
    <Button mnemonicParsing = "false" text = "Show Graph" onAction = "#onHelloButtonClick"/>
</VBox>

модуль.информация

module org.example.graphstream {
    requires javafx.controls;
    requires javafx.swing;
    requires javafx.fxml;

    requires gs.core;
    requires gs.ui.javafx;

    opens org.example.graphstream to javafx.fxml;
    exports org.example.graphstream;
}

ПриветПриложение.java

package org.example.graphstream;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
        stage.setScene(
                new Scene(fxmlLoader.load(), 820, 950)
        );
        stage.show();
    }

    public static void main(String[] args) {
        System.setProperty("org.graphstream.ui", "javafx");
        launch();
    }
}

Приветконтроллер.java

package org.example.graphstream;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.layout.VBox;
import org.graphstream.graph.Graph;
import org.graphstream.graph.implementations.SingleGraph;
import org.graphstream.ui.fx_viewer.FxViewPanel;
import org.graphstream.ui.fx_viewer.FxViewer;
import org.graphstream.ui.javafx.FxGraphRenderer;

public class HelloController {

    @FXML
    private VBox apGraph;

    private Graph graph = new SingleGraph("Test");

    @FXML
    void onHelloButtonClick(ActionEvent event) {
        populateGraph();
        FxViewer v = new FxViewer(graph,FxViewer.ThreadingModel.GRAPH_IN_GUI_THREAD);
        v.enableAutoLayout();
        FxViewPanel panel = (FxViewPanel)v.addDefaultView(false, new FxGraphRenderer());
        apGraph.getChildren().add(panel);
    }

    void populateGraph() {
        graph.addNode("A" );
        graph.addNode("B" );
        graph.addNode("C" );
        graph.addEdge("AB", "A", "B");
        graph.addEdge("BC", "B", "C");
        graph.addEdge("CA", "C", "A");
    }
}

Я могу запустить свой код, не думаю, что это проблема с библиотеками или конфигурацией. Единственный вопрос связан с потоком, в котором работает граф. Даже если я использую ThreadingModel.GRAPH_IN_ANOTHER_THREAD, я получаю то же исключение. Что касается вашего кода, вы уверены, что это последняя версия графстрима? В последней версии Viewer стал абстрактным классом. Я использую gs-core и gs-ui-javafx 2.0 (без предварительной альфа-версии). В любом случае, я не думаю, что это главное. Спасибо в любом случае!

Serinus Serinus 19.07.2024 17:51

Спасибо за ответ!. Я отредактировал вопрос, добавив минимальный воспроизводимый пример.

Serinus Serinus 20.07.2024 11:35

@SerinusSerinus Я не могу повторить вашу проблему. Я добавил код, который пробовал, в раздел «Пример стиля FXML».

jewelsea 23.07.2024 01:10

После долгих усилий над своим кодом мне удалось воспроизвести простую версию без исключений. Я понял, что проблема связана с библиотеками javafx, которые я использовал. Я использовал версию 22-ea+16 от Maven. Я вручную импортировал версию 22.0.2 из сети Oracle, и все работает нормально. Спасибо Jewelsea за то, что подсказали мне несколько интересных предложений.

ea версии являются нестабильными версиями раннего доступа. Вероятно, вы столкнулись с ошибкой в ​​версии раннего доступа, которая, к счастью, была исправлена ​​в релизной версии.
jewelsea 25.07.2024 11:45

Другие вопросы по теме