Hassan Al-Shehari
Hassan Al-Shehari

Reputation: 57

Stop infinite loop paint() method? Add JButton with paint()?

I wrote program to draw wheel (circle with 6 segments) and each segment with different colour. and animate the wheel..

here is the code:

    public class ExamWheel extends JFrame implements ActionListener{
        JButton b_start = new JButton("Start");
        JButton b_stop = new JButton("Stop");
        Thread th;
        Boolean doDraw = true;

        public ExamWheel(){
            setSize(400,400);
            setVisible(true);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setLocationRelativeTo(null);
            setTitle("Wheel..");
            //add(b_start);
            this.setLayout (new FlowLayout());
            this.add(b_stop);
            b_start.addActionListener(this);
        }

        public void actionPerformed(ActionEvent e) {
            if(e.getSource()==b_start)
                doDraw=true;
        }

        public void paint(Graphics graphics) {
        if (doDraw){
            super.paint(graphics);
            Graphics2D g = (Graphics2D) graphics;
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            try{
            // draw the circle
            for(int i=0; ; i=i+1){
                g.setColor(Color.CYAN);
                g.fillArc(50, 50, 300, 300, i+0, 60);
                th.sleep(1);
                g.setColor(Color.red);
                g.fillArc(50, 50, 300, 300, i+60, 60);
                th.sleep(1);
                g.setColor(Color.green);
                g.fillArc(50, 50, 300, 300, i+120, 60);
                th.sleep(1);
                g.setColor(Color.blue);
                g.fillArc(50, 50, 300, 300, i+180, 60);
                th.sleep(1);
                g.setColor(Color.gray);
                g.fillArc(50, 50, 300, 300, i+240, 60);
                th.sleep(1);
                g.setColor(Color.pink);
                g.fillArc(50, 50, 300, 300, i+300, 60);
                th.sleep(1);
            }
            }
            catch(InterruptedException e){
                Thread.currentThread().interrupt();
            }
        }
        }

        public static void main(String[] args) {
            ExamWheel f = new ExamWheel();
        }

    }

Problems: it is infinite loop, and I can't stop it or close the Frame.

so I had idea:

I created Boolean variable (doDraw) with value true, and add JButton, when click the Button the variable will change to false, and in paint() method I'll use if condition at first of paint()

problem: I can't add JButton to the Frame with paint(), so what can I do?

Note: I tried to use paintComponent() but the loop (for with thread) doesn't work.

IT IS SOLVED Thanks for Pete Kirham

I added Timer and replaced paint() by paintComponent()

public class ExamWheel extends JPanel implements ActionListener {
    int i=0;
    Timer tm = new Timer(10, this);
    public void paintComponent(Graphics graphics) {
        super.paintComponent(graphics);
        Graphics2D g = (Graphics2D) graphics;
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        g.setColor(Color.CYAN);
        g.fillArc(50, 50, 300, 300, i+0, 60);
        g.setColor(Color.red);
        g.fillArc(50, 50, 300, 300, i+60, 60);
        g.setColor(Color.green);
        g.fillArc(50, 50, 300, 300, i+120, 60);
        g.setColor(Color.blue);
        g.fillArc(50, 50, 300, 300, i+180, 60);
        g.setColor(Color.gray);
        g.fillArc(50, 50, 300, 300, i+240, 60);
        g.setColor(Color.pink);
        g.fillArc(50, 50, 300, 300, i+300, 60);
        tm.start();
    }
    public void actionPerformed(ActionEvent e) {
        i++;
        repaint();
    }
    public static void main(String[] args) {
        ExamWheel wh = new ExamWheel();
        JFrame jf = new JFrame();
        jf.setSize(500,500);
        jf.setResizable(false);
        jf.setVisible(true);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setLocationRelativeTo(null);
        jf.setTitle("Wheel..");
        jf.add(wh);
    }

Upvotes: 0

Views: 1275

Answers (1)

Pete Kirkham
Pete Kirkham

Reputation: 49321

You need to return from paintComponent to allow the thread which runs the gui to do other stuff, like respond to button events or actually put the contents of the graphics onto the screen.

Use a timer to invalidate the component - see http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html and update the the animation based on the current time, for example current milliseconds modulo 5000 will give a cycle which repeats every five seconds.

Upvotes: 1

Related Questions