Использование JTable приводит к некорректной загрузке остальной части приложения - PullRequest
0 голосов
/ 18 марта 2019

Прежде всего, это для школьного проекта, поэтому я не могу загрузить свой полный код. Нам дали пустой проект и попросили добавить в него функциональность.

Я хочу иметь возможность отображать данные с сервера в различных таблицах, каждая из которых находится на отдельной вкладке, причем каждая «страница» имеет возможность добавлять, редактировать или удалять записи в таблице.

Поскольку у меня довольно много разных таблиц, я написал родительский класс Page, который будет содержать таблицу и несколько JPanels, к которым я могу добавить кнопки при необходимости.

Однако всякий раз, когда я пытаюсь добавить JTable на страницу, это вызывает непредсказуемое поведение между вкладками - обратите внимание, это происходит независимо от того, использую ли я TableModel или нет.

Я пытался использовать метки для отображения того, где должны быть компоненты, что работает нормально, но использование реальных таблиц приводит к тому, что метки-заполнители и вкладки вверху скрываются.

Вкладка с метками для иллюстрации того, где компоненты ДОЛЖНЫ быть

Вкладка после попытки добавить JTable - остальная часть кода (включая другие метки-заполнители) остается такой же

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

Это код для Page.java:

import java.awt.*;

import javax.swing.*;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;

public class Page extends JPanel {
    private static final long serialVersionUID = -4661566573959270000L;
    protected JTable table;
    protected JPanel addPanel;
    protected JPanel fieldPanel;
    protected JPanel buttonPanel;
    protected TableModel model;
    public Page(String[] names) {
        this.setLayout(new GridLayout(2,1));
        final class MyTableModel implements TableModel{
            private static final long serialVersionUID = -4661566573959270000L;
            private String[] columnNames;
            private Object[][] data;
            public MyTableModel(String[] names) {
                columnNames=names;
                data=new Object[names.length][0];
            }
            @Override
            public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
                if(isCellEditable(rowIndex, columnIndex)) {
                    data[rowIndex][columnIndex] = aValue;
                }
             }     

             @Override
             public void removeTableModelListener(TableModelListener l) {

             }

             @Override
             public boolean isCellEditable(int rowIndex, int columnIndex) {
                      return false;
             }

             @Override
             public Object getValueAt(int rowIndex, int columnIndex) {
                 return data[rowIndex][columnIndex];
             }

             @Override
             public int getRowCount() {
                 return data.length;
             }

             @Override
             public String getColumnName(int columnIndex) {
                 return columnNames[columnIndex];
             }

             @Override
             public int getColumnCount() {
                 return columnNames.length;
             }

             @Override
             public Class<?> getColumnClass(int columnIndex) {
                 try {
                     return getValueAt(0, columnIndex).getClass();
                 }
                 catch (Exception e) {
                     return null;
                 }
             }

             @Override
             public void addTableModelListener(TableModelListener l) {

             }
         };


         /**
         * creating and adding a table
         * this is the problematic bit
         */
         table = new JTable(new MyTableModel(names));
         this.add(table);
         //this.add(new Label("Table"));



         //panels for layout
         addPanel = new JPanel();
         fieldPanel = new JPanel();
         buttonPanel = new JPanel();
         //assigning positions
         this.add(addPanel);
         addPanel.setLayout(new BorderLayout());
         addPanel.add(fieldPanel, BorderLayout.CENTER);
         addPanel.add(buttonPanel, BorderLayout.SOUTH);
         //placeholder labels
         fieldPanel.add(new JLabel("Insert fields here"));
         buttonPanel.add(new Button("Buttons"));
     }
 }

Я добавляю новые страницы в свою систему вкладок со следующим кодом:

JTabbedPane tabs = new JTabbedPane();
tabs.add("A", new Page(new String[]{"A"}));
tabs.add("B", new Page(new String[]{"B"}));
tabs.add("C", new Page(new String[]{"C"}));
tabs.add("D", new Page(new String[]{"D"}));

С String [], являющимся именами столбцов, которые я хочу отобразить - обратите внимание, что они будут заменены реальными полезными именами, как только таблицы будут работать правильно.

Есть идеи, что я делаю не так? Я пытался перекрасить свой фрейм с помощью события ChangeListener, но это, похоже, ничего не делает.

Спасибо!

EDIT Включена полная версия кода. Используйте приведенный выше код для Page и используйте его в главном классе:

import java.awt.*;
import javax.swing.*;
public class Main {
    public static void main(String[] args) {
        JFrame window = new JFrame("Components and Containers");
        window.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE) ;
        window.setSize(800,600);

        Container pane = window.getContentPane();
        JTabbedPane tabs = new JTabbedPane();
        tabs.add("A", new Page(new String[]{"A"}));
        tabs.add("B", new Page(new String[]{"B"}));
        tabs.add("C", new Page(new String[]{"C"}));
        tabs.add("D", new Page(new String[]{"D"}));
        pane.add(tabs);
        window.setVisible(true);
    }
}

Я попытался вместо этого добавить таблицу в ScrollPanel, и таблица станет видимой только при наведении на нее курсора. Вкладки по-прежнему не отображаются правильно.

Результат добавления таблицы в отдельную ScrollPanel, а не непосредственно в компонент.

1 Ответ

2 голосов
/ 18 марта 2019

Ваш класс модели таблицы несовместим с порядком строк / столбцов.

В конструкторе вы пишете

data=new Object[names.length][0];

, что означает, что первым индексом является номер столбца ивторой индекс - номер строки.

Однако при доступе к данным (в getValueAt, setValueAt) индексы используются наоборот:

data[rowIndex][columnIndex]

А также, это:

public int getRowCount() {
    return data.length;
}

возвращает количество столбцов как количество строк, что означает, что вы получите ArrayIndexOutOfBoundsException, как только JTable попытается вызвать getValueAt(0, 0).


Чтобы решить эту проблему, вы должны инициализировать массив данных в конструкторе с помощью:

data=new Object[0][names.length];
...