【问题标题】:JTable and DefaultTableModel dosen't refresh table dataJTable 和 DefaultTableModel 不刷新表数据
【发布时间】:2012-09-21 01:57:12
【问题描述】:

我在更新/刷新表中的数据时遇到问题。我正在使用 DefaultTableModel。这是代码,因此请分享您的知识和建议。最好的祝福。

*编辑 1:* 原始代码有一个更新表数据的函数,但由于构造函数一遍又一遍地创建新的 JTable 和新的 JScrollPane,因此证明是错误的。这就是我创建新构造函数并修复该错误的原因。在我实现新的构造函数后,表数据仍然没有刷新。接下来,我尝试调试构造函数接收到的其他类(passDatatoTable 类)的数据。在我使用函数 setValueAt() 和 System.out.println(getValueAt(i,1)) 之后,输出为空。就是这样 首先是创建 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);
    }
});
}

}

第二个是向gui发送数据的类

public class passDatatoTable {
public void passData(){
String str1,str2,str3,str4;
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;
        gui SendStringsToGUI = new gui(str1, str2, str3, str4);

}
}
}

这里是 gui 类。按钮“添加数据”用于填充数据。这是代码:

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 gui(String IP, String PC_NAME, String ttl, String gw) {
//Used this constructor to avoid creating new gui in other classes  
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);
    }

这里是 ActionListener。按钮 next 和 prev 用于分页,按钮“Add Data”用于创建“passDatatoTable”类的变量,用于填充表格数据

代码如下:

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);
 }

 }

【问题讨论】:

  • 您可能希望花费一些精力来描述您的问题的细节。到底发生了什么?应该发生什么?您采取了哪些措施来尝试调试此问题?
  • 好的,我会更新我的问题,我会针对这个问题做些什么
  • 请不要再次发布完全相同的问题 - 而是坚持旧的并尝试理解答案
  • 您还需要 1) 更改您的命名方案以符合 Java 命名约定。类名以大写字母开头,而方法和变量名以小写字母开头。以及 2) 接受您之前问题中的部分答案。

标签: java swing jtable jscrollpane defaulttablemodel


【解决方案1】:

您似乎正在为新的Gui 对象设置表模型数据,该对象与您当前显示的Gui 无关,因此JTable table 中没有出现任何内容。

拥有模型更新方法可以让您根据需要更新模型数据:

public void updateModel(String IP, String PC_NAME, String ttl, String gw) {
   model.setValueAt(IP, i, 0);
   model.setValueAt(PC_NAME, i, 1);
   model.setValueAt(ttl, i, 2);
   model.setValueAt(gw, i, 3);
   i++;
}

您需要将Gui 对象的引用传递给PassDatatoTable 对象。后一个对象在其当前形式中几乎没有功能,因此最好将此功能引入Gui 类。

也无需调用:

model.fireTableDataChanged();

这会自动发生。

【讨论】:

  • 谢谢大家的帮助。我确实使用了您的建议,但效果不佳。感谢您的帮助。
【解决方案2】:

您的问题可能在这里:

class passDatatoTable {
   public void passData() {
      String str1, str2, str3, str4;
      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;
         gui SendStringsToGUI = new gui(str1, str2, str3, str4); // **** line (A)
      }
   }
}

您似乎在 line (A) 上创建了一个新的 gui 对象并将数据传递给它。请注意,这个 gui 对象与正在显示的 gui 对象完全没有关系,因此以这种方式传递数据不会导致显示的数据发生明显的变化。

一种可能的解决方案是通过构造函数参数传递对 gui 对象的引用,然后使用该 gui 对象的公共方法(不是构造函数)来设置或更改数据。

这里有一个简单的例子来说明我的意思:

import java.awt.event.ActionEvent;

import javax.swing.*;

public class GuiTest2 {
   private static void createAndShowGui() {
      Gui2 mainPanel = new Gui2();

      JFrame frame = new JFrame("Gui2");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class Gui2 extends JPanel {
   private JTextField field = new JTextField(10);

   // pass a reference to the GUI object into the controller via
   // its constructor
   private JButton nextBtn = new JButton(new NextController(this, "Next"));

   public Gui2() {
      field.setEditable(false);
      field.setFocusable(false);

      add(field);
      add(nextBtn);
   }

   public void setTextFieldText(String text) {
      field.setText(text);
   }
}

class NextController extends AbstractAction {
   private static final String[] TEXTS = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};
   private Gui2 gui;
   private int index = 0;

   // pass the Gui2 object into the controller's constructor
   public NextController(Gui2 gui, String name) {
      super(name);
      this.gui = gui; // set the Gui2 field with the parameter
   }

   @Override
   public void actionPerformed(ActionEvent arg0) {
      // use the Gui2 object here
      gui.setTextFieldText(TEXTS[index]);
      index++;
      index %= TEXTS.length;
   }

}

【讨论】:

    【解决方案3】:

    谢谢大家的问候。最后我解决了这个问题。最重要的是将一个对象发送到在表中填充数据的类。换句话说,这就是我所做的:

    还记得向表传递数据的类吗?像我在这里做的那样修改它:

    public class passDatatoTable {
    passDatatoTable(ScanFrame gui){
        String str1,str2,str3;
    
        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;
                gui.model.setValueAt(str1, gui.i, 0);
                gui.model.setValueAt(str2, gui.i, 2);
                gui.model.setValueAt(str3, gui.i, 3);
                gui.i++;
        }
    }}
    

    现在让我们回到 gui 类。只需删除构造函数(只需将其重命名为您喜欢的任何内容并在主函数中调用它)。这是示例。注意:所有 2 个构造函数都消失了,因为您不需要它们。

    代码:

    public void CreateAndShowGUI(){
    setVisible(true);//add this line to show 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);
    }
    

    现在重要的标准来了。还记得按钮“添加数据”吗?并非您需要做的就是将此 gui 的引用发送到将数据填充到表的类(passDatatoTable 类),它会起作用。

    public void actionPerformed(ActionEvent e) {
    if ("Add Data".equals(e.getActionCommand())){
    
    passDatatoTable passSomeData = new passDatatoTable();
    passSomeData.passData(this);//here!! just add this and it will work!!
          }
    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);
    }
    
    }
    

    编辑

    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.CreateAndShowGUI();
            }
        });
    }
    
        }
    

    忘记添加主类。就这个。 如果您有任何问题/疑问,请提出。感谢@Hovercraft Full Of Eels 和@Reimeus 为他们的时间提供的大力帮助。

    【讨论】:

    • 您需要在此处以及您在 stackoverflow 上的其他问题中接受最佳答案。
    猜你喜欢
    • 2015-06-03
    • 2012-05-11
    • 1970-01-01
    • 2013-02-15
    • 1970-01-01
    • 2018-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多