我希望能够在关闭 JTable 后再次运行 main

问题描述 投票:0回答:1

我正在运行一个模拟,对到达目的地的对象的移动进行计时,然后在模拟结束后将结果显示在 JTable 上。但是,当包含 JTable 的窗口关闭时,我希望能够再次运行主类。

我正在考虑使用frame.setDefaultCloseOperation();不知何故,但我不确定如何做到这一点。

这是我的代码当前的样子:

public class Main {
        public static void main(String[] args) throws InterruptedException {
        Scanner scan = new Scanner(System.in);

        ArrayList<Integer> inputsA = new ArrayList<>();
        ArrayList<Integer> timesA = new ArrayList<>();

        System.out.println("Please enter the time for A: ");
        int inputA = scan.nextInt();

        inputsA.add(inputA);

        Simulation sim = new Simulation(inputA);
        sim.runSim();

        timesA.add(sim.getA());
        int length = timesA.size();

        Object[][] tableData = new Object[length][2];

        for (int i = 0; i < length; i++) {
            tableData[i] = new Object[]{inputsA.get(i), timesA.get(i)};
        }

        JFrame frame = new JFrame();

        String[] tableColumn = {"Input A", "Time A"};

        TableModel model = new DefaultTableModel(tableData, tableColumn) {
            public Class getColumnClass(int column) {
                Class returnValue;
                if ((column >= 0) && (column < getColumnCount())) {
                    returnValue = getValueAt(0, column).getClass();
                } else {
                    returnValue = Object.class;
                }
                return returnValue;
            }
        };

        RowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);

        JTable table = new JTable(tableData, tableColumn);
        table.setBounds(100, 55, 300, 200);
        table.setRowSorter(sorter);

        JScrollPane jScrollPane = new JScrollPane(table);
        frame.add(jScrollPane);
        frame.setSize(300, 200);
        frame.setVisible(true);
    }
}
java swing jtable simulation
1个回答
0
投票

一个解决方案是

  1. 调用
    framesetDefaultCloseOperation(JFame.DISPOSE_ON_CLOSE);
    以防止关闭JFrame而关闭JVM。但这是 JFrames 的默认设置,因此不需要。
  2. 将主方法中的所有代码放入 while 循环中,该循环将重复执行,直到使用 Scanner 输入哨兵值。

这个解决方案简单、直接、容易,但是错误的,因为它没有解决代码中的明显问题,这些问题包括:

  1. 将线性扫描仪应用程序与事件驱动的 GUI 库 Swing 相结合,后者显示窗口 JFrame。
  2. 将所有代码都放在静态主方法中,使其变得更加难以调试、增强或更改。

相反,我建议你

  1. 为 GUI 和非 GUI 模型代码创建符合 OOP 的类
  2. 坚持一种编程范式,这里我坚持使用事件驱动的 GUI 范式
  3. 这意味着从 GUI(这里是 JFrame)获取所有输入。
  4. 不要创建一堆主应用程序窗口,JFrame。创建one JFrame,并继续使用它。

例如,

import java.awt.BorderLayout;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;

public class Main02 {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("Simulation");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new SimPanel());
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    
    }
}
class SimPanel extends JPanel {
    private static final long serialVersionUID = 1L;
    private JSpinner spinner = new JSpinner(new SpinnerNumberModel(0, 0, 100, 1));
    private JButton button = new JButton("Run Simulation");
    private static final String[] COLUMN_NAMES = { "Input A", "Time A" };
    private DefaultTableModel model = new DefaultTableModel(COLUMN_NAMES, 0);
    private JTable table = new JTable(model);
    
    public SimPanel() {
        JPanel inputPanel = new JPanel();
        inputPanel.add(new JLabel("Time for A: "));
        inputPanel.add(spinner);
        inputPanel.add(button);

        button.addActionListener(e -> {
            int inputA = (Integer) spinner.getValue();
            Simulation sim = new Simulation(inputA);
            sim.runSim();
            model.addRow(new Object[] { inputA, sim.getA() });
        });

        setLayout(new BorderLayout());
        add(inputPanel, BorderLayout.PAGE_START);
        add(new JScrollPane(table), BorderLayout.CENTER);
    }
}

改进是从后台线程(例如 SwingWorker)运行模拟,这样模拟引起的任何时间延迟都不会冻结 GUI。

© www.soinside.com 2019 - 2024. All rights reserved.