Results 1 to 19 of 19
  1. #1
    jkhamler is offline Member
    Join Date
    Nov 2009
    Posts
    24
    Rep Power
    0

    Default GUI Concurrency Problems

    In the simplest way possible, how do I use threads so that two swing windows can talk to each other?

    It seems that if there is a continuous process going on in one, the other window cannot respond.

    As you can tell from this novice and amateur-ish post I am a beginner!

    Any suggestions would be much appreciated.

    Jon

  2. #2
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    You don't use threads for this since all Swing components are run on the single same thread, the Event Dispatch Thread. What you likely have is not a thread problem per se, but a reference problem. You need to have viable references of one Swing object in the other for both to communicate with each other (or perhaps better is to have references of both Swing objects in a separate Control class.

  3. #3
    jkhamler is offline Member
    Join Date
    Nov 2009
    Posts
    24
    Rep Power
    0

    Default

    I tried this but I got a problem - the swing windows wouldn't properly load up.

    Is it because I am using the terminal to enter commands? I want to make a JFrame console with a KeyListener to read input instead - will this work better?

  4. #4
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    Perhaps it would be better if you describe what you are trying to achieve from the user's perspective rather than from a code perspective.

  5. #5
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    For instance, say I have a class that holds a JSlider in it, and I want another class that holds a JLabel to display the value of the slider, I could give the slider holding class a method that allow outside classes to add a change listener to the slider, so that they are notified every time the slider changes and also give the class a public method that returns the current value of the slider, something like so:

    Java Code:
    // the class that holds the JSlider
    class SliderWindow {
      //... code removed to simplify
      private JSlider slider = new JSlider(0, 100, 50);
    
      //... code removed to simplify
    
      // returns the current value of the slider
      public int getValue() {
        return slider.getValue();
      }
    
      // allows outside classes to listen for changes in the slider's value.
      public void addChangeListener(ChangeListener cl) {
        slider.addChangeListener(cl);
      }
    }

    The other class that displays the sliders value would need a public method that allows us to change the display, something like:
    Java Code:
    class NumberDisplay {
      //....
      private JLabel displayLabel = new JLabel();
      
      //  allows outside classes to change the displayed text
      public void setDisplay(String text) {
        displayLabel.setText(text);
      }
    
      //....
    }

    Then in a Control class I would have variables for both classes above, so that they can "talk" to each other. I'd add a change listener to the slider-containing class and in the change listener get the value from the slider and then use this value to set the text in the other class that displays the text:
    Java Code:
        final SliderWindow sliderWindow = new SliderWindow();
        final NumberDisplay numberDisplay = new NumberDisplay();
        
        sliderWindow.addChangeListener(new ChangeListener() {
          
          // this method gets called every time the slider is changed
          public void stateChanged(ChangeEvent arg0) {
            int value = sliderWindow.getValue();  // get value
            String valueString = Integer.toString(value);  // change to string
            numberDisplay.setDisplay(valueString);  // set number display's JLabel 
          }
        });

    Putting it all together:
    Java Code:
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.event.*;
    
    public class SwingCommunication {
      private static void createAndShowGUI() {
        final SliderWindow sliderWindow = new SliderWindow();
        final NumberDisplay numberDisplay = new NumberDisplay();
        numberDisplay.setDisplay(String.valueOf(sliderWindow.getValue()));
        
        sliderWindow.addChangeListener(new ChangeListener() {
          
          // this method gets called every time the slider is changed
          public void stateChanged(ChangeEvent arg0) {
            int value = sliderWindow.getValue();  // get value
            String valueString = Integer.toString(value);  // change to string
            numberDisplay.setDisplay(valueString);  // set number display's JLabel 
          }
        });
        
        JFrame frame = new JFrame("Swing Communication");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(sliderWindow.getPanel());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        
        JDialog displayDialog = new JDialog(frame, "Number Display", false);
        displayDialog.getContentPane().add(numberDisplay.getPanel());
        displayDialog.pack();
        Point p = frame.getLocation();
        displayDialog.setLocation(p.x, p.y - 100);
        displayDialog.setVisible(true);
        
      }
    
      public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            createAndShowGUI();
          }
        });
    
      }
    }
    
    class SliderWindow {
      private JPanel mainPanel = new JPanel();
      private JSlider slider = new JSlider(0, 100, 50);
    
      public SliderWindow() {
        slider.setMajorTickSpacing(20);
        slider.setMinorTickSpacing(5);
        slider.setPaintTicks(true);
        slider.setPaintLabels(true);
        
        mainPanel.setLayout(new GridLayout());
        mainPanel.add(slider);
        mainPanel.setPreferredSize(new Dimension(400, 100));
      }
      
      // returns the current value of the slider
      public int getValue() {
        return slider.getValue();
      }
    
      // allows outside classes to listen for changes in the slider's value.
      public void addChangeListener(ChangeListener cl) {
        slider.addChangeListener(cl);
      }
    
      public JComponent getPanel() {
        return mainPanel;
      }
    }
    
    class NumberDisplay {
      private JPanel mainPanel = new JPanel();
      private JLabel displayLabel = new JLabel("  ", SwingConstants.CENTER);
      
      public NumberDisplay() {
        mainPanel.add(new JLabel("Value: "));
        mainPanel.add(displayLabel);
      }
      
      //  allows outside classes to change the displayed text
      public void setDisplay(String text) {
        displayLabel.setText(text);
      }
    
      public JPanel getPanel() {
        return mainPanel;
      }
    }
    Last edited by Fubarable; 01-19-2010 at 12:28 AM.

  6. #6
    jkhamler is offline Member
    Join Date
    Nov 2009
    Posts
    24
    Rep Power
    0

    Default

    aah.. this 'changelistener' seems to be what I need.

    In one JFrame class, 'House' I have a mouselistener that triggers a method in another non-GUI class, 'Alarm'. 'Alarm' has a timer (using sleep(), emits a system beep - both of which are working), but the last thing I want it to do (which isn't working) is to change the colour of the frame in 'House' and append some text to a frame in another JFrame, 'System Status'..

    I appear to have some kind of deadlock between the frames. I assume this is where the 'changelistener' comes in?

  7. #7
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    Perhaps you will need to show us some code. :)

    Also, I'm a bit worried about the Thread.sleep(...) business. If you are doing this on the EDT (Swing's main thread for doing drawing and user interaction), you will freeze the app. Often we use a Swing Timer instead, but it's tough to know for sure without code.

    Again, much luck!

  8. #8
    jkhamler is offline Member
    Join Date
    Nov 2009
    Posts
    24
    Rep Power
    0

    Default

    Right, so here is the troublesome method. Basically, it won't append the text to the JFrames or colour the JPanels as I'd like it to, although the timer does run in the background and the 'beep' function works. I suspect it's something to do with the 'sleep()' command freezing the program.

    Java Code:
    public static void soundAlarm(){
    
            try{
                for (int i=10;i>0;i--)
                {
                    String s = Integer.toString(i);
                    SystemStatus.jTextArea1.append(s+" ");
                    Thread.sleep(1000); // sleep for a second before looping
                }
            }
            catch(InterruptedException e) {} // catches any exceptions thrown
    
                // turns all rooms red
                MyHouse.jPanel1.setBackground(Color.red);
                MyHouse.jPanel2.setBackground(Color.red);
                MyHouse.jPanel3.setBackground(Color.red);
                MyHouse.jPanel4.setBackground(Color.red);
    
                while (alarmIsArmed==true){
                try{
                    SystemStatus.jTextArea1.append("\nALARM!\n");
                    Thread.sleep(500); // sleep for a second before looping
                    Toolkit.getDefaultToolkit().beep();
                }
                catch(InterruptedException e) {} // catches any exceptions thrown  
                }}
    any suggestions would be greatly appreciated.

  9. #9
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    Quote Originally Posted by jkhamler View Post
    Right, so here is the troublesome method. Basically, it won't append the text to the JFrames or colour the JPanels as I'd like it to, although the timer does run in the background and the 'beep' function works. I suspect it's something to do with the 'sleep()' command freezing the program.

    Java Code:
    public static void soundAlarm(){
    
            try{
                for (int i=10;i>0;i--)
                {
                    String s = Integer.toString(i);
                    SystemStatus.jTextArea1.append(s+" ");
                    Thread.sleep(1000); // sleep for a second before looping
                }
            }
            catch(InterruptedException e) {} // catches any exceptions thrown
    
                // turns all rooms red
                MyHouse.jPanel1.setBackground(Color.red);
                MyHouse.jPanel2.setBackground(Color.red);
                MyHouse.jPanel3.setBackground(Color.red);
                MyHouse.jPanel4.setBackground(Color.red);
    
                while (alarmIsArmed==true){
                try{
                    SystemStatus.jTextArea1.append("\nALARM!\n");
                    Thread.sleep(500); // sleep for a second before looping
                    Toolkit.getDefaultToolkit().beep();
                }
                catch(InterruptedException e) {} // catches any exceptions thrown  
                }}
    any suggestions would be greatly appreciated.
    First and foremost, you need to get rid of everything static in your code. Instead use real objects and OOPs techniques. I'll bet that one reason one part of your GUI isn't talking to the other is that you don't have real objects here. I think it important that you learn and use OOP techniques before trying to do Java GUI programming since the latter is dependent on knowledge of the former.

    Next your House class should have a public non-static method that allows outside classes to set the background color of the 4 panels -- the rooms. Say public void setRoomColor(Color color). The SystemStatus class should have a public method that allows text to be appended to its text areas (the previous classes jpanels and this class's text areas should not be exposed -- should not be public but rather private).

    Next it looks like you should use two Swing timers here, the first one with a delay set to 1000 ms and that does the count down, the second with a delay set at 500 which does the alarm. The Sun tutorials have a decent section on how to use Swing Timers and I suggest that you read it and try to implement this,... but again only after you get rid of those unnecessary statics.

    Why not have a look at the tutorials, give it a go, and see if you can get it to work. If not, come on back with any problems and code.

    Best of luck!

  10. #10
    Steve11235's Avatar
    Steve11235 is offline Senior Member
    Join Date
    Dec 2008
    Posts
    1,046
    Rep Power
    7

    Default

    Just glancing through all the posts, the Swing Timer (javax.swing.Timer, not java.util.Timer) provides the "thread" support you are looking for. I suspect you are freezing the UI with your sleep() commands.

    As Fubarable said, use objects, not a bunch of static methods. And one JFrame is usually enough, with multiple JPanel holding other components to provide arrangement. Swing development isn't hard, but it's not simple, either. Take the time to learn the basics...

  11. #11
    jkhamler is offline Member
    Join Date
    Nov 2009
    Posts
    24
    Rep Power
    0

    Default

    Ok great, thanks guys. I had a feeling it was something to do with the 'static'. I presume I don't want this at all throughout my program, except for the 'main' method?

    The reason I ended up with too many static methods and variables was that when I tried to call a non-static method from the 'main' method (which is static - correct?) I was told that I couldn't access a non-static method from a 'static' context.

  12. #12
    jkhamler is offline Member
    Join Date
    Nov 2009
    Posts
    24
    Rep Power
    0

    Default

    For example, I am now getting this error - 'non-static variable alarmIsArmed' cannot be accessed from a static context'. I have removed all references to static I can find.

    I presume this is due the fact I have insufficient object-orientation in my code?

    Java Code:
    /** method to respond to burglar entering living room **/
        private void jPanel1MouseEntered(java.awt.event.MouseEvent evt) {                                     
    
            if (Alarm.alarmIsArmed == true) // if alarm is armed, execute loop body
                
            {System.out.println
                     ("Intruder Detected in Living Room!\n" +
                      "Alarm will sound in 10 seconds!\n" +
                      "Login to the system to disarm alarm.\n" +
                      "(1 - User, 2 - Admin)\n");
                       jPanel1.setBackground(Color.red);
    
                       while (Alarm.alarmIsArmed==true){
                       Alarm.soundAlarm(); // sets off alarm
                       }
                     }
            else {jPanel1.setBackground(Color.getHSBColor(60, 10, 110));
    
            }
        }

  13. #13
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    Quote Originally Posted by jkhamler View Post
    For example, I am now getting this error - 'non-static variable alarmIsArmed' cannot be accessed from a static context'. I have removed all references to static I can find.
    I presume this is due the fact I have insufficient object-orientation in my code?
    You're calling the method off of the class, Alarm, and not off of an Alarm object. Solution: create an Alarm object and use it.

  14. #14
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,006
    Rep Power
    20

    Default

    Alarm is your class. You should have an instance of Alarm (probably called alarm) that you actually work with.

    Think of Alarm as the blueprint, and alarm as the actual object itself.

  15. #15
    jkhamler is offline Member
    Join Date
    Nov 2009
    Posts
    24
    Rep Power
    0

    Default

    Ok great - so Alarm needs a constructor I presume? Do I instantiate the alarm from the main class?

    Many thanks.

  16. #16
    jkhamler is offline Member
    Join Date
    Nov 2009
    Posts
    24
    Rep Power
    0

    Default

    So I've made a constructor for the alarm but I'm still getting these 'non-static variable alarmIsArmed cannot be accessed from a static context' warnings...

    Java Code:
    public class Alarm {
    
        /** default setting for the alarm - off (false) **/
        private boolean alarmIsArmed;;
    
        /** interval - delay constant used for timer functions (milliseconds) **/
        private int interval;
    
        /**
         * constructor for 'Alarm' objects
         *
         * @param alarmIsArmed - initial state of the alarm (on/off)
         * @param interval - delay constant used for timer functions
         */
    
        public Alarm(){ // constructor for alarm
    
            alarmIsArmed = false; // off
    
            interval = 1000; // 1 second
        }

  17. #17
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,006
    Rep Power
    20

    Default

    Are you calling it as an Alarm object?
    eg
    Java Code:
    Alarm alarm = new Alarm();
    if (alarm.alarmIsArmed) {
        Do something...
    }

  18. #18
    jkhamler is offline Member
    Join Date
    Nov 2009
    Posts
    24
    Rep Power
    0

    Default

    Yes, it's just this static business.

    Getting very worried... I feel like I'm going to have to completely start again, and time is very much against me

    :(

  19. #19
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,006
    Rep Power
    20

Similar Threads

  1. JAR problems
    By Evil Smurf in forum New To Java
    Replies: 4
    Last Post: 09-01-2009, 01:17 AM
  2. Few Problems Help!
    By elad_bj in forum New To Java
    Replies: 4
    Last Post: 04-07-2009, 03:45 AM
  3. Concurrency system, and threads.
    By scarymovie in forum New To Java
    Replies: 2
    Last Post: 03-05-2009, 02:20 AM
  4. concurrency question
    By diggitydoggz in forum New To Java
    Replies: 4
    Last Post: 01-17-2009, 03:48 AM
  5. Explanation bout threading and concurrency?
    By cruxblack in forum New To Java
    Replies: 1
    Last Post: 08-10-2007, 10:33 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •