Grafik2d Objekte drehen, Idee da, Problem in Umsetzung

Status
Nicht offen für weitere Antworten.

arxior

Mitglied
der Sachverhalt:
ich habe viele Klassen, in jeder ein Grafik2d objekt, welches aus mehreren Grafik2d Objekten besteht. erstellt durch die dynamische Klassen der Grundshapes ( siehe Rectangle, eine der dynamischen Klassen). Da jede dynamische Klasse die methode drehen hat, kann ich jedes einzelne Grafik2d objekt in der Klasse selber drehen, jedoch nicht die Ganze Klasse, so als wäre es ein Objekt.

nun ist meine Frage: wie kann ich die ganzen Objekte so drehen, als wäre es ein ganzes Objekt?

ich hab mir schon mehrere gedanken gemacht, 2 Ideen haben sich herauskristalisiert, wobei eine nicht realisierbar ist. ( inzwischen rausgefunden, Danke SlaterB)
hier:
Idee : Aufbau wie der Methode "private Shape gibAktuelleFigur()" der klasse Rectangle. Verknüpfung der einzelnen Objekte durch die append Methode des generalPath.
Haken: beim Zeichnen der Objekte kann ich nicht auswählen ob sie ausgefüllt sein sollen, oder ob nur die Konturen gezeichnet werden. Dies ist sehr wichtig, und wurde bis jetzt über die zeichne() methode weitergegeben, an die innere Klasse der Klasse Leinwand( ShapeMitFarbe)

meine Frage ist nun, wie kann ich diesen "Haken" umgehen oder ausmerzen?

die Canvas findet ihr im 3. Post

vielen lieben Dank!
arxior

updated#2






Code:
import java.awt.Shape;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Line2D;
import java.awt.geom.AffineTransform;


import java.awt.geom.*;
import java.awt.*;


public class Rectangle 
{
    private int xPosition;
    private int yPosition;
    private int orientierung;
    private String farbe;
    private boolean istSichtbar;
    private int breite;
    private int tiefe;
    private boolean filled;

    /**
     * Erzeuge ein neues Bett mit einer Standardfarbe und Standardgroesse
     * an einer Standardposition
     */
    public Rectangle(int xPosition, int yPosition,int breite,int tiefe, boolean filled) {
        this.xPosition=xPosition;
        this.yPosition=yPosition;
        this.breite=breite;
        this.tiefe=tiefe;
        this.filled = filled;
      
        farbe = "schwarz";
        orientierung = 0;
        istSichtbar = false;

    }
    
 
    
    /**
     * Berechnet das zu zeichnende Shape anhand der gegebenen Daten
     * [ Zum Anzeigen der Attributwerte über Inspect muss hier die Sichtbarkeit 
     *  auf public gesetzt werden. ]
     */
    private Shape gibAktuelleFigur() {

        
        // einen GeneralPath definieren
        GeneralPath bett = new GeneralPath();
        Rectangle2D rahmen = new Rectangle2D.Double(xPosition, yPosition, breite, tiefe);
      
        
        /**
         * folgender auskommentierter Teil dient zur späteren orientierung, wie man 2D linien erstellt.
         */
        /* Line2D obererUmschlag = new Line2D.Double(xPosition1, yPosition1, xPosition2, yPosition2);
        //Line2D mitte = new Line2D.Double(0, tiefe/2, breite, tiefe/2);
        //Line2D untererUmschlag = new Line2D.Double(0, tiefe/2, breite, tiefe);
        */
                     
       bett.append(rahmen,false);

        /*bett.append(obererUmschlag,false);
        bett.append(mitte,false);
        bett.append(untererUmschlag,false);
       */ 
        // transformieren:
        AffineTransform t = new AffineTransform();
        t.translate(xPosition, yPosition);
        Rectangle2D umriss = bett.getBounds2D();
        t.rotate(Math.toRadians(orientierung),umriss.getX()+umriss.getWidth()/2,umriss.getY()+umriss.getHeight()/2);
        return  t.createTransformedShape(bett);

    }
    
    /**
     * Mache dieses Objekt sichtbar. Wenn es bereits sichtbar ist, tue nichts.
     */
    public void zeige() {
        if (!istSichtbar) {
            istSichtbar = true;
            zeichne();
        }
    }
    
    /**
     * Mache dieses Objekt unsichtbar. Wenn es bereits unsichtbar ist, tue nichts.
     */
    public void verberge() {
        loesche(); // "tue nichts" wird in loesche() abgefangen.
        istSichtbar = false;
    }
    
    
    /**
     * Füllt das Objekt aus.
     */
    
    public void fuellen() {
        loesche();
        filled= true;
        zeichne();
    }
    /**
     * Zeigt nur die Konturen des Objektes. Gegenteil von der Methode fuellen.
     */
    
    public void nurKonturen() {
        loesche();
        filled= false;
        zeichne();
    }
    
    
    
    
        public double getX1()
    { 
        return xPosition; 

      }
    

    
      public double getY1()
    { 
        return yPosition; 
      }
      
    
    
    
    
    
    /**
     * Drehe auf den angegebenen Winkel
     */
    public void dreheAuf(int neuerWinkel) {
        loesche();
        orientierung = neuerWinkel;
        zeichne();
    }
    
    /**
     * Bewege dieses Objekt horizontal um 'entfernung' Bildschirmpunkte.
     */
    public void bewegeHorizontal(int entfernung) {
        loesche();
        xPosition += entfernung;
        zeichne();
    }
    
    /**
     * Bewege dieses objekt vertikal um 'entfernung' Bildschirmpunkte.
     */
    public void bewegeVertikal(int entfernung) {
        loesche();
        yPosition += entfernung;
        zeichne();
    }
    
    
      /**
     * Aendere die Farbe dieses Objektes in 'neueFarbe'.
     * Gueltige Angaben sind "rot", "gelb", "blau","hellblau", "gruen",
     * "lila", "pink", "grau", "hellgrau", "dunkelgrau", "orange" und "schwarz"
     */
    public void aendereFarbe(String neueFarbe) {
        loesche();
        farbe = neueFarbe;
        zeichne();
    }
    
    /**
     * Zeichne dieses Objekt mit seinen aktuellen Werten auf den Bildschirm.
     */
    public void zeichne() {
        if (istSichtbar) {
            Shape figur = gibAktuelleFigur();
            Leinwand leinwand = Leinwand.gibLeinwand();
            leinwand.zeichne (
              this,           // leinwand kennt das Objekt
              farbe,          // definiert seine Zeichenfarbe
              figur,          // definiert seinen grafischen Aspekt
              filled);       // definiert, ob das Objekt ausgefüllt ist, oder ob nur die Konturen gezeichnet werden 
            leinwand.warte(10);
        }
    }
        /**
     * Loesche dieses Objekt vom Bildschirm.
     */
    public void loesche() {
        if (istSichtbar){
            Leinwand leinwand = Leinwand.gibLeinwand();
            leinwand.entferne(this);
        }
    }
}
 
in ein GeneralPath kannst du nur Shape-Objekte einfügen,
dein Rectangle ist kein Shape und es ist wohl auch nicht realistisch, das Interface selber zu implementieren,

du musst dir irgendein passendes Shape anstelle des Rectangle-Objektes erstellen und einfügen
 
Updated #2
hier das Canvas:
Code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;



import java.awt.*;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Image;
import java.awt.PopupMenu;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;


import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 * Leinwand ist eine Klasse, die einfache Zeichenoperationen auf einer
 * leinwandartigen Zeichenfläche ermöglicht.
 * Sie ist eine vereinfachte Version der Klasse Canvas (englisch für 
 * Leinwand) des JDK und wurde speziell für das Projekt "Figuren"
 * geschrieben.
 * 
 *
 * @author: Bruce Quig
 * @author: Michael Kölling (mik)
 * @author: Axel Schmolitzky
 * 
 * @author: Änderungen von
 * @Java-MS Groupies
 * @hier: Uwe Debacher
 *
 * @version: 1.7 (5.12.2003)
 */
public class Leinwand
{
  // Hinweis: Die Implementierung dieser Klasse (insbesondere die
  // Verwaltung der Farben und Identitäten der Figuren) ist etwas
  // komplizierter als notwendig. Dies ist absichtlich so, weil damit 
  // die Schnittstellen und Exemplarvariablen der Figuren-Klassen
  // für den Lernanspruch dieses Projekts einfacher und klarer
  // sein können.

  private static Leinwand leinwandSingleton;

