【问题标题】:Black screen when initializing JFrame window初始化 JFrame 窗口时出现黑屏
【发布时间】:2019-09-10 18:55:56
【问题描述】:

到现在为止,我觉得我已经尝试了一切。我在尝试着 运行这个简单的俄罗斯方块游戏,但即使我没有 那里的例外情况,它仍然将 JFrame 窗口显示为黑色,并带有一个小 左上角的白色矩形。

这是我已经尝试过的:

  1. 玩弄 f.setVisible(true);正如许多人所建议的那样。
  2. 检查可能的无限循环(将 =+1 更改为 +=1)
  3. 还尝试包括://f.add(panel); //f.pack();

我的代码:

package fritol.sevela.java;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Collections;

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




public class Tetris002 extends JPanel {        


    /**
     * 
     */
    private static final long serialVersionUID = 1L;


    /**
     * 
     */



    private final Point[][][] myPoint= {
            {

                {new Point(0,1),new Point(1,1),new Point(2,1),new Point(3,1)}, 
                {new Point(1,0),new Point(1,1),new Point(1,2),new Point(1,3)}, 
                {new Point(0,1),new Point(1,1),new Point(2,1),new Point(3,1)}, 
                {new Point(1,0),new Point(1,1),new Point(1,2),new Point(1,3)}, 
            },  



            {

                {new Point(0,1),new Point(1,1),new Point(2,1),new Point(2,0)}, 
                {new Point(1,0),new Point(1,1),new Point(1,2),new Point(2,2)}, 
                {new Point(0,1),new Point(1,1),new Point(2,1),new Point(0,1)}, 
                {new Point(1,0),new Point(1,1),new Point(1,2),new Point(0,3)}, 
            },  


            {

                {new Point(0,1),new Point(1,1),new Point(2,1),new Point(2,0)}, 
                {new Point(1,0),new Point(1,1),new Point(1,2),new Point(2,2)}, 
                {new Point(0,1),new Point(1,1),new Point(2,1),new Point(0,0)}, 
                {new Point(1,0),new Point(1,1),new Point(1,2),new Point(2,0)}, 
            },  

            {

                {new Point(0,0),new Point(0,1),new Point(1,0),new Point(1,1)}, 
                {new Point(0,0),new Point(0,1),new Point(1,0),new Point(1,1)}, 
                {new Point(0,0),new Point(0,1),new Point(1,0),new Point(1,1)}, 
                {new Point(0,0),new Point(0,1),new Point(1,0),new Point(1,1)}, 
            },  

    };  


    //Defining COLOURS
    private final Color[] myColor= {Color.CYAN, Color.magenta,Color.orange,Color.yellow,Color.black,Color.pink,Color.red};


    private Point pt;
    private int currentPiece;
    private int rotation;
    private ArrayList<Integer> nextPiece=new ArrayList<Integer>();
    private long score;
    private Color[][] well;



    private void init() {
            well=new Color[12][24];   
            for(int i=0; i<12;i++) {  
                for(int j=0;j<23;j++) { 
                    if(i==0||i==11||i==22) {
                        well[i][j]=Color.pink;
                    }else{
                        well[i][j]=Color.black; 
                    }                               

                }
            }

            newPiece();   
        }   


    public void newPiece() {
        pt=new Point(5,2);
        rotation=0;
        if(nextPiece.isEmpty()) {   
            Collections.addAll(nextPiece, 0,1,2,3);   
            Collections.shuffle(nextPiece);  
        }
    }

    rotation.
    private boolean collidesAt(int x, int y, int rotation) {

        for(Point p: myPoint[currentPiece][rotation]) {
            if(well[p.x+x][p.y+y]!=Color.black) {
                return true;

            }

        }
        return false;
    }

    private void rotate(int i) {    
    int newRotation=(rotation+i)%4;
    if(newRotation<0) {
        newRotation=3;

        }

    if(!collidesAt(pt.x,pt.y, newRotation)){
        rotation=newRotation;

    }
    repaint(); //Some repaint function?

    }   

            //move and move only??
    public void move(int i) {
        if(!collidesAt(pt.x,pt.y,rotation)) {
        pt.x+=i;    
        }

        repaint();

    }
    public void drop() {           
        if(!collidesAt(pt.x,pt.y,rotation)) {
        pt.y+=1;
        }else {
            fixToWell();
        }
        repaint();
        }


    public void  fixToWell() {
        for(Point p: myPoint[currentPiece][rotation]) {
        well[pt.x+p.x]  [pt.y+p.y]=myColor[currentPiece];

        }
        clearRows();
        newPiece();

    }

    public void deleteRow(int row) {         
        for(int j=row-1;j>0;j--) {
            for (int i=1; i<11;i++){
                well[i][j+1]=well[i][j];

            }
        }
    }

    //Now we will create Row

    public void clearRows() {
        boolean gap;
        int numClear=0;
        for(int j=21; j>0; j--) {
            gap=false;
            for(int i=1;i<11;i++) {
                if(well[i][j]==Color.black) {
                gap=true;
                    break;

                }
            }       
        if(!gap) {
            deleteRow(numClear);
            j+=1;
            numClear+=1;    
        }
        }
        switch(numClear) {            //score stuff
            case 1:
                score+=100;
                break;

            case 2:
                score+=300;
                break;

            case 3:
                score+=500;
                break;  

            case 4:
                score+=800;
                break;
            }   


        } //now we provide function to draw the piece //<>[]{}

