我有两个类(SamplingStacker)。 Sampling类(我的Main类)是JFrame的扩展,并具有JButtonActionListener来打开Stacker类。

问题是单击按钮时,Stacker类将打开,但只有一个没有任何组件的框架。当我将main方法切换到Stacker类时,该程序运行正常。问题是什么?

这是代码:

Sampling类:

public class Sampling extends JFrame implements ActionListener
{

    private JButton openStacker;

    Stacker st;

    public Sampling()
    {
        setSize(300,300);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new FlowLayout());
        setLocationRelativeTo(null);

        openStacker = new JButton("Start Stacker!");

        add(openStacker);
        openStacker.addActionListener(this);

        setVisible(true);
    }

    public void actionPerformed(ActionEvent e)
    {
        dispose();
        st = new Stacker();
    }

    public static void main (String args[])
    {
        new Sampling();
    }
}


Stacker游戏类:

public class Stacker  extends JFrame implements KeyListener
{
    int iteration = 1;
    double time = 200;
    int last = 0;
    int m = 10;
    int n = 20;
    JButton b[][];
    int length[] = {5,5};
    int layer = 19;
    int deltax[] = {0,0};
    boolean press = false;
    boolean forward = true;
    boolean start = true;


    public Stacker()
    {

        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setSize(400,580);
        this.setUndecorated(false);
        this.setLocationRelativeTo(null);



        b = new JButton [m][n];
        setLayout(new GridLayout(n,m));
        for (int y = 0;y<n;y++)
        {
            for (int x = 0;x<m;x++)
            {
                    b[x][y] = new JButton(" ");
                    b[x][y].setBackground(Color.DARK_GRAY);
                    add(b[x][y]);
                    b[x][y].setEnabled(false);
            }//end inner for
        }

        this.setFocusable(true);
        this.pack();
        this.addKeyListener(this);
        this.setVisible(true);

        go();

    }


    public void go()
    {
        int tmp = 0;
        Component temporaryLostComponent = null;
        do{
        if (forward == true)
        {
            forward();
        } else {
            back();
        }
        if (deltax[1] == 10-length[1])
        {
            forward = false;
        } else if (deltax[1] == 0)
        {
            forward = true;
        }
        draw();
        try
        {
            Thread.sleep((long) time);
        }
        catch (InterruptedException e)
        {

            e.printStackTrace();
        }

        }while(press == false);
        if (layer>12)
        {
            time= 150-(iteration*iteration*2-iteration);
        } else
        {
            time = time - 2.2;
        }
        iteration++;
        layer--;
        press = false;
        tmp = check();
        length[0] = length[1];
        length[1] = tmp;
        if (layer == -1)
        {
            JOptionPane.showMessageDialog(temporaryLostComponent, "Congratulations! You beat the game!");

            repeat();
        }
        if (length[1] <= 0)
        {
            JOptionPane.showMessageDialog(temporaryLostComponent, "Game over! You reached line "+(18-layer)+"!");

            repeat();
        }
        last = deltax[1];
        start = false;
        go();
    }
    public int check()
    {
        if (start == true)
        {
            return length[1];
        }
        else if (last<deltax[1])
        {
            if (deltax[1]+length[1]-1 <= last+length[0]-1)
            {
                return length[1];
            }
            else
            {
                return length[1]-Math.abs((deltax[1]+length[1])-(last+length[0]));
            }
        }
        else if (last>deltax[1])
        {
            return length[1]-Math.abs(deltax[1]-last);
        }
        else
        {
            return length[1];
        }
    }
    public void forward()
    {
        deltax[0] = deltax[1];
        deltax[1]++;
    }

    public void back()
    {
        deltax[0] = deltax[1];
        deltax[1]--;
    }

    public void draw()
    {
        for (int x = 0;x<length[1];x++)
        {
            b[x+deltax[0]][layer].setBackground(Color.DARK_GRAY);

        }
        for (int x = 0;x<length[1];x++)
        {
            b[x+deltax[1]][layer].setBackground(Color.CYAN);
        }
    }

    public void repeat()
    {
        if(JOptionPane.showConfirmDialog(null, "PLAY AGAIN?","WARNING",JOptionPane.YES_NO_OPTION)== JOptionPane.YES_OPTION)
        {
            dispose();
            new Stacker();
        }else{
            System.exit(0);
        }
    }


    public void keyPressed(KeyEvent e)
    {
        if (e.getKeyCode() == KeyEvent.VK_SPACE)
        {
            press = true;
        }

    }


    public void keyReleased(KeyEvent arg0)
    {

    }


    public void keyTyped(KeyEvent arg0)
    {

    }

}

最佳答案

只是为了将我所有的评论都放入答案中,并给您一个开始的地方:


  评论1:
  取出go();会看到这种情况。我测试了它,它将起作用。如果将其留在那里,甚至连相框的关闭按钮都卡住了。您正在使用while-> Thread.sleep垃圾阻止edt。您将需要进行一些重构。您很难编写代码,而且我也不知道您要做什么,所以我什至没有尝试过
  
  评论2:
  如果您想知道为什么仅在Stacker类中运行main时为什么它起作用,那可能是因为您在EDT之外运行它,
  public static void main(String[] args) { new Stacker(); }。当您单击该按钮时,操作将在EDT中执行,因此您的new Stacker()将在EDT上运行。在这种情况下,EDT将被while循环阻塞。如果尝试从Stacker类运行该程序,但将其包装在SwingUtilities.invokeLater中,您还将注意到该程序无法正常工作。不过,Swing程序应在EDT上运行。
  
  评论2:阅读Concurrency with Swing的前几节


