[AWT] Verzögerung bei Zeichnung von Elementen

Adan0s

Grünschnabel
Hallo,

habe folgendes Problem:
Ich möchte ein geometrisches Objekt langsam zeichnen lassen, so, dass es nicht sofort bereits gezeichnet ist, wenn das Programm gestartet wird.
Rein theoretisch habe ich mir gedacht, dass nach jedem gezeichnetem Pixel eine bestimmte Anzahl an ms geschlafen wird, allerdings bin ich mit dem Threadingmodell von Java nicht gut vertraut, und deshalb werde ich da wohl einen Fehler machen.
Dieser wirkt sich daraufhin hinaus, dass das Objekt zwar so gezeichnet wird, wie ich es will, allerdings zweimal.

Code:
import java.awt.*;
import java.awt.event.*;

public class TestFrame extends Frame
{
  public TestFrame ()
  {
    setTitle("Panel-Beispiel");
    addWindowListener(new TestWindowListener());

    add(new DrawingPanel());

    setSize(320,288);
    setVisible(true);
  }

  class DrawingPanel extends Panel
  {
    public void paint(Graphics g)
    {
     for (int a=0; a<320; a++)
     {
           g.setColor(Color.RED);
           g.fillRect(0,10,a,20);

           try{Thread.sleep(5);}catch(InterruptedException x){}

     }
    }
  }

  class TestWindowListener extends WindowAdapter
  {

    public void windowClosing(WindowEvent e)
    {
      e.getWindow().dispose();
      System.exit(0);
    }

  }

  public static void main (String args[])
  {
    new TestFrame ();
  }
}

Hoffentlich kann mir jemand flink helfen. :)

Vielen Dank im voraus!
 
Die paint wird idR. beim Start 2 mal ausgeführt. Den EDT auszubremsen ist auch keine so gute Idee. Ich würde dem DrawingPanel eine List<Rectangle> verpassen, und in einer extra Thread-Instanz, die nach dem Start der Apps. gestartet wird langsam immer ein Rectangle-Objekt per adder hinzufügen und repaint() aufruft.
 
Danke für die fixe Antwort.
Leider bin ich im Javabereich nicht wirklich arg versiert, deshalb blick ich bei deiner Lösung nicht so ganz durch. Wäre es vielleicht möglich, dass du mir ein kurzes Beispiel schreiben könntest?

EDIT: Hat sich soeben erledigt, konnte ein passendes Beispiel online finden. :) Vielen Dank!
 
Zuletzt bearbeitet:
Natürlich, hab auch damit gerechnet.

Java:
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Panel;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class TestFrame extends Frame
{
	private static final long serialVersionUID = 1L;

	private TestFrame ()
	{
		setTitle("Panel-Beispiel");
		addWindowListener(new TestWindowListener());

		DrawingPanel drawingPanel = new DrawingPanel();
		add(drawingPanel);

		setSize(320,288);
		setVisible(true);
		
		new Thread(new CreateRectanglesRunnable(drawingPanel)).start();
	}
	
	private class CreateRectanglesRunnable implements Runnable //The Thread, the create Rectangles
	{
		private DrawingPanel drawingPanel;
		
		private CreateRectanglesRunnable(DrawingPanel drawingPanel)
		{
			super();
			this.drawingPanel = drawingPanel;
		}
		public void run()
		{
			for(int a = 0; a < 320; a+= 20)
			{
				drawingPanel.addRectangle(new Rectangle(a, 10, 20, 20));
				drawingPanel.repaint();

				try
				{
					TimeUnit.MILLISECONDS.sleep(100);
				}
				catch(InterruptedException x) {}
			}
		}
	}
	private class DrawingPanel extends Panel
	{
		private static final long serialVersionUID = 1L;

		private List<Rectangle> rectangleList;
		
		private DrawingPanel()
		{
			rectangleList = new ArrayList<Rectangle>();
		}
		private void addRectangle(Rectangle rectangle)
		{
			synchronized (rectangleList) //Lock List to don't get Problems with unsyncron access. 
			{
				rectangleList.add(rectangle);
			}
		}
		public void paint(Graphics g)
		{
			g.setColor(Color.RED);
			
			synchronized (rectangleList) //Lock List to don't get Problems with unsyncron access. 
			{
				for(byte b = 0, size = (byte) rectangleList.size(); b < size; b++)
				{
					Rectangle rectangleToDraw = rectangleList.get(b);
					g.fillRect(rectangleToDraw.x, rectangleToDraw.y, rectangleToDraw.width, rectangleToDraw.height);	
				}
			}
		}
	}
	private class TestWindowListener extends WindowAdapter
	{
		public void windowClosing(WindowEvent e)
		{
			e.getWindow().dispose();
			System.exit(0);
		}
	}
	public static void main(String args[])
	{
		new TestFrame ();
	}
}

Wenn du verstehen willst, warum du die Paint nicht ausbremsen darfst, versuch mal wärend er bei deiner Version zeichnet zu beenden. Es geht nicht, weil der Event-Dispatch-Thread gerade die Paint abarbeitet, und deshalb keine Zeit hat, den Listener zu bearbeiten. Paint's und Listener (und alles, was du an SwingUntilitie.invokeLater/invokeAndWait übergibst) wird vom EDT abgearbeitet, und jeder Thread kann nur eine Zeile gleichzeitig ausführen.

Kannst dir auch mal das Tut in meiner Sig anschauen, da steht es auch inkl. Beispiel für eine Animation drinnen, allerdings habe ich bis jetzt noch absolut kein Feedback bekommen, ich weiß also nicht ob es sich für Anfänger wirklich eignet.
 
Zurück