        private void drawPiece(Graphics g) {
            g.setColor(myColor[currentPiece]);
            for(Point p:myPoint[currentPiece][rotation]) {
            g.fillRect((p.x+pt.x)*26,(pt.y+p.y)*26,25,25);

            }       
        }

        public void paintComponent(Graphics g) {    
            g.fillRect(0, 0, 26*12, 26*23);
            for(int i=0; i<23;i++) {
            for (int j=0;j<23;j++)  {
                g.setColor(well[i][j]);
                g.fillRect(26*i,26*j, 25,25);

                }   
            }   
            g.setColor(Color.WHITE);
            g.drawString("Score:"+score, 19*12, 25);        
            drawPiece(g);

        }


    public static void main(String[] args) {



        JFrame f=new JFrame("Tetris002");         
        //JPanel panel=new JPanel(); //Added by me
        //f.setContentPane(panel);  //added by me
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(12*26+10, 26*23+25);
        //f.add(panel);
        //f.pack();
        f.setVisible(true);


        final Tetris002 game=new Tetris002();  


        game.init();
        f.add(game);



        //Now Controls and Keys
        f.addKeyListener(new KeyListener() {

        @Override
        public void keyTyped(KeyEvent e) { 

        }

        public void keyReleased(KeyEvent e) { 



        }

        public void keyPressed(KeyEvent e) { 
            switch(e.getKeyCode()) {
            case KeyEvent.VK_UP:
                game.rotate(-1);
                break;

            case KeyEvent.VK_DOWN:
                game.rotate(+1);
                break;      


            case KeyEvent.VK_LEFT:
                game.move(-1);
                break;  

            //case KeyEvent.VK_RIGHT:        
                //game.move(+1);
                //break;

            case KeyEvent.VK_SPACE:
                game.drop();
                game.score+=1;

                break;

                }
            }
    });
    new Thread() {
        public void run() {
            while(true) {
                try {
                    Thread.sleep(1000); 

            } catch (InterruptedException e) {

                e.printStackTrace();

            }
            game.drop();


            }
        }

        }.start();


        }

}

【问题讨论】:

  • 使用您发布的代码,我没有看到与您说的相同的错误。我在paintComponent 中遇到了一个异常,因为i 最多为24,而数组只有12 个项目长。但如果越界异常得到修复,游戏就会开始(大部分)正确运行。

标签: java swing jframe


【解决方案1】:

您是否在控制台中看到任何可能的错误?因为当我运行您的代码时,我在这一行(在paintComponent 方法内)遇到了ArrayIndexOutOfBounds 异常:g.setColor(well[i][j]);。你的外循环是for (int i = 0; i &lt; 23; i++)well 数组是new Color[12][24]。难怪它为什么会发生。将循环更改为for (int i = 0; i &lt; 12; i++) 将使框架可见。

不过有一些注意事项。

  1. 所有 Swing 应用程序都必须在自己的线程上运行,称为 EDT(Event-Dispatch-Thread)。在您的main 中调用SwingUtilities#invokeLater 并让应用程序在那里运行。

    SwingUtilities.invokeLater(()->{
        JFrame f = new JFrame("Tetris002");
        ....
    });
    
  2. 不要创建new Thread,而是查看how can i pause/sleep/wait in a java swing app. 使用javax.swing.Timer 看起来更好(从代码的角度来看),并且它是为这种情况创建的,因为任务将在 EDT 中运行。几句话,糟糕的(看起来像代码的)Thread 部分变成了:

    new Timer(1000, e -> {
        game.drop();
    }).start();
    
  3. 当您@Override paintComponent 时,请始终致电super.paintComponent(g)。让组件“正常”绘制,然后做你的事情:


@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    //My custom painting
}

【讨论】:

  • 这真的很有帮助,谢谢你的详细建议!改变外循环就可以了,我只需要每次都把它放在全屏上,这样它就可以开始工作了。不过,我会仔细阅读您的其他建议,看看效果如何+我如何从中学习。
【解决方案2】:

问题是函数paintComponent。文你很好地为数组赋值。你要越界了。在遍历数组时,我建议使用 array.length 函数而不是手动输入其长度。无论如何,如果你改变你的功能,它应该可以工作。

public void paintComponent(Graphics g) {
    g.fillRect(0, 0, 26 * 12, 26 * 23);
    for (int i = 0; i < well.length; i++) {
        for (int j = 0; j < well[i].length; j++) {
            g.setColor(well[i][j]);
            g.fillRect(26 * i, 26 * j, 25, 25);
        }
    }
    g.setColor(Color.WHITE);
    g.drawString("Score:" + score, 19 * 12, 25);
    drawPiece(g);
}

【讨论】:

  • 嗯,这似乎没有帮助,仍然需要手动调整大小。我也注意到我的形状不是随机的,只有 L 形不断下降。
  • @MarekŠevela 我只修复了indexoutofboundexception。这相当于将 12 放在外循环中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-05
  • 1970-01-01
  • 2012-12-18
  • 1970-01-01
相关资源
最近更新 更多