Java 画布双缓冲图形不工作
我尝试为画布制作双缓冲图形,但它总是在渲染后立即消失,有时甚至无法渲染,下面是代码:Java 画布双缓冲图形不工作,java,graphics,awt,double-buffering,Java,Graphics,Awt,Double Buffering,我尝试为画布制作双缓冲图形,但它总是在渲染后立即消失,有时甚至无法渲染,下面是代码: package initilizer; import java.awt.AWTException; import java.awt.Canvas; import java.awt.Color; import java.awt.Cursor; import java.awt.Graphics; import java.awt.Image; import java.awt.MouseInfo; import jav
package initilizer;
import java.awt.AWTException;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import input.Keyboard;
public class Main extends Canvas{
static int width = 800;
static int height = 600;
int cx = width/2;
int cy = height/2;
boolean initilized = false;
double FOV = 0.5 * Math.PI;
Camera cam = new Camera(1.0, 5.0, 3.0);
Camera cam1 = new Camera(10.0, 50.0, 30.0);
long lastFpsCheck = System.currentTimeMillis();
public static JFrame frame = new JFrame("3D Engine");
Robot robot;
static Keyboard keyboard = new Keyboard();
Image img;
public static void main(String[] args) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Canvas canvas = new Main();
canvas.setSize(width, height);
canvas.addKeyListener(keyboard);
canvas.setFocusable(true);
canvas.setBackground(Color.black);
frame.add(canvas);
frame.pack();
frame.setVisible(true);
BufferedImage cursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
// Create a new blank cursor.
Cursor blankCursor = Toolkit.getDefaultToolkit().createCustomCursor(
cursorImg, new Point(0, 0), "blank cursor");
// Set the blank cursor to the JFrame.
canvas.setCursor(blankCursor);
}
void init() {
try {
robot = new Robot();
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
double[] rotate2D(double[] pos,double[] rot) {
double x = pos[0];
double y = pos[1];
double s = rot[0];
double c = rot[1];
double[] result = {(x * c) - (y * s), (y * c) + (x * s)};
return result;
}
public void paint(Graphics MainGraphics) {
Point startMousePos = MouseInfo.getPointerInfo().getLocation();
double startMouseX = startMousePos.getX();
double startMouseY = startMousePos.getY();
if(img == null)
{
img = createImage(width, height);
}
Graphics g = img.getGraphics();;
// First run initialization
if (initilized == false) {
initilized = true;
init();
}
// Storing start time for FPS Counting
long startTime = System.currentTimeMillis();
// Clearing Last Frame
//g.clearRect(0, 0, width, height);
// Drawing Crosshair
g.setColor(Color.white);
g.fillRect(cx - 8, cy - 1, 16, 2);
g.fillRect(cx - 1, cy - 8, 2, 16);
// Drawing Debugger Menu
g.drawString("HI WASSUp", 0, 16);
g.dispose();
if (frame.isFocused() == true) {
robot.mouseMove(cx, cy);
Point endMousePos = MouseInfo.getPointerInfo().getLocation();
double endMouseX = endMousePos.getX();
double endMouseY = endMousePos.getY();
double[] rel = {startMouseX - endMouseX, startMouseY - endMouseY};
cam.mouseMotion(rel);
}
// Limiting FPS
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Calculating FPS
long endTime = System.currentTimeMillis();
double delta_time = (endTime - startTime);
if ((lastFpsCheck + 1000) < endTime) {
lastFpsCheck = endTime;
frame.setTitle("3D Engine - FPS: " + (int) (1000/delta_time));
}
// Controlling camera movement
if (keyboard.getW() == true) {
cam.update(delta_time, "W");
}
if (keyboard.getA() == true) {
cam.update(delta_time, "A");
}
if (keyboard.getS() == true) {
cam.update(delta_time, "S");
}
if (keyboard.getD() == true) {
cam.update(delta_time, "D");
}
if (keyboard.getE() == true) {
cam.update(delta_time, "E");
}
if (keyboard.getQ() == true) {
cam.update(delta_time, "Q");
}
// Draw rendered frame
MainGraphics.drawImage(img, 0,0, null);
// Draw next frame
repaint();
}
}
包初始化器;
导入java.awt.AWTException;
导入java.awt.Canvas;
导入java.awt.Color;
导入java.awt.Cursor;
导入java.awt.Graphics;
导入java.awt.Image;
导入java.awt.MouseInfo;
导入java.awt.Point;
导入java.awt.Robot;
导入java.awt.Toolkit;
导入java.awt.image.buffereImage;
导入javax.swing.JFrame;
输入。键盘;
公共类Main扩展画布{
静态整数宽度=800;
静态内部高度=600;
int cx=宽度/2;
int cy=高度/2;
布尔初始化=假;
双视场=0.5*Math.PI;
摄像头=新摄像头(1.0、5.0、3.0);
摄像头cam1=新摄像头(10.0,50.0,30.0);
long lastFpsCheck=System.currentTimeMillis();
公共静态JFrame=新JFrame(“3D引擎”);
机器人;
静态键盘=新键盘();
图像img;
公共静态void main(字符串[]args){
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Canvas Canvas=newmain();
画布。设置大小(宽度、高度);
addKeyListener(键盘);
canvas.setFocusable(true);
帆布背景(颜色:黑色);
frame.add(画布);
frame.pack();
frame.setVisible(true);
BuffereImage cursorImg=新的BuffereImage(16,16,BuffereImage.TYPE_INT_ARGB);
//创建一个新的空白光标。
Cursor blankCursor=Toolkit.getDefaultToolkit().createCustomCursor(
光标,新点(0,0),“空白光标”);
/将空白光标设置为JFrror。
canvas.setCursor(blankCursor);
}
void init(){
试一试{
机器人=新机器人();
}捕获(awtexe){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
双[]旋转2D(双[]位置,双[]旋转){
双x=位置[0];
双y=位置[1];
双s=rot[0];
双c=旋转[1];
双[]结果={(x*c)-(y*s),(y*c)+(x*s)};
返回结果;
}
公共空白绘制(图形主图形){
Point startMousePos=MouseInfo.getPointerInfo().getLocation();
double startMouseX=startMousePos.getX();
double startMouseY=startMousePos.getY();
如果(img==null)
{
img=createImage(宽度、高度);
}
Graphics g=img.getGraphics();;
//首次运行初始化
if(initilized==false){
initilized=true;
init();
}
//存储FPS计数的开始时间
long startTime=System.currentTimeMillis();
//清除最后一帧
//g、 clearRect(0,0,宽度,高度);
//画十字线
g、 setColor(Color.white);
g、 fillRect(cx-8,cy-1,16,2);
g、 fillRect(cx-1,cy-8,2,16);
//图形调试器菜单
g、 抽绳(“HI WASSUp”,0,16);
g、 处置();
if(frame.isFocused()==true){
mouseMove(cx,cy);
Point endMousePos=MouseInfo.getPointerInfo().getLocation();
double-endMouseX=endMousePos.getX();
double-endMouseY=endMousePos.getY();
double[]rel={startMouseX-endMouseX,startMouseY-endMouseY};
mouseMotion(rel);
}
//极限FPS
试一试{
睡眠(1000);
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
//计算FPS
long-endTime=System.currentTimeMillis();
双增量时间=(结束时间-开始时间);
如果((lastFpsCheck+1000)<结束时间){
lastFpsCheck=结束时间;
frame.setTitle(“3D引擎-FPS:”+(int)(1000/delta_时间));
}
//控制摄像机运动
if(keyboard.getW()==true){
凸轮更新(增量时间,“W”);
}
if(keyboard.getA()==true){
凸轮更新(增量时间,“A”);
}
if(keyboard.get()==true){
凸轮更新(增量时间,“S”);
}
if(keyboard.getD()==true){
凸轮更新(增量时间,“D”);
}
if(keyboard.getE()==true){
凸轮更新(增量时间,“E”);
}
if(keyboard.getQ()==true){
凸轮更新(增量时间,“Q”);
}
//绘制渲染帧
MainGraphics.drawImage(img,0,0,空);
//画下一帧
重新油漆();
}
}
我最近发布了一个关于这段代码的问题,如果你愿意,你可以查看上一篇文章中的键盘java,但是请帮助我,我对java编程还不熟悉(我仍然有一些编程经验),谢谢你,你的问题的答案很复杂
JPanel
(或JComponent
)是双缓冲的java.awt.Canvas
的唯一真正原因是,如果希望完全控制绘制过程- 不要做
在Thread.sleep(1000)
方法中,在paint
方法返回之前,不会渲染任何内容。您希望将“更新过程”与“绘制过程”分开。绘画只靠绘画。你所有的决策都应该作为你的“更新通行证”的一部分来完成paint
import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.time.Duration; import java.time.Instant; import java.util.HashSet; import java.util.Set; import java.util.StringJoiner; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.KeyStroke; import javax.swing.Timer; public class Test { public static void main(String[] args) { new Test(); } public Test() { EventQueue.invokeLater(new Runnable() { @Override public void run() { JFrame frame = new JFrame(); Main main = new Main(); frame.add(main); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); main.start(); } }); } // Decouple the input from the implementation enum Input { UP, DOWN, LEFT, RIGHT } public class Main extends JPanel { boolean initilized = false; double FOV = 0.5 * Math.PI; private Instant lastFpsCheck = Instant.now(); private Point mousePosition; private Timer timer; private Set<Input> input = new HashSet<>(); public Main() { MouseAdapter mouseHandler = new MouseAdapter() { @Override public void mouseMoved(MouseEvent e) { // This is within the components coordinate space mousePosition = e.getPoint(); } @Override public void mouseEntered(MouseEvent e) { mousePosition = e.getPoint(); } @Override public void mouseExited(MouseEvent e) { mousePosition = null; } }; addMouseMotionListener(mouseHandler); addMouseListener(mouseHandler); InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW); ActionMap actionMap = getActionMap(); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false), "Pressed.up"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, true), "Released.up"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, false), "Pressed.down"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, true), "Released.down"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, false), "Pressed.left"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, true), "Released.left"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, false), "Pressed.right"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, true), "Released.right"); actionMap.put("Pressed.up", new InputAction(input, Input.UP, true)); actionMap.put("Released.up", new InputAction(input, Input.UP, false)); actionMap.put("Pressed.down", new InputAction(input, Input.DOWN, true)); actionMap.put("Released.down", new InputAction(input, Input.DOWN, false)); actionMap.put("Pressed.left", new InputAction(input, Input.LEFT, true)); actionMap.put("Released.left", new InputAction(input, Input.LEFT, false)); actionMap.put("Pressed.right", new InputAction(input, Input.RIGHT, true)); actionMap.put("Released.right", new InputAction(input, Input.RIGHT, false)); timer = new Timer(15, new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { update(); } }); } public void start() { startTime = Instant.now(); timer.start(); } public void stop() { timer.stop(); } // The start time of a given cycle private Instant startTime; // The estimated number of frames per second private double fps = 0; // The number of acutal updates performed // within a given cycle private int updates = 0; protected void update() { if (startTime == null) { startTime = Instant.now(); } if (input.contains(Input.UP)) { //cam.update(delta_time, "W"); } if (input.contains(Input.LEFT)) { //cam.update(delta_time, "A"); } if (input.contains(Input.DOWN)) { //cam.update(delta_time, "S"); } if (input.contains(Input.RIGHT)) { //cam.update(delta_time, "D"); } // Don't know what these do, so you will need to devices // your own action //if (input.contains(Input.UP)) { //cam.update(delta_time, "E"); //} //if (input.contains(Input.UP)) { //cam.update(delta_time, "Q"); //} Instant endTime = Instant.now(); Duration deltaTime = Duration.between(startTime, endTime); if (lastFpsCheck.plusSeconds(1).isBefore(endTime)) { System.out.println(deltaTime.toMillis()); lastFpsCheck = endTime; fps = updates; updates = 0; startTime = Instant.now(); } updates++; repaint(); } @Override public Dimension getPreferredSize() { return new Dimension(800, 600); } double[] rotate2D(double[] pos, double[] rot) { double x = pos[0]; double y = pos[1]; double s = rot[0]; double c = rot[1]; double[] result = {(x * c) - (y * s), (y * c) + (x * s)}; return result; } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); //Point startMousePos = MouseInfo.getPointerInfo().getLocation(); //double startMouseX = startMousePos.getX(); //double startMouseY = startMousePos.getY(); Graphics2D g2d = (Graphics2D) g.create(); // Drawing Debugger Menu g2d.drawString("HI WASSUp", 0, 20); if (mousePosition != null) { g2d.drawString(mousePosition.x + "x" + mousePosition.y, 0, 40); // Your old code is broken, because MouseInfo.getPointerInfo // doesn't give you the position of the mouse from within // the components coordinate space, but in the screen space // instead //robot.mouseMove(cx, cy); //Point endMousePos = MouseInfo.getPointerInfo().getLocation(); //double endMouseX = endMousePos.getX(); //double endMouseY = endMousePos.getY(); //double[] rel = {startMouseX - endMouseX, startMouseY - endMouseY}; //cam.mouseMotion(rel); } g2d.drawString(Double.toString(fps), 0, 60); StringJoiner sj = new StringJoiner(", "); for (Input item : input) { switch (item) { case DOWN: sj.add("down"); break; case UP: sj.add("up"); break; case LEFT: sj.add("left"); break; case RIGHT: sj.add("right"); break; } } g2d.drawString(sj.toString(), 0, 80); g2d.dispose(); } public class InputAction extends AbstractAction { private final Set<Input> input; private final Input direction; private final boolean add; public InputAction(Set<Input> input, Input direction, boolean add) { this.input = input; this.direction = direction; this.add = add; } @Override public void actionPerformed(ActionEvent evt) { if (add) { input.add(direction); } else { input.remove(direction); } } } } }