Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Swing需要createBufferStrategy(2)来正确绘制_Java_Swing_Jframe_Bufferstrategy - Fatal编程技术网

Java Swing需要createBufferStrategy(2)来正确绘制

Java Swing需要createBufferStrategy(2)来正确绘制,java,swing,jframe,bufferstrategy,Java,Swing,Jframe,Bufferstrategy,我有一些网格是画屏幕一个接一个。我使用箭头键将栅格作为一组移动。据说Swing在默认情况下是双缓冲的,因此我认为frame.createBufferStrategy(2)是一种不好的做法,但问题是当我不使用手动双缓冲时,网格未对齐,并且网格之间出现了一些孔。使用手动双缓冲解决了这个问题 我在实际程序中(不是在SSCCE中)也遇到一些图形问题(例如对话框的按钮显示不正确),因此我认为这可能是由于双缓冲的不正确实现造成的 以下是该程序的SSCCE,当未手动双缓冲时,会导致网格失准: package

我有一些网格是画屏幕一个接一个。我使用箭头键将栅格作为一组移动。据说Swing在默认情况下是双缓冲的,因此我认为
frame.createBufferStrategy(2)
是一种不好的做法,但问题是当我不使用手动双缓冲时,网格未对齐,并且网格之间出现了一些孔。使用手动双缓冲解决了这个问题

我在实际程序中(不是在SSCCE中)也遇到一些图形问题(例如对话框的按钮显示不正确),因此我认为这可能是由于双缓冲的不正确实现造成的

以下是该程序的SSCCE,当未手动双缓冲时,会导致网格失准:

package SSCCE;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LayoutManager;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferStrategy;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Main {
boolean manuallyDoubleBuffered = false; //change this

static Main main;

public final JFrame frame = new JFrame();
public final Keys keys = new Keys();
private JPanel panel;
private BufferStrategy bufferStrategy;

 

public static void main(String[] args) {
    main = new Main();
    main.initiate();
    // --START LOOP--
    Thread loop = new Thread(main.new Looper());
    loop.start();
}

public void initiate() {
    frameInit();
    keys.start();
}

private void frameInit() {
    frame.setSize(1200, 750);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
    setUpGUI();
    if (manuallyDoubleBuffered)
        frame.createBufferStrategy(2); // manual double buffering
    bufferStrategy = frame.getBufferStrategy();
}

private void setUpGUI() {
    panel = new JPanel() {
        @Override
        protected void paintComponent(Graphics g) {
            Graphics2D g2d = (Graphics2D) g;
            Main.main.rendering(g2d);
            super.paintComponent(g);
        }
    };

    LayoutManager layout = new FlowLayout();
    frame.getContentPane().setBackground(Color.black);
    panel.setLayout(layout);
    panel.setOpaque(false);//
    JButton but1 = new JButton("but1");
    panel.add(but1);
    frame.add(panel);
}

class Looper implements Runnable {
    @Override
    public void run() {
        Main.main.gameLoop();
    }
}

private void gameLoop() {
    // variables are declared at start
    while (true) {

        if (manuallyDoubleBuffered)
            paint(); // MANUAL double buffering
        else
            frame.repaint();// no manual double buffering

        update();

        try {
            Thread.sleep(1000 / 60);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}// loop end

private void update() {
    move();

}

private void rendering(Graphics2D g2d) {
    // // testing
    paintGrids(g2d);
}

private void move() {
    x += sx;
    y += sy;
}

int sx = 0; //speedX
int sy = 0; //speedY

//top left corner of the grid
int x = 0; 
int y = 0;

private void paintGrids(Graphics2D g) {
    for (int i = 0; i < 100; i++) {
        for (int t = 0; t < 100; t++) {
            g.setColor(Color.GRAY);
            g.fillRect(i * 50 + x, t * 50 + y, 50, 50);
            g.setColor(Color.BLACK);
            g.drawString(i + "," + t, i * 50 + x, t * 50 + y + 10);
        }
    }

}

public void paint() {
    // uses double buffering system.
    do {
        do {
            Graphics2D g2d = (Graphics2D) bufferStrategy.getDrawGraphics();
            g2d.fillRect(0, 0, frame.getWidth(), frame.getHeight());

            try {
                frame.paint(g2d);
            } catch (NullPointerException e) {
                e.printStackTrace();
            }
            g2d.dispose();
        } while (bufferStrategy.contentsRestored());
        bufferStrategy.show();
    } while (bufferStrategy.contentsLost());
}
}

class Keys implements KeyListener {// Trimmed down to shorten SSCCE
private final int leftKey = 37; // left b.
private final int rightKey = 39; // Right b.
private final int upKey = 38;// up k.
private final int downKey = 40;// down k.

public void start() {

    Main.main.frame.addKeyListener(this);
    Main.main.frame.setFocusable(true);
}

private void left() {
    Main.main.sx -= 10;
}

private void right() {
    Main.main.sx += 10;
}

private void up() {
    Main.main.sy -= 10;
}

private void down() {
    Main.main.sy += 10;
}

@Override
public void keyPressed(KeyEvent e) {
    // TODO Auto-generated method stub
    System.out.println(e.getKeyCode());
    switch (e.getKeyCode()) {
    case leftKey:
        left();
        break;
    case rightKey:
        right();
        break;
    case downKey:
        down();
        break;
    case upKey:
        up();
        break;
    }
}

@Override
public void keyReleased(KeyEvent arg0) {
    // TODO Auto-generated method stub

}

@Override
public void keyTyped(KeyEvent arg0) {
    // TODO Auto-generated method stub

}

}// END OF THE KEYS CLASS
封装SSCCE;
导入java.awt.Color;
导入java.awt.FlowLayout;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.LayoutManager;
导入java.awt.event.KeyEvent;
导入java.awt.event.KeyListener;
导入java.awt.image.BufferStrategy;
导入javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
公共班机{
boolean manuallyDoubleBuffered=false;//更改此值
静态主;
公共最终JFrame=新JFrame();
公共最终密钥=新密钥();
私人JPanel小组;
私有缓冲策略;
公共静态void main(字符串[]args){
main=新的main();
main.initiate();
//--启动循环--
线程循环=新线程(main.new Looper());
loop.start();
}
公共空间启动(){
frameInit();
keys.start();
}
私有void frameInit(){
框架设置尺寸(1200750);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
setUpGUI();
如果(手动双缓冲)
frame.createBufferStrategy(2);//手动双缓冲
bufferStrategy=frame.getBufferStrategy();
}
私有void setUpGUI(){
panel=newjpanel(){
@凌驾
受保护组件(图形g){
Graphics2D g2d=(Graphics2D)g;
Main.Main.rendering(g2d);
超级组件(g);
}
};
LayoutManager布局=新的FlowLayout();
frame.getContentPane().setBackground(颜色:黑色);
面板设置布局(布局);
面板。设置不透明(假)//
JButton but1=新JButton(“but1”);
面板。添加(但不包括1);
框架。添加(面板);
}
类循环器实现可运行{
@凌驾
公开募捐{
Main.Main.gameLoop();
}
}
私有void gameLoop(){
//变量在开始时声明
while(true){
如果(手动双缓冲)
paint();//手动双缓冲
其他的
frame.repaint();//无需手动双缓冲
更新();
试一试{
睡眠(1000/60);
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
}//环端
私有void更新(){
move();
}
专用空心渲染(Graphics2D g2d){
////测试
油漆网格(g2d);
}
私人空位移动(){
x+=sx;
y+=sy;
}
int sx=0;//speedX
int sy=0;//s
//网格的左上角
int x=0;
int y=0;
专用空心油漆格线(图形2D g){
对于(int i=0;i<100;i++){
对于(int t=0;t<100;t++){
g、 setColor(颜色为灰色);
g、 fillRect(i*50+x,t*50+y,50,50);
g、 设置颜色(颜色为黑色);
g、 抽绳(i+“,”+t,i*50+x,t*50+y+10);
}
}
}
公共空间涂料(){
//采用双缓冲系统。
做{
做{
Graphics2D g2d=(Graphics2D)bufferStrategy.getDrawGraphics();
g2d.fillRect(0,0,frame.getWidth(),frame.getHeight());
试一试{
框架涂料(g2d);
}捕获(NullPointerException e){
e、 printStackTrace();
}
g2d.dispose();
}while(bufferStrategy.contentsrestered());
bufferStrategy.show();
}while(bufferStrategy.contentsLost());
}
}
类键实现了KeyListener{//,它被修剪以缩短SSCE
private final int leftKey=37;//左b。
私有final int rightKey=39;//右b。
private final int upKey=38;//up k。
private final int downKey=40;//向下k。
公开作废开始(){
Main.Main.frame.addKeyListener(这个);
Main.Main.frame.setFocusable(true);
}
私人空间左(){
Main.Main.sx-=10;
}
私人无效权(){
Main.Main.sx+=10;
}
私人作废{
Main.Main.sy-=10;
}
私人大厦{
Main.Main.sy+=10;
}
@凌驾
按下公共无效键(按键事件e){
//TODO自动生成的方法存根
System.out.println(e.getKeyCode());
开关(如getKeyCode()){
大小写左键:
左();
打破
案例右键:
对();
打破
案例主键:
向下();
打破
案例向上键:
up();
打破
}
}
@凌驾
公共无效密钥已释放(KeyEvent arg0){
//TODO自动生成的方法存根
}
@凌驾
public void keyTyped(KeyEvent arg0){
//TODO自动生成的方法存根
}
}//密钥类的结束
Oracle swing教程没有解释在游戏循环中的用法。最好的方法是什么?我做错什么了吗

如果视觉错误没有在其他计算机上重现,我将上传一个屏幕截图: 黑色线条是由矩形对齐错误引起的。当手动双缓冲设置为true时,它们不存在

提前谢谢

编辑:我忘了提到网格移动时会出现黑线

我还发现,手动双缓冲大大降低了性能

编辑2:我已经解决了这个问题,并将其作为答案发布,但请随意评论我的代码。主类(除了gameLoop)与我在程序中使用的实际主类相似。

我看不到任何主类
public static void main(String[] args) {
    main = new Main();

    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            main.initiate();
        }           
    });

    // --START LOOP--
    Thread loop = new Thread(main.new Looper());
    loop.start();
}
int x = this.x;
int y = this.y;