Results 1 to 11 of 11
Like Tree1Likes
  • 1 Post By Sutured

Thread: Question about revalidate();

  1. #1
    Sutured is offline Member
    Join Date
    Mar 2012
    Posts
    30
    Rep Power
    0

    Default Question about revalidate();

    Hello all,

    I am having a problem with revalidate when it is followed by code lines to execute. I encountered this at my program and after searching I couldn't find the solution.

    So I created a mini program that has exactly my problem.

    I have a Frame and a mainPanel in it. I created a panelTop and panelBottom putting them top and bottom respectively. I added a button at the panelBottom. I want that whenever I press the button to delete panelTop and create a new one with a label in it.

    I used 3 phases when pressing the button, all of them with a Thread.sleep(1000) between. So in phase 1 I removed the panelTop, created a new one, added it and used revalidate.

    But my problem is that revalidate is executed at the phase 3 and not at 1 as it is intended.

    Java Code:
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    
    public class Controller extends JFrame{
    
    	private static final long serialVersionUID = 1L;
    	private JPanel mainPanel, panelTop, panelBottom;
    	
    	public Controller() {
    
    		setPreferredSize(new Dimension(600,400));
    		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		
    		
    		mainPanel = new JPanel(new GridLayout(2, 1));
    		mainPanel.setBorder(BorderFactory.createTitledBorder("main panel"));
    		add(mainPanel);
    		
    		panelTop = new JPanel();
    		panelTop.setBorder(BorderFactory.createTitledBorder("panel top"));
    		mainPanel.add(panelTop);
    		
    		panelBottom = new JPanel();
    		panelBottom.setBorder(BorderFactory.createTitledBorder("panel bottom"));
    		mainPanel.add(panelBottom);
    		
    		pack();
    		setLocation((Toolkit.getDefaultToolkit().getScreenSize().width - getSize().width)/2, (Toolkit.getDefaultToolkit().getScreenSize().height - getSize().height)/2);
    		setVisible(true);
    		
    		JButton button = new JButton("press me");
    		panelBottom.add(button);
    		
    		button.addActionListener(new ActionListener() {
    			
    			public void actionPerformed(ActionEvent e) {
    				
    				// starting phase 1
    				
    				System.out.println("Phase 1");
    				
    				mainPanel.remove(panelTop);
    				
    				panelTop = new JPanel();
    				panelTop.setBorder(BorderFactory.createTitledBorder("new panel"));
    				mainPanel.add(panelTop, 0);
    				panelTop.add(new JLabel("random text"));
    				
    //				mainPanel.repaint();
    				mainPanel.revalidate();
    				
    				sleep();
    				
    				// starting phase 2
    				System.out.println("Phase 2");
    				sleep();
    				
    				// starting phase 3
    				System.out.println("Phase 3");
    				
    			}
    		});
    		
    	}
    	
    	private void sleep(){
    		
    		try{Thread.sleep(1000);}
    		catch(Exception e){}
    	}
    	
    	public static void main(String[] args) {
    		new Controller();
    	}
    
    }
    Can I get some help please?

    Thank you.

    John

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

    Default Re: Question about revalidate();

    Your problem is not with revalidate but with Thread.sleep(...). You should never call this on the Swing event thread as it will put the event thread to sleep making your GUI completely non-responsive. Better to use a Swing Timer for what you're trying to do above. Google the tutorial on the Swing Timer as it will give a decent explanation on how to use it complete with code example. Also, what's with all the unnecessary whitespace in your code post above?

  3. #3
    Sutured is offline Member
    Join Date
    Mar 2012
    Posts
    30
    Rep Power
    0

    Default Re: Question about revalidate();

    Regarding the whitespace. When I 'group up' some code I leave a line at the top and at the bottom of the 'group' so it's easier for me to reread it.

    For example, at the lines 46-49, I create the new panelTop. So I left lines 45 and 50 blank.

    Heading for the Swing Timer and I will be back with news.

    Thank you Fubarable.

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

    Default Re: Question about revalidate();

    The whitespace I refer to may be some bad behavior of my browser with the forum software, since it shows your code with about 100-200 blank lines of code following it. Please ignore my comment about this above, and sorry for the mistake.

  5. #5
    Sutured is offline Member
    Join Date
    Mar 2012
    Posts
    30
    Rep Power
    0

    Default Re: Question about revalidate();

    Its ok about the whitespace, no problem.

    I can't seem to find what I want. Of course I learnt many things about the Swing Timer class, very useful ones.

    So, just to stop searching and learning a bit, I wanted to see it working, even with a not good way. I substituted Thread.sleep with a not so fancy for loop, just to get it done and see the results I want. But, they were the same! The panel changed at phase 3 again.

    The sleep method I used is this:

    Java Code:
            private void sleep(){
    		
    		for(int a=1; a<=500000;a++){
    			System.out.print(" ");
    		}
    	}
    Shouldn't the panel update at phase 1 using this way?

  6. #6
    Sutured is offline Member
    Join Date
    Mar 2012
    Posts
    30
    Rep Power
    0

    Default Re: Question about revalidate();

    Yes Fubarable, I got it.

    Java Code:
    import java.awt.*;
    import java.awt.event.*;
    
    import javax.swing.*;
    
    
    public class Controller extends JFrame{
    
    	private static final long serialVersionUID = 1L;
    	private JPanel mainPanel, panelTop, panelBottom;
    	private Timer timer;
    	private int counter = 1;
    	private HandleRedraw handleRedraw = new HandleRedraw();
    	
    	public Controller() {
    		
    		
    		
    		setPreferredSize(new Dimension(600,400));
    		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		
    		
    		mainPanel = new JPanel(new GridLayout(2, 1));
    		mainPanel.setBorder(BorderFactory.createTitledBorder("main panel"));
    		add(mainPanel);
    		
    		panelTop = new JPanel();
    		panelTop.setBorder(BorderFactory.createTitledBorder("panel top"));
    		mainPanel.add(panelTop);
    		
    		panelBottom = new JPanel();
    		panelBottom.setBorder(BorderFactory.createTitledBorder("panel bottom"));
    		mainPanel.add(panelBottom);
    		
    		pack();
    		setLocation((Toolkit.getDefaultToolkit().getScreenSize().width - getSize().width)/2, (Toolkit.getDefaultToolkit().getScreenSize().height - getSize().height)/2);
    		setVisible(true);
    		
    		JButton button = new JButton("press me");
    		panelBottom.add(button);
    		
    		button.addActionListener(new ActionListener() {
    			
    			public void actionPerformed(ActionEvent e) {
    				
    				timer = new Timer(1000, handleRedraw);
    					
    				timer.start();
    				
    			}
    		});
    		
    	}
    	
    	private void counter(){
    		System.out.println("Phase " + counter + " begins");
    	}
    	
    	private class HandleRedraw implements ActionListener{
    
    		public void actionPerformed(ActionEvent e) {
    			
    			if(counter == 1){
    				counter();
    				mainPanel.remove(panelTop);
    				counter++;
    				rep();
    			}else if(counter == 2){
    				counter();
    				panelTop = new JPanel();
    				panelTop.setBorder(BorderFactory.createTitledBorder("new panel"));
    				mainPanel.add(panelTop, 0);
    				counter++;
    				reval();
    			}else if(counter == 3){
    				counter();
    				panelTop.add(new JLabel("random text"));
    				counter++;
    				reval();
    				System.out.println("Ended");
    				timer.stop();
    			}
    		}
    		
    	}
    	
    	public void reval(){
    		mainPanel.revalidate();
    	}
    	
    	public void rep(){
    		mainPanel.repaint();
    	}
    	
    	public static void main(String[] args) {
    		new Controller();
    	}
    	
    }
    Thank you again.

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

    Default Re: Question about revalidate();

    Quote Originally Posted by Sutured View Post
    Yes Fubarable, I got it.
    ....
    Thank you again.
    You're welcome, but one nitpick -- don't forget to call pack() after you've added all your components. You're calling it before you've added the JButton , and so it may not show unless the JFrame is re-sized.

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

    Default Re: Question about revalidate();

    Also, another possible solution to a similar issue is to create a queue of Runnable objects and run each Runnable in your Swing Timer. Something like so:

    Java Code:
    import java.awt.Dimension;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyEvent;
    import java.util.LinkedList;
    import java.util.Queue;
    
    import javax.swing.*;
    
    public class Controller2 {
       private static final Dimension MAIN_SIZE = new Dimension(600, 350);
       public static final int TIMER_DELAY = 2000;
       private JPanel mainPanel = createPanel("main panel");
       private JPanel topPanel = createPanel("panel top");
       private JPanel bottomPanel = createPanel("panel bottom");
       private JPanel newPanel = createPanel("new panel");
       private Queue<Runnable> runList = new LinkedList<Runnable>();
       
       public Controller2() {
          mainPanel.setPreferredSize(MAIN_SIZE);
          mainPanel.setLayout(new GridLayout(0, 1));
          
          mainPanel.add(topPanel);
          mainPanel.add(bottomPanel);
          
          fillRunList();
          
          bottomPanel.add(new JButton(new ButtonAction("Press Me", KeyEvent.VK_P)));
       }
       
       private void fillRunList() {
          runList.add(new Runnable() {
             public void run() {
                mainPanel.remove(topPanel);
                mainPanel.repaint();
             }
          });
          runList.add(new Runnable() {
             public void run() {
                mainPanel.add(newPanel, 0);
                mainPanel.revalidate();
                mainPanel.repaint();
             }
          });
          runList.add(new Runnable() {
             public void run() {
                newPanel.add(new JLabel("New Label"));
                newPanel.revalidate();
                newPanel.repaint();
             }
          });
          
    
       }
    
       public JComponent getMainComponent() {
          return mainPanel;
       }
    
       private JPanel createPanel(String title) {
          JPanel panel = new JPanel();
          panel.setBorder(BorderFactory.createTitledBorder(title));
          return panel;
       }
       
       private class ButtonAction extends AbstractAction {
          public ButtonAction(String name, int keyCode) {
             super(name);
             putValue(MNEMONIC_KEY, keyCode);
          }
    
          @Override
          public void actionPerformed(ActionEvent evt) {
             JButton btn = (JButton) evt.getSource();
             if (runList.size() > 0) {
                btn.setEnabled(false);
                new Timer(TIMER_DELAY, new TimerAction(btn)).start();
             }
          }
       }
       
       private class TimerAction implements ActionListener {
          private JButton btn;
    
          public TimerAction(JButton btn) {
             this.btn = btn;
          }
    
          @Override
          public void actionPerformed(ActionEvent e) {
             if (runList.size() > 0) {
                runList.poll().run();
             } else {
                Timer t = (Timer) e.getSource();
                t.stop();
                btn.setEnabled(true);
             }
          }
       }
    
       private static void createAndShowGui() {
          Controller2 mainPanel = new Controller2();
    
          JFrame frame = new JFrame("Controller2");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.getContentPane().add(mainPanel.getMainComponent());
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    }
    This way, you don't have to hard code your actions to some counter number, but rather the order that the actions are performed only depends on when they've been added to the list, FIFO -- first in, first out.

  9. #9
    Sutured is offline Member
    Join Date
    Mar 2012
    Posts
    30
    Rep Power
    0

    Default Re: Question about revalidate();

    While I was searching earlier for a solution to my program, I came up a suggestion to use invokeLater and Runnable. I didn't know what they were so I started reading them. I couldn't figure them out so I dropped them. After a bit I thought a way of doing this using the counter to determine the chain of the events to happen.

    But now I have the best thing in hand. My program refactored this way. This one screams for heavy study and complete understanding.

    Thank you Fubarable for your time spent on creating this for me.
    awinston likes this.

  10. #10
    Sutured is offline Member
    Join Date
    Mar 2012
    Posts
    30
    Rep Power
    0

    Default Re: Question about revalidate();

    The

    Java Code:
    setLocationRelativeTo(null);
    is huge.

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

Similar Threads

  1. Replies: 2
    Last Post: 05-25-2012, 04:00 PM
  2. Replies: 3
    Last Post: 11-20-2011, 05:50 PM
  3. question posted by indissa: library question.
    By Fubarable in forum New To Java
    Replies: 2
    Last Post: 11-18-2011, 01:14 AM
  4. Question mark colon operator question
    By orchid in forum Advanced Java
    Replies: 9
    Last Post: 12-19-2010, 08:49 AM
  5. Replies: 6
    Last Post: 06-16-2010, 06:03 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
  •