getWidth(); getHeight(); außerhalb von paintComponent

Status
Nicht offen für weitere Antworten.

MrGe

Mitglied
Um paintComponent schlank zu halten, sollen die zu zeichnenden Komponenten außerhalb erzeugt werden.
Wie aber komme ich außerhalb von paintComponent an die Maße der Zeichenfläche heran?
Oder
Wie baut man getWidth() und getHeight() sauber ein?

Vielen Dank für die Tipps!

(Und vielen Dank an Wildcard für das Tutorial!!!)

Java:
//Bspl. nach "Zeichnen in Swing Tutorial"
public class SimpleRectangle {
	private NaivePaintingComponent paintingComponent = new NaivePaintingComponent();
	public SimpleRectangle() {
		JFrame frame = new JFrame("");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                paintingComponent.setPreferredSize(new Dimension(300,300));
                frame.add(paintingComponent);
                frame.pack();
                frame.setVisible(true);
                frame.setLocationRelativeTo(null);

           	Rectangle2D.Float rect = new Rectangle2D.Float(10f,10f,100f,100f);
    	       paintingComponent.setShape(rect);
           	paintingComponent.setColor(Color.BLACK);
           	paintingComponent.repaint();
           }
           public static void main(String[] args){new SimpleRectangle();}
}//class SimpleRectangle
 
class NaivePaintingComponent extends JComponent{
    private Shape shape;
    private Color c;
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if(shape!=null && c!=null){
            Graphics2D g2d = (Graphics2D)g;
            g2d.setColor(c);
            g2d.draw(shape);
        }
    }
    public void setColor(Color c) {this.c = c;}
    public void setShape(Shape shape) {this.shape = shape;}
}//class NaivePaintingComponent
 
Ich verstehe offenbar das Problem nicht...
Code:
getX()
,
Code:
getY()
,
Code:
getWidth()
und
Code:
getHeight()
von JComponent liefern doch stets die Größe, bzw. den Bereich in dem man zeichnen kann.
 
erst wenn die Komponente zu sehen ist, das Layout gesetzt wurde,
wenn paintComponent aufgerufen wird ist das garantiert schon der Fall gewesen,

außerhalb hat man die Gefahr, dass man zu früh getWidth() & Co. aufruft, z.B. bevor das initiale
setVisible(true);
noch nicht ausgeführt oder eine neue Komponente noch nicht ins GesamtLayout eingegliedert wurde
 
Ich würde es so einbauen:
Java:
public class A extends JComponent {
  public A() {
    enableEvents(AWTEvent.COMPONENT_EVENT_MASK);
  }

  protected void processComponentEvent(ComponentEvent e) {
    super.processComponentEvent(e);
    if ((e.getID() & ComponentEvent.COMPONENT_RESIZED) != 0) {
      rebuildDrawnObjects(); // <== oder so ähnlich
    }
  }
}
Ebenius
 
Vielen Dank für den Tipp !!

Aber wie bekomme ich die veränderten Werte dahin, wo die Figuren erzeugt werden?

Ich habe mal eine Lösung mit einem selbstgestrickten "Observer" gebastelt.

Ist das so OK, oder gibt es elegantere Lösungen?

Vielen Dank für Tipps.

Java:
package draw_resizing_figures;

import java.awt.Dimension;

import javax.swing.JFrame;

public class MainGUI extends JFrame{

	public NaivePaintingComponent paintingComponent = new NaivePaintingComponent();
	
	public MainGUI() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		new RectangleCreator(paintingComponent);
		new CircleCreator(paintingComponent);
		paintingComponent.setPreferredSize(new Dimension(300,300));
		add(paintingComponent);
		pack();
		setVisible(true);
		setLocationRelativeTo(null);
	}//MainGUI
	
	public static void main(String[] args){new MainGUI();}
}

Die Klassen, die Figuren erzeugen, implementieren dieses Interface.
Java:
package draw_resizing_figures;

public interface XY_Observer {
	public void updateXY(int x, int y);
}

Diese Klasse stellt die Zeichenfläche bereit, sie kann eine Größenveränderung erkennen.
Klassen, die Figuren erstellen, bekommen eine Referenz auf diese Klasse und
können so ihre Figuren übergeben.

Klassen, die Figuren erstellen, können sich in eine ArrayList in dieser Klasse
eintragen.
Bei einer Größenveränderung werden sie darüber informiert und erstellen dann
angepasste Figuren.

Java:
package draw_resizing_figures;

import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.ComponentEvent;
import java.util.ArrayList;

import javax.swing.JComponent;

public class NaivePaintingComponent extends JComponent{
	
	/**die arraylist speichert alle zu zeichnenden figuren*/
	private ArrayList<Shape> al_shape = new ArrayList<Shape>();
	
	/**die arraylist speichert alle beobachter*/
	private ArrayList<XY_Observer> xy_observer= new ArrayList<XY_Observer>(); 

	public NaivePaintingComponent() {
		enableEvents(AWTEvent.COMPONENT_EVENT_MASK);
	}
	
	/**reagiert auf veraenderung der groesse*/
	public void processComponentEvent(ComponentEvent e){
		super.processComponentEvent(e);
		//if(e.getID() != 0 && ComponentEvent.COMPONENT_RESIZED!= 0){
		//so gehts eleganter:
		if((e.getID() & ComponentEvent.COMPONENT_RESIZED) != 0){	
			System.out.println("new width/height = "+getWidth()+" / "+getHeight());
			//die vorhandenen figuren werden geloescht
			//die neuen werden spaeter angeliefert
			al_shape.clear();
			//die beobachter werden informiert
			informObservers(getWidth(), getHeight());
		}
	}

	public void addShape(Shape sh){
		al_shape.add(sh);
	}
	
	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		if(al_shape.size()>0){
			Graphics2D g2d = (Graphics2D)g.create();
			g2d.setColor(Color.BLACK);
			//alle figuren werden gezeichnet
			for(int i = 0; i<al_shape.size(); i++){
				g2d.draw(al_shape.get(i));
			}
		}
	}

	/**beobachter hinzufuegen*/
	public void addCuriousComponent(XY_Observer nc) {
		xy_observer.add(nc);
	}

	/**beobachter loeschen*/
	public void removeCuriousComponent(XY_Observer b) {
		int i = xy_observer.indexOf(b);
		if (i >= 0){xy_observer.remove(i);}
	}
	
	/**beobachter informieren*/
	public void informObservers(int x, int y) {
		if(xy_observer.size()>0){
			for (int i = 0; i < xy_observer.size(); i++){
				XY_Observer b = xy_observer.get(i);
				b.updateXY(x, y);
			}
		}
	}
}


Diese Klasse erstellt Kreise.

Java:
package draw_resizing_figures;

import java.awt.geom.Ellipse2D;

public class CircleCreator implements XY_Observer {

	private NaivePaintingComponent npc;
	
	public CircleCreator(NaivePaintingComponent n){
		System.out.println("CircleCreator");
		this.npc = n;
		//anmelden als beobachter
		npc.addCuriousComponent(this);
	}
		
	@Override
	public void updateXY(int x, int y) {
		System.out.println("CircleCreator updateXY");
		Ellipse2D.Float circle = new Ellipse2D.Float(10, 10, x-20, y-20);
		npc.addShape(circle);
	}
}

Diese Klasse erstellt Rechtecke.

Java:
package draw_resizing_figures;

import java.awt.geom.Rectangle2D;

public class RectangleCreator implements XY_Observer{
	
	private NaivePaintingComponent npc;
	
	public RectangleCreator (NaivePaintingComponent n){
		System.out.println("RectangleCreator");
		this.npc = n;
		//anmelden als beobachter
		npc.addCuriousComponent(this);
	}

	@Override
	public void updateXY(int x, int y) {
		System.out.println("RectangleCreator updateXY");
		Rectangle2D.Float rect = new Rectangle2D.Float(10,10,x-20,y-20);
		npc.addShape(rect);
	}
}
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben