Swing: JScrollPane не обновляется после изменений в структуре JTable - PullRequest
3 голосов
/ 14 марта 2012

У меня есть JTable, связанный с DefaultTableModel, в JPanel с SpringLayout, который находится в JScrollPane.

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

public void updateProjectView() {
    SwingProjectViewerController spvc = SwingProjectViewerController.
            getInstance();
    this.projectTitle.setText(spvc.getAcronym() + " : " + spvc.getTitle());
    Object[][] tableContent =
            spvc.getCriteria(CriteriaPreselectionController.getInstance().
            getCriteriaPreselection());
    Object[] columnsName = new Object[]{"Col1", "Col2"};
    this.tableModel.setDataVector(tableContent, columnsName);
    this.tableModel.fireTableStructureChanged();
} 

Любая помощь очень ценится!

Ответы [ 3 ]

8 голосов
/ 15 марта 2012

Вот тестовая программа, которая показывает, что когда JTable удерживается JScrollPane и DataVector объекта DefaultTableModel изменяется с помощью setDataVector(...), нет необходимости вызывать fireTableDataChanged() в модели, чтобы данные JTable корректно изменились и были смотреть правильно.

Графический интерфейс программы выглядит как изображения ниже.
До изменения данных:
enter image description here

После изменения данных:
enter image description here

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;

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

@SuppressWarnings("serial")
public class ScrollPaneRefresh extends JPanel {
   private static final int PREF_W = 600;
   private static final int PREF_H = 200;
   private Integer[][] initialData = {
         {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 0},
         {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 0},
         {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 0}
         };
   private Integer[][] newData = {
         {1, 2}, {3, 4}
         };
   private String[] columnNames = {"Col1", "Col2"};
   private TablePanel gregsPanel = new TablePanel("With fireTableDataChanged", initialData, columnNames);
   private TablePanel myPanel = new TablePanel("Without fireTableDataChanged", initialData, columnNames);

   public ScrollPaneRefresh() {
      gregsPanel.setButtonAction(new AbstractAction("Change Table Data") {
         private boolean changeToNewData = true;

         @Override
         public void actionPerformed(ActionEvent evt) {
            if (changeToNewData) {
               gregsPanel.setTableModelDataVector(newData, columnNames);
            } else {
               gregsPanel.setTableModelDataVector(initialData, columnNames);
            }
            gregsPanel.fireTableDataChanged();
            changeToNewData = !changeToNewData;
         }
      });
      myPanel.setButtonAction(new AbstractAction("Change Table Data") {
         private boolean changeToNewData = true;

         @Override
         public void actionPerformed(ActionEvent evt) {
            if (changeToNewData) {
               myPanel.setTableModelDataVector(newData, columnNames);
            } else {
               myPanel.setTableModelDataVector(initialData, columnNames);
            }
            // myPanel.getScrollPane().getViewport().revalidate();
            changeToNewData = !changeToNewData;
         }
      });

      setLayout(new GridLayout(1, 0));
      add(gregsPanel.getMainPanel());
      add(myPanel.getMainPanel());
   }

   @Override // so scrollbars will show
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   private static void createAndShowGui() {
      ScrollPaneRefresh mainPanel = new ScrollPaneRefresh();

      JFrame frame = new JFrame("ScrollPaneRefresh");
      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 TablePanel {
   private JPanel mainPanel = new JPanel();
   private DefaultTableModel dm;
   private JTable table = new JTable();
   private JButton changeTableBtn = new JButton();
   private JScrollPane scrollpane = new JScrollPane(table);

   public TablePanel(String title, Object[][] data, Object[] columnNames) {
      dm = new DefaultTableModel(data, columnNames);
      table.setModel(dm);
      JPanel btnPanel = new JPanel();
      btnPanel.add(changeTableBtn);

      mainPanel.setBorder(BorderFactory.createTitledBorder(title));
      mainPanel.setLayout(new BorderLayout(5, 5));
      mainPanel.add(scrollpane, BorderLayout.CENTER);
      mainPanel.add(btnPanel, BorderLayout.PAGE_END);
   }

   public void setButtonAction(Action action) {
      changeTableBtn.setAction(action);
   }

   public void setTableModelDataVector(Object[][] data, Object[] columnNames) {
      dm.setDataVector(data, columnNames);
   }

   public void fireTableDataChanged() {
      dm.fireTableDataChanged();
   }

   public JScrollPane getScrollPane() {
      return scrollpane;
   }

   public JComponent getMainPanel() {
      return mainPanel;
   }
}

Недостаток моего примера выше в том, что он не воспроизводит проблему оригинального плаката, и я думаю, что это связано с использованием нами SpringLayout, который он не полностью описывает или показывает код:

У меня есть JTable, связанный с DefaultTableModel, в JPanel с SpringLayout, который находится в JScrollPane.

Для большей и лучшей помощи, ОП должен будет создать свою собственную sscce , похожую (или более простую), чем то, что я опубликовал выше. Либо так, либо решите его проблему, не используя SpringLayout для хранения JTable, а добавьте его непосредственно в представление окна просмотра JScrollPane или добавьте его в BorderLayout с помощью JPanel (заботясь также о добавлении заголовка JTable) и добавьте его в JScrollPane. окно просмотра.

6 голосов
/ 15 марта 2012

Я сталкивался с этой проблемой раньше.

Попробуйте сделать недействительной JTable и перерисовать JScrollPane.

table.invalidate();
scrollPane.repaint();
2 голосов
/ 18 декабря 2013

Попробуйте вызвать метод revalidate () для таблицы.В соответствии со спецификацией JScrollPanel http://docs.oracle.com/javase/tutorial/uiswing/components/scrollpane.html#update - «Динамически изменяющийся размер клиента» этот метод должен уведомлять панель прокрутки.

table.revalidate();
...