Ich hab mich heute mal an die Arbeit gemacht und
eine etwas ältere Komponente von mir überarbeitet.
Es geht um ein JPanel
auf dem man ein Hintergrundbild setzt und ein weiteres Bild,
welches man zoomen kann.
Hatte mir damals sehr viele Probleme bereitet:
http://www.java-forum.org/awt-swing-swt/81823-zoom-jpanel-repaint.html
http://www.java-forum.org/awt-swing-swt/80224-zoomimage-flackert-fehler-repaint-aufruf-geloest.html
Heute habe ich mich mal ein wenig durch das Internet geforstet und den Zoom-Vorgang optimiert,
hauptsächliche Neuerung ist die überarbeitete paintComponent-Methode ("On-The-Fly Scaling):
The Perils of Image.getScaledInstance() | Java.net
Gibt es vielleicht noch andere Ansätze die mein Vorhaben eleganter (wollte nicht "schneller", "besser" schreiben ^^) lösen?
Würde mich über Anregungen freuen
Hier mal meine Klasse:
Nachtrag:
Hab jetzt mal vom JComponent erben lassen,
da ich Funktionen vom JPanel nicht mehr brauche ...
eine etwas ältere Komponente von mir überarbeitet.
Es geht um ein JPanel
auf dem man ein Hintergrundbild setzt und ein weiteres Bild,
welches man zoomen kann.
Hatte mir damals sehr viele Probleme bereitet:
http://www.java-forum.org/awt-swing-swt/81823-zoom-jpanel-repaint.html
http://www.java-forum.org/awt-swing-swt/80224-zoomimage-flackert-fehler-repaint-aufruf-geloest.html
Heute habe ich mich mal ein wenig durch das Internet geforstet und den Zoom-Vorgang optimiert,
hauptsächliche Neuerung ist die überarbeitete paintComponent-Methode ("On-The-Fly Scaling):
The Perils of Image.getScaledInstance() | Java.net
Gibt es vielleicht noch andere Ansätze die mein Vorhaben eleganter (wollte nicht "schneller", "besser" schreiben ^^) lösen?
Würde mich über Anregungen freuen
Hier mal meine Klasse:
Java:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ZoomImage5 extends JComponent {
private static final long serialVersionUID = 1L;
private int startX;
private int startY;
private BufferedImage zoomImg;
private BufferedImage bakImg;
private int quality;
private int pixel;
private Image currentImage;
// for painting
private boolean zoom;
private int tmpWidth;
private int tmpHeight;
// zoomMax
private int maxWidth;
private int maxHeight;
public ZoomImage5() {
this.startX = 0;
this.startY = 0;
this.quality = Image.SCALE_AREA_AVERAGING;
this.pixel = 2;
this.zoom = false;
initCurrentImage();
}
public void setBakImg(BufferedImage bakImg) {
this.bakImg = bakImg;
if (this.bakImg != null) {
this.setPreferredSize(new Dimension(this.bakImg.getWidth(),
this.bakImg.getHeight()));
}
}
public void setImg(BufferedImage zoomImage, int startX, int startY,
int startWidth, int startHeight) {
this.zoomImg = zoomImage;
this.startX = startX;
this.startY = startY;
this.tmpWidth = startWidth;
this.tmpHeight = startHeight;
initCurrentImage();
}
/**
* Zommt auf dem Panel.
*
* @param modus
* 0 = nach rechts, unten; 1 = nach links, unten 2 = nach rechts,
* oben; 3 = nach links, oben
*/
public void zoomImage(int modus) {
if (this.zoomImg != null) {
this.maxWidth = this.zoomImg.getWidth();
this.maxHeight = this.zoomImg.getHeight();
// wenn zu breit
if (maxWidth > this.bakImg.getWidth()) {
this.maxHeight = (this.maxHeight * this.bakImg.getWidth())
/ this.maxWidth;
this.maxWidth = this.bakImg.getWidth();
}
// wenn zu hoch
if (maxHeight > this.bakImg.getHeight()) {
this.maxWidth = (this.maxWidth * this.bakImg.getHeight())
/ this.maxHeight;
this.maxHeight = this.bakImg.getHeight();
}
myZoom(modus);
}
}
/**
* modifizierte "paint"-Methode, zeichnet das jeweilige Hintergrundbild und
* das aktuelle Bild.
*/
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (zoom) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
g2.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_SPEED);
g2.drawImage(this.bakImg, 0, 0, null);
g2.drawImage(this.currentImage, startX, startY, tmpWidth,
tmpHeight, null);
} else {
g.drawImage(this.bakImg, 0, 0, null);
g.drawImage(this.currentImage, startX, startY, null);
}
}
/**
* interne zoom-Methode.
*/
private void myZoom(int modus) {
new zoomThread(modus).start();
}
private void initCurrentImage() {
if (this.zoomImg != null) {
this.currentImage = this.zoomImg.getScaledInstance(this.tmpWidth,
this.tmpHeight, this.quality);
}
}
private void startXYfix(int modus) {
switch (modus) {
case 1: {
this.startX -= tmpWidth;
break;
}
case 2: {
this.startY -= tmpHeight;
break;
}
case 3: {
this.startX -= tmpWidth;
this.startY -= tmpHeight;
break;
}
}
}
private void changeXY(int modus, int diffH, int diffW) {
if (modus <= 0) {
// zoome nach rechts unten
// nichts machen
} else if (modus <= 1) {
// zoome nach links unten
this.startX -= pixel;
} else if (modus <= 2) {
// zoome nach rechts oben
this.startY -= diffH;
} else {
// zoome nach links oben
this.startX -= diffW;
this.startY -= diffH;
}
}
// Thread für den ZoomVorgang
private class zoomThread extends Thread {
private int modus;
public zoomThread(int modus) {
this.modus = modus;
}
@Override
public void run() {
zoom = true;
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
repaint();
}
});
} catch (Exception e) {
e.printStackTrace();
}
startXYfix(modus);
int clearH = zoomImg.getHeight();
int clearW = zoomImg.getWidth();
int lastH = 0;
int lastW = 0;
int iterations = (maxWidth - tmpWidth) / pixel;
// zeichnen sämtlicher Bilder (Zoomvorgang)
for (int i = 0; i < iterations; i++) {
lastH = tmpHeight;
lastW = tmpWidth;
if (maxHeight > maxWidth) {
tmpHeight += pixel;
tmpWidth = (tmpHeight * clearW) / clearH;
} else {
tmpWidth += pixel;
tmpHeight = (tmpWidth * clearH) / clearW;
}
try {
Thread.sleep(0, 1);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
changeXY(modus, tmpHeight - lastH, tmpWidth - lastW);
try {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
repaint(startX, startY, tmpWidth, tmpHeight);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
currentImage = zoomImg.getScaledInstance(tmpWidth, tmpHeight,
quality);
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
repaint();
}
});
} catch (Exception e) {
e.printStackTrace();
}
zoom = false;
}
}
}
Nachtrag:
Hab jetzt mal vom JComponent erben lassen,
da ich Funktionen vom JPanel nicht mehr brauche ...
Zuletzt bearbeitet: