Есть ли способ, которым я могу зациклить проверку состояния Frame.state, без зацикливания кода в проверке? - PullRequest
0 голосов
/ 20 октября 2019

Я хочу иметь возможность постоянно проверять значение Frame.state, без непрерывного циклического выполнения кода внутри проверок. Я хочу иметь возможность либо проверить значение, либо проверить, когда была нажата кнопка, и заново распечатать значения в Jpane соответствующим образом.

Я взял проверки и поместил их в ActionListener () дляКнопка «Далее» в кадре, но я не хочу делать это, если это абсолютно необходимо. Я попытался поместить проверки if в цикл while, результатом было непрерывное повторение всего внутри каждой проверки, основанное на состоянии кнопки, то есть: код в первой проверке "if (Frame.state == 1) {array.setRandom (100); array.print ();} "будет непрерывно перепечатывать массив случайными числами, вместо того, чтобы выполнить действие один раз и ждать повторного нажатия кнопки.

Я неполагаю, что ArrayObject2d важен для помощи или решения этой проблемы, и решил оставить его, если этот код необходим, пожалуйста, дайте мне знать.

public class MainClass {
public static void main(String[] args) {
        @SuppressWarnings("unused")
        Frame frame = new Frame();
        ArrayObject2d array = new ArrayObject2d(10, 5);

        if (Frame.state == 1) {
            array.setRandom(100);
            array.print();
        } else if (Frame.state == 2) {
            array.setAll(99999);
            array.print();
        } else if (Frame.state == 3) {
            array.numberAll();
            array.print();
        } else if (Frame.state == 4) {
            array.showIndex();
        }

    }

Ниже код находится в другом классе, под конструктором, которыйполностью создает фрейм со всеми компонентами



//assume all imports have been written
public class Frame extends JFrame {
    public Frame() {
        super();
        setDefaultCloseOperation(3);
        setBackground(new Color(245, 252, 255));
        setResizable(false);
        setSize(1280, 720);
        setVisible(true);
        setLocationRelativeTo(null);
        JButton next = new JButton();

        next.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (state > 3) {
                    state = 1;
                } else {
                    state++;
                }       
            }
        });
    }   
}

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

1 Ответ

2 голосов
/ 20 октября 2019

Нет, не зацикливайтесь и постоянно опрашивайте вашего объекта на предмет его состояния, так как это очень неэффективно. Скорее, вы должны сделать state «связанным» полем и позволить другому коду присоединять слушателей изменения свойств к объекту, чтобы объект GUI мог уведомить всех слушателей об изменении состояния.

Итак:

  • Сделайте поле состояния частным полем экземпляра вашего класса Frame.
  • Дайте классу public static final String STATE = "state"; константу
  • Создание метода получения и установки для состояния, public int getState(), public void setState(int state)
  • В методе setState(...) создайте две локальные переменные int oldValue и newValue и передайте соответствующие значения состояния (параметр и значение this) в эти переменные.
  • Ваш фрейм имеет поддержку изменения свойств. Поэтому используйте его, чтобы уведомить всех подключенных слушателей о том, что состояние изменилось, вызывая firePropertyChange(STATE, oldValue, newValue);

Например:

Основной класс, который создает и ArrayObject2d, и ваш объект Frame (здесь с именем Frame2 toизбегайте путаницы с java.awt.Frame)

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.event.*;
import javax.swing.*;

public class MainClass {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            final Frame2 frame = new Frame2();
            frame.setVisible(true);
            final ArrayObject2d array = new ArrayObject2d(10, 5);

            frame.addPropertyChangeListener(Frame2.FRAME_STATE, propChngEvent -> {
                if (frame.getFrameState() == 1) {
                    array.setRandom(100);
                    array.print();
                } else if (frame.getFrameState() == 2) {
                    array.setAll(99999);
                    array.print();
                } else if (frame.getFrameState() == 3) {
                    array.numberAll();
                    array.print();
                } else if (frame.getFrameState() == 4) {
                    array.showIndex();
                }
            });
        });
    }
}

Класс Frame2 находится ниже. Обратите внимание, что поле состояния было переименовано в frameState, чтобы избежать путаницы с внутренним полем Swing с тем же именем.

@SuppressWarnings("serial")
class Frame2 extends JFrame {
    public static final String FRAME_STATE = "frame state";
    private static final Dimension PANEL_SIZE = new Dimension(640, 400);
    private JLabel frameStateLabel = new JLabel("1");
    private int frameState = 1;    

    public Frame2() {
        super();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        JButton next = new JButton("Next");
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setPreferredSize(PANEL_SIZE);
        panel.setBackground(new Color(245, 252, 255));
        panel.add(next);
        panel.add(Box.createHorizontalStrut(15));
        panel.add(new JLabel("Frame State: "));
        panel.add(frameStateLabel);

        next.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (frameState > 3) {
                    setFrameState(1);  // ***Always*** change frameState by the setter method
                } else {
                    setFrameState(frameState + 1);  // ** Ditto **
                }       
            }
        });

        add(panel);
        pack();
        setResizable(false);
        setLocationRelativeTo(null);
    }   

    public int getFrameState() {
        return frameState;
    }

    public void setFrameState(int frameState) {
        int oldValue = this.frameState;
        int newValue = frameState;
        this.frameState = frameState;
        firePropertyChange(FRAME_STATE, oldValue, newValue);
        frameStateLabel.setText("" + frameState);
    }
}

Это класс-макет для вашего класса ArrayObject2d, поскольку у меня нет фактического кода. Он выведет, какой метод был вызван:

class ArrayObject2d  {

    public ArrayObject2d(int rows, int columns) {
        // TODO finish
    }

    public void showIndex() {
        System.out.println("show index");
    }

    public void numberAll() {
        System.out.println("number all");
    }

    public void setAll(int i) {
        System.out.println("set all: " + i);
    }

    public void print() {
        System.out.println("print");
    }

    public void setRandom(int i) {
        System.out.println("set random: " + i);
    }

}
...