Ja, es ist ein altes und oft diskutiertes Thema und noch scheinbar ohne Lösung. Ich habe mittlerweile etliche Stunden damit verbracht und auch im Internet nichts gefunden.
Daher möchte hier mal einen Aufruf starten um es gemeinsam zu lösen.
Das Problem:
Wenn man ein JFrame mit setSize() resized wird zuerst der ganze Hintergrund gelöscht und dann neu gezeichnet. Daher entsteht ein permanentes Flackern.
Lösungsansätze:
Wenn man die Methode findet, in der der Hintergrund gelöscht wird, könnte man das Flackern z.B. mit Doppelpufferung umgehen, d.h. ein Bild vom Fenster machen, es darüberlegen und dann paint() aufrufen.
Was ich bisher weiß:
Bei anderen Components wird in update() zuerst gelöscht und dann paint() aufgerufen. Beim JFrame.setSize() jedoch nicht. Ich habe herausgefunden, dass keine der Methoden aufgerufen wird:
Es wird lediglich doLayout() und dann paint() aufgerufen.
Ich denke in doLayout() wird sicher nichts gelöscht.
Was wird da nur vor dem paint() aufgerufen? Oder wird sogar erst in paint() gelöscht?
Kann es sein, dass Window.paint() völlig nativ ist? In Eclipse zeigt er rechts bei Outline an, dass es in der Window.class die Methode paint(Graphics) gibt, sie ist aber nicht im Source Code drin. Was bedeutet das?
Zu guter Letzt noch ein kleines Beispielprogramm, damit ihr es schnell nachverfolgen könnt:
Daher möchte hier mal einen Aufruf starten um es gemeinsam zu lösen.
Das Problem:
Wenn man ein JFrame mit setSize() resized wird zuerst der ganze Hintergrund gelöscht und dann neu gezeichnet. Daher entsteht ein permanentes Flackern.
Lösungsansätze:
Wenn man die Methode findet, in der der Hintergrund gelöscht wird, könnte man das Flackern z.B. mit Doppelpufferung umgehen, d.h. ein Bild vom Fenster machen, es darüberlegen und dann paint() aufrufen.
Was ich bisher weiß:
Bei anderen Components wird in update() zuerst gelöscht und dann paint() aufgerufen. Beim JFrame.setSize() jedoch nicht. Ich habe herausgefunden, dass keine der Methoden aufgerufen wird:
- paintComponents(Graphics g)
- repaint()
- update()
Es wird lediglich doLayout() und dann paint() aufgerufen.
Ich denke in doLayout() wird sicher nichts gelöscht.
Was wird da nur vor dem paint() aufgerufen? Oder wird sogar erst in paint() gelöscht?
Kann es sein, dass Window.paint() völlig nativ ist? In Eclipse zeigt er rechts bei Outline an, dass es in der Window.class die Methode paint(Graphics) gibt, sie ist aber nicht im Source Code drin. Was bedeutet das?
Zu guter Letzt noch ein kleines Beispielprogramm, damit ihr es schnell nachverfolgen könnt:
Java:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class ResizableFrame extends JFrame{
int mouseX = 0;
int mouseY = 0;
public void addResizer(){
JPanel resizer = new JPanel();
resizer.setPreferredSize(new Dimension(100,30));
resizer.setBackground(Color.red);
resizer.addMouseListener(new MouseListener() {
public void mouseReleased(MouseEvent e) {}
public void mousePressed(MouseEvent e) {
mouseX = e.getX();
mouseY = e.getY();
}
public void mouseExited(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {}
});
resizer.addMouseMotionListener(new MouseMotionListener() {
public void mouseMoved(MouseEvent e) {}
public void mouseDragged(MouseEvent e) {
setSize(getWidth()-(mouseX-e.getX()), getHeight()-(mouseY-e.getY()));
mouseX = e.getX();
mouseY = e.getY();
}
});
JLabel label = new JLabel("Drag here");
resizer.add(label);
JPanel background = new JPanel();
getContentPane().add(background);
background.add(resizer);
}
public static void main(String[] args) {
ResizableFrame frame = new ResizableFrame();
frame.addResizer();
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}