Results 1 to 19 of 19
Thread: GUI Concurrency Problems
- 01-18-2010, 11:48 PM #1
Member
- Join Date
- Nov 2009
- Posts
- 24
- Rep Power
- 0
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
-
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.
- 01-19-2010, 12:05 AM #3
Member
- Join Date
- Nov 2009
- Posts
- 24
- Rep Power
- 0
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?
-
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.
-
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.
- 01-19-2010, 11:46 AM #6
Member
- Join Date
- Nov 2009
- Posts
- 24
- Rep Power
- 0
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?
-
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!
- 01-19-2010, 10:02 PM #8
Member
- Join Date
- Nov 2009
- Posts
- 24
- Rep Power
- 0
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.
any suggestions would be greatly appreciated.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 }}
-
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!
- 01-20-2010, 01:56 AM #10
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...
- 01-20-2010, 10:08 AM #11
Member
- Join Date
- Nov 2009
- Posts
- 24
- Rep Power
- 0
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.
- 01-20-2010, 10:39 AM #12
Member
- Join Date
- Nov 2009
- Posts
- 24
- Rep Power
- 0
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)); } }
-
- 01-20-2010, 12:11 PM #14
Moderator
- Join Date
- Apr 2009
- Posts
- 10,460
- Rep Power
- 16
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.
- 01-20-2010, 12:24 PM #15
Member
- Join Date
- Nov 2009
- Posts
- 24
- Rep Power
- 0
Ok great - so Alarm needs a constructor I presume? Do I instantiate the alarm from the main class?
Many thanks.
- 01-20-2010, 02:15 PM #16
Member
- Join Date
- Nov 2009
- Posts
- 24
- Rep Power
- 0
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 }
- 01-20-2010, 02:51 PM #17
Moderator
- Join Date
- Apr 2009
- Posts
- 10,460
- Rep Power
- 16
Are you calling it as an Alarm object?
eg
Java Code:Alarm alarm = new Alarm(); if (alarm.alarmIsArmed) { Do something... }
- 01-20-2010, 03:31 PM #18
Member
- Join Date
- Nov 2009
- Posts
- 24
- Rep Power
- 0
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
:(
- 01-20-2010, 03:40 PM #19
Moderator
- Join Date
- Apr 2009
- Posts
- 10,460
- Rep Power
- 16
Similar Threads
-
JAR problems
By Evil Smurf in forum New To JavaReplies: 4Last Post: 09-01-2009, 01:17 AM -
Few Problems Help!
By elad_bj in forum New To JavaReplies: 4Last Post: 04-07-2009, 03:45 AM -
Concurrency system, and threads.
By scarymovie in forum New To JavaReplies: 2Last Post: 03-05-2009, 02:20 AM -
concurrency question
By diggitydoggz in forum New To JavaReplies: 4Last Post: 01-17-2009, 03:48 AM -
Explanation bout threading and concurrency?
By cruxblack in forum New To JavaReplies: 1Last Post: 08-10-2007, 10:33 AM


LinkBack URL
About LinkBacks
Reply With Quote

Bookmarks