Canvas-Inhalt in Laufzeit ändern

.SyS

Mitglied
Hallo,
ich wende mich in allerhöchster Not an euch. Bis morgen soll ein Projekt fertig werden, und es sieht aus als würde es an einer Kleinigkeit scheitern.
Das Wesentliche skizziere ich grob: Ein mit NetBeans erstelltes Fenster(MainFrame) enthält ein simCanvas(siehe unten) und einige Steuerelemente. Für eine Simulation soll sich in diesem Canvas immer die aktuelle Situation darstellen. Im Konstruktor des MainFrame wird ein simCanvas erstellt.

Das ist der Code der simCanvas-Klasse:
Java:
import java.awt.*;
 
public class simCanvas extends Canvas {

    public void paint(final Graphics g){
        super.paint(g);
        
        g.setColor(Color.RED);
        g.fillRect(0, 0, 500, 500); 
    }
}

Wenn ich die main()-Methode des MainFrame aufrufe, dann erhalte ich auch eine rote Fläche, allerdings entzieht sich trotz intensiver Durchsicht hunderter Foren und Tutorials die Funktionsweise von repaint() bzw. update() meinem Verständnis.

Meine Frage: Wie kann ich in Laufzeit (z.B. durch Druck auf einen Button) von MainFrame aus ein Rechteck in mein Canvas malen und zwar so, dass alles außenrum erhalten bleibt.

Ich glaube es ist wirklich nur eine Kleinigkeit, aber ich komme nicht dahinter.

Vielen vielen dank für schnelle Antworten!
.SyS
 

Marco13

Top Contributor
Was heißt dass "alles außenrum erhalten bleibt"?

Java:
public class simCanvas extends Canvas 
{
    private boolean malDasDing = false;

    public void setMalDasDing(boolean b)
    {
        this.malDasDing = b;
        repaint();
    }
 
    public void paint(final Graphics g){
        super.paint(g);
        if (malDasDing)
        {        
            g.setColor(Color.RED);
            g.fillRect(0, 0, 500, 500); 
        }
    }
}
 

.SyS

Mitglied
Vielen Dank für deine Antwort!

Aber ich glaube ich habe meine Frage falsch formuliert:
Wie kann ich ein neues Rechteck (dessen Parameter ich von außen übergeben kann) über das bereits vorhandene drüber malen?

Aber eine neue Erkenntniss habe ich jetzt gewonnen: repaint() ruft also paint() nochmal auf. Wie kann ich mir das also zu meinem Zweck zunutze machen?

EDIT: Ich habe jetzt folgenden Code:
Java:
import java.awt.*;
 
public class simCanvas extends Canvas {
    int x = 0, y = 0, w = 500, h = 500;
    Color color = Color.RED;
    
    public void paint(final Graphics g){
        super.paint(g);
        
        g.setColor(color);
        g.fillRect(x, y, w, h); 
    }
    
    
    
    public void newRect(int x_new, int y_new, int w_new, int h_new, Color color_new)
    {
        x = x_new;
        y = y_new;
        w = w_new;
        h = h_new;
        color = color_new;
        
        repaint();
    }
}

Vielleicht ist es umständlich und geht einfacher, aber zumindest erscheint jetzt auf Knopfdruck das gewünschte Rechteck. Nur leider verschwindet das rote "Standard"-Rechteck. Wie kann ich das neue darüber malen?
 
Zuletzt bearbeitet:

Marco13

Top Contributor
Oh ja.

ALLES, was gezeichnet wird, muss von der paint-Methode aus gezeichnet werden.

(soo, erstmal setzen lassen...)


Jetzt die Details:
repaint() ruft also paint() nochmal auf.
Das ist so nicht ganz richtig. "repaint()" ist nur ein Hinweis: "Zeichne mal so bald wie möglich neu". Das eigentliche Aufrufen von "paint" macht dann sozusagen(!!!) das Betriebssystem (GANZ grob gesagt..).

In diesem Fall wäre die Lösung demnach (auch ganz grob) sowas wie
Java:
public class simCanvas extends Canvas 
{
    private List<Rectangle> rectangles = new ArrayList<Rectangle>();
    private List<Color> colors = new ArrayList<Color>();

    void addNewRectangle(int x, int y, int w, int h, Color color)
    {
        rectangles.add(new Rectangle(x,y,w,h));
        colors.add(color);
        repaint();
    }
 
    public void paint(final Graphics gr){
        super.paint(gr);
        Graphics2D g = (Graphics2D)gr;

        g.setColor(Color.RED);
        g.fillRect(0, 0, 500, 500); 

        for (int i=0; i<rectangles.size(); i++) 
        {
            g.setColor(colors.get(i));
            g.fill(rectangles.get(i));
        }
    }
}

Eine Alternative, die etwas näher an dem ist, was du vielleicht meintest, aber selten in dieser Form wirklich sinnvoll (außer z.B. bei Dingen, die in Richtung eines "Malprogramms" gehen) wäre, alles in ein BufferedImage zu zeichnen, und NUR dieses BufferedImage in der paint-Methode zu malen. In diesem BufferedImage würde natürlich "alles erhalten bleiben", aber man muss sich überlegen, ob das für den jeweiligen Anwendungsfall wirklich das beste ist...
 

.SyS

Mitglied
Vielen vielen tausendfachen Dank! Es funktioniert! Und es sieht genauso aus, wie ich es mir vorgestellt habe!
Jetzt noch eine kleine Frage: Wie sind die Performanceunterschiede zwischen der Lösung mit den ArrayLists und dem BufferedImage für den Fall dass bis zu 30.000 kleine Rechtecke verwaltet werden sollen?
Falls in dem Fall BufferedImage sinnvoller wäre, wie wende ich das ganze dann wieder auf paint() an?
 

Marco13

Top Contributor
OK, das ist dann schon was anderes ... bei 30000 kleinen Rechtecken dürfte das mit dem BufferedImage schon allein wegen der Performance sinnvoll sein, allein wenn man davon ausgeht, dass in jedem Schritt nur wenig neu gezeichnet wird (und 29999 Rechtecke gleich bleiben).

Wieder GANZ grob anskizziert
Java:
class SimCanvas
{
    private BufferedImage bufferedImage = null;

    private List<Rectangle> rectangles = new ArrayList<Rectangle>();
    private List<Color> colors = new ArrayList<Color>();
 
    void addNewRectangle(int x, int y, int w, int h, Color color)
    {
        Rectangle rectangle = new Rectangle(x,y,w,h);
        rectangles.add(rectangle);
        colors.add(color);

        paintIntoImage(rectangle, color);
        repaint();
    }
    
    // Malt ein einzelnes Rechteck ins Bild
    private void paintIntoImage(Rectangle rectangle, Color color)
    {
        Graphics2D g = bufferedImage.createGraphics();
        g.setColor(color);
        g.fill(rectangle);
        g.dispose();
    }

    // Malt NUR das Bild    
    public void paint(Graphics g)
    {
        super.paint(g);
        if (bufferedImage == null)
        {
            bufferedImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
            updateImage();
        }
        g.drawImage(bufferedImage, 0, 0, null);
    }

    // Malt ALLE Rechtecke ins bild
    private void updateImage()
    {
        Graphics2D g = bufferedImage.createGraphics();

        g.setColor(Color.WHITE);
        g.fillRect(0,0,bufferedImage.getWidth(), bufferedImage.getHeight());

        g.setColor(Color.RED);
        g.fillRect(0, 0, 500, 500); 
 
        for (int i=0; i<rectangles.size(); i++) 
        {
            g.setColor(colors.get(i));
            g.fill(rectangles.get(i));
        }
        g.dispose();
    }
}

Da muss man sich dann halt noch überlegen ob man die Rechtecke und Farben wirklich nochmal speichern muss, oder ob's reicht, wenn sie einmal ins Bild gemalt wurden. Dabei sollte man beachten, dass evtl. ein neues BufferedImage angelegt werden muss, wenn die Größe des Canvas sich ändert (das würde man dann zusätzlich zur Abfrage "if (bufferedImage == null)" noch testen). Dann hat man die Möglichkeit, dort das alte (ggf. kleinere) Bild reinzumalen, oder ein komplettes "update" zu machen, wie oben angedeutet. Wenn man das aber nicht braucht, muss man auch die Listen nicht unbedingt speichern...
 

.SyS

