Java, wie zu zeichnen ständig wechselnden Grafiken
Dies nicht getan haben, bevor, so offensichtlich habe ich es zu saugen. Hier 64 Pixel um aktuelle position der Maus hineingezogen werde, etwas größer auf einem Formular. Problem ist, dass es 'irgendwie' zu langsam, und ich habe keine Ahnung, wo zu beheben beginnen.
Außerdem, ich habe einen thread, der ständig ruft der Aktualisierung von Grafiken, wenn es fertig ist und ein wenig fps wie text, zeigen wirklich, wie schnell die Dinge gezeichnet werden.
Bild-Beispiel: (Bild ist vom Buchstaben 'a' in Eclipse)
Code Beispiel :
@SuppressWarnings("serial")
public static class AwtZoom extends Frame {
private BufferedImage image;
private long timeRef = new Date().getTime();
Robot robot = null;
public AwtZoom() {
super("Image zoom");
setLocation(new Point(640, 0));
setSize(400, 400);
setVisible(true);
final Ticker t = new Ticker();
this.image = (BufferedImage) (this.createImage(320, 330));
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
t.done();
dispose();
}
});
try {
robot = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
t.start();
}
private class Ticker extends Thread {
public boolean update = true;
public void done() {
update = false;
}
public void run() {
try {
while (update == true) {
update(getGraphics());
//try {
//Thread.sleep(200);
//} catch (InterruptedException e) {
//e.printStackTrace();
//return;
//}
}
} catch (Exception e) {
update=false;
}
}
}
public void update(Graphics g) {
paint(g);
}
boolean isdone = true;
public void paint(Graphics g) {
if (isdone) {
isdone=false;
int step = 40;
Point p = MouseInfo.getPointerInfo().getLocation();
Graphics2D gc = this.image.createGraphics();
try {
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
gc.setColor(robot.getPixelColor(p.x - 4 + x, p.y
- 4 + y));
gc.fillOval(x * step, y * step, step - 3, step - 3);
gc.setColor(Color.GRAY);
gc.drawOval(x * step, y * step, step - 3, step - 3);
}
}
} catch (Exception e) {
e.printStackTrace();
}
gc.dispose();
isdone = true;
iter++;
}
g.drawImage(image, 40, 45, this);
g.setColor(Color.black);
StringBuilder sb = new StringBuilder();
sb.append(iter)
.append(" frames in ")
.append((double) (new Date().getTime() - this.timeRef) / 1000)
.append("s.");
g.drawString(sb.toString(), 50, 375);
}
int iter = 0;
}
Änderungen:
* Hinzugefügt "gc.dispose();"
* Hinzugefügt "isdone", so Neuzeichnen konnte nicht aufgerufen werden schneller, dann es sollte.
* Hinzugefügt dieser link zu thrashgod source umschreiben
* Hinzugefügt dieser link zu thrashgod Quelle rewrite 2
- warum nicht nur streichen, wenn ein mouse-move-Ereignis Auftritt?
- Warum sind Sie aufrufen der garbage collector während
paint
? - Wirklich wollen, um zu malen, was ist in der Nähe der Maus, und wollen es zu arbeiten, wo immer die Maus (so schnell wie es konnte, auch wenn auf ein video). Das problem nehme ich Sie fand, war, dass paint-Ereignis auch genannt werden könnte, die nicht von thread t auf. Ich denke, es war kein problem, aber fixiert es mit dem hinzufügen von "isdone" ohnehin.
- Einige Allgemeine Hinweise (1) Sie sollte nur Malerei auf der Event-Dispatch-Thread, aber Sie zu sein scheinen, die Malerei in den Ticker-Thread. (2) Sie sollte nicht müssen den "fertig" - Variablen, da eine single-thread kann nicht ausgeführt werden zwei bits von code auf einmal. (3) Versuchen, und trennen Sie diese in ein Modell (ein 8*8 array von Farben) und die View (die Sie bitten, Sie zu streichen, wenn das Modell aktualisiert wird). (4) Prüfen, mit repaint(x, y, w, h), die angibt, einen clipping-Bereich und daher repaints schneller.
- Ich habe einige profiling - Roboter.getPixelColor(..) ist Hund langsam auf meinem Mac. Das ist ein guter Ort, um zu beginnen, Verbesserungen
Du musst angemeldet sein, um einen Kommentar abzugeben.
Hier meine komplette Neufassung mit folgende nennenswerte änderungen:
Den ticker läuft ständig. Wenn es erkennt eine änderung in den pixel-Farbe (entweder durch die Maus bewegen, um eine andere region oder das Pixel unter der Maus ändert), es erkennt genau, was sich geändert hat, aktualisiert das Modell, dann fordert Sie die Ansicht neu zu streichen. Dieser Ansatz updates sofort für das menschliche Auge. 289 Bildschirm-updates nahm kumulativ 1 Sekunde.
Es war eine schöne Herausforderung für einen ruhigen Samstag Abend.
createScreenCapture()
auf speed up my alternativen code.Wenn Sie nichts dagegen haben mit Swing, diese Beispiel zeigt, wie schnell Zoomen auf ein
BufferedImage
erhielt von einemIcon
. In Ihrem Fall, Sie möchten eine 8x8BufferedImage
, die gefüllt wird, inmouseMoved()
mit den Pixeln gesehen durch den Roboter.Nachtrag: Hier ist ein snapshot von der oberen, linken Ecke Ihres Beispiel.
Nachtrag:
Der langsame Teil ist immer Pixel vom desktop; die Skalierung ist gering. Wenn Sie nur wollen, um zu sehen, eine Vielzahl von Animations-Techniken, haben Sie einen Blick auf diese Beispiel.
Nachtrag: Als erste einzelne Pixel ist langsam und die
createScreenCapture()
vorgeschlagene Methode von @Steve McLeod ist schnell, hier ist die Idee, ich fuhr an. Sie sehen es auch updates, die viel mehr reibungslos. Beachten Sie, dass die Freigabe der Maus-Schaltfläche erlaubt, um zu sehen die aufgenommenen Farben.Fügen Sie diese Methode, um die Paint-Methode:
Okay, so verwenden Sie timer, um zu verlangsamen, verzögern, kein threading, das ist schlecht.
Einfach mit einem time delay-Schleife.Anschließend können Sie die Feineinstellung der Verzögerung durch anpassen der Grenzen des ich.Es gibt Ihnen auch die regler, um den übergang Geschwindigkeiten durch einige Treffer und versuche.
for(long i=0;i<=100000000000;i++);
Leinwand.repaint();
Funktioniert es sehr gut mit mir und auch keine Notwendigkeit für die Verwendung der gepufferten Bilder.