How to update a chart dynamically using JFreeChart? - java

I am trying to generate a chart dynamically that will show the value change over time. I am storing those value in an ArrayList< Integer, ArrayList<Integer>> and retrieving those values in this class. But it doesn't show the addition of the values in that ArrayList over time.
Here actually another two thread is updating that ArrayList and I need to show the values of that Arraylist in a chart that will be dynamic.
The below is the code based on this example:
package com.model.presentation;
import java.awt.BorderLayout;
import java.awt.Dimension;
//import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
//import java.util.Random;
import java.util.Map.Entry;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.Timer;
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.category.DefaultCategoryDataset;
import com.model.resources.Household;
/**
* #see https://stackoverflow.com/a/15715096/230513
* #see https://stackoverflow.com/a/11949899/230513
*/
public class DisplayChart {
//private static final int N = 128;
//private static final Random random = new Random();
private int n = 1;
static int count = 0;
public void display()
{
JFrame f = new JFrame("Community Rescilience Model");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JTabbedPane jtp = new JTabbedPane();
jtp.add(String.valueOf(n), createPane());
f.add(jtp, BorderLayout.CENTER);
JPanel p = new JPanel(new FlowLayout(FlowLayout.RIGHT));
p.add(new JButton(new AbstractAction("Add") {
public void actionPerformed(ActionEvent e) {
jtp.add(String.valueOf(++n), createPane());
jtp.setSelectedIndex(n - 1);
}
}));
f.add(p, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private ChartPanel createPane()
{
final DefaultCategoryDataset dataset = new DefaultCategoryDataset();
final String name = "Community ";
/* for (int i = 0; i < random.nextInt(N) + N / 2; i++)
{
while (iterator.hasNext())
{
Map.Entry map = (Map.Entry) iterator.next();
String community_name = name + String.valueOf(map.getKey());
ArrayList<Integer> dataArrayList = (ArrayList<Integer>) map.getValue();
for (Iterator<Integer> it = dataArrayList.iterator(); it.hasNext();)
{
dataset.addValue(it.next(), community_name, String.valueOf(count));
count++;
}
}
}*/
// XYSeriesCollection dataset = new XYSeriesCollection(series);
new Timer(100, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
Iterator<Entry<Integer, ArrayList<Integer>>> iterator = Household.goods.entrySet()
.iterator();
while (iterator.hasNext())
{
Map.Entry map = (Map.Entry) iterator.next();
String community_name = name + String.valueOf(map.getKey());
ArrayList<Integer> dataArrayList = (ArrayList<Integer>) map.getValue();
for (Iterator<Integer> it = dataArrayList.iterator(); it.hasNext();)
{
dataset.setValue(it.next(), community_name, String.valueOf(count));
count++;
}
}
}
}).start();
JFreeChart lineChart = ChartFactory.createLineChart("Resource Production/Consumption over time", "Time",
"Number of GOODS", dataset, PlotOrientation.VERTICAL,
true, true, false);
return new ChartPanel(lineChart) {
#Override
public Dimension getPreferredSize()
{
return new Dimension(1000, 500);
}
};
}
/*public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new DisplayChart().display();
}
});
}
}*/
}
The main class is :
public class Main_class {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new DisplayChart().display();
}
});
}
This code works but at certain point, it gets stuck. It means it does not show the value of the changes in that Arraylist.

I have it running indefinitely although i am not sure it is still working as you intended.
I didn't have the Household class so I just faked it with.
class Household {
static public Map<Integer, ArrayList<Integer>> goods = new HashMap<>();
}
I also don't think I have your code for adding data to the plot. I did it like this:
Random rand = new Random();
while (true) {
try {
Thread.sleep(100);
for (int i = 0; i < 10; i++) {
final int fi = i;
EventQueue.invokeLater(new Runnable() {
public void run() {
ArrayList<Integer> l = Household.goods.get(fi);
if (l == null) {
l = new ArrayList<>();
}
l.add(rand.nextInt(100));
if (l.size() > 20) {
l.remove(0);
}
Household.goods.put(fi, l);
}
});
}
} catch (InterruptedException ex) {
}
}
Note that it is important to do it in the EventQueue thread or you will get a ConcurrentModificationException.
The real issue seems to be that your adding the same data in the list over and over again associated with different counts.
So I changed:
for (Iterator<Integer> it = dataArrayList.iterator(); it.hasNext();)
{
dataset.setValue(it.next(), community_name, String.valueOf(count));
count++;
}
To :
for (count = 0; count < dataArrayList.size(); count++) {
dataset.setValue(dataArrayList.get(count), community_name, String.valueOf(count));
}

Related

Swing app freezes after a while when JFreeChart have a lot series

I'm writing a program which would display incoming data while day. It's getting data about every 600 milliseconds and adding it to the TimeSeries Chart. The problem is: after about 10 minutes of work, GUI starts freezing. But if display only few series of 33 it's become fine. So maybe I am doing something wrong?
How to solve that freezing? My SwingWorker may be weak, or chosen JFreeChart collection.
Any tips might be helpful, thank you!
My short code example:
import java.awt.event.ActionEvent;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.ChartFactory;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.data.xy.XYSeries;
import org.jfree.chart.JFreeChart;
import org.jfree.data.xy.XYDataset;
import java.awt.Dimension;
import java.awt.Component;
import javax.swing.JCheckBox;
import org.jfree.chart.ChartPanel;
import java.awt.LayoutManager;
import java.awt.BorderLayout;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import java.awt.event.ActionListener;
import java.awt.Window;
import org.jfree.chart.ui.UIUtils;
import javax.swing.JPanel;
import java.awt.Container;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Paint;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import javax.swing.SwingWorker;
import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.ui.ApplicationFrame;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
public class HideSeriesDemo1 extends ApplicationFrame {
public HideSeriesDemo1(final String title) {
super(title);
this.setContentPane(new MyDemoPanel());
}
public static JPanel createDemoPanel() {
return new MyDemoPanel();
}
public static void main(final String[] args) {
final HideSeriesDemo1 demo = new HideSeriesDemo1("JFreeChart: HideSeriesDemo1.java");
demo.pack();
UIUtils.centerFrameOnScreen(demo);
demo.setVisible(true);
}
static class MyDemoPanel extends JPanel implements ActionListener {
final JFreeChart chart;
private JPanel boxPanel;
TimeSeriesCollection seriesArray;
private XYItemRenderer renderer;
private void setLinesVisible() {
for (int i = 0; i < seriesArray.getSeriesCount(); i++) {
renderer.setSeriesVisible(i, true);
JCheckBox box = (JCheckBox) boxPanel.getComponent(i);
box.setSelected(true);
}
}
private void setLinesInvisible() {
for (int i = 0; i < seriesArray.getSeriesCount(); i++) {
renderer.setSeriesVisible(i, false);
JCheckBox box = (JCheckBox) boxPanel.getComponent(i);
box.setSelected(false);
}
}
private XYDataset createNumberedDataSet(int num) {
seriesArray = new TimeSeriesCollection();
for (int i = 0; i < num; i++) {
int num2 = i + 1;
TimeSeries s1 = new TimeSeries("Channel №" + num2);
seriesArray.addSeries(s1);
}
return seriesArray;
}
public MyDemoPanel() {
super(new BorderLayout());
final XYDataset dataset = this.createNumberedDataSet(33);
chart = this.createChart(dataset);
final ChartPanel chartPanel = new ChartPanel(chart);
boxPanel = new JPanel();
boxPanel.setLayout(new GridLayout(0, 11));
boxPanel.validate();
for (int i = 0; i < 33; i++) {
int numchik = i + 1;
JCheckBox box1 = new JCheckBox("Channel №" + numchik);
String com = "S" + numchik;
box1.setSelected(true);
box1.setActionCommand(com);
box1.addActionListener(this);
boxPanel.add(box1);
}
boxPanel.validate();
final JButton btn = new JButton("All not sellected");
btn.setVisible(true);
btn.setActionCommand("btn");
btn.addActionListener(this);
boxPanel.add(btn);
final JButton btn2 = new JButton("All sellected");
btn2.setVisible(true);
btn2.setActionCommand("btn2");
btn2.addActionListener(this);
boxPanel.add(btn2);
final JButton btn3 = new JButton("SwingWorker?");
btn3.setVisible(true);
btn3.setActionCommand("btn3");
btn3.addActionListener(this);
boxPanel.add(btn3);
this.add(chartPanel);
this.add(boxPanel, "South");
JPopupMenu pop = chartPanel.getPopupMenu();
pop.add(new JSeparator());
JMenuItem remBtn = new JMenuItem("All not selected");
remBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
setLinesInvisible();
}
});
pop.add(remBtn);
JMenuItem addBtn = new JMenuItem("All visible");
addBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
setLinesVisible();
}
});
pop.add(addBtn);
}
private JFreeChart createChart(final XYDataset dataset) {
final JFreeChart chart = ChartFactory.createTimeSeriesChart("xDisplay", "Time", "Data", dataset, true, true, false);
final XYPlot plot = (XYPlot) chart.getPlot();
this.renderer = plot.getRenderer();
return chart;
}
#Override
public void actionPerformed(final ActionEvent e) {
int series = -1;
if (e.getActionCommand().equals("btn")) {
this.setLinesInvisible();
System.out.println("set invisible btn pressed");
boxPanel.validate();
// System.out.println("btn pressed");
return;
}
if (e.getActionCommand().equals("btn2")) {
setLinesVisible();
boxPanel.validate();
System.out.println("setBtnVisible pressed");
return;
}
if (e.getActionCommand().equals("btn3")) {
System.out.println("swingworker");
MySwingWorker swi = new MySwingWorker();
swi.execute();
}
for (int i = 0; i<33;i++){
String s="S"+i;
if (e.getActionCommand().equals(s)) {
series = i-1;
}
}
if (series >= 0) {
final boolean visible = this.renderer.getItemVisible(series, 0);
this.renderer.setSeriesVisible(series, !visible);
}
}
private class MySwingWorker extends SwingWorker<Boolean, double[]> {
LinkedList<Double> fifo = new LinkedList<Double>();
public MySwingWorker() {
fifo.add(0.0);
}
#Override
protected Boolean doInBackground() {
while (!isCancelled()) {
try {
Thread.sleep(600);
} catch (InterruptedException ex) {
Logger.getLogger(HideSeriesDemo1.class.getName()).log(Level.SEVERE, null, ex);
}
fifo.add(fifo.get(fifo.size() - 1) + Math.random() - .5);
if (fifo.size() > 1000) {
fifo.removeFirst();
}
double[] array = new double[fifo.size()];
for (int i = 0; i < fifo.size(); i++) {
array[i] = fifo.get(i);
}
System.out.println(array.length + " : " + Arrays.toString(array) + "Array: ");
publish(array);
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// eat it. caught when interrupt is called
System.out.println("MySwingWorker shut down." + " name:" + Thread.currentThread().getName());
}
}
return true;
}
#Override
protected void process(List<double[]> chunks) {
double[] mostRecentDataSet = chunks.get(chunks.size() - 1);
for (int i = 0; i < seriesArray.getSeriesCount(); i++) {
TimeSeries series = seriesArray.getSeries(i);
series.addOrUpdate(new Millisecond(), mostRecentDataSet[0] + i);
}
fifo.removeFirst();
System.out.println(" repaint zone " + " name:" + Thread.currentThread().getName());
}
}
}
}

Multiple animations(threads) in a JPanel

I am trying to code a board game in Java.
I have 11 classes including Main. Board class which extends JPanel and draws the board image as well as the dice image. The class Player which extends JCoponent and implements Runnable(Thread). Every player instance is a pawn-animation that it is moving across the board. The player class draws the pawn on the board.
Pattern
How the code it looks like :
Board b=new Board();
Player p=new Player();
b.add(p);
JPanel panel=new JPanel();
panel.add(b);
add(panel); //adding the panel to the frame.
The problem is that I can't have more than one pawn simultaneously on the board. I have already tried to re-paint all the players (as non-animation) in another class but it didn't work. I also tried JLayeredPane but maybe I am doing something wrong. Unfortunately, I can't change the above pattern so don't make this suggestion.
Thank you in advance for your help.
P.S: I can't post any code because its huge.
P.P.S: more clarifications will be given, if you ask me.
EDIT: I reform my question. Is it possible to have two animations simultaneously on the same panel? if the answer is a yes ..how I can do that?
It's most likely possible to have many components moving all at once. Either use javax.swing.Timer ou SwingWorker for this to work.
Here is a quick example showing you this. It puts 16 pawns on a board and moves them randomly from one place to another.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestAnimation {
private static final String PAWN_URL = "http://files.chesskidfiles.com/images_users/tiny_mce/BoundingOwl/bishop_happywhite.png";
private Image pawn;
private Map<Location, Pawn> pawnLocations = new HashMap<>();
private Board board;
private Timer timer;
private JLayeredPane glassPane;
public TestAnimation() {
try {
pawn = new ImageIcon(new URL(PAWN_URL)).getImage();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
private static class Location {
public final int row;
public final int col;
public Location(int row, int col) {
super();
this.row = row;
this.col = col;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + col;
result = prime * result + row;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Location other = (Location) obj;
return (col == other.col && row == other.row);
}
}
private static class Cell extends JPanel {
private final Location location;
public Cell(Location location) {
super(new BorderLayout());
this.location = location;
setOpaque(true);
setBackground(((location.row + location.col) % 2) == 0 ? Color.WHITE : Color.BLACK);
}
#Override
protected void addImpl(Component comp, Object constraints, int index) {
while (getComponentCount() > 0) {
remove(0);
}
super.addImpl(comp, constraints, index);
}
}
private static class Board extends JPanel {
private Map<Location, Cell> cells = new HashMap<>();
public Board() {
super(new GridLayout(8, 8));
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
Cell cell = new Cell(new Location(i, j));
add(cell);
cells.put(new Location(i, j), cell);
}
}
}
public void add(Pawn pawn, Location location) {
cells.get(location).add(pawn);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
public Cell getCell(Location location) {
return cells.get(location);
}
}
private class Pawn extends JComponent {
public Pawn() {
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(pawn, 0, 0, getWidth(), getHeight(), this);
}
}
protected void initUI() {
JFrame frame = new JFrame(TestAnimation.class.getSimpleName());
board = new Board();
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 2; j++) {
Location location = new Location(i, j);
Pawn aPawn = new Pawn();
board.add(aPawn, location);
pawnLocations.put(location, aPawn);
}
}
for (int i = 0; i < 8; i++) {
for (int j = 6; j < 8; j++) {
Location location = new Location(i, j);
Pawn aPawn = new Pawn();
board.add(aPawn, location);
pawnLocations.put(location, aPawn);
}
}
timer = new Timer(7000, new Animation());
timer.setInitialDelay(0);
timer.setRepeats(true);
timer.setCoalesce(false);
glassPane = new JLayeredPane();
glassPane.setOpaque(false);
frame.add(board);
frame.setGlassPane(glassPane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
timer.start();
glassPane.setVisible(true);
}
public class Animation implements ActionListener {
private Map<Location, Pawn> futureLocations;
private Random random = new Random();
private Timer subTimer;
private List<Pawn> movingPawns;
private Map<Pawn, Point> originalCoordinates = new HashMap<>();
private Map<Pawn, Point> futureCoordinates = new HashMap<>();
#Override
public void actionPerformed(ActionEvent e) {
futureLocations = new HashMap<>();
movingPawns = new ArrayList<>();
for (Pawn p : pawnLocations.values()) {
int row = random.nextInt(8);
int col = random.nextInt(8);
Location location;
while (futureLocations.containsKey((location = new Location(row, col)))) {
row = random.nextInt(8);
col = random.nextInt(8);
}
futureLocations.put(location, p);
Cell futureCell = board.getCell(location);
futureCoordinates.put(p, SwingUtilities.convertPoint(futureCell, 0, 0, glassPane));
movingPawns.add(p);
}
for (Pawn p : movingPawns) {
Point locationInGlassPane = SwingUtilities.convertPoint(p.getParent(), 0, 0, glassPane);
glassPane.add(p);
p.setLocation(locationInGlassPane);
originalCoordinates.put(p, locationInGlassPane);
}
subTimer = new Timer(50, new AnimationSteps());
subTimer.setInitialDelay(0);
subTimer.setCoalesce(true);
subTimer.setRepeats(true);
subTimer.start();
}
public class AnimationSteps implements ActionListener {
private int step = 0;
#Override
public void actionPerformed(ActionEvent e1) {
if (step < 50 + 1) {
for (Pawn p : movingPawns) {
Point p1 = originalCoordinates.get(p);
Point p2 = futureCoordinates.get(p);
int x = (int) (p1.x + ((p2.x - p1.x) * (double) step / 50));
int y = (int) (p1.y + ((p2.y - p1.y) * (double) step / 50));
p.setLocation(x, y);
}
} else {
for (Entry<Location, Pawn> e : futureLocations.entrySet()) {
board.add(e.getValue(), e.getKey());
}
board.revalidate();
subTimer.stop();
pawnLocations = futureLocations;
}
step++;
}
}
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
UnsupportedLookAndFeelException {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestAnimation().initUI();
}
});
}
}
Maybe your problem is trying to develop a program with a thread for each object, most popular games run with a single thread, two at most. The reason: It will be very complex to synchronize threads with each other, not to mention that your performance will be poor. Even the graphics engine in Java is single threaded and that means you won't have two threads drawing at the same time.

Dynamic JFreeChart at 30 second intervals

I am new in JFreeChart and new to Java also.
I have this data from our claims table:
SEQ IP_CLAIMS_RECEIVED HB_CLAIMS_RECEIVED IP_AVERAGE_RESPONSE HB_AVERAGE_RESPONSE
30 Seconds 29 19 4 4
This data every 30 seconds will change giving the amount of claims processed and with the avarage seconds it took to process this.
So my graph I want it on the Y-Axis to display the round seconds like (0,,5,10,15,20,25,30,35,40) and then on the X-Axis to display the time - the 30 seconds intervals showing the refresh times. And then the spike-lines would show the average-response times... And if it will be possible have two combined graphs one for IP Claims and another for HB Claims. I have a perfect example of the graph but its confusing me a bit here is the code of it below:
package timeseriesdemo;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.Timer;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.time.DynamicTimeSeriesCollection;
import org.jfree.data.time.Second;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
/** #see https://stackoverflow.com/questions/5048852 */
public class TimeSeriesDemo extends ApplicationFrame {
private static final String TITLE = "Dynamic Series";
private static final String START = "Start";
private static final String STOP = "Stop";
private static final float MINMAX = 100;
private static final int COUNT = 2 * 60;
private static final int FAST = 100;
private static final int SLOW = FAST * 5;
private static final Random random = new Random();
private Timer timer;
public TimeSeriesDemo(final String title) {
super(title);
final DynamicTimeSeriesCollection dataset =
new DynamicTimeSeriesCollection(1, COUNT, new Second());
dataset.setTimeBase(new Second(0, 0, 0, 1, 1, 2011));
dataset.addSeries(gaussianData(), 0, "Gaussian data");
JFreeChart chart = createChart(dataset);
final JButton run = new JButton(STOP);
run.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if (STOP.equals(cmd)) {
timer.stop();
run.setText(START);
} else {
timer.start();
run.setText(STOP);
}
}
});
final JComboBox combo = new JComboBox();
combo.addItem("Fast");
combo.addItem("Slow");
combo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if ("Fast".equals(combo.getSelectedItem())) {
timer.setDelay(FAST);
} else {
timer.setDelay(SLOW);
}
}
});
this.add(new ChartPanel(chart), BorderLayout.CENTER);
JPanel btnPanel = new JPanel(new FlowLayout());
btnPanel.add(run);
btnPanel.add(combo);
this.add(btnPanel, BorderLayout.SOUTH);
timer = new Timer(FAST, new ActionListener() {
float[] newData = new float[1];
#Override
public void actionPerformed(ActionEvent e) {
newData[0] = randomValue();
System.out.println("dataset1 : " + dataset.advanceTime());
dataset.advanceTime();
dataset.appendData(newData);
}
});
}
private float randomValue() {
System.out.println("randomvalue : " + (float) (random.nextGaussian() * MINMAX / 3));
return (float) (random.nextGaussian() * MINMAX / 3);
}
private float[] gaussianData() {
float[] a = new float[COUNT];
for (int i = 0; i < a.length; i++) {
a[i] = randomValue();
}
return a;
}
private JFreeChart createChart(final XYDataset dataset) {
final JFreeChart result = ChartFactory.createTimeSeriesChart(
TITLE, "hh:mm:ss", "Claims Received", dataset, true, true, false);
final XYPlot plot = result.getXYPlot();
ValueAxis domain = plot.getDomainAxis();
domain.setAutoRange(true);
ValueAxis range = plot.getRangeAxis();
range.setRange(-MINMAX, MINMAX);
return result;
}
public void start() {
timer.start();
}
public static void main(final String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
TimeSeriesDemo demo = new TimeSeriesDemo(TITLE);
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
demo.start();
}
});
}
}

working with Swing timer : creating mess

Just want the color of the letters to change with a little pauses (pause may vary as per the time given for a word and length of the word).
The following code works fine for me.But I think I have created a mess with my logic.I can understand, but it should be easy for my team mates to understand.
Code:
import java.awt.Color;
import java.lang.reflect.InvocationTargetException;
import java.awt.Toolkit;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.Timer;
public class Reminder
{
static JFrame frame;
Toolkit toolkit;
Timer timer;
int point=0,temp=0,hil=0,point2=0;long time1=0,time2=0;
static StyledDocument doc;
static JTextPane textpane;
String[] arr={"Tes"," hiiii"," what"," happpn"};
int i=0;
int[] a=new int[5];
public Reminder()
{
a[0]=1000;
a[1]=900;
a[2]=300;
a[3]=1500;
a[4]=1700;
ActionListener actionListener = new ActionListener()
{
public void actionPerformed(ActionEvent actionEvent)
{
point =arr[i].length();
temp=point+1;
time1=System.currentTimeMillis();
new Thread(new t1()).start();
}
};
timer = new Timer(a[i], actionListener);
timer.setInitialDelay(0);
timer.start();
}
public class t1 implements Runnable
{ /* true idea to use current time is beacuse i want to check and make
sure that the time taken since the timer started, and the present time should
not exceed the time given in the array in any case*/
public void run()
{
try
{
time2=System.currentTimeMillis();
while(time2-time1<=a[i]-200){Thread.sleep((long) (a[i] / (arr[i].length() * 4)));
if(hil<=temp-1)
{
doc.setCharacterAttributes(point2,hil, textpane.getStyle("Red"), true);}
hil++;
time2=System.currentTimeMillis();
}
doc.setCharacterAttributes(point2,point+1, textpane.getStyle("Red"), true);
point2+=point;hil=0;i++;
timer.setDelay(a[i]);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
public static void newcompo()
{
JPanel panel = new JPanel();
doc = (StyledDocument) new DefaultStyledDocument();
textpane = new JTextPane(doc);
textpane.setText("Test hiiii what happpn");
javax.swing.text.Style style = textpane.addStyle("Red", null);
StyleConstants.setForeground(style, Color.RED);
panel.add(textpane);
frame.add(panel);
frame.pack();
}
public static void main(String args[]) throws InterruptedException
, InvocationTargetException
{
SwingUtilities.invokeAndWait(new Runnable()
{
#Override
public void run()
{
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
newcompo();
Reminder aa= new Reminder();
}
});
}
}
Any suggestions?How can I simplify?
UPDATE FOR ERROR
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class KaraokeTest {
private int[] timingsArray = {1000, 900, 300, 1500};//word/letters timings
private String[] individualWordsToHighlight = {"Tes", " hiiii", " what", " happpn"};//each individual word/letters to highlight
private int count = 0;
private final JTextPane jtp = new JTextPane();
private final JButton startButton = new JButton("Start");
private final JFrame frame = new JFrame();
public KaraokeTest() {
initComponents();
}
private void initComponents() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
for (String s : individualWordsToHighlight) {
String tmp = jtp.getText();
jtp.setText(tmp + s);
}
jtp.setEditable(false);
startButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
startButton.setEnabled(false);
count = 0;
//create Arrays of individual letters and their timings
final ArrayList<String> chars = new ArrayList<>();
final ArrayList<Integer> charsTiming = new ArrayList<>();
for (String s : individualWordsToHighlight) {
for (int i = 0; i < s.length(); i++) {
chars.add(String.valueOf(s.charAt(i)));
System.out.println(String.valueOf(s.charAt(i)));
}
}
for (int x = 0; x < timingsArray.length; x++) {
for (int i = 0; i < individualWordsToHighlight[x].length(); i++) {
charsTiming.add(timingsArray[x] / individualWordsToHighlight[x].length());
System.out.println(timingsArray[x] / individualWordsToHighlight[x].length());
}
}
new Timer(1, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {
if (count < charsTiming.size()) {
highlightNextWord();
//restart timer with new timings
((Timer) ae.getSource()).setInitialDelay(charsTiming.get(count));
((Timer) ae.getSource()).restart();
} else {//we are at the end of the array
reset();
((Timer) ae.getSource()).stop();//stop the timer
}
count++;//increment counter
}
}).start();
}
});
frame.add(jtp, BorderLayout.CENTER);
frame.add(startButton, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
private void reset() {
startButton.setEnabled(true);
jtp.setText("");
for (String s : individualWordsToHighlight) {
String tmp = jtp.getText();
jtp.setText(tmp + s);
}
JOptionPane.showMessageDialog(frame, "Done");
}
private void highlightNextWord() {
//we still have words to highlight
int sp = 0;
for (int i = 0; i < count + 1; i++) {//get count for number of letters in words (we add 1 because counter is only incrementd after this method is called)
sp += 1;
}
//highlight words
Style style = jtp.addStyle("RED", null);
StyleConstants.setForeground(style, Color.RED);
((StyledDocument) jtp.getDocument()).setCharacterAttributes(0, sp, style, true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new KaraokeTest();
}
});
}
}
Gives me Exception:
Exception in thread "AWT-EventQueue-0" java.lang.RuntimeException: Uncompilable source code - illegal start of type
at KaraokeTest$1.actionPerformed(KaraokeTest.java:47)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
at java.awt.Component.processMouseEvent(Component.java:6263)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
at java.awt.Component.processEvent(Component.java:6028)
at java.awt.Container.processEvent(Container.java:2041)
at java.awt.Component.dispatchEventImpl(Component.java:4630)
at java.awt.Container.dispatchEventImpl(Container.java:2099)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
at java.awt.Container.dispatchEventImpl(Container.java:2085)
at java.awt.Window.dispatchEventImpl(Window.java:2475)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
OK, here is a cleaned up version of your code which should approximatively perform the same thing:
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class Reminder {
private static final String TEXT = "Test hiiii what happpn";
private static final String[] WORDS = TEXT.split(" ");
private JFrame frame;
private Timer timer;
private StyledDocument doc;
private JTextPane textpane;
private List<Integer> times = Arrays.asList(1000, 900, 300, 1500);
private int stringIndex = 0;
private int index = 0;
public void startColoring() {
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
doc.setCharacterAttributes(stringIndex, 1, textpane.getStyle("Red"), true);
stringIndex++;
try {
if (stringIndex >= doc.getLength() || doc.getText(stringIndex, 1).equals(" ")) {
index++;
}
if (index < times.size()) {
double delay = times.get(index).doubleValue();
timer.setDelay((int) (delay / WORDS[index].length()));
} else {
timer.stop();
System.err.println("Timer stopped");
}
} catch (BadLocationException e) {
e.printStackTrace();
}
}
};
timer = new Timer(times.get(index), actionListener);
timer.setInitialDelay(0);
timer.start();
}
public void initUI() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
doc = new DefaultStyledDocument();
textpane = new JTextPane(doc);
textpane.setText(TEXT);
javax.swing.text.Style style = textpane.addStyle("Red", null);
StyleConstants.setForeground(style, Color.RED);
panel.add(textpane);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
public static void main(String args[]) throws InterruptedException, InvocationTargetException {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
Reminder reminder = new Reminder();
reminder.initUI();
reminder.startColoring();
}
});
}
}
A few tricks to help others read and understand your code:
Use coherent and appropriate indentation (I personnally try to stick to default Sun Java conventions)
Follow the Java coding conventions (constants are in upper-case, class name starts with an upper-case, variables and methods start with a lower case, use camel case)
Use meaningful variable and method names
class member should be declared one by one (don't use int i, j, k; )
Use a single instruction per line (avoid stuffs like if(something) doSomething(); else {doSomethingElse1(); doSomethingElse2();} on a single line)
Avoid unnecessary usage of the static keyword (to the exception of constants)
Try to avoid coupling your code so much (try to make the minimum assumptions on how the rest of the code performs)
Add javadoc and comments in your code, this is always a good practice and it is of great help for you and others.
Your main cause for concern is that you not doing the updates related to JTextPane on the Event Dispatch Thread.
For a situation like this, when you really wanted to update a certain thingy from another Thread, always use EventQueue.invokeLater(...) or EvenQueue.invokeAndWait(), which can asynchronously (former)/synchronously (latter) update your request on the EDT, though care must be taken, as invokeAndWait() might can lead to deadlocks/run conditions if not used in the right sense.
Here is your updated code, that might work for your expectations. Hope you can modify the code, as per your liking.
import javax.swing.*;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import java.awt.*;
import java.lang.reflect.InvocationTargetException;
/**
* Created with IntelliJ IDEA.
* User: Gagandeep Bali
* Date: 1/12/13
* Time: 5:55 PM
* To change this template use File | Settings | File Templates.
*/
public class ColouringText
{
private StyledDocument document;
private JTextPane textPane;
private String message;
private String[] parts;
private Timer timer;
private int counter;
private int start, end;
private Thread thread = new Thread()
{
#Override
public void run()
{
while (counter < parts.length)
{
final int len = parts[counter++].length();
try
{
EventQueue.invokeAndWait(new Runnable()
{
#Override
public void run()
{
document.setCharacterAttributes(
start, len, textPane.getStyle("RED"), true);
}
});
Thread.sleep(len * 1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
catch (InvocationTargetException e)
{
e.printStackTrace();
}
start += (len + 1);
}
}
};
public ColouringText()
{
document = (StyledDocument) new DefaultStyledDocument();
message = "Hello there... Joey Rohan. Had you ever thought about putting indentations before pasting your code.";
parts = message.split(" ");
counter = 0;
start = 0;
end = 6;
System.out.println("Message Length : " + message.length());
}
private void displayGUI()
{
JFrame frame = new JFrame("Colouring Text Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = new JPanel();
textPane = new JTextPane(document);
textPane.setText(message);
Style style = textPane.addStyle("RED", null);
StyleConstants.setForeground(style, Color.RED);
contentPane.add(textPane);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
thread.start();
}
public static void main(String... args)
{
EventQueue.invokeLater(new Runnable()
{
#Override
public void run()
{
new ColouringText().displayGUI();
}
});
}
}
Having been the one who answered your 2 previous questions on a similar task:
highlighting words in java
highlighting the word in java
and others not agreeing on my close vote, I decided to work on this a bit.
I have taken my latest example and edited to simplify where possible etc to make things more readable for you to understand, which in turn should help you understand how to go about simplifying your own.
I dont understand why you start a new thread to make words highlight slowly. Simply use my other examples and supply single letters rather than multiple letters and their timings to highlight, thus they will be highlighted individually. Or just make a method to do this work for you and iterate through those arrays as the letters and timings.
The below example uses an array of integers which hold the timings for words to be highlighted. It also contains an array for each individual word/letters we would like to highlight:
private int[] timingsArray = {1000, 900, 300, 1500};//word/letters timings
private String[] individualWordsToHighlight = {"Tes", " hiiii", " what", " happpn"};//each individual word/letters to highlight
In our start button we have a method to convert the above to single timings/letters for each individual letter for a letter by letter highlight:
//create Arrays of individual letters and their timings
final ArrayList<String> chars = new ArrayList<>();
final ArrayList<Integer> charsTiming = new ArrayList<>();
for (String s : individualWordsToHighlight) {
for (int i = 0; i < s.length(); i++) {
chars.add(String.valueOf(s.charAt(i)));
System.out.println(String.valueOf(s.charAt(i)));
}
}
for (int x = 0; x < timingsArray.length; x++) {
for (int i = 0; i < individualWordsToHighlight[x].length(); i++) {
charsTiming.add(timingsArray[x] / individualWordsToHighlight[x].length());
System.out.println(timingsArray[x] / individualWordsToHighlight[x].length());
}
}
Next there is a single Timer which will be started when start button is pressed which will highlight words/letters and restart itself with a new delay each time until all words/letters have been highlighted:
new Timer(1, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {
if (count < charsTiming.size()) {
highlightNextWord();
//restart timer with new timings
((Timer) ae.getSource()).setInitialDelay(charsTiming.get(count));
((Timer) ae.getSource()).restart();
} else {//we are at the end of the array
reset();
((Timer) ae.getSource()).stop();//stop the timer
}
count++;//increment counter
}
}).start();
Hope this helps.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class KaraokeTest {
private int[] timingsArray = {1000, 900, 300, 1500};//word/letters timings
private String[] individualWordsToHighlight = {"Tes", " hiiii", " what", " happpn"};//each individual word/letters to highlight
private int count = 0;
private final JTextPane jtp = new JTextPane();
private final JButton startButton = new JButton("Start");
private final JFrame frame = new JFrame();
public KaraokeTest() {
initComponents();
}
private void initComponents() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
for (String s : individualWordsToHighlight) {
String tmp = jtp.getText();
jtp.setText(tmp + s);
}
jtp.setEditable(false);
startButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
startButton.setEnabled(false);
count = 0;
//create Arrays of individual letters and their timings
final ArrayList<String> chars = new ArrayList<>();
final ArrayList<Integer> charsTiming = new ArrayList<>();
for (String s : individualWordsToHighlight) {
for (int i = 0; i < s.length(); i++) {
chars.add(String.valueOf(s.charAt(i)));
System.out.println(String.valueOf(s.charAt(i)));
}
}
for (int x = 0; x < timingsArray.length; x++) {
for (int i = 0; i < individualWordsToHighlight[x].length(); i++) {
charsTiming.add(timingsArray[x] / individualWordsToHighlight[x].length());
System.out.println(timingsArray[x] / individualWordsToHighlight[x].length());
}
}
new Timer(1, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {
if (count < charsTiming.size()) {
highlightNextWord();
//restart timer with new timings
((Timer) ae.getSource()).setInitialDelay(charsTiming.get(count));
((Timer) ae.getSource()).restart();
} else {//we are at the end of the array
reset();
((Timer) ae.getSource()).stop();//stop the timer
}
count++;//increment counter
}
}).start();
}
});
frame.add(jtp, BorderLayout.CENTER);
frame.add(startButton, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
private void reset() {
startButton.setEnabled(true);
jtp.setText("");
for (String s : individualWordsToHighlight) {
String tmp = jtp.getText();
jtp.setText(tmp + s);
}
JOptionPane.showMessageDialog(frame, "Done");
}
private void highlightNextWord() {
//we still have words to highlight
int sp = 0;
for (int i = 0; i < count + 1; i++) {//get count for number of letters in words (we add 1 because counter is only incrementd after this method is called)
sp += 1;
}
//highlight words
Style style = jtp.addStyle("RED", null);
StyleConstants.setForeground(style, Color.RED);
((StyledDocument) jtp.getDocument()).setCharacterAttributes(0, sp, style, true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new KaraokeTest();
}
});
}
}
UPDATE
In response to your edited question.
Again the code complies fine for me, which brings me to the conclusion our java Runtimes differ and might be causing a problem. Mine is:
java version "1.7.0_10" Java(TM) SE Runtime Environment (build
1.7.0_10-b18) Java HotSpot(TM) 64-Bit Server VM (build 23.6-b04, mixed mode)
UPDATE 2:
As per your comment on your java version:
JDK 6, NetBeans 6.5.1
Have you tried:
final ArrayList<String> chars = new ArrayList<String>();
final ArrayList<Integer> charsTiming = new ArrayList<Integer>();
note i dont use <> anymore as Java 6 does not support the Diamond operator it would have to have the data type included i.e <Integer>.

Random errors when changing series using JFreeChart

I'm making a GUI that display result of background calculations. But before that, I wanted to test changing the dataset. Here is my code:
DefaultXYDataset dataset = new DefaultXYDataset();
#Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < periods; i++) {
series[0][i] = (double) i;
series[1][i] = 0;
}
dataset.addSeries("Series0", series);
for (int it = 0; it < 10; it++) {
series[1][random.nextInt(periods)] = random.nextInt(100) / 2;
double[][] d = new double[2][periods];
for (int i = 0; i < periods; i++) {
d[0][i] = series[0][i];
d[1][i] = series[1][i];
}
dataset.removeSeries("Series0");
dataset.addSeries("Series0", series);
// try {
// Thread.sleep(100);
// } catch (java.lang.InterruptedException ex) {
// }
}
As you can see, I want to change points on the graph (every time it finishes 'some complicated computations') - this change is in the thread invoked by me in another class. My problem is that this whole concept is not working. It throws 'Series index out of bounds'-IllegalArgumentException, 'index out of bounds' - of some library inner arraylist etc.. I'm not using DynamicTimeSeriesCollection because I need the X axis to be the number of my inner iterations not the time period, and also update when 'some computations' are finished not every some time period. Can you tell me what I'm doing wrong? Or is there a better way to update/refresh the graph?
Your snippet is incorrectly synchronized; you should update your dataset from the process() method of a SwingWorker, as shown here. Because your domain is "the number of my inner iterations", don't use a DateAxis; instead, use a NumberAxis, as shown in ChartFactory.createXYLineChart().
Addendum: This variation on the example plots the worker's progress on a line chart. Note that createXYLineChart() uses NumberAxis for both domain and range. Given a series in the line chart's dataset, note also how the implementation of process() can safely update the dataset as new data arrives; the listening chart will update itself in response.
private XYSeries series = new XYSeries("Result");
…
#Override
protected void process(List<Double> chunks) {
for (double d : chunks) {
label.setText(df.format(d));
series.add(++n, d);
}
}
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
import java.text.DecimalFormat;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
/**
* #see https://stackoverflow.com/a/13205322/230513
* #see https://stackoverflow.com/questions/4637215
*/
public final class ChartWorker {
private static final String S = "0.000000000000000";
private final JProgressBar progressBar = new JProgressBar();
private final JLabel label = new JLabel(S, JLabel.CENTER);
private final XYSeries series = new XYSeries("Result");
private final XYDataset dataset = new XYSeriesCollection(series);
private void create() {
JFrame f = new JFrame("√2");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(progressBar, BorderLayout.NORTH);
JFreeChart chart = ChartFactory.createXYLineChart(
"Newton's Method", "X", "Y", dataset,
PlotOrientation.VERTICAL, false, true, false);
XYPlot plot = (XYPlot) chart.getPlot();
plot.getRangeAxis().setRange(1.4, 1.51);
plot.getDomainAxis().setStandardTickUnits(
NumberAxis.createIntegerTickUnits());
XYLineAndShapeRenderer renderer
= (XYLineAndShapeRenderer) plot.getRenderer();
renderer.setSeriesShapesVisible(0, true);
f.add(new ChartPanel(chart) {
#Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
}, BorderLayout.CENTER);
f.add(label, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
runCalc();
}
private void runCalc() {
progressBar.setIndeterminate(true);
TwoWorker task = new TwoWorker();
task.addPropertyChangeListener((PropertyChangeEvent e) -> {
if ("progress".equals(e.getPropertyName())) {
progressBar.setIndeterminate(false);
progressBar.setValue((Integer) e.getNewValue());
}
});
task.execute();
}
private class TwoWorker extends SwingWorker<Double, Double> {
private static final int N = 5;
private final DecimalFormat df = new DecimalFormat(S);
double x = 1;
private int n;
#Override
protected Double doInBackground() throws Exception {
for (int i = 1; i <= N; i++) {
x = x - (((x * x - 2) / (2 * x)));
setProgress(i * (100 / N));
publish(x);
Thread.sleep(1000); // simulate latency
}
return x;
}
#Override
protected void process(List<Double> chunks) {
for (double d : chunks) {
label.setText(df.format(d));
series.add(++n, d);
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new ChartWorker()::create);
}
}

Categories