Program works by debugging but not executing

2

I'm making a game of the old one and I wonder if the tight button I set up in class MenuPrincipal is returning the correct value for the main class that controls the change between windows.

Running the program normally does not work, but by putting a breakpoint in line 16 of class main, in line if(menu.botao) , and putting it to debug in Eclipse, the program executes correctly.

Method main:

import javax.swing.JFrame;
import javax.swing.JOptionPane;

import interfaceMenu.MenuPrincipal;

public class main {

        public static void main(String[] args) {

        MenuPrincipal menu = new MenuPrincipal();
        menu.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        menu.setSize(500, 500);
        menu.setVisible(true);
        //JOptionPane.showMessageDialog(null,menu.getOpcao());
        while(true) {
            if(menu.botao) {
                System.out.println("botao apertado");

            switch (menu.getOpcao()) {
            case "Novo Jogo" : 
                                System.out.println("Botao Novo jogo apertado"); break;
            case "Sair": 
                System.out.println("Botao Sair apertado");break;
            default: System.out.println("nada");
            }

            menu.setOpcao("Nada selecionado");
            }
        }
    }
}

Main Menu Class:

package interfaceMenu;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.Menu;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;


public class MenuPrincipal extends JFrame {

    private final JLabel textoInicial = new JLabel("Jogo da velha");
    JPanel areaDosBotoes = new JPanel(new GridLayout());
    private JButton[] botoes = new JButton[2];
    private String opcao = "Nada selecionado";
    public boolean botao = false;

    public MenuPrincipal() {

        super("Jogo da Velha"); // Barra de titulo;     
        botoes[0] = new JButton("Novo Jogo");
        botoes[1] = new JButton("Sair");    
        //TODO: MAIS OPÇÕES
        areaDosBotoes.setLayout(new GridLayout(1, botoes.length));
        for (JButton botao : botoes) {
            areaDosBotoes.add(botao);
            botao.addActionListener(new TratadorDeEventos());
        add(textoInicial, BorderLayout.NORTH);
        add(areaDosBotoes, BorderLayout.SOUTH);
        }
    }


    private class TratadorDeEventos implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            setOpcao(arg0.getActionCommand());
            botao = true;
            //JOptionPane.showMessageDialog(null, getOpcao());
        }

    }

    public String getOpcao() {
        return this.opcao;
    }

    public void setOpcao(String opcao) {
        this.opcao = opcao;
    }
}
    
asked by anonymous 09.03.2018 / 12:18

1 answer

2

I believe that if you want to control the execution of the buttons, this way you are doing is not suitable for two reasons:

  • First that the interfaces made with the swing API are dispatched to a new thread , and do operations outside this loop to control the screen may experience thread concurrency problems, since the main method executes on a different thread.

  • Secondly because the API already has a full support for this type of situation, and it is best to use the ActionListener itself, since it also occurs within the same interface thread.

To demonstrate that this loop is irrelevant, you can run the following code with the changes I made:

package swing.examples7;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


public class MenuPrincipal extends JFrame {

    private final JLabel textoInicial = new JLabel("Jogo da velha");
    JPanel areaDosBotoes = new JPanel(new GridLayout());
    private JButton[] botoes = new JButton[2];
    private String opcao = "Nada selecionado";
    public boolean botao = false;

    public MenuPrincipal() {

        super("Jogo da Velha"); // Barra de titulo;
        botoes[0] = new JButton("Novo Jogo");
        botoes[1] = new JButton("Sair");
        // TODO: MAIS OPÇÕES
        areaDosBotoes.setLayout(new GridLayout(1, botoes.length));
        for (JButton botao : botoes) {
            areaDosBotoes.add(botao);
            botao.addActionListener(new TratadorDeEventos());
            add(textoInicial, BorderLayout.NORTH);
            add(areaDosBotoes, BorderLayout.SOUTH);
        }
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(500, 500);
    }

    private class TratadorDeEventos implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent arg0) {

            JOptionPane.showMessageDialog(null, arg0.getActionCommand());               
            botao = true;

        }
    }

    public static void main(String[] args) {

        SwingUtilities.invokeLater(() -> new MenuPrincipal().setVisible(true));
    }

}

Running:

InadditiontothechangesrelativetoActionListenerandtheremovaloftheinfiniteloop,itisworthmentioningotherpointschangedinthecode,whichisimportanttotakeintoaccount:

  • AsI'vealreadymentioned,swinginterfacesshouldalwaysbestartedwithinthethread event-dispatch-thread , in the already mentioned link you will find better explanations of the reasons for this;

  • You're setting screen characteristics out of it without even defining it on the screen itself, this is a violation of the encapsulation and also does not make much sense. The object itself must have all the necessary information at the time it is created, and these characteristics must be reported in the on-screen constructor. For these reasons I have moved the methods setSize() and setDefaultCloseOperation() to the constructor.

09.03.2018 / 13:48