enderização personalizada @AWT - capture redimensionamentos suaves e elimine o redimensionamento de cintilação
Venho analisando isso há vários meses e, até agora, esse é o melhor que eu já criei.
A estrutura (renderizada fora da EDT) não está em debate, pois nosso aplicativo funciona dessa maneira e não será reescrito. O aplicativo possui um modelo de layout e um modelo de script integrados e renderização de unidade, portanto, a renderização deve ser executada fora do modelo de pintura AW
O que estou tentando chegar é a maneira ideal e confiável de executar a renderização personalizad
O seguinte SSCCE funciona bastante bem para nós. No entanto, durante o redimensionamento de quadros, há 2 desvantagens:
Há oscilações ocasionais, especialmente em redimensionamentos rápidos O hack "redimensionar suavemente", que é para invocar o redimensionamento (via checkSize aqui) de uma chamada paint (), funciona apenas para expansões. Ao reduzir o quadro, ele normalmente não é renderizado até o botão do mouse ser liberado Além disso, mas não tão evidente aqui, ele gera IllegalStateExceptions ocasionais - não há problema em simplesmente pegar / ignorar esses itenTambém é útil informar se essa é a abordagem ideal para um caminho de renderização personalizado que ocorre fora do EDT. Eu tentei mais e fiz uma pesquisa bastante extensa. Essa combinação (imagem de backbuffer, estratégia de buffer duplo) parece funcionar melhor.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferStrategy;
public class SmoothResize extends Frame implements ComponentListener, MouseMotionListener {
public SmoothResize() {
addComponentListener(this);
addMouseMotionListener(this);
}
private boolean sizeChanged = false;
private Dimension old = new Dimension(0, 0);
private synchronized void checkSize(String source) {
int width = getWidth();
int height = getHeight();
if (old.width == width && old.height == height)
return;
sizeChanged = true;
String type =
(old.width > width && old.height > height) ? "shrink" :
(old.width < width && old.height < height) ? "expand" : "resize";
System.out.println(source + " reports " + type + ": "+getWidth()+", "+getHeight());
old.setSize(width, height);
}
public void componentResized(ComponentEvent arg0) { checkSize("componentResized"); }
public void mouseMoved(MouseEvent e) { checkSize("mouseMoved"); }
public void paint(Graphics g) { checkSize("paint"); }
public void update(Graphics g) { paint(g); }
public void addNotify() {
super.addNotify();
createBufferStrategy(2);
}
private synchronized void render() {
BufferStrategy strategy = getBufferStrategy();
if (strategy==null || !sizeChanged) return;
sizeChanged = false;
// Render single frame
do {
// The following loop ensures that the contents of the drawing buffer
// are consistent in case the underlying surface was recreated
do {
System.out.println("render");
Graphics draw = strategy.getDrawGraphics();
Insets i = getInsets();
int w = getWidth()-i.left-i.right;
int h = getHeight()-i.top-i.bottom;
draw.setColor(Color.YELLOW);
draw.fillRect(i.left, i.top+(h/2), w/2, h/2);
draw.fillRect(i.left+(w/2), i.top, w/2, h/2);
draw.setColor(Color.BLACK);
draw.fillRect(i.left, i.top, w/2, h/2);
draw.fillRect(i.left+(w/2), i.top+(h/2), w/2, h/2);
draw.dispose();
// Repeat the rendering if the drawing buffer contents
// were restored
} while (strategy.contentsRestored());
// Display the buffer
strategy.show();
// Repeat the rendering if the drawing buffer was lost
} while (strategy.contentsLost());
}
public static void main(String[] args) {
Toolkit.getDefaultToolkit().setDynamicLayout(true);
System.setProperty("sun.awt.noerasebackground", "true");
SmoothResize srtest = new SmoothResize();
//srtest.setIgnoreRepaint(true);
srtest.setSize(100, 100);
srtest.setVisible(true);
while (true) {
srtest.render();
}
}
public void componentHidden(ComponentEvent arg0) { }
public void componentMoved(ComponentEvent arg0) { }
public void componentShown(ComponentEvent arg0) { }
public void mouseDragged(MouseEvent e) { }
}