Also ich habs ausprobiert und das Filter mit dem Textfeld wieder eingefügt, ist im Prinzip schon das was ich mir vorgestellt habe - nur hab ich jetzt das Problem, das animierte GIFs nicht mehr funktionieren. Das Skalieren funktioniert problemlos, nur die animierten Gifs sind jetzt ein Standbild des ersten Frames. Das liegt denke ich an dem BufferedImage…
Edit: Google bestätigt mich - ImageIcons können animierte Gifs anzeigen, BufferedImage ist dafür jedoch nicht gemacht. Müsste also quasi doch wieder zurück auf ImageIcon umsteigen
Edit²: Dazu kommt der GifImageReader bei bestimmten Gifs zu einer AIOOBE
java.lang.ArrayIndexOutOfBoundsException: 4096
at com.sun.imageio.plugins.gif.GIFImageReader.read(GIFImageReader.java:984)
Ich hab nachgeschaut und wie ich die Implementierung verstehe passiert das, wenn die GIF’s eine zu große Größe erreichen. Das GIF das bei mir den Fehler auslöst ist 6,5MB groß.
Edit³: java - ArrayIndexOutOfBoundsException: 4096 while reading gif file - Stack Overflow
Bekannter allgemeiner Bug bei ImageIO… ImageIO wird mir immer unsympathischer
Edit4: Habs umgeschrieben auf ImageIcon, funktioniert jetzt auch. mit dem Skalieren, nur das Problem ist, das Bild wird nur animiert, wenn ich das Fenster permanent mit der Maus bewege - heißt wenn repaint ausgeführt wird. Ansonsten bleibt das auch Still - wird aber mitskaliert. Das 6,5MB große GIf wird auch problemlos so geladen.
Jetzt die Frage, wie löse ich das. Wenn ich es wieder als Icon hinzufüge, ist es wieder animiert, wird aber nicht skaliert. Mache ich es auf Marcos Weiße, wird es skaliert, aber nur beim wiederholten ausführen von repaint animiert
Entweder ich kriegs heute noch hin oder ich probiers morgen mal…
So ist Marcos Klasse umgeschrieben, das das Textfeld wieder ne Funktion zum Filtern hat (Brauch ich einfach gif eingeben und sehe nur die gifs bzw den Namen des großen gifs um zu schauen ob die Exception kommt) und BufferedImage komplett rausfliegt und nurnoch ImageIcon zum Zuge kommt.
Edit5: Nochmal umgeschrieben - diesmal wird in ImageLabel noch setIcon ausgeführt.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.accessibility.AccessibleContext;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
public class BilderForum2Icon {
private static List<File> getFiles(JFileChooser fc, FileFilter filter,
boolean multiSelection, boolean onlyDirectories) {
if (!onlyDirectories) {
fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
} else {
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
}
fc.setMultiSelectionEnabled(multiSelection);
int returnVal = fc.showDialog(null, "Wählen");
if (returnVal == JFileChooser.APPROVE_OPTION) {
List<File> list = new ArrayList<>();
File[] files;
if (multiSelection) {
files = fc.getSelectedFiles();
} else {
files = new File[]{fc.getSelectedFile()};
}
Arrays.stream(files).forEach(f -> {
if (f.isDirectory()) {
addDirectory(f, list, filter);
} else if (filter.accept(f)) {
list.add(f);
} else {
System.out.println("Nicht akzeptiert: " + f.getName());
}
});
return list;
}
return new ArrayList<>();
}
private static void addDirectory(File directory, List<File> list,
FileFilter filter) {
Arrays.stream(directory.listFiles()).filter(filter::accept)
.forEach(f -> {
if (!f.isDirectory()) {
list.add(f);
} else {
addDirectory(f, list, filter);
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static List<File> selectFiles() {
JFileChooser fc = new JFileChooser();
FileFilter filter = new FileNameExtensionFilter(
"Unterstützte Formate (.gif, .jpg, .jpeg, .png)", "gif", "jpeg",
"jpg", "png");
fc.setCurrentDirectory(new File("E:\\Lol-Bilder"));
fc.setFileFilter(filter);
fc.addChoosableFileFilter(filter);
fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
List<File> files = getFiles(fc, filter, true, false);
return files;
}
private static class ImageLabel extends JLabel {
private ImageIcon image;
public void setImage(ImageIcon image) {
this.image = image;
super.setIcon(image);
repaint();
}
public ImageIcon getImage() {
return image;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (getIcon() != null) {
int iw = image.getIconWidth();
int ih = image.getIconHeight();
double factorW = (double) getWidth() / iw;
double factorH = (double) getHeight() / ih;
double factor = Math.min(factorW, factorH);
int w = (int) (factor * iw);
int h = (int) (factor * ih);
int x = (getWidth() - w) / 2;
int y = (getHeight() - h) / 2;
g.drawImage(image.getImage(), x, y, w, h, null);
}
}
}
private static class ImageComponent extends JPanel {
private ImageIcon image;
public void setImage(ImageIcon image) {
this.image = image;
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) {
int iw = image.getIconWidth();
int ih = image.getIconHeight();
double factorW = (double) getWidth() / iw;
double factorH = (double) getHeight() / ih;
double factor = Math.min(factorW, factorH);
int w = (int) (factor * iw);
int h = (int) (factor * ih);
int x = (getWidth() - w) / 2;
int y = (getHeight() - h) / 2;
g.drawImage(image.getImage(), x, y, w, h, null);
}
}
}
private static void createAndShowGui() {
List<File> files = selectFiles();
Collections.shuffle(files);
JFrame f = new JFrame("Bilder");
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setLayout(new BorderLayout());
f.setMinimumSize(new Dimension(800, 600));
JButton nextButton = new JButton("Nächstes");
ImageLabel label = new ImageLabel();
JTextField filterTextField = new JTextField(8);
JPanel controlPanel = new JPanel();
controlPanel.add(nextButton);
controlPanel.add(filterTextField);
f.getContentPane().add(controlPanel, BorderLayout.NORTH);
f.getContentPane().add(label, BorderLayout.CENTER);
nextButton.addActionListener(new ActionListener() {
private int index;
private final Random r = new Random();
private int maxBilder = 0;
@Override
public void actionPerformed(ActionEvent e) {
index = r.nextInt(files.size());
File file = files.get(index);
while (!filterTextField.getText().isEmpty() && !containsIgnoreCase(file.getName(), filterTextField.getText()) && maxBilder < 10_000_000) {
index = r.nextInt(files.size());
System.out.println("Index: " + index);
file = files.get(index);
maxBilder++;
}
ImageIcon image = read(file);
label.setImage(image);
f.setTitle(file.getName());
index = r.nextInt(files.size());
}
});
f.setExtendedState(JFrame.MAXIMIZED_BOTH);
f.pack();
f.setVisible(true);
nextButton.doClick();
}
private static ImageIcon read(File file) {
System.out.println("Read: " + file.getName());
return new ImageIcon(file.getPath());
}
public static boolean containsIgnoreCase(String str, String searchStr) {
if (str == null || searchStr == null) {
return false;
}
final int length = searchStr.length();
if (length == 0) {
return true;
}
for (int i = str.length() - length; i >= 0; i--) {
if (str.regionMatches(true, i, searchStr, 0, length)) {
return true;
}
}
return false;
}
}
JETZT wird es korrekt skaliert UND ist animiert - jedoch sieht man links in Originalgröße das Bild eben erneut . halt das mit setIcon hinzugefügte Icon. Ich hab allerdings nicht rausfinden können, was JLabel bei seinem Icon anders macht, das es repaint die ganze Zeit aufruft und die Gifs ordnungsgemäß animiert. paintcomponent muss ja die ganze Zeit ausgeführt werden das unser selbst programmiertes ImageLabel so ja auch auf einmal animiert wird…
Edit6: Lösung gefunden - aber sehr unschön und vorallem sehr unperformant…
Einfach das unten hinzufügen:
TimerTask task = new TimerTask() {
@Override
public void run() {
label.repaint();
}
};
Timer timer = new Timer("Bilder");
timer.scheduleAtFixedRate(task, 0, 100);
Allerdings… Selbst mit 100ms geht meine CPU Auslastung auf 35% von dem Programm und wirklich flüssig sind viele da auch nicht mehr