Cha*_*win 6 java resize awt frame
我已经看了好几个月了,到目前为止这是我提出的最好的.
由于我们的应用程序以这种方式运行并且不会被重写,因此结构(在EDT之外呈现)不值得辩论.该应用程序具有布局模型和脚本模型,它们是集成的并且驱动渲染,因此渲染必须在AWT绘制模型之外执行.
我想要达到的是执行自定义渲染的最佳和可靠的方法.
以下SSCCE对我们来说效果很好.但是,在帧大小调整期间,它有两个缺点:
同样有用的是输入这是否是在EDT之外发生的自定义渲染路径的最佳方法.我尝试过最多,并做了相当广泛的研究.这种组合(后备缓冲图像,双缓冲策略)似乎效果最好.
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) { }
}
Run Code Online (Sandbox Code Playgroud)
下面是使用外部线程完成所有工作进行渲染的代码。它通过能够渲染实现该Renderable接口的任何内容来实现这一点。JFrame我已经用 Swing 和 AWT(和)对此进行了测试Frame,并且它没有闪烁。JRootPane请注意,如果您在 a 上实现并将该窗格设置为 的JFrame根窗格,它会闪烁。这与组件的缓冲方式有关,如果您想这样使用它,则可以修复它。
如果这仍然不是您想要的,请直接说,我会再试一次。这实际上很有趣,因为我已经有一段时间没有做过任何 Java GUI 工作了。
无论如何,给你:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Toolkit;
import javax.swing.JFrame;
public class SmoothResize extends Frame implements Renderable {
public static void main(String[] args) {
Toolkit.getDefaultToolkit().setDynamicLayout(true);
System.setProperty("sun.awt.noerasebackground", "true");
SmoothResize srtest = new SmoothResize();
RenderThread renderThread = new RenderThread(srtest);
renderThread.start();
srtest.setSize(100, 100);
srtest.setVisible(true);
}
public SmoothResize() {
}
public void addNotify() {
super.addNotify();
createBufferStrategy(2);
}
@Override
public Dimension getSize() {
return new Dimension(getWidth(), getHeight());
}
@Override
public Graphics acquireGraphics() {
return this.getGraphics();
}
}
class RenderThread extends Thread {
Renderable target;
Dimension last_size = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
public RenderThread(Renderable d) {
if (d == null) {
throw new NullPointerException("Drawable target cannot be null.");
}
target = d;
}
@Override
public void run() {
while (true) {
render(false);
}
}
private synchronized void render(boolean force) {
Dimension size;
do {
size = target.getSize();
if (size == null) {
return;
}
Graphics draw = target.acquireGraphics();
if (draw == null) {
return;
}
draw.setPaintMode();
int w = (int) (((double) (size.width)) / 2 + 0.5);
int h = (int) (((double) (size.height)) / 2 + 0.5);
draw.setColor(Color.YELLOW);
draw.fillRect(0, h, w, h);
draw.fillRect(w, 0, w, h);
draw.setColor(Color.BLACK);
draw.fillRect(0, 0, w, h);
draw.fillRect(w, h, w, h);
draw.dispose();
// Repeat the rendering if the target changed size
} while (!size.equals(target.getSize()));
}
}
interface Renderable {
public Graphics acquireGraphics();
public Dimension getSize();
}
Run Code Online (Sandbox Code Playgroud)