I'm having trouble with a program. A user clicks a button, then the program starts to print out words every second or so. I've made a button and create the actionPerformed() to handle it. The problem lies in actionPerformed(). It seems that it only prints the tests After the whole thing had been drawn. Inside actionPerformed, an object is suppose to called repaint() and draw something, but paintComponent() is never called until the end. File But.java import javax.swing.*; import java.awt.*; import java.awt.event.*; public class But implements ActionListener { JFrame frame; JPanel panel; JButton btn; Ani a; Direc b; public But() { frame = new JFrame(); panel = new JPanel(); panel.setLayout(new GridLayout(2,1)); btn = new JButton("button"); btn.addActionListener(this);
a = new Ani(); panel.add(btn); panel.add(a); frame.getContentPane().add(panel); frame.setSize(new Dimension(500,500)); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); //works fine if not in actionPerformed. //b = new Direc(a); //b.draw(); } public void actionPerformed(ActionEvent e) { //doesn't call paintComponent() when refresh() is called. //only calls paintComponent when the draw is finished, which //i don't want. b = new Direc(a); b.draw(); } public static void main(String[] args) { new But(); } }
File Ani.java import javax.swing.*; import java.awt.*; public class Ani extends JComponent { int tar = 0; public void draw(int _tar) { tar = _tar; System.out.println("Repainting"); repaint(); System.out.println("Repainting Done"); } public void paintComponent(Graphics g) { if (tar == 0) return; System.out.println("Inside"); for ( int i = 0; i < tar; i++) { g.drawString("Tests..", i, 20 * i); } } } File Direc.java public class Direc { Ani a; public Direc(Ani _a) { a = _a; } public void draw() { for ( int i = 0; i < 10; i++) { a.draw(i); try { Thread.currentThread().sleep(500); } catch(Exception e) { } } } } I hope this make sense. Thanks for any help.
HI Bon, Your problem stems from the fact that you are running a sequential program. In order to change that you need to make use of threads. In Java it is pretty easy to do that. In your program, I would make Direc class implement Runnable. Change the draw method into the run method. It would look like this.
Then you can have your But class call it slightly differently because we want to start up another thread. It's actionPerformed routine would look like this.
This should now work as you expected it to in the first place. Regards, Manfred.
Bon, i agree with Manfred. by way of explanation, both the call to actionPerformed() and the call to paintComponent() are done by one thread - the AWT event thread. the call to repaint() requests the call to paintComponent() which will be done at the next opportunity by that AWT event thread - i.e. once it has finished executing actionPerformed(). hope that helps, dan.
dan moore, infomatiq ltd.<br />email dan@infomatiq.co.uk<br /><a href="http://www.infomatiq.co.uk" target="_blank" rel="nofollow">http://www.infomatiq.co.uk</a>
dan moore
Ranch Hand
Joined: Nov 04, 2001
Posts: 68
posted
0
Bon, in fact, doing a currentThread().sleep() on the AWT event thread is a complete no-no, as it will effectively hang the UI for the duration. cheers, dan.
Bon Hall
Greenhorn
Joined: Nov 29, 2001
Posts: 2
posted
0
Thanks Manfred, Dan. It help alot. The display screen was hanging and was driving me nuts because my textbooks doesn't mention about it. Thanks.