  /**
   * Fabrikmethode, die eine Referenz auf das einzige Exemplar
   * dieser Klasse zurückliefert. Wenn es von einer Klasse nur
   * genau ein Exemplar gibt, wird dieses als 'Singleton'
   * bezeichnet.
   */
  public static Leinwand gibLeinwand()
  {
    if (leinwandSingleton == null)
    {
      leinwandSingleton =
        new Leinwand("Möbelprojekt Grafik", 800, 800, Color.white);
    }
    leinwandSingleton.setzeSichtbarkeit(true);
    return leinwandSingleton;
  }

  //  ----- Exemplarvariablen -----

  private JFrame fenster;
  private Zeichenflaeche zeichenflaeche;
  private Graphics2D graphic;
  private Color hintergrundfarbe;
  private Image leinwandImage;
  public List figuren;
  private Map figurZuShape; // Abbildung von Figuren zu Shapes

  /**
   * Erzeuge eine Leinwand.
   * @param titel  Titel, der im Rahmen der Leinwand angezeigt wird
   * @param breite  die gewünschte Breite der Leinwand
   * @param hoehe  die gewünschte Höhe der Leinwand
   * @param grundfarbe die Hintergrundfarbe der Leinwand
   */
  private Leinwand(String titel, int breite, int hoehe, Color grundfarbe)
  {
    fenster = new JFrame();
    zeichenflaeche = new Zeichenflaeche();
    fenster.setContentPane(zeichenflaeche);
    fenster.setTitle(titel);
    zeichenflaeche.setPreferredSize(new Dimension(breite, hoehe));
    hintergrundfarbe = grundfarbe;
    fenster.pack();
    figuren = new ArrayList();
    figurZuShape = new HashMap();

}


  /**
   * Setze, ob diese Leinwand sichtbar sein soll oder nicht. Wenn die
   * Leinwand sichtbar gemacht wird, wird ihr Fenster in den
   * Vordergrund geholt. Diese Operation kann auch benutzt werden, um 
   * ein bereits sichtbares Leinwandfenster in den Vordergrund (vor
   * andere Fenster) zu holen.
   * @param sichtbar boolean für die gewünschte Sichtbarkeit: 
   * true für sichtbar, false für nicht sichtbar.
   */
  public void setzeSichtbarkeit(boolean sichtbar)
  {
    if (graphic == null)
    {
      // erstmaliger Aufruf: erzeuge das Bildschirm-Image und fülle
      // es mit der Hintergrundfarbe
      Dimension size = zeichenflaeche.getSize();
      leinwandImage = zeichenflaeche.createImage(size.width, size.height);
      graphic = (Graphics2D) leinwandImage.getGraphics();
      graphic.setColor(hintergrundfarbe);
      graphic.fillRect(0, 0, size.width, size.height);
      graphic.setColor(Color.black);
    }
    fenster.setVisible(sichtbar);
  }

  /**
   * Zeichne für das gegebene Figur-Objekt eine Java-Figur (einen Shape)
   * auf die Leinwand.
   * @param  figur  das Figur-Objekt, für das ein Shape gezeichnet
   *                 werden soll
   * @param  farbe  die Farbe der Figur
   * @param  shape  ein Objekt der Klasse Shape, das tatsächlich
   *                 gezeichnet wird
   */
  public void zeichne(Object figur, String farbe, Shape shape, boolean filled)
  {
    figuren.remove(figur); // entfernen, falls schon eingetragen
    figuren.add(figur); // am Ende hinzufügen
    figurZuShape.put(figur, new ShapeMitFarbe(shape, farbe, filled));
    erneutZeichnen();
  }

  /**
   * Entferne die gegebene Figur von der Leinwand.
   * @param  figur  die Figur, deren Shape entfernt werden soll
   */
  public void entferne(Object figur)
  {
    figuren.remove(figur); // entfernen,falls schon eingetragen
    figurZuShape.remove(figur);
    erneutZeichnen();
  }

