Открытие нового JFrame с помощью JButton

1

У меня есть два класса (Sampling and Stacker). Класс Sampling (мой основной класс) расширяет JFrame и имеет JButton с ActionListener чтобы открыть класс Stacker.

Проблема в том, что при нажатии кнопки открывается класс Stacker, но только кадр без каких-либо компонентов. Когда я переключаю основной метод в класс 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) 
    {

    }

}
  • 0
    1) См . Использование нескольких JFrames, хорошая / плохая практика? 2) Единственная пустая строка пробела в исходном коде - это все, что когда-либо необходимо. Пустые строки после { или до } также обычно избыточны. 3) Для более быстрой помощи, опубликуйте MCVE (Минимальный завершенный проверяемый пример).
  • 0
    Вынь go(); вижу, что происходит. Я проверил это, и это будет работать. Если вы оставите его там, даже кнопка закрытия рамки заклинит. Вы блокируете редактирование с помощью мусора while-> Thread.sleep. Вы хотите сделать рефакторинг. Твоему коду трудно следовать, и я понятия не имею, что ты пытаешься сделать, поэтому я даже не пытался.
Показать ещё 6 комментариев
Теги:
swing
jframe
jbutton

1 ответ

1
Лучший ответ

Просто, чтобы вставить все мои комментарии в ответ и дать вам где-то начать с:

Комментарий 1: Выньте go(); см., что происходит. Я тестировал его, и он будет работать. Если вы оставите его там, даже кнопка закрытия кадра замята. Вы блокируете edt с помощью while-> мусора Thread.sleep. Вы захотите сделать рефакторинг. Вам сложно следовать, и я понятия не имею, что вы пытаетесь сделать, поэтому я даже не попытался это сделать

Комментарий 2: Если вам интересно, почему это работает, когда вы просто запускаете основной из класса Stacker, возможно, потому, что вы используете его вне EDT,

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

Что происходит, когда вы нажимаете кнопку, это действие выполняется в EDT, и, следовательно, ваш new Stacker() будет запущен на EDT. В этом случае EDT блокируется вашим циклом while. Если вы попробуете запустить программу из класса Stacker, но заверните ее в SwingUtilities.invokeLater, вы также заметите, что программа не работает. Однако программы Swing должны запускаться на EDT.

Комментарий 2: Прочитайте первые несколько разделов о параллелизме с 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 каждую итерацию.

Потратьте немного времени на то, как использовать таймеры Swing

Чтобы игра работала правильно, вам все равно нужно внести некоторые коррективы, но это должно дать вам начало.

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. Ссылка на Concurrency In Swing даст вам больше информации.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню