java Jtable 不刷新/更新数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12646240/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 09:41:09  来源:igfitidea点击:

Jtable doesn't refresh/update data

javaswingjtablejscrollpanedefaulttablemodel

提问by ZhiZha

I have a problem with JTable/JScrollPane. My data table is not refreshing/updating. I am using DefultTableModeland according to the code everything is fine and I don't have any errors. Also I have a table with paging and that's why I am using action listeners and buttons "prev" and "next". I am passing from other function to function that is coded in class where is JTable. Problem is that I fill arrays which contains data for table but table won't update/refresh it. Here is my code. Thanks advance.

我有问题JTable/ JScrollPane。我的数据表没有刷新/更新。我正在使用DefultTableModel,根据代码一切都很好,我没有任何错误。此外,我有一个带分页的表格,这就是为什么我使用动作侦听器和按钮“上一个”和“下一个”。我正在从其他函数传递到在类中编码的函数 where is JTable。问题是我填充了包含表数据的数组,但表不会更新/刷新它。这是我的代码。先谢谢了。

BIG EDITOld code was removed. I added new codes that will help you guys/girls to understand problem that I have. Hope that this will help. Regards.

大编辑旧代码已删除。我添加了新的代码,可以帮助你们理解我遇到的问题。希望这会有所帮助。问候。

First here is class that show gui:

首先是显示gui的类:

import javax.swing.*;
public class Glavni {
public static void main(String[] args)  {
    // TODO Auto-generated method stub
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
                gui Scanner = new gui();
                Scanner.setVisible(true);
        }
    });
}

}

Second here is class that pass String to gui class that contains jtable

第二个是将字符串传递给包含 jtable 的 gui 类的类

public class passDatatoTable {
public void passData(){
    String str1,str2,str3,str4;
    gui SendStringsToGUI = new gui();
    for (int i =0;i<=10;i++){
            str1="Column 1 of row: "+i;
            str2="Column 2 of row: "+i;
            str3="Column 3 of row: "+i;
            str4="Column 4 of row: "+i;
            SendStringsToGUI.WriteMonitorData(str1, str2, str3, str4);

    }
  }
}

Next here is declaration of gui (contructor):

接下来是gui(构造函数)的声明:

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class gui extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
 String[][] data = new String[100][4];

 String[] columnNames = new String[]{
         "IP", "PC_NAME", "ttl", "db"
 };
 DefaultTableModel model = new DefaultTableModel(data,columnNames);


    JTable table =  new JTable(model);
    JScrollPane scrollPane = new JScrollPane(table);
    int i=0;
public void WriteMonitorData (String IP, String PC_NAME, String ttl, String gw)
{
    System.out.println(IP);//just for testing (check if data was passed)
    model.setValueAt(IP, i, 0);
    model.setValueAt(PC_NAME, i, 1);
    model.setValueAt(ttl, i, 2);
    model.setValueAt(gw, i, 3);

    i++;
    model.fireTableDataChanged();
    table.repaint();
    scrollPane.repaint();

}   
gui(){

JButton addData= new JButton("Add Data");
JButton next = new JButton("next");
JButton prev = new JButton("prev");
addData.addActionListener(this);
next.addActionListener(this);
prev.addActionListener(this);
JPanel panel = new JPanel(new BorderLayout());
JPanel buttonPanel = new JPanel();
buttonPanel.add(addData);
buttonPanel.add(prev);
buttonPanel.add(next);
panel.add(buttonPanel, BorderLayout.SOUTH);
panel.add(table.getTableHeader(), BorderLayout.PAGE_START);
panel.add(scrollPane, BorderLayout.CENTER);
getContentPane().add(panel);
}

Here is actionListeners:

这是 actionListeners:

public void actionPerformed(ActionEvent e) {
if ("Add Data".equals(e.getActionCommand())){

        passDatatoTable passSomeData = new passDatatoTable();
        passSomeData.passData();
              }
 if ("next".equals(e.getActionCommand())) {
         Rectangle rect = scrollPane.getVisibleRect();
         JScrollBar  bar = scrollPane.getVerticalScrollBar();
         int blockIncr = scrollPane.getViewport().getViewRect().height;
             bar.setValue(bar.getValue() + blockIncr);
             scrollPane.scrollRectToVisible(rect);
     }
     if ("prev".equals(e.getActionCommand())) {
         Rectangle rect = scrollPane.getVisibleRect();
         JScrollBar  bar = scrollPane.getVerticalScrollBar();
         int blockIncr = scrollPane.getViewport().getViewRect().height;
             bar.setValue(bar.getValue() - blockIncr);
             scrollPane.scrollRectToVisible(rect);
     }

  }

回答by David Kroukamp

Your first snippet shows this:

您的第一个片段显示了这一点:

JTable table = new JTable(model);

JTable table = new JTable(model);

but your gui()constructor shows:

但你的gui()构造函数显示:

JTable table = new JTable(data, columnNames);

JTable table = new JTable(data, columnNames);

You initiate the table twice. Once using the TableModel(JTable(TableModel tm)) the next using JTable(int rows,int cols)this is not good, initiate the JTableonce in the constructor:

您启动该表两次。一旦使用TableModel( JTable(TableModel tm)) 下一次使用JTable(int rows,int cols)this 不好,JTable在构造函数中启动一次:

gui() {
DefaultTableModel model = new DefaultTableModel(data,columnNames);
JTable table =  new JTable(model);
JScrollPane scrollPane = new JScrollPane(table);

JButton next = new JButton("next");
JButton prev = new JButton("prev");
next.addActionListener(this);
prev.addActionListener(this);
JPanel panel = new JPanel(new BorderLayout());
JPanel buttonPanel = new JPanel();
buttonPanel.add(prev);
buttonPanel.add(next);
panel.add(buttonPanel, BorderLayout.SOUTH);
panel.add(table.getTableHeader(), BorderLayout.PAGE_START);
panel.add(scrollPane, BorderLayout.CENTER);
getContentPane().add(panel);
}

UPDATE:

更新:

Here is an example that has a thread which will start 2.5 secinds after the UI is visible and change a value of the JTable:

这是一个示例,它有一个线程,该线程将在 UI 可见后 2.5 秒启动并更改 的值JTable

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;

public class Test extends JFrame {

    public static void main(String[] args) throws Exception {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new Test().createAndShowUI();
            }
        });

    }

    private void createAndShowUI() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        initComponents(frame);
        frame.pack();
        frame.setVisible(true);
        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    Thread.sleep(2500);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
                } 
                SwingUtilities.invokeLater(new Runnable() {

                     @Override
                     public void run() {
                       model.setValueAt("hello", 0, 0);
                     }
                });
            }
        }).start();
    }
    static DefaultTableModel model;

    private void initComponents(JFrame frame) {

        String data[][] = {
            {"1", "2", "3"},
            {"4", "5", "6"},
            {"7", "8", "9"},
            {"10", "11", "12"}
        };

        String col[] = {"Col 1", "Col 2", "Col 3"};

        model = new DefaultTableModel(data, col);
        JTable table = new JTable(model);

        frame.getContentPane().add(new JScrollPane(table));
    }
}

回答by Robin

From what I understand from the comments and the question, you have first created a DefaultTableModelby passing the data as arrays in the constructor

根据我从评论和问题中的理解,您首先DefaultTableModel通过在构造函数中将数据作为数组传递来创建一个

String[][] data = new String[100][4];
String[] columnNames = new String[]{
     "IP", "PC_NAME", "ttl", "db"};
DefaultTableModel model = new DefaultTableModel(data,columnNames);

and you try to modify the table afterwards by adjusting those arrays. That will never ever have any effect, as the DefaultTableModeldoes not use those arrays. This can be seen in the source code of that class

然后您尝试通过调整这些数组来修改表。这永远不会有任何影响,因为DefaultTableModel不使用这些数组。这可以在那个类的源代码中看到

public DefaultTableModel(Object[][] data, Object[] columnNames) {
    setDataVector(data, columnNames);
}

which in the end comes down to

最终归结为

protected static Vector convertToVector(Object[][] anArray) {
    if (anArray == null) {
        return null;
    }
    Vector<Vector> v = new Vector<Vector>(anArray.length);
    for (Object[] o : anArray) {
        v.addElement(convertToVector(o));
    }
    return v;
}

So all the elements of the array are copied into an internal Vectorand the array is no longer used.

因此数组的所有元素都被复制到内部Vector并且不再使用该数组。

Solution: do not update the arrays but update the DefaultTableModel. That class provides all the API you need to add/remove data to/from it.

解决方案:不要更新数组,而是更新DefaultTableModel. 该类提供了向其中添加/从中删除数据所需的所有 API。