james james - 7 months ago 11
Java Question

How to plot a Line Graph in Java using dataset from a text file?

I have written a Java GUI program which opens a text file and reads the data in the left panel. Now I want to display a graph of the data read from the same file on the right panel.

I have used

JFileChooser
to open files and read the data and display them on a text area. I want the data read from the file to be displayed using a two dimensional X-Y graph. The axis of the graph should be labeled using the label information specified in the data file. The values on the X-axis should begin from the x-axis start value specified, with intervals which increment at a rate determined by the x-axis interval value. The values on the Y-axis will need to be determined from the data itself. Each point plotted on the graph should be joined using a single line.

I have used several methods but none worked. I have tried reading each line on the text file as arrays and use the arrays as the dataset, but it didn't work as well. Please help me plot a graph from the data on the text file. Any help would be appreciated. Thanks.

P.S The graph should be plotted using AWT/Swing libraries only.

The data on the file is as follows:

Title: Effect of Age on Ability
Xlabel: Age
Ylabel: Ability
start: 0
interval: 15
0, 3, 4.2, 7, 5.1, 10, 3.2


Following are my code which I have written so far:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.List;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Scanner;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

@SuppressWarnings("serial")
public class GUI extends JFrame {

private String[] readLines = new String[6];

public GUI() {
// Setting Title, size and layout
setTitle("Data Visualiser");
setSize(950, 1000);
setLayout(new BorderLayout());

// Creates a menubar for a JFrame
final JMenuBar menuBar = new JMenuBar();

// Add the menubar to the frame
setJMenuBar(menuBar);

// Define and add two drop down menu to the menubar, "file" and "help"
JMenu fileMenu = new JMenu("File");
JMenu helpMenu = new JMenu("Help");
menuBar.add(fileMenu);
menuBar.add(helpMenu);

// adding menu items and icons to the "file" drop down menu,
final JMenuItem openAction = new JMenuItem("Open", new ImageIcon("images/Open-icon.png"));

final JMenuItem saveAction = new JMenuItem("Save", new ImageIcon("images/save-file.png"));

final JMenuItem exitAction = new JMenuItem("Exit", new ImageIcon("images/exit-icon.png"));

final JMenuItem aboutAction = new JMenuItem("About", new ImageIcon("images/about-us.png"));

//////////////////////////////////////////////////////////////////////////////////////////////
// Create a text area.
final JTextArea textArea = new JTextArea("");
textArea.setFont(new Font("Serif", Font.BOLD, 16));
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.setEditable(false);
JScrollPane textScrollPane = new JScrollPane(textArea);
// textArea.add(textScrollPane, BorderLayout.CENTER); //add the
// JScrollPane to the panel

// Scrollbars
textScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
textScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

textScrollPane.setPreferredSize(new Dimension(350, 550));
textScrollPane.setBorder(
BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Textual Representation"),
BorderFactory.createEmptyBorder(5, 5, 5, 5)));

// Create an graphics pane.
JPanel graphicsArea = new JPanel();
//graphicsArea.setFont(new Font("Serif", Font.BOLD, 16));
JScrollPane graphicsScrollPane = new JScrollPane(graphicsArea);

// Scrollbars
graphicsScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
graphicsScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

graphicsScrollPane.setPreferredSize(new Dimension(550, 550));
graphicsScrollPane.setBorder(
BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Graphical Representation"),
BorderFactory.createEmptyBorder(5, 5, 5, 5)));

// Put the graphics pane and the text pane in a split pane.
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, textScrollPane, graphicsScrollPane);
splitPane.setOneTouchExpandable(true);
splitPane.setResizeWeight(0.5);

JPanel rightPane = new JPanel(new GridLayout(1, 0));
rightPane.add(splitPane);

// Put everything together.
JPanel leftPane = new JPanel(new BorderLayout());
add(rightPane, BorderLayout.LINE_END);

////////////////////////////////////////////////////////////////////////////////////////////////////////////
// file menu shortcut
fileMenu.setMnemonic(KeyEvent.VK_F);

fileMenu.add(openAction);
// openAction.addActionListener(this);
openAction.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent arg0) {
if (arg0.getSource().equals(openAction)) {

// using JFileChooser to open the text file
JFileChooser fileChooser = new JFileChooser();

if (fileChooser.showOpenDialog(fileChooser) == JFileChooser.APPROVE_OPTION) {
// fileChooser.setCurrentDirectory(new
// File(System.getProperty("user.home"))); // setting
// current
// directory
File file = fileChooser.getSelectedFile();
BufferedReader br = null;

try {
// FileReader fr = new FileReader(file);
Scanner f = new Scanner(file);
for (int i = 0; i < 6; i++) {
readLines[i] = f.nextLine();
textArea.setText(textArea.getText() + readLines[i] + "\n");
String array[] = readLines[i].split(" ");

}
} catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(new JFrame(), "File not found!", "ERROR!",
JOptionPane.ERROR_MESSAGE); // error message
// if file not
// found
} catch (NullPointerException e) {
// System.out.println(e.getLocalizedMessage());
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

}
}
}
});

fileMenu.add(saveAction);
fileMenu.add(exitAction);

// exit button shortcut
exitAction.setMnemonic(KeyEvent.VK_X);
exitAction.addActionListener(new ActionListener() {

// setting up exit button
public void actionPerformed(ActionEvent arg0) {
if (arg0.getSource().equals(exitAction)) {
System.exit(0);
}
}
});

fileMenu.addSeparator();

helpMenu.addSeparator();
helpMenu.add(aboutAction);

// about button shortcut
aboutAction.setMnemonic(KeyEvent.VK_A);
aboutAction.addActionListener(new ActionListener() {

// clicking on about button opens up a dialog box which contain
// information about the program
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(menuBar.getComponent(0),
"This program is based on the development of a data visualization tool. \n"
+ "The basic concept is to produce a piece of software which reads in raw textual data, \n"
+ "analyses that data, then presents it graphically to the user.",
"About Us", JOptionPane.PLAIN_MESSAGE);
}
});

}
}

Answer

Starting from your example, note the following:

  • Use a ChartPanel for your graphicsArea; then, your openAction() can simply invoke setChart().

  • Parse the chosen file in creatChart(); the title and data lines are shown, but the remaining attributes are left as an exercise.

  • Consider using Properties for your file format;

  • For greater flexibility, use Action as shown here.

  • To change the chart panel's default size, override getPreferredSize() as shown here.

  • Swing GUI objects should be constructed and manipulated only on the event dispatch thread.

P.S. The graph should be plotted using AWT/Swing libraries only.

For a single chart, replace ChartPanel with JPanel and override paintComponent() to perform the rendering. You can transform coordinates using the approach is outlined here or here.

image

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

//* @see http://stackoverflow.com/a/36764715/230513 */
public class GUI extends JFrame {

    public GUI() {
        super("Data Visualiser");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        final JMenuBar menuBar = new JMenuBar();
        setJMenuBar(menuBar);
        JMenu fileMenu = new JMenu("File");
        JMenu helpMenu = new JMenu("Help");
        menuBar.add(fileMenu);
        menuBar.add(helpMenu);

        final JMenuItem openAction = new JMenuItem("Open", new ImageIcon("images/Open-icon.png"));
        final JMenuItem saveAction = new JMenuItem("Save", new ImageIcon("images/save-file.png"));
        final JMenuItem exitAction = new JMenuItem("Exit", new ImageIcon("images/exit-icon.png"));
        final JMenuItem aboutAction = new JMenuItem("About", new ImageIcon("images/about-us.png"));

        final JTextArea textArea = new JTextArea(8, 16);
        textArea.setFont(new Font("Serif", Font.BOLD, 16));
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        textArea.setEditable(false);
        JScrollPane textScrollPane = new JScrollPane(textArea);
        textScrollPane.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createTitledBorder("Textual Representation"),
            BorderFactory.createEmptyBorder(5, 5, 5, 5)));

        ChartPanel graphicsArea = new ChartPanel(null);
        graphicsArea.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createTitledBorder("Graphical Representation"),
            BorderFactory.createEmptyBorder(5, 5, 5, 5)));

        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, textScrollPane, graphicsArea);
        splitPane.setOneTouchExpandable(true);
        splitPane.setResizeWeight(0.5);
        add(splitPane, BorderLayout.LINE_END);

        fileMenu.setMnemonic(KeyEvent.VK_F);
        fileMenu.add(openAction);
        openAction.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                if (arg0.getSource().equals(openAction)) {
                    JFileChooser fileChooser = new JFileChooser(new File("."));
                    if (fileChooser.showOpenDialog(fileChooser) == JFileChooser.APPROVE_OPTION) {
                        File file = fileChooser.getSelectedFile();
                        graphicsArea.setChart(creatChart(file));
                    }
                }
            }

            private JFreeChart creatChart(File file) {
                String title = null;
                String xAxisLabel = null;
                String yAxisLabel = null;
                BufferedReader in = null;
                int start = 0;
                int interval = 0;
                String data = null;
                String line = null;
                try {
                    in = new BufferedReader(new FileReader(file));
                    while ((line = in.readLine()) != null) {
                        textArea.append(line + "\n");
                        if (line.startsWith("Title")) {
                            title = line.split(":")[1].trim();
                        }
                        // parse other lines here
                        if (!line.contains(":")) {
                            data = line;
                        }
                    }
                } catch (IOException ex) {
                    ex.printStackTrace(System.err);
                }
                XYSeries dataset = new XYSeries(file.getName());
                for (String s : data.split(",")) {
                    dataset.add(start, Double.valueOf(s));
                    start += interval;
                }
                return ChartFactory.createXYLineChart(title,
                    xAxisLabel, yAxisLabel, new XYSeriesCollection(dataset));
            }
        });
        fileMenu.add(saveAction);
        fileMenu.add(exitAction);
        exitAction.setMnemonic(KeyEvent.VK_X);
        exitAction.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                if (arg0.getSource().equals(exitAction)) {
                    System.exit(0);
                }
            }
        });
        fileMenu.addSeparator();
        helpMenu.addSeparator();
        helpMenu.add(aboutAction);
        aboutAction.setMnemonic(KeyEvent.VK_A);
        aboutAction.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                JOptionPane.showMessageDialog(null,
                    "Visualization tool.",
                    "About Us", JOptionPane.PLAIN_MESSAGE);
            }
        });
        pack();
        setLocationRelativeTo(null);
        setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            new GUI();
        });
    }
}
Comments