problem repaint()

0

Witam. Mam takie dwie klasy:

public class UpdateDrawing {
public static void main(String [] args){
JFrame frame = new JFrame();
final Drawing drawing = new Drawing();
JButton button = new JButton("Change Color");
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){

			drawing.drawingRepaint();
		}
	});
	
	frame.setTitle("Frame");
	frame.add(drawing);
	frame.add(button, BorderLayout.SOUTH);
	
	frame.pack();
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	frame.setLocationRelativeTo(null);
	frame.setVisible(true);
}

}
public class Drawing extends JPanel{

public int rgb[] = {255, 0, 0};

public Drawing(){
	setPreferredSize(new Dimension(140, 140));
}


public void paintComponent(Graphics g){
	super.paintComponent(g);
	Graphics2D g2d = (Graphics2D)g;
	
	g2d.setColor(new Color(rgb[0], rgb[1], rgb[2]));
	g2d.fillOval(20, 20, 100, 100);
}


public void drawingRepaint(){
	//for(int i=0;i<10;i++){
		rgb[0] = (int)(Math.random()*255);
		rgb[1] = (int)(Math.random()*255);
		rgb[2] = (int)(Math.random()*255);
	
		repaint();
	//}
}

}

Gdy 'for' jest wykomentowany - działa. Kiedy chcę, aby po kliknięciu kolor zmienił się 10 razy - nie działa. Kolor zmienia się tylko raz. Dlaczego tak się dzieje i jak to zmienić? Potrzebuję używać repaint() w pętli, bo tworzę wizualizację procesu i chcę żeby mi się odświeżało na bieżąco.

Z góry dzięki za pomoc.

0

Wg mnie kolor zmienia się 10 razy, tylko Ty masz za wolne oko by to zobaczyć. Wstaw do pętli

            repaint();
            try
            {
                Thread.sleep(1000);
            }
            catch(InterruptedException e)
            {
            }
0

Też właśnie tak myślałem, ale jak wstawiam sleepa, to przycisk pozostaje wciśnięty na 10sec a potem raz zmienia się kolor.

0

Musisz się pobawić wątkami, np. tak:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class UpdateDrawing {
        public static void main(String [] args){
                JFrame frame = new JFrame();
                final Drawing drawing = new Drawing();
                JButton button = new JButton("Change Color");
                button.addActionListener(new ActionListener(){
                        public void actionPerformed(ActionEvent e){

                                drawing.rysuj();
                        }
                });

                frame.setTitle("Frame");
                frame.add(drawing);
                frame.add(button, BorderLayout.SOUTH);

                frame.pack();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
        }

}
class Drawing extends JPanel implements Runnable
{
       
        public int rgb[] = {255, 0, 0};
        private Thread runner=null;
        public Drawing(){
                setPreferredSize(new Dimension(140, 140));
        }
       
       
        public void paintComponent(Graphics g){
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D)g;
               
                g2d.setColor(new Color(rgb[0], rgb[1], rgb[2]));
                g2d.fillOval(20, 20, 100, 100);
        }
       
        public void rysuj()
        {
            if (runner==null)
            {
                runner=new Thread(this);
                runner.start();
            }
        }
        public void run()
        {
            Thread ten=Thread.currentThread();
                for(int i=0;i<10;i++){
                        rgb[0] = (int)(Math.random()*255);
                        rgb[1] = (int)(Math.random()*255);
                        rgb[2] = (int)(Math.random()*255);
                        try
                        {
                            Thread.sleep(100);
                        }
                        catch(Exception e)
                        {
                        }
                        repaint();
                }
                runner=null;
        }
}
0

Działa, dzięki bogdans. A napisz dlaczego trzeba to odpalić z osobnego wątku? Spędziłem nad tym kilka dni, naczytałem się o event dispatch thread i nigdzie nic nawet nie sugerowało takiego rozwiązania.

0

Poszukaj na forum wypowiedzi @Olamagato na temat wątków i Swinga.

0

Ok, jeszcze raz dzięki.

0

Ja bym tylko pokrótce dodał, że wywołanie repaint() powinno zostać wywołane z najlepiej metody run() anonimowej klasy będącej argumentem invokeLater(), ewentualnie invokeAndWait(). Wywoływanie dowolnej metody dowolnej klasy Swinga może* spowodować wywrotkę programu lub nieoczekiwane zakleszczenie. Swing jest zawsze jednowątkowy mimo, że sama Java nie jest. Iterowanie repaintów można bezpiecznie wywoływać tylko tak jak podałem. Żeby sam kod okienkowy działał, to z procedury obsługi (takiej jak actionPerformed()) należy jak najszybciej wychodzić, żeby w ogóle odrysowywały się okienka. Wstawienie sleep gdziekolwiek w procedurze wywoływanej przez wątek Swing zawsze powoduje zawieszanie kodu okienkowego.

*- czasem ujdzie to na sucho w krótkich programach. W długim w którymś momencie zostaną wywołane równocześniej dwie metody repaint() i w efekcie albo zlecenie jednego z nich zostanie zgubione, albo do kolejki zadań zostaną wrzucone zmiksowane śmiecie dające łącznie komunikat zupełnie inny niż polecenie odmalowania.

1 użytkowników online, w tym zalogowanych: 0, gości: 1