Mehrere Komponenten zeichnen

ipspy4711

Grünschnabel
Hallo zusammen,

ich bin noch relativ am Anfang meiner Javakünste und hänge im Moment stark. Jetzt hoffe ich, dass ihr mir helfen könnt:

Ich habe ein GUI entwickelt, auf dem ich verschiedene Figuren abbilden möchte. Mein GUI ist ein JFrame in das ich ein Objekt "Anzeige" der Klasse "Zeichnung" gesetzt habe.

Nun habe ich eine Klasse "Zeichnung", die ein "extends JComponent" enhält, erstellt und dort die die Methode paintComponent() überschrieben. Wenn ich nun in meinem GUI nacheinander einige Objekte zeichnen möchte, erhalte ich in meinem GUI nur das letzte definierte Objekt. Selbst wenn ich nur einmal das repaint() aufrufe, erhalte ich nur das letzte Objekt. Kann mir einer sagen, was ich falsch mache?

Meine Methode im GUI:
Code:
 public void zeichne()
    {
        Anzeige.setzeFarbe("schwarz");
        Anzeige.setzeFigur(new Ellipse2D.Float(20, 300, 10, 10));
        Anzeige.repaint();
        Anzeige.setzeFigur(new Ellipse2D.Float(300, 20, 10, 10));
        Anzeige.repaint();
        Anzeige.setzeFigur(new Line2D.Float(20, 300, 300, 20));
        Anzeige.setzeLinienstaerke(3);
        Anzeige.repaint();
    }

Meine Klasse Zeichnung:
Code:
import java.awt.*;
import javax.swing.*;

class Zeichnung extends JComponent
{
    private static int linienstaerke = 1;

    private Shape figur;
    private String farbe;
    private Image zeichnungsImage;
    
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if(figur!=null && farbe!=null)
        {
            Graphics2D g2d = (Graphics2D)g;
            
            if (farbe.equals("rot")) 
            {
                g2d.setColor(Color.red);
            } 
            else if (farbe.equals("schwarz")) 
            {
                g2d.setColor(Color.black);                
            } 
            else if (farbe.equals("blau")) 
            {
                g2d.setColor(Color.blue);
            } 
            else if (farbe.equals("gelb"))
            {
                g2d.setColor(Color.yellow);
            } 
            else if (farbe.equals("gruen"))
            {
                g2d.setColor(Color.green);
            } 
            else if (farbe.equals("lila")) 
            {
                g2d.setColor(Color.magenta);
            } 
            else if (farbe.equals("orange"))
            {
                g2d.setColor(Color.orange);
            } 
            else 
            {
                g2d.setColor(Color.black);
            }
            g2d.setStroke(new BasicStroke(linienstaerke));
            g2d.fill(figur);
            g2d.draw(figur);
        }
    }
    
    public void setzeLinienstaerke(int linienstaerke)
    {
        this.linienstaerke = linienstaerke;
    }
    
    public void setzeFarbe(String farbe) {
        this.farbe = farbe;
    }
 
    public void setzeFigur(Shape figur) {
        this.figur = figur;
    }
}

Vielen Dank schon jetzt für die, die sich da hineindenken! :)
 
Das ist einfach : du manipulierst immer nur ein und dasselbe Graphics-Objekt was natürlich immer die letzte Figur darstellt da die anderen überschrieben werden. Willst du mehrere Objekte darstellen musst du auch mehrere Objekte erzeugen.

Am einfachste lässt sich das anhand eines einfach JButtons erklären :
Du hast EINEN JButton und weist ihm einen Text zu ... dann addest du ihn auf das JFrame und lässt ihn zeichnen. Danach setzt du für diesen eben gezeichneten JButton einen neuen Text und addest ihn wieder auf das JFrame ... diesmal allerdings in einer anderen Position. Da nun der JButton nur die neue Position und auch nur den neuen Text kenn wird er mit dem neuen Text an dieser nun neuen Position gezeichnet. Dabei wird allerdings die alte Zeichnung des JButtons wieder übermalt da ja an dieser Stelle nun nichts mehr ist.

Es ist einer der Grundsätze das EINE JComponent nur EINEN Zustand hat und sich auch nur EINMAL auf dem Container befindet. Daraus lässt sich *wie oben bereits erwähnt* schlussfolgern : wenn du mehrere Objekte gleichzeitig auf dem Container haben willst musst du diese auch als eigenständige Objekte in deinem Code erzeugen. Mit nur einer JComponent ist sowas nicht möglich.

*Zu mindest nicht unter Swing ... unter AWT wäre es mit etws Aufwand möglich ... sollte man aber nicht machen.*
 
Hey, vielen Dank für die schnelle Antwort. Bedeutet das dann, dass ich eher im GUI ein JPanel als Datenfeld setzen sollte und in dieses JPanel soviele Instanzen, wie ich von der Klasse "Zeichnung" benötige "adden" muss? Oder gibt es eine einfachere Möglichkeit. Sorry, wenn die Frage zu "einfach" ist. Sitze inzwischen seit knappen 8 Std. an dem Problem und sehe glaub ich langsam den Wald vor lauter Bäumen nicht mehr. :D
 
Richtig. Jedes graphische Element, das du irgendwo hinzufügst, darf nur ein mal hinzugefügt werden. Daher musst du z.B. für jeden JButton, den man sehen soll, eine neue Instanz erzeugen.

BTW: 8 Stunden... dann mach doch ne Pause und genieße das Wetter ;)
 
leider regnet es hier fast durchgängig, wo ist die Sonne******** Hab aber zwischendurch immer mal wieder Pausen gemacht. Ich will auch endlich mal Feierabend machen, weiß aber, wenn ich das Problem nicht gelöst kriege, werd ich mich in meinen Alpträumen damit rumschlagen... :eek:

Ich habe das probiert und die Klasse Zeichnung mehfrach instanziert und in das Panel, in dem es angezeigt werden soll, eingefügt. Aber irgendwie will das ganze nicht so, wie ich es will :( Eigentlich dachte ich, dass ich über die Methode updateUI() das Panel so updaten kann, dass es im Fenster angezeigt wird. Leider bleibt aber alles weiß. :(

Code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.border.*;

public class GUI
{
    private JFrame fenster;
    private JPanel anzeige;
    private JLable ueberschrift;

    
    public GUI()
    {
        fensterErzeugen();
    }

   
    public void fensterErzeugen()
    {
        fenster = new JFrame("Anzeige");
        JPanel contentPane = (JPanel) fenster.getContentPane();
        contentPane.setLayout(new BorderLayout());
        contentPane.setBorder(new EmptyBorder(6,6,6,6));
        
        // Werkzeugleiste erstellen
        JPanel werkzeugleiste = new JPanel();
        werkzeugleiste.setLayout(new GridLayout(0,1));
               
        JButton button1 = new JButton ("Button");
        knotenHinzufuegen.addActionListener(new ActionListener(){
                      public void actionPerformed(ActionEvent event) {
                            einfuegen();
                      }
        });
        werkzeugleiste.add(button1);

        JButton button2= new JButton("Button");
        farbeKnoten.addActionListener(new ActionListener(){
                      public void actionPerformed(ActionEvent event) {
                            aendern();
                      }
        });
        werkzeugleiste.add(button2);
        .....
        
        JPanel anordnung = new JPanel();
        anordnung.add(werkzeugleiste);
        contentPane.add(anordnung, BorderLayout.WEST);
        
        
        // Contentbereich erstellen, in dem die Graphics eingefügt werden sollen
        JPanel anzeigehintergrund = new JPanel();
        anzeigehintergrund.setBorder(new EtchedBorder());
        anzeigehintergrund.setBackground(new Color(255, 255, 255));
        anzeigehintergrund.setLayout(new BorderLayout());
        
        anzeige= new JPanel();
        anzeige.setBackground(new Color(255, 255, 255));
        ueberschrift = new JLabel("Hier entsteht mein Muster");
        anzeigehintergrund.add(anzeige, BorderLayout.CENTER);
        anzeigehintergrund.add(ueberschrift, BorderLayout.NORTH);
        
        contentPane.add(anzeigehintergrund, BorderLayout.CENTER);
             
        fenster.setVisible(true);
        
    }
}

und die Methode, die eigentlich funktionieren sollte - zumindest in meinen Augen ;)

Code:
public void zeichne()
    {
        Zeichnung kreis1 = new Zeichnung();
        kreis1.setzeFarbe("schwarz");
        kreis1.setzeFigur(new Ellipse2D.Float(20, 300, 10, 10));
        kreis1.repaint();
        graphAnzeige.add(kreis1);
        
        Zeichnung kreis2= new Zeichnung();
        kreis2.setzeFigur(new Ellipse2D.Float(300, 20, 10, 10));
        kreis2.repaint();
        anzeige.add(kreis2);
        
        Zeichnung linie= new Zeichnung();
        linie.setzeFigur(new Line2D.Float(20, 300, 300, 20));
        linie.setzeLinienstaerke(3);
        linie.repaint();
        anzeige.add(linie);
        
        anzeige.updateUI();
    }
 
Ich würde generell mal
Java:
JFrame.validate();
JFrame.update(JFrame.getGraphics();
versuchen wenn du schon wie wild drin rumzeichnest WÄHREND das JFrame angezeigt wird.
 
Einen wunderschönen guten Morgen alle zusammen, :)

ich zeichne doch nicht "wild" herum, das ist alles geplant. :D
Leider funktioniert weder ein repaint() noch ein JFrame.validate(), noch ein JFrame.update(JFrame.getGraphics()). :( Es muss doch irgendwie möglich sein, eine Zeichnung darzustellen, wenn das JFrame angezeigt wird, oder******
 
äähhhmm... ich dachte eigentlich, dass ich nichts anderes gemacht habe... in meinem Code oben hab ich doch ein JPanel "anzeige", das ich in das JFrame "fenster" eingefügt habe. Danach rufe ich die Methode "zeichne" auf und adde die Instanzen meiner Klasse "Zeichnung" in das JPanel. Oder steh ich jetzt völlig neben mir******!
 
Zurück