Mitglied
Perfekt! Du warst die Rettung des Projekts. Alles sieht so aus, wie es soll, und nebenbei zumindest ein Stück weit in die Funktionsweise von Canvas eingestiegen... Irgenwann versteh ichs vielleicht mal :D
DANKE!
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
J Canvas Inhalt als Bild speichern! AWT, Swing, JavaFX & SWT 16
P Canvas Inhalt löschen AWT, Swing, JavaFX & SWT 4
D Inhalt einer Canvas löschen (SWT.NO_BACKGROUND gesetzt) AWT, Swing, JavaFX & SWT 3
P Inhalt eines Canvas verkleinern AWT, Swing, JavaFX & SWT 3
H JavaFX Canvas neu zeichnen anstoßen AWT, Swing, JavaFX & SWT 34
H JavaFX Gedrehter Text auf Canvas (Positionierung) AWT, Swing, JavaFX & SWT 6
ExceptionOfExpectation Textdarstellung auf einem Canvas mit Hilfe von repaint(); AWT, Swing, JavaFX & SWT 6
W Clear Canvas und anschließendes neues Erstellen von Objekten auf Canvas aus ArrayList AWT, Swing, JavaFX & SWT 4
W Canvas oder Polygone? AWT, Swing, JavaFX & SWT 3
Monokuma Canvas Form entfernen AWT, Swing, JavaFX & SWT 2
Monokuma KeyEvent in der Canvas Klasse AWT, Swing, JavaFX & SWT 0
M Internal Frames und Canvas-Element AWT, Swing, JavaFX & SWT 9
TheJavaKid Auf eine Zeichnung im Canvas reagieren AWT, Swing, JavaFX & SWT 13
M Halbkreiszeichnen(Canvas) - Diesen mit Mouseevents bestücken AWT, Swing, JavaFX & SWT 3
dereki2000 AWT Canvas zeichnet nicht AWT, Swing, JavaFX & SWT 7
D Canvas oder scene graph? AWT, Swing, JavaFX & SWT 16
J Canvas wird nicht angezeigt AWT, Swing, JavaFX & SWT 10
Y Objekte grafisch darstellen ohne GMF - Composite auf Canvas? AWT, Swing, JavaFX & SWT 2
Prafy AWT Klickbare Bereiche auf Canvas AWT, Swing, JavaFX & SWT 2
J JavaFX JavaFX Canvas einfaches Zeichenprogramm AWT, Swing, JavaFX & SWT 7
P MalProgramm mit JScrollPane und Canvas AWT, Swing, JavaFX & SWT 2
Cromewell JavaFX Nur bestimmten Teil eines Canvas rendern und anzeigen AWT, Swing, JavaFX & SWT 2
N Swing Benötige Hilfe um ein Swing Canvas zu speichern AWT, Swing, JavaFX & SWT 4
L JavaFX Canvas max size? AWT, Swing, JavaFX & SWT 1
J JavaFX Rendering von Canvas sehr langsam AWT, Swing, JavaFX & SWT 2
P AWT Canvas freihändig zeichnen AWT, Swing, JavaFX & SWT 1
Regedit JavaFX Java Canvas hört ständig auf zu aktualisieren/malen AWT, Swing, JavaFX & SWT 3
H JavaFX Freezes beim Zeichnen mit Canvas AWT, Swing, JavaFX & SWT 3
Z Canvas in Frame einfügen. Problem mit 4-Gewinnt AWT, Swing, JavaFX & SWT 1
B JavaFX KeyEvent und Canvas draw Problem AWT, Swing, JavaFX & SWT 9
K Fragen zu JavaFx Canvas AWT, Swing, JavaFX & SWT 0
C Java FX Canvas missing getGraphicContext2D AWT, Swing, JavaFX & SWT 5
windl Overlay mit Transparentem JWindow und Canvas AWT, Swing, JavaFX & SWT 2
S JavaFX Canvas - nur eine Figur auf der Zeichenfläche färben? AWT, Swing, JavaFX & SWT 1
R JComponent auf Canvas AWT, Swing, JavaFX & SWT 8
S Canvas durch transparentes JPanel sichtbar machen AWT, Swing, JavaFX & SWT 2
A JavaFX Menubar wird von Canvas überzeichnet AWT, Swing, JavaFX & SWT 8
antonbracke Multiplayer Shooter- Wie geht das mit Canvas & Graphics AWT, Swing, JavaFX & SWT 6
Luk10 KeyBindings mit Canvas? AWT, Swing, JavaFX & SWT 3
B LookAndFeel GWT: Canvas in TabSet nicht sichtbar AWT, Swing, JavaFX & SWT 2
K canvas zeig nach repaint nichts an AWT, Swing, JavaFX & SWT 8
T Canvas clipping AWT, Swing, JavaFX & SWT 4
S 2 Canvas übereinander AWT, Swing, JavaFX & SWT 2
S 2D-Grafik Canvas Problem(Größe) AWT, Swing, JavaFX & SWT 6
K 3D-Grafik Canvas ist ein eigener Frame?! AWT, Swing, JavaFX & SWT 13
F Canvas Objekt außerhalb des Frames zeichnen AWT, Swing, JavaFX & SWT 3
M Wofür Canvas? AWT, Swing, JavaFX & SWT 5
frankred Swing Canvas nach "Window-resize" neu Zeichnen lassen wegen Anzeigefehler AWT, Swing, JavaFX & SWT 4
S Canvas in ScrollPane wird beim scrollen immer neu gezeichnet AWT, Swing, JavaFX & SWT 3
F Nur ein Objekt auf Canvas neu zeichnen AWT, Swing, JavaFX & SWT 4
B AWT Canvas überdeckt nach repaint() JComboBox-Optionen AWT, Swing, JavaFX & SWT 2
lumo SWT Canvas transparent AWT, Swing, JavaFX & SWT 4
2 AWT Zeichnen in Canvas AWT, Swing, JavaFX & SWT 5
B 2D-Grafik Malen/übermalen mit Canvas AWT, Swing, JavaFX & SWT 5
L Dynamisch Objekte in Canvas zeichnen AWT, Swing, JavaFX & SWT 5
G Auf Canvas zeichnen nur über boolean-Abfragen? AWT, Swing, JavaFX & SWT 5
R In JFrame oder in Canvas mit grafischen Elemente zeichnen AWT, Swing, JavaFX & SWT 2
I Canvas Repaint Probleme AWT, Swing, JavaFX & SWT 2
S Bild wird auf Canvas in Applet nicht gezeichnet AWT, Swing, JavaFX & SWT 4
G SWT Linie unter transparentes Canvas zeichnen AWT, Swing, JavaFX & SWT 4
F Swing Paint mit Canvas Element AWT, Swing, JavaFX & SWT 35
S SWT Canvas: Flackernde Bilder AWT, Swing, JavaFX & SWT 3
T AWT canvas AWT, Swing, JavaFX & SWT 3
P Canvas: String wird nicht gezeichnet AWT, Swing, JavaFX & SWT 5
T SWT Canvas Koordinaten per MouseMove auslesen AWT, Swing, JavaFX & SWT 1
H Zeichnen auf smartgwt Canvas AWT, Swing, JavaFX & SWT 4
G Drag and Drop JTree to Canvas AWT, Swing, JavaFX & SWT 7
K Swing Sinuskurve zeichnen auf Canvas AWT, Swing, JavaFX & SWT 2
M AWT Component/Canvas erzeugt unerwünschten Rahmen bei paint AWT, Swing, JavaFX & SWT 3
J Canvas / paint() AWT, Swing, JavaFX & SWT 2
D Canvas soll angezeigtes jpg-Bild aktualisieren AWT, Swing, JavaFX & SWT 4
N zeichnen auf awt canvas AWT, Swing, JavaFX & SWT 9
G Ein Wort in einem String färben in einer Canvas AWT, Swing, JavaFX & SWT 10
T zeichnen mit canvas AWT, Swing, JavaFX & SWT 3
S repaint im Canvas AWT, Swing, JavaFX & SWT 3
D Canvas und Buttons AWT, Swing, JavaFX & SWT 20
P Zeichnen in Canvas und Neuzeichnen AWT, Swing, JavaFX & SWT 3
G Canvas + Swing-Objekte AWT, Swing, JavaFX & SWT 5
C canvas.draw zeichne ohne ausfüllen AWT, Swing, JavaFX & SWT 9
P Canvas in JFrame mit GridLayout AWT, Swing, JavaFX & SWT 4
B Graphics und Canvas - Problem AWT, Swing, JavaFX & SWT 2
T Canvas gegen Container austauschen --> GUI fehlt AWT, Swing, JavaFX & SWT 4
D Canvas über JMenuBar AWT, Swing, JavaFX & SWT 7
F ToolTip auf Canvas AWT, Swing, JavaFX & SWT 2
L Probleme mit mehreren Canvas: Überlagerungseffekte? AWT, Swing, JavaFX & SWT 5
N Zu hoher Speicherverbrauch beim Zeichnen (Canvas) AWT, Swing, JavaFX & SWT 5
G Canvas im JPanel - "Freie" Fläche Problem AWT, Swing, JavaFX & SWT 10
T Textfeldwert in canvas AWT, Swing, JavaFX & SWT 4
D cannot access Canvas AWT, Swing, JavaFX & SWT 13
G Canvas in SWT aktualisieren AWT, Swing, JavaFX & SWT 21
S AUF Canvas Zeichnen Fehler! AWT, Swing, JavaFX & SWT 10
G Canvas löschen AWT, Swing, JavaFX & SWT 15
H Sowas wie ein Canvas AWT, Swing, JavaFX & SWT 3
G GridBagLayout mit Canvas-Positionsproblem AWT, Swing, JavaFX & SWT 5
J Canvas und JTextField AWT, Swing, JavaFX & SWT 2
T erkennen ob innerhalb oder außerhalb von canvas gezeichnet AWT, Swing, JavaFX & SWT 2
S Problemen mit Canvas-Objekten im GridLayout AWT, Swing, JavaFX & SWT 8
P Tranparentes Canvas AWT, Swing, JavaFX & SWT 8
G Canvas, JMenu, und BufferStrategy AWT, Swing, JavaFX & SWT 2
M Codeteilung -> Canvas zeichnet nicht mehr AWT, Swing, JavaFX & SWT 40

Ähnliche Java Themen

Neue Themen


Oben