Custom AbstractTableModel неправильно отображает данные

Я хочу извлечь данные из таблицы в базе данных на основе столбцов, которые я указываю с помощью AbstractTableModel. В таблице 8 столбцов, но вы хотите показать только 3 из 8 столбцов.

Например:

В базе данных есть такие столбцы: ID, First_Name, Last_Name, ...., Phone_Number. Если я укажу, что хочу отображать в таблице First_Name, Last_Name, Phone_Number, он покажет мне ID, First_Name и Last_Name. Я думаю, что мне следует указать индекс имени столбца из базы данных, чтобы отобразить правильный столбец, но не знаю, как реализовать это в моем пользовательском классе AbstractTableModel.

public class PhysicianModelController extends AbstractTableModel 
{
    PhysicianBroker pb = PhysicianBroker.getPhysicianBroker();

private String[] columnNames =  {"First Name", "Last Name", "Phone Number"};

private ArrayList<Physician> ph = pb.getAllPhysicians();

@Override
public int getRowCount() {
    return ph.size();
}

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

@Override
public String getColumnName(int col)
{
    System.out.println(col);
    return columnNames[col];
}   

@Override
public String getValueAt(int rowIndex, int columnIndex) {  
    System.out.println(rowIndex + " : " + columnIndex);
    Physician p = ph.get(rowIndex);
    switch (columnIndex)
    {
        case 0:
            return Integer.toString(p.getEmployeeId());                
        case 1:
            return p.getFirstName();
        case 2:
            return p.getLastName();
        case 3:
            return p.getBirthDate();
        case 4:
            return p.getStartDate();
        case 5:
            return p.getEndDate();
        case 6:
            return p.getAddress();
        case 7:
            return p.getPhoneNumber();
        default:
            return "Incorrect input";                          
    }
}

public void addRow(Physician p) 
{
    ph.add(p);
    int row = ph.size();
    fireTableRowsInserted(row,row);
    fireTableDataChanged();
}

@Override
public Class getColumnClass(int c)
{
    return getValueAt(0,c).getClass();
}

}

Я переопределил методы getRowCount(), getColumnCount(), getColumnName(), getValueAt() и getColumnClass() в своей реализации. Все работает правильно, как только я задаю все столбцы из таблицы базы данных.

Кто-нибудь будет достаточно любезен, чтобы помочь мне, как это сделать?

Спасибо


person wojg21    schedule 30.03.2013    source источник
comment
Добавлен мой собственный класс AbstractTableModel. Спасибо за быстрый ответ   -  person wojg21    schedule 31.03.2013
comment
Какую именно ошибку вы получаете?   -  person Vishal K    schedule 31.03.2013
comment
Вы не переопределили метод setValueAt   -  person Vishal K    schedule 31.03.2013
comment
@VishalK Я думаю, что setValueAt используется только при редактировании ячеек таблицы вручную.   -  person Eng.Fouad    schedule 31.03.2013
comment
@ wojg21 wojg21, поскольку все столбцы имеют тип String, почему бы не использовать return String.class; внутри getColumnClass()? Кроме того, getValueAt() должно иметь только 3 переключателя.   -  person Eng.Fouad    schedule 31.03.2013
comment
@Eng.Fouad: да, ты прав... но посмотри на метод getValueAt, у него всего 3 столбца, но он тестирует 7 случаев...   -  person Vishal K    schedule 31.03.2013
comment
Чтобы уточнить, я отображаю только три столбца, но как только я нажимаю на строку, я получаю остальную информацию в текстовых полях, где я могу редактировать данные.   -  person wojg21    schedule 31.03.2013
comment
@ wojg21: Итак, вы имеете в виду, что когда вы щелкаете эту строку, новое диалоговое окно будет иметь JTextFields, содержащее другую информацию, которую вы не показываете в JTable. правильно?   -  person Vishal K    schedule 31.03.2013


Ответы (1)


Следите за своим getValueAt методом. У вас есть только три столбца. Таким образом, вы должны вернуть значение в соответствии с этим. Что происходило, что для столбца 0 вы получали идентификатор сотрудника, тогда как вам нужно было имя..Итак...

@Override
public String getValueAt(int rowIndex, int columnIndex) {  
    System.out.println(rowIndex + " : " + columnIndex);
    Physician p = ph.get(rowIndex);
    switch (columnIndex)
    {

        case 0:
            return p.getFirstName();
        case 1:
            return p.getLastName();
        case 2:
            return p.getPhoneNumber();
        default:
            return "Incorrect input";                          
    }
}

ОБНОВЛЕНИЕ
Вот демонстрация кода для добавления строки в JTable. Взгляните на это:

import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.table.*;
import java.util.*;
class Person
{
    String name;
    String roll;
    String subject;
    public Person(String name,String roll,String subject)
    {
        this.name = name;
        this.roll = roll;
        this.subject = subject;
    }
    public String getName()
    {
        return name;
    }
    public String getRoll()
    {
        return roll;
    }
    public String getSubject()
    {
        return subject;
    }
    public void setName(String name)
    {
        this.name = name;
    }
    public void setRoll(String roll)
    {
        this.roll = roll;
    }
    public void setSubject(String subject)
    {
        this.subject = subject;
    }
}
class TableRowAdd extends JFrame  
{
    private JTable table;
    private JScrollPane jsPane;
    private MyModel myModel;
    private JPanel dialogPanel;
    private JTextField tf[];
    private JLabel     lbl[];
    private JButton    button;
    JDialog dialog;
    public void prepareAndShowGUI()
    {
        myModel = new MyModel();
        table = new JTable(myModel);
        jsPane = new JScrollPane(table);
        button = new JButton("Add");
        button.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent evt)
            {
                dialog.setVisible(true);
            }
        });
        getContentPane().add(button,BorderLayout.SOUTH);
        getContentPane().add(jsPane);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        prepareDialogPanel();
        pack();
        setVisible(true);

    }
    private void prepareDialogPanel()
    {
        dialogPanel = new JPanel();
        int col = table.getColumnCount();
        dialogPanel.setLayout(new GridLayout(col,2));
        tf = new JTextField[col];
        lbl = new JLabel[col];
        for (int i = 0; i < col; i++)
        {
            lbl[i] = new JLabel(table.getColumnName(i));
            tf[i] = new JTextField(10);
            dialogPanel.add(lbl[i]);
            dialogPanel.add(tf[i]);
        }
        dialog = new JDialog(this,"Enter details",true);
        dialog.getContentPane().add(dialogPanel);
        JButton okButton = new JButton("OK");
        dialog.getContentPane().add(okButton,BorderLayout.SOUTH);
        okButton.addActionListener( new ActionListener()
        {
            public void actionPerformed(ActionEvent evt)
            {
                dialog.dispose();
                myModel.addRow(new Person(tf[0].getText(),tf[1].getText(),tf[2].getText()));
            }
        });
        dialog.pack();
    }
    private class MyModel extends AbstractTableModel 
    {
        String[] columns = {
                            "Roll No.",
                            "Name",
                            "Subject"
                            };
        ArrayList<Person> inData = new ArrayList<Person>()
                            {
                                {
                                    add(new Person("1","Anthony Hopkins","CS01"));
                                    add(new Person("2","James William","CS02"));
                                    add(new Person("3","Mc. Donald","CS03"));
                                }
                            };
        @Override
        public void setValueAt(Object value, int row, int col)
        {
            Person person = inData.get(row);
            switch(col)
            {
                case 0: 
                    person.setRoll((String)value);
                    break;
                case 1:
                    person.setName((String)value);
                    break;
                case 2:
                    person.setSubject((String)value);
                    break;
                default:
                    System.out.println("Invalid col");

            }
            fireTableCellUpdated(row,col);
        }
        @Override
        public Object getValueAt(int row, int col)
        {
            Person person = inData.get(row);
            switch(col)
            {
                case 0: 
                    return person.getRoll();
                case 1:
                    return person.getName();
                case 2:
                    return person.getSubject();
                default:
                    return null;
            }
        }
        @Override
        public int getColumnCount()
        {
            return columns.length;
        }
        @Override 
        public int getRowCount()
        {
            return inData.size();
        }
        @Override
        public String getColumnName(int col)
        {
            return columns[col];
        }
        @Override
        public boolean isCellEditable(int row ,int col)
        {
            return true;
        }
        //This method adds a row to the table
        public void addRow(Person person)
        {
            inData.add(person);
            fireTableRowsInserted(inData.size() - 1 ,inData.size() - 1);
        }
    }
    public static void main(String st[])
    {
        SwingUtilities.invokeLater( new Runnable()
        {
            @Override
            public void run()
            {
                TableRowAdd td = new TableRowAdd();
                td.prepareAndShowGUI();
            }
        });
    }
}
person Vishal K    schedule 30.03.2013
comment
Спасибо, это имеет смысл, но смогу ли я получить остальные данные (дата_рождения, дата_начала, дата_окончания и т. д.), когда я нажму на строку таблицы? Остальные данные нужны для редактирования на случай ошибки? - person wojg21; 31.03.2013
comment
@mKorbel: ты здесь уже довольно много дней... ты хоть представляешь, почему моя репутация не растет с голосованием? - person Vishal K; 31.03.2013
comment
@ wojg21: В этом случае вы должны создать новый DialogBox или любой другой графический интерфейс, который появляется при нажатии на строку ... и имеет 8 текстовых полей со значениями, заполненными из вашего списка массивов ... и после того, как вы измените данные внутри него, сделайте соответствующие изменение в arraylist тоже.. и изменение в JTable также.. - person Vishal K; 31.03.2013
comment
@Vishal K каждый постер здесь может получить только 200 баллов (20 x голосов) в день от голосов, другой балл (более того) от принятия, наград и голосовавших за собственный вопрос, пхааа, поздравляю, подробный список - person mKorbel; 31.03.2013
comment
@VishalK: Спасибо за очень быстрый вклад. Смогу ли я заполнить текстовые поля из этого класса или мне нужно будет создать новый класс, чтобы просто сделать это? - person wojg21; 31.03.2013
comment
@mKorbel ахха, спасибо за поздравления ;) .. Так что мне придется искать ответы, чтобы их приняли .. ;) - person Vishal K; 31.03.2013
comment
вы не можете видеть только свой собственный профиль или профиль пользователя, который в данный момент вошел в систему ТАК, ссылка одинакова для всех пользователей, я могу видеть там только свои сообщения - person mKorbel; 31.03.2013
comment
comment
@ wojg21 wojg21: вы можете заполнить текстовые поля из того же класса через список массивов, который вы получаете из метода getPhysicianBroker. создайте отдельный метод в своем классе, откройте JDialog, содержащий 8 полей, оставьте поле ID отключенным.. И заполните поля методом arraylist.get(rowindex) и после внесения изменений в значения JTextfield и нажмите «ОК», используйте метод setValueAt() AbstractTableModel ... - person Vishal K; 31.03.2013
comment
@wojg21: см. пример, который я разместил по этой ссылке stackoverflow.com/a/15555696/1981279.. Просто скопируйте код, написанный выше раздела UPDATE, и запустите его. Вы бы узнали. Я надеюсь, что это может помочь вам. - person Vishal K; 31.03.2013
comment
Я включил метод addRow(Physician p) {...}, чтобы добавить строку в список массивов, и я запускаю fireTableRowsInserted(row,row) для перерисовки добавленной строки, но вообще не получаю изменений? Как вы думаете, что я делаю неправильно? - person wojg21; 01.04.2013
comment
@wojg21: где вы добавили этот метод? - person Vishal K; 01.04.2013
comment
@VishalK: внутри класса PhysicianModelController - person wojg21; 01.04.2013
comment
@ wojg21 wojg21, пожалуйста, укажите этот метод в своем посте. Я хочу взглянуть на него. - person Vishal K; 01.04.2013
comment
вместо этого используйте fireTableRowsInserted(row - 1,row - 1);. - person Vishal K; 01.04.2013
comment
@VishalK: только что попробовал, и JTable не добавляет эту строку. Когда я закрываю программу и запускаю ее снова, в таблице появляется новая строка. - person wojg21; 01.04.2013
comment
@ wojg21: Вы имеете в виду, что когда вы закрываете окно, содержащее JTable, а затем снова открываете его, строка становится видимой ..? - person Vishal K; 01.04.2013
comment
@ wojg21: Поскольку у меня нет всего вашего кода ... Поэтому я публикую здесь простую демонстрацию кода ... Он делает именно то, что вы ищете ... взгляните на него ... - person Vishal K; 01.04.2013
comment
@VishalK: ДА!! Сейчас это работает. Я создавал новый экземпляр модели абстрактной таблицы в конструкторе и на панели, где находится моя таблица. Теперь, когда я удалил этот addRow, он работает правильно. Спасибо за вашу помощь. - person wojg21; 01.04.2013
comment
@wojg21 wojg21 Я так рад, что это помогло вам решить вашу проблему ... с удовольствием .. :) И StackOverflow всегда приветствует вас :) - person Vishal K; 01.04.2013