2

I am trying to compare outputs of community detection algorithms and I would like to do a side-by-side comparison. The idea is, that I will have two windows showing the same layout of the graph and I colour nodes and edges based on the selected output. A simple example is something like this: Example view if GUI

I am able to produce a graph and create views, but I did not found, how to force the same graph layout in Graphstream for two graphs or assign different UI attributes based on the Graphstream view.

Does anyone have experience with this?

In a toy example, it seems that I get a similar result, although not the same. The problem starts, once I use thousands of nodes, it seems, that layout is quite different. Unfortunately, I cannot provide a dataset for such a case. Here is an example with bigger data:

enter image description here Both graphs have the same layout manager (SpringBox) and use the same data.

I am using Java 8, Graphstream 2.0 and Swing

EDIT: I found, that it is possible to pass Random as a seed into Layout, but unfortunately it is not resulting in the same graph.

import org.graphstream.graph.Element;
import org.graphstream.graph.Graph; 
import org.graphstream.graph.implementations.DefaultGraph;
import org.graphstream.ui.layout.springbox.implementations.SpringBox;
import org.graphstream.ui.swing.SwingGraphRenderer;
import org.graphstream.ui.swing_viewer.DefaultView;
import org.graphstream.ui.swing_viewer.SwingViewer;
import org.graphstream.ui.swing_viewer.ViewPanel;
import org.graphstream.ui.view.Viewer;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Main {


public static void main(String[] args) {
    Main main = new Main();
    SwingUtilities.invokeLater(main::display);
}


private void display(){
    System.setProperty("org.graphstream.ui", "swing");

    Graph sourceGraph = prepareGraph();

    Viewer viewer1 = new SwingViewer(sourceGraph, Viewer.ThreadingModel.GRAPH_IN_GUI_THREAD);
    viewer1.enableAutoLayout(new SpringBox());
    Viewer viewer2 = new SwingViewer(sourceGraph, Viewer.ThreadingModel.GRAPH_IN_GUI_THREAD);
    viewer2.enableAutoLayout(new SpringBox());
    ViewPanel viewPanel1 = new DefaultView(viewer1,"panel1",new SwingGraphRenderer());
    viewPanel1.setPreferredSize(new Dimension(750,350));
    ViewPanel viewPanel2 = new DefaultView(viewer2,"panel2",new SwingGraphRenderer());
    viewPanel2.setPreferredSize(new Dimension(750,350));


    JPanel panel1 = new JPanel();
    panel1.setBackground(Color.gray);
    panel1.setLayout(new BorderLayout());
    panel1.setPreferredSize(new Dimension(750,350));
    panel1.add(viewPanel1,BorderLayout.CENTER);

    JPanel panel2 = new JPanel();
    panel1.setBackground(Color.blue);
    panel2.setLayout(new BorderLayout());
    panel2.setPreferredSize(new Dimension(750,350));
    panel2.add(viewPanel2, BorderLayout.CENTER);

    JPanel graphPanel = new JPanel();
    graphPanel.setPreferredSize(new Dimension(1600, 600));
    graphPanel.setLayout(new BorderLayout(10,10));
    graphPanel.add(panel1,BorderLayout.WEST);
    graphPanel.add(panel2, BorderLayout.EAST);

    JComboBox<String> lCCommunitiesNames = new JComboBox<>();
    lCCommunitiesNames.setPreferredSize(new Dimension(795,30));
    
    JPanel lCComboPanel = new JPanel();
    lCComboPanel.setLayout(new BorderLayout());
    lCComboPanel.add(lCCommunitiesNames,BorderLayout.CENTER);


    JComboBox<String> minoltaCommunitiesNames = new JComboBox<>();
    minoltaCommunitiesNames.setPreferredSize(new Dimension(795,30));
    JPanel minoltaComboPanel = new JPanel();
    minoltaComboPanel.setLayout(new BorderLayout());
    minoltaComboPanel.add(minoltaCommunitiesNames, BorderLayout.CENTER);

    JPanel selectorPanel = new JPanel();
    selectorPanel.setLayout(new BorderLayout(10,10));
    graphPanel.setPreferredSize(new Dimension(1600, 100));
    selectorPanel.add(lCComboPanel,BorderLayout.WEST);
    selectorPanel.add(minoltaCommunitiesNames, BorderLayout.EAST);

    JFrame f=new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.setSize(new Dimension(1600,900));
    f.setLayout(new BorderLayout(200,10));
    f.add(graphPanel,BorderLayout.WEST);
    f.add(selectorPanel,BorderLayout.SOUTH);
    f.setVisible(true);

}

private Graph prepareGraph(String path){
    Graph graph = new DefaultGraph("sampleGraph");
    graph.setAutoCreate(true);
    graph.setStrict(false);
    graph.addNode("A");
    graph.addNode("B");
    graph.addNode("C");
    graph.addNode("D");
    graph.addNode("E");
    graph.addEdge("1","A","B");
    graph.addEdge("2","A","C");
    graph.addEdge("3","C","B");
    graph.addEdge("4","C","D");
    graph.addEdge("5","C","E");
    return graph;
}
}
Jakub Peschel
  • 135
  • 1
  • 8

1 Answers1

0

You'll have to add your graphs, but here's the GUI I came up with.

Multiple Views

I created a JFrame, and two main JPanels. Inside each main JPanel is a view JPanel and a JComboBox. I gave a preferred size to the two view JPanels because they don't have any Swing components to size them. I hope the graphs you create will size the view JPanels.

I used BorderLayouts throughout the GUI. I created each JPanel in its own method so I could test different Swing layout managers. You can adjust the empty borders in the two main JPanel methods if you want more whitespace.

Here's the complete runnable code.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;

import javax.swing.BorderFactory;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class MultipleViews implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new MultipleViews());
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Multiple Views");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.add(createPanel1(), BorderLayout.BEFORE_LINE_BEGINS);
        frame.add(createPanel2(), BorderLayout.AFTER_LINE_ENDS);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    private JPanel createPanel1() {
        JPanel panel = new JPanel(new BorderLayout(5, 5));
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        panel.add(createView1(), BorderLayout.CENTER);
        
        JComboBox<Transaction> lCCommunitiesNames = new JComboBox<>();
        panel.add(lCCommunitiesNames, BorderLayout.AFTER_LAST_LINE);
        
        return panel;
    }
    
    private JPanel createView1() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBackground(Color.gray);
        panel.setPreferredSize(new Dimension(750, 350));
        return panel;
    }
    
    private JPanel createPanel2() {
        JPanel panel = new JPanel(new BorderLayout(5, 5));
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        panel.add(createView2(), BorderLayout.CENTER);
        
        JComboBox<Transaction> minoltaCommunitiesNames = new JComboBox<>();
        panel.add(minoltaCommunitiesNames, BorderLayout.AFTER_LAST_LINE);
        
        return panel;
    }

    private JPanel createView2() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBackground(Color.blue);
        panel.setPreferredSize(new Dimension(750, 350));
        return panel;
    }
    
    public class Transaction {
        
    }

}
Gilbert Le Blanc
  • 50,182
  • 6
  • 67
  • 111
  • Thank you for a reply, I will edit the question. The problem is not in the swing layout, but in the graph layout in graphstream. I am getting a different view on the same graph and I need the same view. Also, I need to edit colours on both graphs, so just duplication of the view is not a solution. – Jakub Peschel Apr 07 '21 at 13:12