初始化 JFrame 时黑屏 window

Black screen when initializing JFrame window

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

这是我已经尝试过的:

  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 方法内)得到了一个 ArrayIndexOutOfBounds 异常:g.setColor(well[i][j]);。您的外循环是 for (int i = 0; i < 23; i++),而 well 数组是 new Color[12][24]。难怪为什么会这样。将循环更改为 for (int i = 0; i < 12; i++) 将使框架可见。

虽然有些通知。

  1. 所有 swing 应用程序必须 运行 在自己的线程上,称为 EDT(事件调度线程)。在您的 main 中调用 SwingUtilities#invokeLater 并让应用程序 运行 在那里。

    SwingUtilities.invokeLater(()->{
        JFrame f = new JFrame("Tetris002");
        ....
    });
    
  2. 而不是创建 new Thread,看看 使用 javax.swing.Timer 看起来更好(从代码的角度来看),它是为这种情况创建的因为任务将在美国东部时间 运行。简而言之,糟糕的(代码外观)Thread 部分变成了:

    new Timer(1000, e -> {
        game.drop();
    }).start();
    
  3. 当你@OverridepaintComponent时,总是调用super.paintComponent(g)。让组件被绘制 "normally" 然后做你的事情:


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

问题是函数 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);
}