Java 使用createBufferStrategy()的正确方法是什么?
即使在使用JavaSwing一年多之后,它对我来说仍然是一种魔力。如何正确使用缓冲策略,特别是方法Java 使用createBufferStrategy()的正确方法是什么?,java,swing,bufferstrategy,Java,Swing,Bufferstrategy,即使在使用JavaSwing一年多之后,它对我来说仍然是一种魔力。如何正确使用缓冲策略,特别是方法createBufferSrategy() 我想有一个JFrame和一个画布,可以添加到其中,然后进行绘制。我还希望能够调整画布的大小(setSize())。每次我调整画布的大小时,我的BufferStrategy似乎都被破坏了,或者说变得无用,因为在BufferStrategy上使用show()。另外,createBufferStrategy()有一种奇怪的非确定性行为,我不知道如何正确地同步它
createBufferSrategy()
我想有一个JFrame和一个画布,可以添加到其中,然后进行绘制。我还希望能够调整画布的大小(setSize()
)。每次我调整画布的大小时,我的BufferStrategy
似乎都被破坏了,或者说变得无用,因为在BufferStrategy
上使用show()。另外,createBufferStrategy()
有一种奇怪的非确定性行为,我不知道如何正确地同步它
我的意思是:
public class MyFrame extends JFrame {
MyCanvas canvas;
int i = 0;
public MyFrame() {
setUndecorated(false);
setVisible(true);
setSize(1100, 800);
setLocation(100, 100);
setDefaultCloseOperation(EXIT_ON_CLOSE);
canvas = new MyCanvas();
add(canvas);
canvas.makeBufferStrat();
}
@Override
public void repaint() {
super.repaint();
canvas.repaint();
//the bigger threshold's value, the more likely it is that the BufferStrategy works correctly
int threshold = 2;
if (i < threshold) {
i++;
canvas.makeBufferStrat();
}
}
}
我只是从main方法中的while(true)循环调用MyFrame
的repaint()
方法。
当threshold
很小时(即2),bufferStrat.show()
在大约70%的情况下没有任何作用-启动程序时JFrame只是保持灰色。剩下的30%是它应该如何绘制矩形的。如果我做threshold=200代码>,在我执行程序的时间里,绘画成功率接近100%。Javadoc说,createBufferStrategy()
可能需要一段时间,所以我认为这就是问题所在。但是,如何正确地同步和使用它?很明显,我做错了什么。我无法想象它是怎么被使用的
有人有一个最简单的工作示例吗?创建缓冲策略的方法是“好的”,您可以看看有一个简洁的小示例的
你使用它的方式值得怀疑。使用BufferStrategy
的主要原因是,您希望从Swing的绘制算法(被动)中控制绘制过程(主动绘制)
但是,你似乎试图两者兼而有之,这就是为什么它会引起你的问题。相反,您应该有一个“main”循环,负责决定缓冲区应该绘制什么以及何时绘制,例如
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferStrategy;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
TestPane testPane = new TestPane();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(testPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
// The component needs to be attached to displayed window before
// the buffer can be created
testPane.startPainting();
}
});
}
public class TestPane extends Canvas {
private AtomicBoolean painting = new AtomicBoolean(true);
private PaintCycle paintCycle;
private Rectangle clickBounds;
public TestPane() {
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (clickBounds != null && clickBounds.contains(e.getPoint())) {
painting.set(false);
}
}
});
}
public void startPainting() {
if (paintCycle == null) {
createBufferStrategy(2);
painting.set(true);
paintCycle = new PaintCycle();
Thread t = new Thread(paintCycle);
t.setDaemon(true);
t.start();
}
}
public void stopPainting() {
if (paintCycle != null) {
painting.set(false);
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public class PaintCycle implements Runnable {
private BufferStrategy strategy;
private int xDelta = 2;
private int yDelta = 2;
@Override
public void run() {
System.out.println("Painting has started");
int x = (int) (Math.random() * (getWidth() - 40));
int y = (int) (Math.random() * (getHeight() - 40));
do {
xDelta = (int) (Math.random() * 8) - 4;
} while (xDelta == 0);
do {
yDelta = (int) (Math.random() * 8) - 4;
} while (yDelta == 0);
clickBounds = new Rectangle(x, y, 40, 40);
strategy = getBufferStrategy();
while (painting.get()) {
// Update the state of the model...
update();
// Paint the state of the model...
paint();
try {
// What ever calculations you want to use to maintain the framerate...
Thread.sleep(40);
} catch (InterruptedException ex) {
}
}
System.out.println("Painting has stopped");
}
protected void update() {
int x = clickBounds.x + xDelta;
int y = clickBounds.y + yDelta;
if (x + 40 > getWidth()) {
x = getWidth() - 40;
xDelta *= -1;
} else if (x < 0) {
x = 0;
xDelta *= -1;
}
if (y + 40 > getHeight()) {
y = getHeight() - 40;
yDelta *= -1;
} else if (y < 0) {
y = 0;
yDelta *= -1;
}
clickBounds.setLocation(x, y);
}
protected void paint() {
// 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 {
// Get a new graphics context every time through the loop
// to make sure the strategy is validated
Graphics2D graphics = (Graphics2D) strategy.getDrawGraphics();
// Render to graphics
// ...
graphics.setColor(Color.BLUE);
graphics.fillRect(0, 0, getWidth(), getHeight());
graphics.setColor(Color.RED);
graphics.fill(clickBounds);
// Dispose the graphics
graphics.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());
}
}
}
}
导入java.awt.Canvas;
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.EventQueue;
导入java.awt.Graphics2D;
导入java.awt.Rectangle;
导入java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入java.awt.image.BufferStrategy;
导入java.util.concurrent.AtomicBoolean;
导入java.util.logging.Level;
导入java.util.logging.Logger;
导入javax.swing.JFrame;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
公开课考试{
公共静态void main(字符串[]args){
新测试();
}
公开考试(){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
例如printStackTrace();
}
TestPane TestPane=新建TestPane();
JFrame=新JFrame(“测试”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(testPane);
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
//组件需要先附着到显示的窗口,然后才能显示
//可以创建缓冲区
testPane.startPainting();
}
});
}
公共类TestPane扩展了画布{
私有原子布尔绘制=新原子布尔(true);
私人画册画册;
私有矩形单击边界;
公共测试窗格(){
addMouseListener(新的MouseAdapter(){
@凌驾
公共无效mouseClicked(MouseEvent e){
if(clickBounds!=null&&clickBounds.contains(e.getPoint())){
绘画。设置(假);
}
}
});
}
公共无效开始打印(){
if(paintCycle==null){
创新战略(2);
绘画。设置(真实);
paintCycle=新的paintCycle();
螺纹t=新螺纹(喷漆周期);
t、 setDaemon(true);
t、 start();
}
}
公众休憩用漆(){
if(paintCycle!=null){
绘画。设置(假);
}
}
@凌驾
公共维度getPreferredSize(){
返回新维度(200200);
}
公共类PaintCycle实现了Runnable{
私人缓冲战略;
私有int xDelta=2;
私人int yDelta=2;
@凌驾
公开募捐{
System.out.println(“绘制已开始”);
intx=(int)(Math.random()*(getWidth()-40));
int y=(int)(Math.random()*(getHeight()-40));
做{
xDelta=(int)(Math.random()*8)-4;
}而(xDelta==0);
做{
yDelta=(int)(Math.random()*8)-4;
}而(yDelta==0);
单击边界=新矩形(x、y、40、40);
strategy=getBufferStrategy();
while(绘制.get()){
//更新模型的状态。。。
更新();
//绘制模型的状态。。。
油漆();
试一试{
//您希望使用什么计算来保持帧速率。。。
睡眠(40);
}赶上
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferStrategy;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
TestPane testPane = new TestPane();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(testPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
// The component needs to be attached to displayed window before
// the buffer can be created
testPane.startPainting();
}
});
}
public class TestPane extends Canvas {
private AtomicBoolean painting = new AtomicBoolean(true);
private PaintCycle paintCycle;
private Rectangle clickBounds;
public TestPane() {
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (clickBounds != null && clickBounds.contains(e.getPoint())) {
painting.set(false);
}
}
});
}
public void startPainting() {
if (paintCycle == null) {
createBufferStrategy(2);
painting.set(true);
paintCycle = new PaintCycle();
Thread t = new Thread(paintCycle);
t.setDaemon(true);
t.start();
}
}
public void stopPainting() {
if (paintCycle != null) {
painting.set(false);
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public class PaintCycle implements Runnable {
private BufferStrategy strategy;
private int xDelta = 2;
private int yDelta = 2;
@Override
public void run() {
System.out.println("Painting has started");
int x = (int) (Math.random() * (getWidth() - 40));
int y = (int) (Math.random() * (getHeight() - 40));
do {
xDelta = (int) (Math.random() * 8) - 4;
} while (xDelta == 0);
do {
yDelta = (int) (Math.random() * 8) - 4;
} while (yDelta == 0);
clickBounds = new Rectangle(x, y, 40, 40);
strategy = getBufferStrategy();
while (painting.get()) {
// Update the state of the model...
update();
// Paint the state of the model...
paint();
try {
// What ever calculations you want to use to maintain the framerate...
Thread.sleep(40);
} catch (InterruptedException ex) {
}
}
System.out.println("Painting has stopped");
}
protected void update() {
int x = clickBounds.x + xDelta;
int y = clickBounds.y + yDelta;
if (x + 40 > getWidth()) {
x = getWidth() - 40;
xDelta *= -1;
} else if (x < 0) {
x = 0;
xDelta *= -1;
}
if (y + 40 > getHeight()) {
y = getHeight() - 40;
yDelta *= -1;
} else if (y < 0) {
y = 0;
yDelta *= -1;
}
clickBounds.setLocation(x, y);
}
protected void paint() {
// 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 {
// Get a new graphics context every time through the loop
// to make sure the strategy is validated
Graphics2D graphics = (Graphics2D) strategy.getDrawGraphics();
// Render to graphics
// ...
graphics.setColor(Color.BLUE);
graphics.fillRect(0, 0, getWidth(), getHeight());
graphics.setColor(Color.RED);
graphics.fill(clickBounds);
// Dispose the graphics
graphics.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());
}
}
}
}