Results 1 to 4 of 4
  1. #1
    Digital Larry is offline Member
    Join Date
    Mar 2013
    Posts
    47
    Rep Power
    0

    Default Variation on the Swing invokelater() issue

    OK, so I have a little JFrame with a JPanel in it. And I was a good boy and put the Swing element initialization inside of an invokeLater() clause, or structure, or whatever you call it.

    I also have a little mathematical function that I want drawn on the JPanel. This is done by a little function called drawFunc(). When I call drawFunc from within my listeners (that affect aspects of the mathematical function) it is drawn fine. But NOT when my frame initializes!

    I have traced this using the Eclipse debugger and in fact, the drawFunc() does get executed when the frame constructor is called. But it has no visible effect until I move one of the controls invoking a listener.

    Here's the code which demonstrates this:

    Java Code:
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics2D;
    import java.awt.event.ItemEvent;
    import java.awt.event.ItemListener;
    
    import javax.swing.BoxLayout;
    import javax.swing.JCheckBox;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JSlider;
    import javax.swing.SwingUtilities;
    import javax.swing.event.ChangeEvent;
    import javax.swing.event.ChangeListener;
    
    class ClipControlControlPanel implements ChangeListener, ItemListener {
    
    	/**
    	 * 
    	 */
    	private static final long serialVersionUID = -4717076120154216169L;
    	private JSlider gainSlider = new JSlider(JSlider.HORIZONTAL, 100, 500, 200);
    	private JLabel gainLabel = new JLabel("Hi");
    	private JCheckBox invert = new JCheckBox();
    	private JCheckBox flip = new JCheckBox();
    	private JFrame frame;
    	private JPanel graph;
    	double gain = 2.3;
    	boolean flipFlip = false;
    	boolean invertInvert = false;
    
    	public ClipControlControlPanel() {
    		gainSlider.addChangeListener(this);
    		flip.addItemListener(this);
    		invert.addItemListener(this);
    		SwingUtilities.invokeLater(new Runnable() {
    			public void run() {
    				frame = new JFrame("Clip Control");
    				frame.setTitle("");
    				frame.setPreferredSize(new Dimension(150, 220));
    				frame.setResizable(false);
    				graph = new JPanel();
    				frame.getContentPane().add(graph);
    				frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
    
    				invert.setText("Invert");
    				flip.setText("Flip");
    				graph.setBackground(Color.GREEN);
    				gainSlider.setMajorTickSpacing(25);
    
    				frame.add(gainLabel);
    				frame.add(gainSlider);
    				frame.add(invert);
    				frame.add(flip);
    				frame.add(graph);
    
    				frame.pack();
    				gainSlider.setValue((int) Math.round(gain) * 100);
    				gainLabel.setText(String.format("%2.2f", gain));
    				invert.setSelected(invertInvert);
    				flip.setSelected(flipFlip);
    				drawFunc();
    				frame.setVisible(true);
    			}
    		});
    	}
    
    	@Override
    	public void itemStateChanged(ItemEvent arg0) {
    		// TODO Auto-generated method stub
    		Object source = arg0.getItemSelectable();
    
    		if (source == flip) {
    			if(flipFlip == true) {
    				flipFlip = false;
    			}
    			else
    				flipFlip = true;	    		
    		} else if (source == invert) {
    			if(invertInvert == true) {
    				invertInvert = false;
    			}
    			else
    				invertInvert = true;	    		
    		} 		
    		drawFunc();
    	}
    
    	@Override
    	public void stateChanged(ChangeEvent e) {
    		// TODO Auto-generated method stub
    		if (e.getSource() == gainSlider) {
    			gain = ((double) gainSlider.getValue()/100.0);
    			gainLabel.setText(String.format("%2.2f", gain));
    		}
    		drawFunc();
    	}	
    
    	public void drawFunc() {
    		double i;
    		Graphics2D g2 = null;
    
    		//debug GSW
    		if(graph == null) return;
    		try {
    			//code
    			g2 = (Graphics2D) graph.getGraphics();
    		} catch(java.lang.Throwable t) {
    			System.out.println( t.getClass().getName() ); //this'll tell you what class has been thrown
    			t.printStackTrace(); //get a stack trace
    		}
    
    		if(g2 == null) return;
    
    		double x_scale = graph.getWidth();
    		double x_offset = 0; //graph.getWidth();
    		double y_scale = graph.getHeight();
    		double y_offset = 0;// graph.getHeight();
    
    		double p = gain;
    		g2.setColor(Color.BLACK);
    		g2.fillRect(0, 0, graph.getWidth(), graph.getHeight());
    
    		for(i = 0; i < 1.0; i += 0.01) {
    			double j;
    			double ii;
    
    			if(flipFlip == true) {
    				j = 1.0 - i;
    			}
    			else {
    				j = i;
    			}
    
    			if(invertInvert == true) {
    				ii = Math.min(1.0, j * p);
    			}
    			else {
    				ii = 1.0 - Math.min(1.0, j * p);
    			}
    
    			g2.setColor(Color.CYAN);
    			g2.drawRect((int) ((i * x_scale) + x_offset),(int) ((ii * y_scale) - y_offset),1,1);
    		}
    	}
    
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		new ClipControlControlPanel();
    
    	}
    }
    Last edited by Digital Larry; 05-11-2013 at 03:07 PM.

  2. #2
    JosAH's Avatar
    JosAH is online now Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,368
    Blog Entries
    7
    Rep Power
    20

    Default Re: Variation on the Swing invokelater() issue

    If your frame isn't visualized yet (setVisible(true)) your graph (a JPanel) isn't visible either; invisible components don't have a Graphics object and so your drawFunc( ... ) method simply terminates because you have told it so (line #116).

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

  3. #3
    Digital Larry is offline Member
    Join Date
    Mar 2013
    Posts
    47
    Rep Power
    0

    Default Re: Variation on the Swing invokelater() issue

    I changed the order of those lines and set the JPanel to visible:
    Java Code:
    				
    				frame.setVisible(true);
    				graph.setVisible(true);
    				drawFunc();
    assuming that's what you meant, it does not change the behavior. I traced this with the debugger and g2 is not null at that point, in fact it goes through the entire drawFunc() twice before it comes up with the green background.
    Last edited by Digital Larry; 05-11-2013 at 02:56 PM.

  4. #4
    Digital Larry is offline Member
    Join Date
    Mar 2013
    Posts
    47
    Rep Power
    0

    Default Re: Variation on the Swing invokelater() issue

    All right, I figured it out. Looks like the secret is in extending JPanel and then defining a custom paint method.

    Java Code:
    package painting;
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.event.ItemEvent;
    import java.awt.event.ItemListener;
    
    import javax.swing.BoxLayout;
    import javax.swing.JCheckBox;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JSlider;
    import javax.swing.SwingUtilities;
    import javax.swing.event.ChangeEvent;
    import javax.swing.event.ChangeListener;
    
    class ClipControlControlPanel implements ChangeListener, ItemListener {
    
    	private JSlider gainSlider = new JSlider(JSlider.HORIZONTAL, 100, 500, 200);
    	private JLabel gainLabel = new JLabel("Hi");
    	private JCheckBox invert = new JCheckBox();
    	private JCheckBox flip = new JCheckBox();
    	private JFrame frame;
    	private ClipPanel graph;
    	double gain = 2.3;
    	boolean flipFlip = true;
    	boolean invertInvert = true;
    
    	public ClipControlControlPanel() {
    		gainSlider.addChangeListener(this);
    		flip.addItemListener(this);
    		invert.addItemListener(this);
    		SwingUtilities.invokeLater(new Runnable() {
    			public void run() {
    				frame = new JFrame("Clip Control");
    				frame.setTitle("Clip");
    				frame.setPreferredSize(new Dimension(150, 220));
    				frame.setResizable(false);
    				graph = new ClipPanel();
    				frame.getContentPane().add(graph);
    				frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
    
    				invert.setText("Invert");
    				flip.setText("Flip");
    				graph.setBackground(Color.GREEN);
    				//				    graph.setBorder(BorderFactory.createEmptyBorder(0,10,10,10)); 
    
    				gainSlider.setMajorTickSpacing(25);
    
    				frame.add(gainLabel);
    				frame.add(gainSlider);
    				frame.add(invert);
    				frame.add(flip);
    				frame.add(graph);
    
    				frame.pack();
    				gainSlider.setValue((int) Math.round(gain) * 100);
    				gainLabel.setText(String.format("%2.2f", gain));
    				invert.setSelected(invertInvert);
    				flip.setSelected(flipFlip);
    				frame.setVisible(true);
    				graph.setVisible(true);
    				frame.repaint();
    			}
    		});
    	}
    
    	@Override
    	public void itemStateChanged(ItemEvent arg0) {
    		Object source = arg0.getItemSelectable();
    
    		if (source == flip) {
    			if(flipFlip == true) {
    				flipFlip = false;
    			}
    			else
    				flipFlip = true;	    		
    		} else if (source == invert) {
    			if(invertInvert == true) {
    				invertInvert = false;
    			}
    			else
    				invertInvert = true;	    		
    		} 		
    		frame.repaint();
    	}
    
    	@Override
    	public void stateChanged(ChangeEvent e) {
    		if (e.getSource() == gainSlider) {
    			gain = ((double) gainSlider.getValue()/100.0);
    			gainLabel.setText(String.format("%2.2f", gain));
    		}
    		frame.repaint();
    	}	
    
    	class ClipPanel extends JPanel {
    
    		/**
    		 * 
    		 */
    		private static final long serialVersionUID = 1L;
    
    		public ClipPanel() {
    
    		}
    
    		protected void paintComponent(Graphics g) {
    			super.paintComponent(g);       
    			g.drawString("This is my custom Panel!",10,20);
    			double i;
    			//debug GSW
    
    			if(g == null) return;
    
    			double x_scale = getWidth();
    			double x_offset = 0; //graph.getWidth();
    			double y_scale = getHeight();
    			double y_offset = 0;// graph.getHeight();
    
    			double p = gain;
    			g.setColor(Color.BLACK);
    			g.fillRect(0, 0, graph.getWidth(), graph.getHeight());
    
    			for(i = 0; i < 1.0; i += 0.01) {
    				double j;
    				double ii;
    
    				if(flipFlip == true) {
    					j = 1.0 - i;
    				}
    				else {
    					j = i;
    				}
    
    				if(invertInvert == true) {
    					ii = Math.min(1.0, j * p);
    				}
    				else {
    					ii = 1.0 - Math.min(1.0, j * p);
    				}
    
    				g.setColor(Color.CYAN);
    				g.drawRect((int) ((i * x_scale) + x_offset),(int) ((ii * y_scale) - y_offset),1,1);
    			}
    		}
    	}
    
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		new ClipControlControlPanel();
    
    	}
    }
    Goodnight everybody!

Similar Threads

  1. AWT/Swing Mixing Still and issue on MAC OSX?
    By Confused in forum AWT / Swing
    Replies: 2
    Last Post: 02-21-2010, 08:34 PM
  2. SwingUtilities.invokeLater();
    By Lil_Aziz1 in forum New To Java
    Replies: 4
    Last Post: 02-08-2010, 10:11 PM
  3. what is SwingUtilities.invokeLater(new Runnable())
    By sivakumar_sakam in forum AWT / Swing
    Replies: 3
    Last Post: 05-06-2009, 04:47 AM
  4. Swing Timers Issue.
    By killpoppop in forum AWT / Swing
    Replies: 4
    Last Post: 03-09-2009, 11:17 PM
  5. Use of swingutilities.invokeLater
    By neha_negi in forum AWT / Swing
    Replies: 2
    Last Post: 09-19-2008, 02:48 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
  •