简体   繁体   中英

My Java swing button doesn't work

I've been making a battleship program that I've been trying to get working with a GUI, but it doesn't want to work. The way in theory it should work is that the GUI starts, it outputs a question to a box(which works), and then the computer waits and executes nothing until you press the button after you've answered your answer to the question. The problem is, my method that waits until you've clicked the button to fetch the data in the text field doesn't do anything. I've written a similar piece of code which demonstrates my problem below.

Test.java (main class)

package taest;
import javax.swing.*;

public class Test {
    public static void main(String args[]){
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                @SuppressWarnings("unused")
                JFrame frame = new Frame();
            }
        });
        Frame.display.setText(getButtonClick());
        }
    public static String getButtonClick(){
        while(true){
            if (Frame.hasClicked){
                break;
            }
        }
        return Frame.text.getText();
    }
}

Frame.java (Frame class) package taest;

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

public class Frame extends JFrame{
    JFrame panel = new JFrame("Something");
    public static JTextArea text = new JTextArea();
    JButton button = new JButton("Click");
    public static JTextField display = new JTextField("NOthing");
    static boolean hasClicked = false;
    static String storage = "";

    public Frame(){
        setLayout(new BorderLayout());
        setSize(400,400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        button.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                hasClicked = true;
                storage = text.getText();
            }

        });

        Container c = getContentPane();
        c.add(display, BorderLayout.CENTER);
        c.add(text, BorderLayout.PAGE_START);
        c.add(button, BorderLayout.PAGE_END);

        setVisible(true);
    }
}
  • Static is not your friend and it's use should be greatly limited. It should NEVER be used to provide "easy" access to class fields for inter class communication
  • You need to turn the concept on it's head and possibly use some kind of Observer Pattern . This is where you have a class which is "observing" changes on your other class. When a change occurs the observed class notifies the observing class of the change. This decouples the responsibility as the observed class shouldn't care beyond notifying interested parties about something that happens

As a really primitive example...

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class Test {

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

    public Test() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                @SuppressWarnings("unused")
                JFrame frame = new Frame(new ViewController() {
                    @Override
                    public void messageChanged(View view, String msg) {
                        view.appendLog(msg);
                    }
                });
            }
        });
    }

    public interface ViewController {

        public void messageChanged(View view, String msg);

    }

    public interface View {

        public void appendLog(String log);

    }

    public class Frame extends JFrame implements View {

//      JFrame panel = new JFrame("Something");
        private JTextArea text = new JTextArea(5, 5);
        private JButton button = new JButton("Click");
        private JTextField display = new JTextField("NOthing");
        private String storage = "";

        private ViewController viewController;

        public Frame(ViewController controller) {
            this.viewController = controller;
            setLayout(new BorderLayout());
            setSize(400, 400);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            button.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    storage = text.getText();
                    viewController.messageChanged(Frame.this, storage);
                }

            });

            System.out.println("display = " + display.hashCode());
            System.out.println("text = " + text.hashCode());

            Container c = getContentPane();
            c.add(display, BorderLayout.CENTER);
            c.add(text, BorderLayout.PAGE_START);
            c.add(button, BorderLayout.PAGE_END);

            setVisible(true);
        }

        @Override
        public void appendLog(String log) {
            display.setText(log);
        }
    }

}

You should also become farmiluar within the concept of Model–view–controller

You are mixing things up,

First things first, the difference between Classes and Objects. A class is a blueprint for an object, so an example of a class is Car . The blueprint of such an object however knows nothing about the state of a particular instance of that class, lets assume that you drive 100 km/u, then you have an instance of Car that stores that it is going at 100 km/u. Blueprints are classes, Objects are instances.

So, public class Car makes an blueprint for cars, and new Car() makes a specific instance of that blueprint in which you can store runtime information.

Now there is a way to tell Java that things belong to the blueprint, static. If a variable is static it is attached to the blueprint. So to keep up with the analogy of cars, a static variable for a car can be its wheelbase, thats something that is defined at compiletime (or in the car analogy at create time).

Back to your problem, you are mixing up classes and objects, what you want to do is have a BattleshipWindow of which instances exist. Of this BattleshipWindow an instance can be created with new , and then its properties can be changed.

Not exactly the answer you want probably, but I hope you now understand the difference between classes and objects, that will help you solve your problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM