Hallo liebes Forum!
Ich habe folgendes Problem: Ich will eine ganz stinknormale Foto-Slideshow in Java programmieren. Dazu habe ich mir eine Klasse gebastelt, die JPanel extended und verschiedene Methoden implementiert. Unter anderem das Setzen des Hintergrundbildes und das Sliden von einem Bild aufs nächste (Das alte Bild wandert auf der einen Panelseite heraus, während das andere sich auf der anderen Seite hineinschiebt).
Nun zu den Problemen:
1. Beim Sliden kommt es bei der Anzeige immer wieder zu Rucklern und "lag", so das das Endergebnis als Animation unzufriedenstellend ist. Ich habe mich zwar mit Doppelpufferung beschäftigt und dazu Tests durchgeführt (bigPaint(); ist einer dieser Tests), jedoch habe ich das Prinzip entweder nicht verstanden, oder es ist nicht für mein Problem geeignet. Die Ruckler hat es jedenfalls nicht beseitigt.
2. Der Slide an sich wird bis jetzt in Absolutwerten und durchgeführt (soll heißen, das bild wird um jeweils einen Pixel verschoben, die geschwindigkeit wird über ein Thread.sleep(sleeptime); geregelt. Auch diese vorläfige Lösung ist mmn äußerst unbefriedigend, da bei aufziehen des Fensters (Vollbild) die Geschwindigkeit gleich bleibt -> zum Füße einschlafen langsam. Auch ist die Maximalgeschwindigkeit begrenzt, da man nicht schneller als 1Pixel pro "Zykluszeit?" ->(wenn Thread.sleep(0); also die schnellstmögliche Durchlaufzeit) fahren kann.
Ich bitte hier nicht um eine "Komplettlösung" aber ich würde mich sehr über Verbesserungsvorschläge bezüglich der Probleme und natürlich auch anderer Fehler/Unrenheiten im Code freuen.
Nun, hier der Code:
(Anmerkung: Der Code ist aufgrund einiger Tests und ungereimtheiten leider nicht was an strukturiert oder Aufgeräumt nennen kann. Ich entschuldge mich für die Unannehmlichkeiten.)
(Anmerkung2: Die Veriegelung der Threads untereinander um nicht mehrere Slides gleichzeitig zu zeichen - Was natürlich in ein heilloses durcheinander enden würde - ist noch nicht funktionstüchtig, jedoch nicht essentiell für meine eigentlichen Probleme. Dieses Problem kann ich selbst lösen.)
Konkret will ich also das ruckeln wegbringen und den Slide an sich in einer angemessenen Geschwindigkeit und eventuell "smooth" (langsam anfahren, schneller werden, wieder langsam abbremsen) machen.
Danke im Voraus für die Hilfe. :toll:
Ich habe folgendes Problem: Ich will eine ganz stinknormale Foto-Slideshow in Java programmieren. Dazu habe ich mir eine Klasse gebastelt, die JPanel extended und verschiedene Methoden implementiert. Unter anderem das Setzen des Hintergrundbildes und das Sliden von einem Bild aufs nächste (Das alte Bild wandert auf der einen Panelseite heraus, während das andere sich auf der anderen Seite hineinschiebt).
Nun zu den Problemen:
1. Beim Sliden kommt es bei der Anzeige immer wieder zu Rucklern und "lag", so das das Endergebnis als Animation unzufriedenstellend ist. Ich habe mich zwar mit Doppelpufferung beschäftigt und dazu Tests durchgeführt (bigPaint(); ist einer dieser Tests), jedoch habe ich das Prinzip entweder nicht verstanden, oder es ist nicht für mein Problem geeignet. Die Ruckler hat es jedenfalls nicht beseitigt.
2. Der Slide an sich wird bis jetzt in Absolutwerten und durchgeführt (soll heißen, das bild wird um jeweils einen Pixel verschoben, die geschwindigkeit wird über ein Thread.sleep(sleeptime); geregelt. Auch diese vorläfige Lösung ist mmn äußerst unbefriedigend, da bei aufziehen des Fensters (Vollbild) die Geschwindigkeit gleich bleibt -> zum Füße einschlafen langsam. Auch ist die Maximalgeschwindigkeit begrenzt, da man nicht schneller als 1Pixel pro "Zykluszeit?" ->(wenn Thread.sleep(0); also die schnellstmögliche Durchlaufzeit) fahren kann.
Ich bitte hier nicht um eine "Komplettlösung" aber ich würde mich sehr über Verbesserungsvorschläge bezüglich der Probleme und natürlich auch anderer Fehler/Unrenheiten im Code freuen.
Nun, hier der Code:
Java:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package fba_bilderkennung.GUI_Slideshow.guihelper;
import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBaseIterators;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author ****
*/
public class ImagePanel extends javax.swing.JPanel implements slideObserver {
private BufferedImage img;
private static boolean inProgress = false;
/**
* Creates new form ImagePanel
*/
public ImagePanel() {
initComponents();
}
@Override
public void paint(Graphics g) {
super.paint(g);
}
private void bigPaint(Graphics g) {
g.drawImage(img, 0, 0, getWidth(), getHeight(), null);
}
private final GraphicsConfiguration gfxConf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
private BufferedImage offImg;
@Override
protected void paintComponent(Graphics g) {
if (offImg == null || offImg.getWidth() != getWidth() || offImg.getHeight() != getHeight()) {
offImg = gfxConf.createCompatibleImage(getWidth(), getHeight());
bigPaint(offImg.createGraphics());
}
g.drawImage(offImg, 0, 0, this);
bigPaint( g );
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
setLayout(new java.awt.GridLayout(1, 0));
}// </editor-fold>
// Variables declaration - do not modify
// End of variables declaration
public void setImage(BufferedImage img) {
this.img = img;
repaint();
}
public void slideLeft(BufferedImage imgOld, BufferedImage imgNew, Graphics g) {
super.paint(g);
SlideThread slide = new SlideThread("slider", imgOld, imgNew, g, this, "l");
slide.setDaemon(true);
slide.start();
}
public void slideRight(BufferedImage imgOld, BufferedImage imgNew, Graphics g) {
super.paint(g);
SlideThread slide = new SlideThread("slider", imgOld, imgNew, g, this, "r");
slide.setDaemon(true);
slide.start();
}
@Override
public void update(BufferedImage img, boolean inProgress) {
// System.out.println("UPDATE");
ImagePanel.inProgress = inProgress;
setImage(img);
}
private void setInProgress(boolean inProgress) {
ImagePanel.inProgress = inProgress;
}
private static class SlideThread extends Thread {
private final BufferedImage imgOld;
private final BufferedImage imgNew;
private final Graphics g;
private final ImagePanel p;
private final String direction;
public SlideThread(String name, BufferedImage imgOld, BufferedImage imgNew, Graphics g, ImagePanel p, String direction) {
super(name);
this.imgOld = imgOld;
this.imgNew = imgNew;
this.g = g;
this.p = p;
this.direction = direction;
}
@Override
public void run() {
while (ImagePanel.inProgress) {
//System.out.println("waiting: "+direction);
}
ImagePanel.inProgress = true;
int slidepix = 0;
if (direction.equalsIgnoreCase("l")) {
while (slidepix <= p.getWidth()) {
BufferedImage combined = new BufferedImage(p.getWidth(), p.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D cg = (Graphics2D) combined.getGraphics();
cg.drawImage(imgOld, 0 - slidepix, 0, p.getWidth(), p.getHeight(), null);
cg.drawImage(imgNew, p.getWidth() - slidepix, 0, p.getWidth(), p.getHeight(), null);
p.update(combined, true);
try {
Thread.sleep(((int) ((Math.pow((slidepix - (p.getWidth() / 2)), 1.1)) + (p.getWidth() / 2))) + 2); //Versuch die animation "smooth" zu machen
} catch (InterruptedException ex) {
//Logger.getLogger(ImagePanel.class.getName()).log(Level.SEVERE, null, ex);
}
slidepix++;
System.out.println("Sliding: " + slidepix + "px");
}
}
if (direction.equalsIgnoreCase("r")) {
while (slidepix >= -p.getWidth()) {
BufferedImage combined = new BufferedImage(p.getWidth(), p.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D cg = (Graphics2D) combined.getGraphics();
cg.drawImage(imgOld, 0 - slidepix, 0, p.getWidth(), p.getHeight(), null);
cg.drawImage(imgNew, -p.getWidth() - slidepix, 0, p.getWidth(), p.getHeight(), null);
p.update(combined, true);
try {
double progress = (slidepix + .0) / (p.getWidth() + .0);
System.out.println("" + progress);
int sleepingtime = (int) (Math.pow(Math.abs(progress - 0.5), 1.01));
System.out.println("Time: " + sleepingtime + "ms");
Thread.sleep(sleepingtime);
} catch (InterruptedException ex) {
//Logger.getLogger(ImagePanel.class.getName()).log(Level.SEVERE, null, ex);
}
slidepix--;
System.out.println("Sliding: " + slidepix + "px");
}
}
p.update(imgNew, false);
}
}
}
(Anmerkung: Der Code ist aufgrund einiger Tests und ungereimtheiten leider nicht was an strukturiert oder Aufgeräumt nennen kann. Ich entschuldge mich für die Unannehmlichkeiten.)
(Anmerkung2: Die Veriegelung der Threads untereinander um nicht mehrere Slides gleichzeitig zu zeichen - Was natürlich in ein heilloses durcheinander enden würde - ist noch nicht funktionstüchtig, jedoch nicht essentiell für meine eigentlichen Probleme. Dieses Problem kann ich selbst lösen.)
Konkret will ich also das ruckeln wegbringen und den Slide an sich in einer angemessenen Geschwindigkeit und eventuell "smooth" (langsam anfahren, schneller werden, wieder langsam abbremsen) machen.
Danke im Voraus für die Hilfe. :toll: