kostenloser Webspace werbefrei: lima-city


Paint Methode einmal aufrufen

lima-cityForumProgrammiersprachenJava

  1. Autor dieses Themas

    pixilab

    Kostenloser Webspace von pixilab

    pixilab hat kostenlosen Webspace.

    Hallo, Es soll ein Schaubild mit einigen 100Tausend Linien gezeichnet werden.
    Das Zeichnen soll nur einmal ausgeführt und die Zeit dafür gemessen werden.

    Das Zeichnen der Linien wird durch den folgenden Code realisiert. Leider führt die paint Methode den Code zweimal aus, was nicht erwünscht ist. Was muss man tun, damit die for- Schleife in der Paint-Methode nur einmal ausgeführt wird?

    public class Run extends JFrame {
    
    	private static final long serialVersionUID = 4185573446960650955L;
    
    	public Run(){
            super();
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setSize(800,800);
        } 
    	
    	
    	public void paint(Graphics g){
    		
    		Test test = new Test();
    
    		System.out.println("painted");
    		ArrayList<Line> lines = test.getCircleTest(4, 100, new Point(400,400), 10);
    		for(Line p : lines){
    			g.drawLine(p.start.x, p.start.y, p.end.x, p.end.y);
    		}
            
        } 
    
    	public static void main(String[] args){
    		new Run().setVisible(true);
        } 
    }




    Beitrag zuletzt geändert: 19.3.2012 18:45:20 von pixilab
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. Ich kann jetzt keinen Grund sehen. Wie äußert es sich denn, dass es zweimal ausgeführt wird? Eigentlich sollte man es doch nicht sehen, da ja noch einmal genau dasselbe gezeichnet wird.
  4. Autor dieses Themas

    pixilab

    Kostenloser Webspace von pixilab

    pixilab hat kostenlosen Webspace.

    Im Beispielcode oben habe ich doch dieses "System.out.println("painted");" , das steht in der Console dann zweimal da, sobald der Code ausgeführt wird. Das es nochmal gezeichnet wird, wäre nicht so schlimm, wie du schon sagst, es wird einfach überzeichnet.

    Bei dem Test wird später ein mehrere Gigabyte großer Datensatz mit Linien eingelesen und gezeichnet, der Vorgang dauert dann Minuten lang. Es wäre unnötig doppelt so lang zu warten :)
  5. Nimm den Code einfach aus der Paint-Methode raus und erstelle eine eigene dafür. Diese Methode rufst du dann gesondert nach dem .setVisible auf.

    Da die Paint-Methode von JFrame überschrieben wird, wird diese bei jedem (neu)zeichnen der Frame aufgerufen, d.h. beim .setVisible und beim .setSize [oder bei jeder anderen manuellen Operation die die Frame zum neuzeichnen veranlassen würde].

    mfg
  6. Die paint-Methode wird immer aufgerufen, wenn anzunehmen ist, dass irgendetwas in dem Fenster nicht mehr aktuell sein könnte. Die Methode wird auch aufgerufen, wenn das Fenster seine Größe ändert, oder wenn das Fenster vorher durch etwas anderes verdeckt war. Solche Situationen können häufig vorkommen und daher hängt das weniger mit Java zusammen, als mit deiner Desktopumgebung.

    Mein Ratschlag: Verwende lieber die Java 2D API um ein Bild zu erzeugen, das zunächst nicht auf dem Bildschirm angezeigt wird. Wenn dieses Bild dann fertig erzeugt ist, kannst du es einfach anzeigen. Ein fertiges Bild in einer GUI einzubinden ist deutlich resourcenschonender als ein solches bei Änderungen am Fenster jedes mal neu zu berechnen.

    Beitrag zuletzt geändert: 19.3.2012 19:16:13 von bladehunter
  7. Noch ein bisschen Senf von mir (da ich vemute, dass du ein Problem mit der Geschwindigkeit deines Zeichen-Codes hast):

    1) Das überscheiben der paint()-Methode von JFrame gilt im Allgemeinen als schlechter Stil und ist nur in spieziellen Fällen aktzeptabel. Ich möchte hier nicht ins detail gehen, aber wenn du wissen willst warum, dann solltest du dich über den Unterschied zwischen Heavyweight- und Lightweight-Components informieren, und du solltest wissen, dass JFrame eine der wenigen Heavyweigth-Components in Swing ist. Du solltest also lieber JPanel zum zeichnen benutzen (und das JPanel dann in ein JFrame packen).

    2) Bei Swing-Componenten sollte man auch nicht direkt die paint()-Methode überschreiben, sondern eigentlich die paintComponent()-Methode (noch ein Grund warum du nicht JFrame benutzen solltest). Warum ist hier und hier erklärt.

    Die Verwendung von Lightweight-Components sollte deinen Code noch etwa schneller machen (zusätzlich zu Java 2D usw.)




    Beitrag zuletzt geändert: 19.3.2012 21:46:27 von wrertzu
  8. Autor dieses Themas

    pixilab

    Kostenloser Webspace von pixilab

    pixilab hat kostenlosen Webspace.

    Hab das mal so gelöst. Die paint Methode wird noch verwendet, man kommt glaub garnicht um sie herum. Mit dem Setzen und Zurücksetzen der Variable "paint" wird sichergestellt, dass nur auf Knopfdruck gezeichnet wird. Funktioniert zwar, nur habe ich so ein Gefühl, dass man das so nicht macht :nosmile::

    Code zum Zeichnen
    public class PaintPanel extends JPanel {
    	
    	public boolean paint = false;
    	
    	public void paintComponent( Graphics g ) {
    		super.paintComponent(g); 
    		if(paint) {
    			System.out.println("paint it");
    			drawLines(g);	
    			paint = false;
    		}		
    	}
    		
    	public void drawLines(Graphics g) {
    		Test test = new Test();
    		ArrayList<Line> lines = test.getCircleTest(20, 200, new Point(400,400), 1);
    		Graphics2D g2 = (Graphics2D) g;
    			
    		for(Line p : lines){
    			g2.draw(new Line2D.Double(p.start.x, p.start.y, p.end.x, p.end.y));
    			//g.drawLine(p.start.x, p.start.y, p.end.x, p.end.y);
    		}	
    	}
    
    }


    Code um das Zeichnen auszulösen.
    ...
    paintButton.addActionListener(new ActionListener() {
    			
    			@Override
    			public void actionPerformed(ActionEvent ev) {
    				
    				if(ev.getSource().equals(paintButton)) {
    					panel.paint = true;
    					panel.repaint();
    				}
    			}
    		});
  9. Der Tipp mit Java 2D war etwas anderst gemeint. Gemeint war du zeichnest in ein BufferedImage und lässt es dann mit paintComponent() einfach nur anzeigen. So wird das was du zeichnen willst nur einmal generiert (wie oft die paintComponent Methode aufgerufen wird kannst du nicht beinflussen). Wenn dir das nicht hilft, könntest du erklären warum es so wichtig ist das es tatsächlich nur einmal gezeichnet wird?

    Gemeint war etwa folgendes:
    public class DrawingPanel extends JPanel {
    	BufferedImage output = new BufferedImage(600,600,BufferedImage.TYPE_INT_ARGB);
    	@Override public void paintComponent(Graphics g){
    		super.paintComponent(g);
    		g.drawImage(output,0,0,null);
    		System.out.println("Drawing");
    	}
    	public void drawStuff(){
    		Random rand = new Random();
    		Graphics2D g2 = output.createGraphics();
    		for(int i=0; i < 100000; i++){
    			Color c = new Color(rand.nextInt(255),rand.nextInt(255),rand.nextInt(255));
    			g2.setColor(c);
    			g2.drawLine(rand.nextInt(600), rand.nextInt(600), rand.nextInt(600), rand.nextInt(600));
    		}
    		System.out.println("Generating the Image");
    	}
    }

    paintbutton.addActionListener(new ActionListener(){
    			public void actionPerformed(ActionEvent e){
    				drawingpanel.drawStuff();
    				drawingpanel.repaint();
    			}
    		});


    Den kompletten Code findest du hier.
  10. Autor dieses Themas

    pixilab

    Kostenloser Webspace von pixilab

    pixilab hat kostenlosen Webspace.

    Danke, ich schau mir das mal an.

    könntest du erklären warum es so wichtig ist das es tatsächlich nur einmal gezeichnet wird?


    Es sind sehr viele Linien die gezeichnet werden müssen. In einem weiteren Schritt werden die Koordinaten dieser Linien noch miteinander verglichen und für weitere Vorgänge verwendet. Allein das Generieren der Linien dauert einige Minuten. Ich möchte einfach, dass nach jedem Teilvorgang der Benutzer die Möglichkeit hat das Zwischenergebnis einmal zu betrachten und anschließend manuell den nächsten Vorgang zu starten. Einmal den gleichen Vorgang durchführen reicht, bei solchen Wartezeiten^^.



    Beitrag zuletzt geändert: 20.3.2012 20:19:54 von pixilab
  11. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!