0

I am trying to determine the best way to pass data and updates between swing components and threads. Below is an example of what I am faced with

This is the main windows that the user interacts with, it holds a JTabbedPanel with a single JPanel as a tab of the tabbed panel. It also holds a JTextPane that is used to show the user some information.

public class MainView extends JFrame
{
    JTextPane m_jtOutput;
    JTabbedPane m_jtpTabs;

    JSortPanel m_jpSortTab;

    public LinkedList<DataPoint> data;
    DataPoint curPoint;

    public MainView()
    {
        m_jtpTabs = new JTabbedPane();
        m_jpSortTab = new JSortPanel(this);
        m_jtpTabs.addTab("Sort", m_jpSortTab);
        this.add(m_jtpTabs);
        this.add(m_jtOutPut);
    }

    public void newStatus(String inStat)
    {
        m_jtOutput.setText(inStat);
    }

    public DataPoint getCurPoint()
    {
        return curPoint;
    }
}

This is the JPanel that is shown in the JTabbedPanel within the main view. It has a worker thread that does some sorting on the data. It also writes some updates to the main views output text pane.

 public class JSortPanel extends JPanel
 {
     JButton doSort; 
     MainView mainVw;
     SortThread sortThread;

     public JSortPanel(MainView inView)
     {
         mainVw = inView;
         this.add(doSort); // also get the listener hooked up
         sortThread = new SortThread(mainView);
     }

     public void doSortClicked(EventArgs e)
     {
         sortThread.start();
         mainView.newStatus("Started sorting");
     }
 }

This is the sorting thread. It initially reads the data from the main view and then sorts it, periodically writing some information to the main views text pane about the state of the sorting.

public class SortThread extends Thread
{
    MainView mainVw;
    LinkedList<DataPoint> data;

    public SortThread(MainView inView)
    {
        mainVw = inView;
        System.out.println("Cur data " + mainView.getCurData());
    }

    public void run()
    {
        data = mainVw.data;
        while(true)
        {
            doASortingStep(data);
            mainVw.newStatus("Did a sorting step");
        }
    }
}

My questions are.

  1. Can JSortPanel call mainView.newStatus() safely? Can it only call it in the scope of an event handler, such as when a user clicks the doSort button?

  2. Can SortThread call mainView.newStatus() safely? Would that call be on the Swing EDT?

  3. Can SortThread call mainView.getCurData() and get the return value safely, I assume it is also either on the EDT or not based on the answer to the previous question?

  4. If all calls are on the EDT, can you give an example of a call that would not be on the EDT?

  5. If either or both JSortPanel and SortThread cannot call mainView.newStatus(..) safely, then how can they?

KDecker
  • 6,928
  • 8
  • 40
  • 81
  • you need to read about the event dispatching thread: http://www.google.com/url?url=http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html&rct=j&frm=1&q=&esrc=s&sa=U&ei=z0sHVLKBC8vCggSN7IHgDw&ved=0CDYQFjAF&usg=AFQjCNGBBzXOTG3FMBIRMdPKUUjVgpxtUg – ControlAltDel Sep 03 '14 at 17:12
  • Ok so `SortThread` needs to extend `SwingWorker` and can use the `.process` method (called by `this.publish(..)` in the SwingWorker) to update the main JFrames text output, I can also use the `.cancel` method to cancel the task. What about calling `mainView.getCurData()` from `SortThread`? Can I call that in an overriden `.process` method? // Otherwise `JSortPanel` can call `mainView.newStatus(..)` safely from what I can tell? – KDecker Sep 03 '14 at 17:32
  • In your case, JSortPanel is safe, but only because to doSortClicked method will be invoked by the UIThread. Otherwise, you'd call it in a Runnable using SwingUtilities.invokeLater(...) – ControlAltDel Sep 03 '14 at 17:44
  • Ok that makes sense. Say `SortThread` extended `SwingWorker` and overrode the `process()` method, it also has a public field `DataPoint curData`. Within the method `process()` it does `curData = mainView.getCurItem()`. Is this safe/correct? – KDecker Sep 03 '14 at 17:53

1 Answers1

1

Before a component is visualized on the screen / other device, it is generally safe for multi-threading. After a component is shown, all changes should be done on the UIThread via a SwingWorker or SwingUtilities.invokeLater

ControlAltDel
  • 33,923
  • 10
  • 53
  • 80
  • 2
    As noted [here](http://stackoverflow.com/a/7158505/230513), "Swing components and models should be created, modified, and queried _only_ from the event-dispatching thread." – trashgod Sep 03 '14 at 18:34