4

Friends, i am developing a java application. Thats for performance monitoring. on that i am getting values in one class and drawing a graph in another class. i want to use swingworker to perform those two class alternatively.

        ResultSet rs;
        Connection conn = null;

        conn = (Connection)getMySqlConnection();

        Statement st = conn.createStatement();
        rs = st.executeQuery("SHOW GLOBAL STATUS");
        while(rs.next())
        {
            Map_MySql.put(rs.getString(1), rs.getString(2));
        }
        conn.close();

Above class for collecting server status and store it in hash map. this class called as "MySQLClass".

        System.out.println("Graph Occur");
        XYDataset Dataset;
        TimeSeries Series = new TimeSeries("Random Data");
        Second sec = new Second();
        ChartPanel CPanel;
        if(Operation_Combo.getSelectedItem().toString() == "MySQL")
        {
         if(MySQLClass.Map_MySql.get(""+MainWindow.SelectedNode+"") == null)
         {
             Value = 0;
         }
         else
         {
             Value = Integer.parseInt(MySQLClass.Map_MySql.get(""+MainWindow.SelectedNode+""));
         }
         System.out.println(Value);
        }
        if(Operation_Combo.getSelectedItem().toString() == "SQL Server")
        {
         if(SqlServerClass.Map_SQLServer.get(""+MainWindow.SelectedNode+"") == null)
         {
             Value = 0;
         }
         else
         {
             Value = Integer.parseInt(SqlServerClass.Map_SQLServer.get(""+MainWindow.SelectedNode+""));
         }
         System.out.println(Value);
        }
        String CounterName = MainWindow.SelectedNode.toString();
        Series.add(sec, Value);
        Dataset = new TimeSeriesCollection(Series);
        Chart = ChartFactory.createTimeSeriesChart(CounterName, "Time", "Range", Dataset, true, false, false);
        XYPlot Plot = (XYPlot)Chart.getPlot();
        Plot.setBackgroundPaint(Color.LIGHT_GRAY);
        Plot.setDomainGridlinePaint(Color.WHITE);
        Plot.setRangeGridlinePaint(Color.RED);
        CPanel = new ChartPanel(Chart);
        Panel1.revalidate();
        Panel1.add(CPanel);
        System.out.println("Chart Added");
        Panel1.validate();
        Panel1.repaint();
        Thread.sleep((int)MainWindow.Interval_Combo.getSelectedItem() * 1000);
        System.out.println("Sleep="+((int)MainWindow.Interval_Combo.getSelectedItem() * 1000));
        System.gc();

Above is the code for drawing Graph in one class called "Graph". How can i use swing worker to perform this alternatively and draw graph in every iteration. if you know help me please.

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
A.Mohamed Bilal
  • 115
  • 1
  • 13
  • 2
    Take a look at [Concurrency with Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html). There's a section on using `SwingWorker` – Paul Samsotha Jan 06 '14 at 07:04
  • Unrelated: Please learn java naming conventions and stick to them. – kleopatra Jan 06 '14 at 11:38
  • possible duplicate of [JFreeChart does not show the graph at every iteration on thread?](http://stackoverflow.com/questions/20884694/jfreechart-does-not-show-the-graph-at-every-iteration-on-thread) – trashgod Jan 06 '14 at 17:13

2 Answers2

7

SwingWorker is a lot simpler to use them it might seem.

Basically, you need to make a few basic decisions about what you want to achieve.

  • Do you want to return periodically updates while the process is running or
  • Do you want to return a result of the process...or both?
  • Do you want to provide progression updates?

Depending on what you want to do, will change the way you declare the SwingWorker.

For example...

public class HardWorker extends SwingWorker<ReturnValueType, PeriodicalType> {

Where ReturnValueType is the final result that will be generated by the worker and PeriodicalType is the type of object that could be sent back to the UI thread should you want to perform periodical updates (these are values you can specify yourself).

You can specify Void or Object for either of these values should you not care

When executed, the SwingWorker will call doInBackground, this method will be called within its own thread, allowing to perform your long running task outside of the Event Dispatching Thread.

If you want to send a value back to the UI before the doInBackground method has finished, you can call publish(instanceOfPeriodicalType). The values passed to this method will, eventually, be passed to the process method.

Because it's possible for multiple items to sent to the publish method, the process method provides a List<PeriodicalType> argument. When called, this method will be executed within the context of the EDT, allowing you to up date the UI.

Once doInBackground completes, it will return a return value of type ReturnValueType (or null if you don't care).

If you're interested in this result, you should use SwingWorker#get, but you should beware that this method will block until doInBackground returns, meaning you shouldn't call this method within the EDT until you know the doInBackground method has returned. You can check the state of worker using it's isDone or isCancelled methods, or...

You could use a PropertyChangeListener and monitor the state property or override the done method of the SwingWorker.

If you want to provide progress updates, while in the doInBackground method, you can call setProgress to update the progress of the worker. This will trigger a PropertyChangeEvent named progress, which you can monitor through the use of a PropertyChangeListener. Calls to this listener will be made within the context of the EDT.

Take a look at:

For more details.

Generally, in order to use a SwingWorker, what you want to do, is separate your design into two groups. Every thing that can be done in the background and everything that needs to be done within the EDT.

You can start building the basic concept of your worker.

Basic Example...

This assumes a lot. Basically, it assumes that UI is already setup and this would be used to pick out new results and pass them back to a specific series.

Basically, as required, the worker would be insansiated, and the series passed to it...

GraphWorker worker = new GraphWorker(series);
worker.execute();

The work would then execute the query and pass the results back to the process method

public class GraphWorker extends SwingWorker<Void, String[]> {

    private TimeSeries series;
    private Second sec;

    public GraphWorker(TimeSeries series) {
        this.series = series;
        sec = new Second();
    }

    @Override
    protected Void doInBackground() throws Exception {
        ResultSet rs;
        Connection conn = null;
        try {

            conn = (Connection) getMySqlConnection();

            Statement st = conn.createStatement();
            rs = st.executeQuery("SHOW GLOBAL STATUS");
            while (rs.next()) {
                publish(new String[]{rs.getString(1), rs.getString(2)});
            }
        } finally {
            conn.close();
        }
        return null;
    }

    @Override
    protected void process(List<String[]> chunks) {
        for (String[] value : chunks) {

            try {
                int iValue = Integer.parseInt(value[1]);
                series.add(sec, Value);
            } catch (NumberFormatException exp) {
                exp.printStackTrace();
            }

        }            
    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • can anyone tell me how to call these two set of codings in Swingworker alternatively. any sample format for my problem means also really appreciated. please.,.... – A.Mohamed Bilal Jan 06 '14 at 12:00
  • @A.MohamedBilal: A complete example is examined [here](http://stackoverflow.com/a/13205322/230513). – trashgod Jan 06 '14 at 12:29
  • oh thanks. but thats for generating graph coding. i want to know how to make these two classes work alternatively using swing worker and, i want to generate graph in every iteration. Can you just give that coding only.If i got this, my project get finished. please. @trashgod – A.Mohamed Bilal Jan 06 '14 at 14:01
  • The example cited adds a point to the graph with every iteration. – trashgod Jan 06 '14 at 17:08
  • On each iteration, pass the result of the interaction to `publish` – MadProgrammer Jan 06 '14 at 19:32
  • MySQLClass MySQL = new MySQLClass(); MySQL.execute(); Its my coding. and i just write query in doinBackground function, store those details in hashmap and publish the hashmap. In process function i just write graph generated coding. On that also, i get output not a alternative form. output like, MySql Occur MySql Occur Connection Close Connection Close Graph Occur 71547 Chart Added Sleep=1000 Graph Occur 71547 Chart Added Sleep=1000 What should i do to perform it in alternative form. – A.Mohamed Bilal Jan 07 '14 at 05:24
  • Basically. I've add a very basic example and you're going to have to tweak it to make it work... – MadProgrammer Jan 07 '14 at 11:19
0

At first, i just call the doInBackground() function from MySQL.execute(); using this. And then in doInBackground() function , i just collect those counter values and use publish(); function to passcertain value. here i just pass flag to denote data's were collected successfully. publish(GraphLock);

After calling the Publish(); method, Process(List chunks) method get invoked. On that i just check the condition and call the Graph class to generate the graph.

    if(GraphLock==true)
        SwingUtilities.invokeLater(new Graph());

It works properly...

A.Mohamed Bilal
  • 115
  • 1
  • 13