因此,您可以做的是在游戏循环中使用Swing计时器(在EDT上运行)。我所做的只是稍微重构了您的代码。它并没有按照您想要的方式运行,只是因为我并不真正了解您的代码的逻辑。所以我无法使它工作。不过,我所做的是将某些逻辑放入计时器中。

Timer timer = new Timer((int)time, new ActionListener(){
    public void actionPerformed(ActionEvent event) {
        if (forward == true) {
            forward();
        } else {
            back();
        }
        if (deltax[1] == 10 - length[1]) {
            forward = false;
        } else if (deltax[1] == 0) {
            forward = true;
        }
        draw();
    }
});


调用go()方法时,它只是通过调用timer.start()来启动计时器。基本上,您需要了解的计时器是,每个滴答声(经过的毫秒数),都会调用actionPerformed。因此,您可以使用该方法更新游戏状态,就像在每次迭代的while循环中所做的一样。

花点时间浏览How to Use Swing Timers

为了使游戏正常运行,您仍然需要进行一些调整,但这应该可以帮助您抢先一步。

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Sampling extends JFrame implements ActionListener {

    private JButton openStacker;

    Stacker st;

    public Sampling() {
        setSize(300, 300);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new FlowLayout());
        setLocationRelativeTo(null);

        openStacker = new JButton("Start Stacker!");

        add(openStacker);
        openStacker.addActionListener(this);

        setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        dispose();
        st = new Stacker();
    }

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable(){
            public void run() {
                new Sampling();
            }
        });
    }
}

class Stacker extends JFrame implements KeyListener {

    int iteration = 1;
    double time = 200;
    int last = 0;
    int m = 10;
    int n = 20;
    JButton b[][];
    int length[] = {5, 5};
    int layer = 19;
    int deltax[] = {0, 0};
    boolean press = false;
    boolean forward = true;
    boolean start = true;

    Timer timer = new Timer((int)time, new ActionListener(){
        public void actionPerformed(ActionEvent event) {
            if (forward == true) {
                forward();
            } else {
                back();
            }
            if (deltax[1] == 10 - length[1]) {
                forward = false;
            } else if (deltax[1] == 0) {
                forward = true;
            }
            draw();
        }
    });

    public Stacker() {

        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setSize(400, 580);
        this.setUndecorated(false);
        this.setLocationRelativeTo(null);

        b = new JButton[m][n];
        setLayout(new GridLayout(n, m));
        for (int y = 0; y < n; y++) {
            for (int x = 0; x < m; x++) {
                b[x][y] = new JButton(" ");
                b[x][y].setBackground(Color.DARK_GRAY);
                add(b[x][y]);
                b[x][y].setEnabled(false);
            }//end inner for
        }

        this.setFocusable(true);
        this.pack();
        JPanel panel = (JPanel)getContentPane();
        panel.addKeyListener(this);
        this.setVisible(true);
        panel.requestFocusInWindow();

        go();
    }

    public void go() {

        int tmp = 0;
        Component temporaryLostComponent = null;
        timer.start();
        if (layer > 12) {
            time = 150 - (iteration * iteration * 2 - iteration);
        } else {
            time = time - 2.2;
        }
        iteration++;
        layer--;
        press = false;
        tmp = check();
        length[0] = length[1];
        length[1] = tmp;
        if (layer == -1) {
            JOptionPane.showMessageDialog(temporaryLostComponent, "Congratulations! You beat the game!");

            repeat();
        }
        if (length[1] <= 0) {
            JOptionPane.showMessageDialog(temporaryLostComponent, "Game over! You reached line " + (18 - layer) + "!");

            repeat();
        }
        last = deltax[1];
        start = false;
        //go();
    }

    public int check() {
        if (start == true) {
            return length[1];
        } else if (last < deltax[1]) {
            if (deltax[1] + length[1] - 1 <= last + length[0] - 1) {
                return length[1];
            } else {
                return length[1] - Math.abs((deltax[1] + length[1]) - (last + length[0]));
            }
        } else if (last > deltax[1]) {
            return length[1] - Math.abs(deltax[1] - last);
        } else {
            return length[1];
        }
    }

    public void forward() {
        deltax[0] = deltax[1];
        deltax[1]++;
    }

    public void back() {
        deltax[0] = deltax[1];
        deltax[1]--;
    }

    public void draw() {
        for (int x = 0; x < length[1]; x++) {
            b[x + deltax[0]][layer].setBackground(Color.DARK_GRAY);

        }
        for (int x = 0; x < length[1]; x++) {
            b[x + deltax[1]][layer].setBackground(Color.CYAN);
        }
    }

    public void repeat() {
        if (JOptionPane.showConfirmDialog(null, "PLAY AGAIN?", "WARNING", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
            dispose();
            new Stacker();
        } else {
            System.exit(0);
        }
    }

    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_SPACE) {
            System.out.println("Pressed");
            press = true;
        }

    }

    public void keyReleased(KeyEvent arg0) {

    }

    public void keyTyped(KeyEvent arg0) {

    }

}


注意SwingUtilities.invokeLater中的main。这样便可以在EDT上启动程序。 Swing中的并发链接将为您提供更多信息。

关于java - 使用JButton打开新的JFrame,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26072653/

10-08 23:53