Schnelleres Malen

NicoHatProbleme2

Bekanntes Mitglied
Ich habe eine Klasse gemacht, mit dem man einzelne Pixel einzeln bemalen kann...
Ich habe auch ein layer System, mit dem man z.B. Figuren an über und einander vorbeibewegen kann.
Wie kann ich das schneller und effektiver machen, da man oft nur 0.25fps haben kann?
Java:
for(int i = 0; i < yM; i++) {
            for(int j = 0; j < xM; j++) {
                //pixel[i][j][0].clear();
                for(int k = firstLayer; k < lastLayer; k++) {
                    if(visible) pixel[i][j][k].draw();
                }
            }
        }
Er geht jede Klasse Pixel im array durch und sagt ihr, zu malen.
Code:
public Pixel(int x, int y, int size, JPanel panel) {
        this.panel = panel;
        g = panel.getGraphics();
        outline = panel.getGraphics();
        this.x = x;
        this.y = y;
        this.size = size;
        //System.out.println("new pixel");
    }
    public void setBounds(int x, int y, int size) {
        this.x = x;
        this.y = y;
        this.size = size;
    }
    public void draw() {
        if(color != null) {
            g.fillRect((int) ((x*increase)+offset.x), (int) ((y*increase)+offset.y), (int) (size*increase), (int) (size*increase));
        }
        if(showOutline) {
            outline.drawRect((int) ((x*increase)+offset.x), (int) ((y*increase)+offset.y), (int) (size*increase), (int) (size*increase));
        }
    }
ich habe auch gehört, dass man alles lieber @overide paintComponent von panel nehmen sollte, da es auch alles neu malt, wenn ich das Fenster schließe und wieder öffne, doch wie geht das hiermit am besten?
 

KonradN

Super-Moderator
Mitarbeiter
Vermutlich geht es schneller, wenn Du immer nur das aktiv malst, was du wirklich malen musst.

So kannst Du z.B. den Fensterinhalt in einem Bild halten und das Fenster malt immer nur das Bild. Die einzelnen Ebenen könnten dann auch Bilder sein. Es geht bestimmt schneller, paar Bilder übereinander zu malen als Pixel für Pixel selbst alles durchzugehen.

Dann wirst Du vermutlich vieles zusammen packen können - Dann hast Du maximal 3 Ebenen: Die unteren Ebenen als Background, die aktuelle, die verschoben wird / verändert wird und die darüber liegenden Ebenen. Dann hast Du also maximal die Zeit, die Du brauchst um diese drei Bilder abzubilden.

Das Ganze würde ich einfach unter dem Gesichtspunkt "Caching" zusammen fassen.
 

KonradN

Super-Moderator
Mitarbeiter
Also wenn Du ein Bild z.B. in BufferedImage hältst, dann kannst Du in dem Bild wie in der paintComponent Methode malen: Über ein Graphics2D Objekt. Dazu dient BufferedImage.createGraphics.
Du musst da nur ein bisschen aufpassen: Es macht ggf. Sinn, da mit zwei Gruppen von Bildern zu arbeiten: Eine Gruppe mit Bildern, die angezeigt werden und eine Gruppe mit Bildern, die angepasst werden (können). Damit verhinderst Du, dass ein Bild, das du gerade malst, schon angezeigt wird.
 

NicoHatProbleme2

Bekanntes Mitglied
in nem png gespeichert, sieht es richtig aus, mit der drawImage nicht
Java:
panel.getGraphics().drawImage(img[i], x*size, y*size, null);
 

KonradN

Super-Moderator
Mitarbeiter
Was genau machst Du denn da mit dem panel? Die Idee sollte immer sein, dass die UI Elemente sich selbst malen. In der paint oder paintComponent Methode hast Du ein Grahics Objekt, das Du dazu nutzen kannst. An dem Ablauf solltest Du nichts ändern. JComponent.getGraphics solltest Du also nicht einfach so verwenden.
 

KonradN

Super-Moderator
Mitarbeiter
ist gerade nur vorübergehend, doch habe herausgefunden, dass das mit dem mehreren Bildern übereinander malen nicht funktioniert...
Was geht nicht? Bitte immer klare Aussagen machen, damit wir nicht raten müssen!

Hast Du evtl. keinen transparenten Hintergrund? Dann würdest du z.B. immer alles übermalen und nicht nur die Bereiche, die Du gerne hättest.
 

KonradN

Super-Moderator
Mitarbeiter
Also einfach einmal ein kleines minimales Beispiel, welches einfach zwei Bilder erstellt. Einmal mit einer Horizontalen Linie und einmal mit einer Vertikalen Linie. Dann malen wir ein Bild aus den beiden Bildern und das wird dann im Panel angezeigt.

Java:
package de.kneitzel;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;

public class Main {

    static JFrame frame;

    public static BufferedImage createImage(int dx, int dy, boolean horizontal) {
        Color drawing = new Color(255, 0, 0, 255);

        BufferedImage image = new BufferedImage(dx, dy, BufferedImage.TYPE_4BYTE_ABGR);
        Graphics graphics = null;
        try {
            graphics = image.getGraphics();
            graphics.setColor(drawing);
            if (horizontal) {
                graphics.drawLine(0, dy/2, dx, dy/2);
            } else {
                graphics.drawLine(dx/2, 0, dx/2, dy);
            }
        } finally {
            if (graphics != null) graphics.dispose();
        }
        return image;
    }

    public static BufferedImage combine(BufferedImage image1, BufferedImage image2) {
        BufferedImage image = new BufferedImage(image1.getWidth(), image1.getWidth(), BufferedImage.TYPE_4BYTE_ABGR);
        Graphics graphics = null;
        try {
            graphics = image.getGraphics();
            graphics.drawImage(image2, 0, 0, null);
            graphics.drawImage(image1, 0, 0, null);
        } finally {
            if (graphics != null) graphics.dispose();
        }
        return image;
    }

    public static void main(String[] args) {
        int dx=400;
        int dy=300;

        BufferedImage imageH = createImage(dx, dy, true);
        BufferedImage imageV = createImage(dx, dy, false);
        final BufferedImage result = combine(imageH, imageV);

        frame = new JFrame("Test");
        frame.setSize(400,300);

        JPanel panel = new JPanel() {
            @Override
            public void paintComponent(Graphics g) {
                g.drawImage(result, 0, 0, null);
            }
        };
        frame.add(panel);
        frame.setVisible(true);
    }
}
 

NicoHatProbleme2

Bekanntes Mitglied
ich meine ehr, dass früher der, wenn er an einer Stelle nichts malen sollte, einfach an einer Stelle nichts gemalt hat. Doch seit dem Image malt der an Stellen, an denen er nichts malen sollte einfach schwarz...
 

KonradN

Super-Moderator
Mitarbeiter
Dann zeig den Code! Was erstellst du wie? Wie malst du? Hast du ein BufferedImage erstellt, das Transparenz unterstützt? ARGB wäre das z.B. mit einem extra Byte Alpha (den du auch bei Color angeben kannst - Siehe mein Beispiel!)

Die transparente Farbe wird ggf wichtig, wenn Du etwas schon gemaltes löschen willst.
 

NicoHatProbleme2

Bekanntes Mitglied
ok... also... erstmal erschaffe ich das BufferedImage und gebe es weiter an alle neuen Pixelobjeckte
Java:
img = new BufferedImage(xPixels*minPixel, yPixels*minPixel, BufferedImage.TYPE_INT_RGB);
        pixel = new Pixel[yPixels][xPixels][layers];
        for(int i = 0; i < pixel.length; i++) {
            for(int j = 0; j < pixel[i].length; j++) {
                for(int k = 0; k < pixel[i][j].length; k++) {
                    pixel[i][j][k] = new Pixel(j*minPixel, i*minPixel, minPixel, img);
                    pixel[i][j][k].setColor();
                   
                }
            }  
        }
Dann lösche ich alles im img und sage jedem Pixel, ins Bild zu zeichnen

Code:
img.createGraphics().clearRect(
            0,
            0,
            img.getWidth(),
            img.getHeight());
        int yM = (int) (pixel.length/(magnification/10.0));
        if(yM > pixel.length) yM = pixel.length;
        int xM = (int) (pixel[0].length/(magnification/10.0));
        if(xM > pixel[0].length) xM = pixel[0].length;
        for(int i = 0; i < yM; i++) {
            for(int j = 0; j < xM; j++) {
                //pixel[i][j][0].clear();
                for(int k = firstLayer; k < lastLayer; k++) {
                    if(visible) {
                        pixel[i][j][k].draw();
                    }
                }
            }
        }
        //zum testen:
        /**File file = new File("test.png");
        try {
            ImageIO.write(img, "png", file);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }**/
        panel.getGraphics().drawImage(img, x, y, null, panel);
Und zeichne es dann
Pixel:
Code:
public void draw() {
        System.out.println(color);
        if(color != null) {
            g.fillRect((int) (x*increase), (int) (y*increase), (int) (size*increase), (int) (size*increase));
        }
        if(showOutline) {
            outline.drawRect((int) (x*increase), (int) (y*increase), (int) (size*increase), (int) (size*increase));
        }
    }
 

KonradN

Super-Moderator
Mitarbeiter
Also jetzt habe ich mir auch etwas Deinen Code angesehen und ich frage mich, was Du da überhaupt treibst:
  • Dein draw malt auf irgend einem Graphics herum - woher das kommt weisst Du vermutlich selbst nicht. Das von Deinem Bild ist es vermutlich nicht.
  • Dann immer noch dieses panel.getGraphics
  • Dann das drawImage an der Stelle - was sind denn da die Parameter? bgColor gibst Du als null zurück? Wie kommst Du auf die Idee, dass da null erlaubt sei? Da könnte man - so man mit transparenten Dingen nichts überschreiben will, z.B eine Transparente Farbe mitgeben (also mit dem alpha Wert auf 0)

"Dann lösche ich alles im img und sage jedem Pixel, ins Bild zu zeichnen" was aber eigentlich fast genauso lange braucht...
Wenn Du immer alles malst, dann hast Du natürlich beim Cache keinen Effekt. Der Effekt vom Cache kommt halt daher, dass Du nur noch weniger malst. Wenn Du also mehrere Ebenen hast, dann musst Du nur die Ebenen neu malen, die sich verändert haben. Wenn sich einzelne Punkte verändern, dann könnte man ggf. auch schauen, ob man nur die Veränderung im bestehenden Bild nachmalen könnte.
 

KonradN

Super-Moderator
Mitarbeiter
Und ganz wichtig: was macht denn dein fillRect? Mit welcher Farbe füllst Du denn das ganze Bild?

Da solltest Du also ggf. einfach einmal eine transparente Farbe setzen ehe Du das machst.

Also etwas wie:
Java:
Color transparent  = new Color(0, 0, 0, 0);
graphics = image.getGraphics();
graphics.setColor(transparent);
graphics.fillRect(0, 0, image.getWidth(), image.getHeight());
 

NicoHatProbleme2

Bekanntes Mitglied
Ok... das mit dem transparent funktioniert schonmal...
Also jetzt habe ich mir auch etwas Deinen Code angesehen und ich frage mich, was Du da überhaupt treibst:
  • Dein draw malt auf irgend einem Graphics herum - woher das kommt weisst Du vermutlich selbst nicht. Das von Deinem Bild ist es vermutlich nicht.
  • Dann immer noch dieses panel.getGraphics
  • Dann das drawImage an der Stelle - was sind denn da die Parameter? bgColor gibst Du als null zurück? Wie kommst Du auf die Idee, dass da null erlaubt sei? Da könnte man - so man mit transparenten Dingen nichts überschreiben will, z.B eine Transparente Farbe mitgeben (also mit dem alpha Wert auf 0)


Wenn Du immer alles malst, dann hast Du natürlich beim Cache keinen Effekt. Der Effekt vom Cache kommt halt daher, dass Du nur noch weniger malst. Wenn Du also mehrere Ebenen hast, dann musst Du nur die Ebenen neu malen, die sich verändert haben. Wenn sich einzelne Punkte verändern, dann könnte man ggf. auch schauen, ob man nur die Veränderung im bestehenden Bild nachmalen könnte.
1. g = img.createGraphics(); (img = BufferedImage)
2. ja, ich weiß... muss ich noch ändern
3. Da ich bei dem draw nur das zeichne, was ich brauche und deshalb nur bei dem clearRect den Hintergrund auf transparent gesetzt habe

Und ist doch jetzt schon um einiges schneller... vl. bekomme ich es jetzt noch durch Threads schneller hin, muss mal gucken, wie viel CPU das jetzt frisst
 

NicoHatProbleme2

Bekanntes Mitglied
Java:
panel = new JPanel() {
            @Override public void paintComponent(Graphics g) {
                super.paintComponent(g);
                paintC(g);
            }
        };
Wieso funktioniert das nicht?
 

KonradN

Super-Moderator
Mitarbeiter
Was genau funktioniert nicht? Was für eine Meldung kommt? Wie sieht der weitere Code aus? Ohne konkrete Informationen wird man Dir nicht helfen können.
 

NicoHatProbleme2

Bekanntes Mitglied
ok, hat jetzt doch geklappt, war nur ein dummer Fehler von mir, der mich so ne h Zeit zum rausfinden gekostet hat... mir ist nämlich aufgefallen, dass ich den nicht auf visible gesetzt habe...
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
E Auf JPanel malen und davor JComponenten anzeigen AWT, Swing, JavaFX & SWT 12
Java_RY Bin Ratlos bzgl Malen in Swing AWT, Swing, JavaFX & SWT 5
M Punkte malen AWT, Swing, JavaFX & SWT 1
M Schrift "malen" AWT, Swing, JavaFX & SWT 11
Regedit JavaFX Java Canvas hört ständig auf zu aktualisieren/malen AWT, Swing, JavaFX & SWT 3
Z Auf ein JLabel drauf malen? AWT, Swing, JavaFX & SWT 1
J Swing Bild laden, Kreise drin malen, Schreiben AWT, Swing, JavaFX & SWT 2
L Gradient Hintergrund malen und durchscheinen lassen AWT, Swing, JavaFX & SWT 8
windl Querstreifen beim Bilder malen und anpassen an neue CPU AWT, Swing, JavaFX & SWT 12
S JButton in JLabel malen AWT, Swing, JavaFX & SWT 7
E JButton Text malen AWT, Swing, JavaFX & SWT 3
J Swing Malen auf JPanel mit transparentem Hintergrund AWT, Swing, JavaFX & SWT 21
B 2D-Grafik Malen/übermalen mit Canvas AWT, Swing, JavaFX & SWT 5
K swing/awt Panel punkte malen AWT, Swing, JavaFX & SWT 4
G Auf Image malen AWT, Swing, JavaFX & SWT 12
B Wie Panel neu Laden/Malen/Aktualisieren AWT, Swing, JavaFX & SWT 14
G kreis malen -> welche funktion? AWT, Swing, JavaFX & SWT 3
V Framework zum Zeichnen/Malen? AWT, Swing, JavaFX & SWT 7
D bei Thread in JComponent malen NullPointerException AWT, Swing, JavaFX & SWT 3
J Einmal gleichzeitig auf zwei Graphics malen? AWT, Swing, JavaFX & SWT 5
C ".tif" Image in Java einbinden und malen lassen AWT, Swing, JavaFX & SWT 7
H auf einem Bild malen AWT, Swing, JavaFX & SWT 4
N malen => 1 Sekunde warten => malen AWT, Swing, JavaFX & SWT 2
V Punkte malen im Panel AWT, Swing, JavaFX & SWT 3
U Malen auf Buffered Image AWT, Swing, JavaFX & SWT 9
V Auf Knopfdruck malen ?????? AWT, Swing, JavaFX & SWT 5

Ähnliche Java Themen

Neue Themen


Oben