0

I want to extract data from a table in the database based on the columns I specify using an AbstractTableModel. There are 8 columns in the table but want to only show 3 of the 8 columns.

For example:

The database has these columns: ID, First_Name, Last_Name, ...., Phone_Number. If I specify that I want to display First_Name, Last_Name, Phone_Number in the table it shows me ID, First_Name, and Last_Name. I think I should specify the index of the column name from the database to display the correct column but do not know how to implement that in my custom AbstractTableModel class.

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

}

I have overridden the getRowCount(), getColumnCount(), getColumnName(), getValueAt(), and getColumnClass() methods with my implementation. Everything works correctly once I supply all the columns from the database table.

Would someone be kind enough to lend me a hand on how to do this?

Thanks

wojg21
  • 93
  • 1
  • 10
  • Added my custom AbstractTableModel class. Thanks for the quick response – wojg21 Mar 30 '13 at 21:49
  • What exact error are you getting? – Vishal K Mar 30 '13 at 21:52
  • You have not overridden `setValueAt` method – Vishal K Mar 30 '13 at 21:53
  • @VishalK I think `setValueAt` is used only when editing the table cells manually. – Eng.Fouad Mar 30 '13 at 21:57
  • @wojg21 since all the columns of type `String`, why not using `return String.class;` inside `getColumnClass()`? Also, `getValueAt()` should have only 3 switch-cases. – Eng.Fouad Mar 30 '13 at 21:59
  • @Eng.Fouad: yeah you are right..but watch at `getValueAt` method, He got only 3 columns but he is testing for 7 cases.. – Vishal K Mar 30 '13 at 22:02
  • To elaborate, I display only three columns, but once I click on a row I get the rest of the information in textfields where i can edit the data. – wojg21 Mar 30 '13 at 22:05
  • @wojg21: So you mean that when you click that row a new DialogBox will having `JTextFields` containing the other information that you are not showing in `JTable`. right? – Vishal K Mar 30 '13 at 22:09

1 Answers1

1

Watch your getValueAt method. You have only three columns . So you should return the value according to that. What was happening that for column 0 you was getting employee id whereas you wanted Firstname..So on...

@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";                          
    }
}

UPDATE
Here is a code demo to add a row in JTable. Have a look on it:

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();
            }
        });
    }
}
Vishal K
  • 12,976
  • 2
  • 27
  • 38
  • Thank you, that makes sense but will I be able to get the rest of the data (birth_date, start_date, end_date, etc) when I click on the row of the table? I need the rest of the data for editing in case there is a mistake? – wojg21 Mar 30 '13 at 22:10
  • @mKorbel: you are here for quite many days..have you any idea that why my reputations not increasing with upvotes? – Vishal K Mar 30 '13 at 22:12
  • @wojg21: In that case you should create a new DialogBox or any other GUI which popup when you click on a row..and it has 8 textfields with values populated from your arraylist..and after you change the data within it make the corresponding change in arraylist too..and change in JTable also.. – Vishal K Mar 30 '13 at 22:13
  • @Vishal K every posters here can get only 200 points (20 x upvotes) per one day from upvotes, other point are (moreover) from accepting, bounties and upvoters to own question, phaaa congrats, [detailed list is](http://stackoverflow.com/reputation) – mKorbel Mar 30 '13 at 22:17
  • @VishalK: Thanks for the very quick input. Would I be able to populate the textfields from this class or would I need to create a new class to just do that? – wojg21 Mar 30 '13 at 22:19
  • @mKorbel ahha thanks for congrats ;).. So I would have to look for my answers to be accepted..;) – Vishal K Mar 30 '13 at 22:19
  • not you can to see only you own profile, or users profile that is currently logged in SO, link is the same for all users, I can see there only my posts – mKorbel Mar 30 '13 at 22:21
  • @Vishal K [once time I was idiot, with the same question too](http://meta.stackexchange.com/questions/109392/missing-reputation) :-) ..... – mKorbel Mar 30 '13 at 22:23
  • @wojg21: you can populate the textfields from this same class via the arrayList that you are getting from `getPhysicianBroker` method. create separate method in you class there open a `JDialog` containing 8 fields, Keep ID field disabled..And populate the fields by the arraylist.get(rowindex) method and after you make changes in JTextfield values, and click ok use `setValueAt()` method of `AbstractTableModel` ... – Vishal K Mar 30 '13 at 22:25
  • @wojg21: See the example that I have posted in this link http://stackoverflow.com/a/15555696/1981279.. Just copy the code written above **UPDATE** section and run it. You would come to know . I hope it might help you. – Vishal K Mar 30 '13 at 22:34
  • I have included an addRow(Physician p) {...} method to add the row to the arrayList and I run the fireTableRowsInserted(row,row) to repaint the row added but do not get a change at all? What do you think i am doing wrong? – wojg21 Apr 01 '13 at 17:17
  • @wojg21: where have you added this method? – Vishal K Apr 01 '13 at 17:35
  • @VishalK: inside PhysicianModelController class – wojg21 Apr 01 '13 at 17:36
  • @wojg21 pls .put that method in your post..I want to have a look at it. – Vishal K Apr 01 '13 at 17:37
  • use `fireTableRowsInserted(row - 1,row - 1);` instead. – Vishal K Apr 01 '13 at 17:42
  • @VishalK: Just tried it and the JTable does not add that row. When I close the program and run it again the new row appears in the table. – wojg21 Apr 01 '13 at 17:47
  • @wojg21: Do you mean when you close the window containing JTable and then reopen it then the row is visible..? – Vishal K Apr 01 '13 at 18:05
  • @wojg21:Since I don't have your entire code..So I am posting here a simple demo of code .. It does exactly what you are looking for..have a look on it .. – Vishal K Apr 01 '13 at 18:52
  • @VishalK: YES!! It is working now. I was creating a new instance of the abstract table model in the constructor and in the panel where my table is located. Now that I have removed that addRow is functioning correctly. Thanks for your help. – wojg21 Apr 01 '13 at 19:14
  • @wojg21 I am so glad that it helped you to sort out your problem..my pleasure..:) And StackOverflow always welcomes you :) – Vishal K Apr 01 '13 at 19:15