  /**
   * Setze die Zeichenfarbe der Leinwand.
   * @param  farbname der Name der neuen Zeichenfarbe.
   */
  public void setzeZeichenfarbe(String farbname)
  {
    if (farbname.equals("rot"))
      graphic.setColor(Color.red);
    else if (farbname.equals("schwarz"))
      graphic.setColor(Color.black);
    else if (farbname.equals("blau"))
      graphic.setColor(Color.blue);
    else if (farbname.equals("hellblau"))
      graphic.setColor(Color.cyan);
    else if (farbname.equals("dunkelgrau"))
      graphic.setColor(Color.DARK_GRAY);
    else if (farbname.equals("grau"))
      graphic.setColor(Color.gray);
    else if (farbname.equals("hellgrau"))
      graphic.setColor(Color.LIGHT_GRAY);
    else if (farbname.equals("gelb"))
      graphic.setColor(Color.yellow);
    else if (farbname.equals("orange"))
      graphic.setColor(Color.orange);
    else if (farbname.equals("pink"))
      graphic.setColor(Color.pink);
    else if (farbname.equals("gruen"))
      graphic.setColor(Color.green);
    else if (farbname.equals("lila"))
      graphic.setColor(Color.magenta);
    else if (farbname.equals("weiss"))
      graphic.setColor(Color.white);
    else
      graphic.setColor(Color.black);
  }

  /**
   * Warte für die angegebenen Millisekunden.
   * Mit dieser Operation wird eine Verzögerung definiert, die
   * für animierte Zeichnungen benutzt werden kann.
   * @param  millisekunden die zu wartenden Millisekunden
   */
  public void warte(int millisekunden)
  {
    try
    {
      Thread.sleep(millisekunden);
    }
    catch (Exception e)
    {
      // Exception ignorieren
    }
  }

  /**
   * Zeichne erneut alle Figuren auf der Leinwand.
   */
  private void erneutZeichnen()
  {
    loeschen();
    for (Iterator i = figuren.iterator(); i.hasNext();)
    {
      ((ShapeMitFarbe) figurZuShape.get(i.next())).draw(graphic);
    }
    zeichenflaeche.repaint();
  }

  /**
   * Lösche die gesamte Leinwand.
   */
  private void loeschen()
  {
    Color original = graphic.getColor();
    graphic.setColor(hintergrundfarbe);
    Dimension size = zeichenflaeche.getSize();
    graphic.fill(new Rectangle(0, 0, size.width, size.height));
    graphic.setColor(original);
  }


  
  /************************************************************************
   * Interne Klasse Zeichenflaeche - die Klasse für die GUI-Komponente,
   * die tatsächlich im Leinwand-Fenster angezeigt wird. Diese Klasse
   * definiert ein JPanel mit der zusätzlichen Möglichkeit, das auf ihm
   * gezeichnet Image aufzufrischen (erneut zu zeichnen).
   */
  private class Zeichenflaeche extends JPanel implements MouseMotionListener
  {
    public void paint(Graphics g)
    {
      g.drawImage(leinwandImage, 0, 0, null);
    }
    
        public void mouseMoved(MouseEvent e) {
          System.out.println("mouseMoved ");
    }
    
    public void mouseDragged(MouseEvent e) {
         System.out.println("mouseDragged");
    }



  }

  /************************************************************************
   * Interne Klasse ShapeMitFarbe - Da die Klasse Shape des JDK nicht auch
   * eine Farbe mitverwalten kann, muss mit dieser Klasse die Verknüpfung
   * modelliert werden.
    */
  private class ShapeMitFarbe
  {
    private Shape shape;
    private String farbe;
    private boolean filled;
    
    public ShapeMitFarbe(Shape shape, String farbe, boolean filled)
    {
      this.shape = shape;
      this.farbe = farbe;
      this.filled = filled;
    }

    public void draw(Graphics2D graphic)
    {
                
      setzeZeichenfarbe(farbe);
      if (filled==true)
      {
      graphic.fill(shape);
    }
    else {
    graphic.draw(shape);
          }
    }
  }

}
 
SlaterB hat gesagt.:
in ein GeneralPath kannst du nur Shape-Objekte einfügen,
dein Rectangle ist kein Shape und es ist wohl auch nicht realistisch, das Interface selber zu implementieren,

du musst dir irgendein passendes Shape anstelle des Rectangle-Objektes erstellen und einfügen

Vielen Dank, sowas dachte ich mir bereits.
siehe post #3, Idee 2!

dann bräuchte ich jetzt eine Lösung für Idee #2. ich zerbrech mir mal weiter den kopf :/

mfg arxiii
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben