Program works by debugging but not running

Asked

Viewed 65 times

2

I’m doing an old game and I’d like to know if the button pressed that I set in class MenuPrincipal is returning the correct value to the main class that controls the change between windows.

Normally running the program does not work, but when placing a breakpoint on line 16 of the main class on the line if(menu.botao), and put to debug in Eclipse the program runs in the correct way.

Main method:

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");
            }
        }
    }
}

Menuprincipal 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;
    }
}
  • You’re mixing graphical interface with text mode, maybe that’s the reason.

  • The problem persists even using Joptionpane.showMessageDialog instead println there in the main class

  • From the moment the boot is tightened, it will be eternally true, and its loop will never stop running.

  • I don’t know what is the point of using text mode in graphical interface, and what is the use of this infinite loop that never stops, but Oce needs to define the moment when the loop should be finished, otherwise it will never leave the loop.

  • Yes, I forgot, after pressing button, set if the boot was pressed to false, but still it should at least work at first run, right? I’ll fix it from the ever true button

  • This loop will be finished when the exit button is pressed, however I first need to know if the main class is getting the correct button pressed option

  • Your logic is wrong, swing by itself is already an API that runs under a loop, you are adding another and this will lock the application, I suggest q remove this loop, it is not necessary for the interface to work, alias, it will mess up. Try removing all the code from while and you’ll see, the screen doesn’t need this loop. If you want to control the buttons pressed, you’re doing it the wrong way.

  • then, what would be the correct way to control the button pressed?

  • Within the actionlistener.

  • Why did you undo my editing? I had no reason to, I just improved some of the text, I didn’t change anything.

Show 5 more comments

1 answer

2


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

  • First that the interfaces made with the swing API are dispatched to a new thread, and perform operations outside this loop to control the screen may result in threads competing problems, since the main method runs on a different thread.

  • Second because the API already has a whole support for this type of situation, and the most appropriate is to use the own ActionListener, since it also occurs within the same interface thread.

To demonstrate that this loop is irrelevant, you can run the code below, 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));
    }

}

In operation:

inserir a descrição da imagem aqui

In addition to the amendments relating to ActionListener and the removal of the infinite loop, it is worth mentioning other points changed in the code, which is important to take into account:

  • As I mentioned, swing interfaces should always be initiated inside the thread , in the aforementioned link you will find better explanations of the reasons for this;

  • You are defining screen features outside of it without even having set on the screen itself, this is a violation of 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 informed in the screen constructor. For these reasons I moved the methods setSize() and setDefaultCloseOperation() for the builder.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.