有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java动态地将行添加到JTable中为什么它们会同时出现?

在本例中,我试图向GUI中添加一个表,然后动态地向其中添加行(以显示进度)。我不明白的是为什么所有的行同时出现。我是说,桌子在变,不是吗?谁能给我解释一下吗

import java.awt.Component;

public class Main {
  public static void main(String[] args) {
    // Show GUI
    java.awt.EventQueue.invokeLater(new Runnable() {
      public void run() {
        GUI gui = new GUI();
        gui.setVisible(true);

        DefaultTableModel model = new DefaultTableModel(
          new String[] { "Column 1", "Column 2" }, 0);
        JTable table = new JTable(model);

        gui.add(table);
        gui.validate();

        for (int i = 0; i < 10; i++) {
          System.out.println("Row " + i);
          model
            .addRow(new String[] { "Row", String.valueOf(i) });
          // model.fireTableDataChanged();

          try {
            Thread.sleep(250);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }

        }
      }
    });
  }
}

class GUI extends JFrame {
  private static final long serialVersionUID = 1L;

  public GUI() {
    setTitle("GUI");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 350, 100);
    setLocationRelativeTo(null);

    JPanel cp = new JPanel();
    cp.setBorder(new EmptyBorder(10, 10, 10, 10));
    setContentPane(cp);
  }
}

共 (2) 个答案

  1. # 1 楼答案

    重申克利奥帕特拉:不要睡EDT

    您可以改为使用javax.swing.Timer,如this answer

    enter image description here


    编辑

    我不想把你的代码弄得太乱(只是因为它看起来很奇怪),但我做了一些修改,添加了计时器

    import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.Timer;
    import javax.swing.border.EmptyBorder;
    import javax.swing.table.DefaultTableModel;
    
    public class Main {
    
        static JTable table;
        static GUI gui;
        static Processor p = null;
    
        public static void main(String[] args) {
            // Show GUI
            java.awt.EventQueue.invokeLater(new Runnable() {
                public void run() {
                    gui = new GUI();
    
                    p = new Processor() {
    
                        @Override
                        public void execute() {
                            final JTable table = new JTable(p.getTableModel());
                            final JScrollPane scrollPane = new JScrollPane(table);
                            gui.getContentPane().add(scrollPane, BorderLayout.CENTER);
                            gui.setLocationRelativeTo(null);
                            gui.setVisible(true);
    
                            Timer timer = new Timer(100, new ActionListener(){
                                public void actionPerformed(ActionEvent e) {
                                    p.processRow();
                                    table.scrollRectToVisible(table.getCellRect(table.getRowCount() - 1, 0, true));
                                }
                            });
                            timer.start();
                        }
                    };
                    p.execute();
                }
            });
        }
    }
    
    class GUI extends JFrame {
    
        private static final long serialVersionUID = 1L;
    
        public GUI() {
            setTitle("GUI");
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setBounds(100, 100, 350, 400);
    
            JPanel contentPane = new JPanel();
            contentPane.setBorder(new EmptyBorder(10, 10, 10, 10));
            contentPane.setLayout(new BorderLayout(0, 0));
    
            setContentPane(contentPane);
        }
    }
    
    interface Callback {
    
        void execute();
    }
    
    abstract class Processor implements Callback {
    
        private final String[] cols = {"COL", "COL", "COL", "COL", "COL"};
        private DefaultTableModel tableModel;
        int numRows;
        int numCols;
        int a, b, c, d, e;
    
        Processor() {
            a = 1; b = 2; c = 3; d = 4; e = 4;
            numRows = 1000;
            tableModel = new DefaultTableModel(cols, numCols);
        }
    
        public DefaultTableModel getTableModel() {
            return tableModel;
        }
    
        public void processRow() {
            tableModel.addRow(new Object[]{a, b, c, d, e});
            a++; b++; c++; d++; e++;
        }
    }
    
  2. # 2 楼答案

    因为在代码运行时,无法执行其他事件(例如重绘事件)——在完成之前,您将阻塞事件线程

    您可以直接调用repaint,但在代码运行时,UI仍然对输入没有响应。最好在单独的工作线程中运行循环,并在需要时使用invokeLater或invokeAndWait对UI执行更新