I am trying to get the following text file to come up into this 'Jtable'.. I’m having a hard time getting all the data/columns to appear.. I know that it’s something easy I’m just new to java so any help would be appreciated.
My text file:
1;2;3;4;5;6
1b;2b;3b;4b;5b;6b
1C;2C;3C;4C;5C;6C
My code so far:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
public class JtableTest {
public static void main(String[] args) throws Exception{
Runnable r = new Runnable() {
public void run() {
new JtableTest ().createUI();
}
};
EventQueue.invokeLater(r);
}
private void createUI() {
try {
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
JTable table = new JTable();
String readLine = null;
// DatabaseTableModel tableModel = new DatabaseTableModel();
File file = new File ("JtableTest.txt");
FileReader reader = new FileReader(file);
BufferedReader bufReader = new BufferedReader(reader);//Need to close this
List<Dentry> studentList = new ArrayList<Dentry>();
while ((readLine = bufReader.readLine()) != null) {
String[] splitData = readLine.split(";");
Dentry dentry = new Dentry();
dentry.setName(splitData[0]);
dentry.setNumbers(Arrays.copyOfRange(splitData, 1, splitData.length));
studentList.add(dentry);
}
DatabaseTableModel tableModel = new DatabaseTableModel();
tableModel.setList(studentList);////////////
table.setModel(tableModel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(table));
frame.setTitle("File to JTable");
frame.pack();
frame.setVisible(true);
} catch(IOException ex) {}
}
class Dentry {
private String name;
private String[] number;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber(int index) {
String value = null;
if (index >= 0 && index < number.length) {
value = number[index];
}
return value;
}
public void setNumbers(String... number) {
this.number = number;
class DatabaseTableModel extends AbstractTableModel {
private List<Dentry> list = new ArrayList<Dentry>();
private String[] columnNames = {"1", "2", "3", "4", "5", "6"};
public void setList(List<Dentry> list) {
this.list = list;
fireTableDataChanged();
}
#Override
public String getColumnName(int column) {
return columnNames[column];
}
public int getRowCount() {
return list.size();
}
public int getColumnCount() {
return columnNames.length;
}
public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0:
return list.get(rowIndex).getName();
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
return list.get(rowIndex).getNumber(columnIndex);
default:
return null;
}
}
}
}
}
}
Your data contains 6 columns, but your pojo only allows for 2 (the name and a number).
Start by changing your pojo to support multiple columns
class Dentry {
private String name;
private String[] number;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber(int index) {
String value = null;
if (index >= 0 && index < number.length) {
value = number[index];
}
return value;
}
public void setNumbers(String... number) {
this.number = number;
}
}
All I've done here is allowed your to apply a variable length of numbers and provided a convenience method to access them.
Next, you need to change the way you're loading the data so you can supply all the other elements from the line in the file to your pojo
List<Dentry> studentList = new ArrayList<Dentry>();
while ((readLine = bufReader.readLine()) != null) {
String[] splitData = readLine.split(";");
Dentry dentry = new Dentry();
dentry.setName(splitData[0]);
dentry.setNumbers(Arrays.copyOfRange(splitData, 1, splitData.length));
studentList.add(dentry);
}
This just creates a copy of the splitData from the second element (index 1) to the last element inclusive.
I also changed the getVaueAt method to make it simpler to get the number for the specified column...
public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0:
return list.get(rowIndex).getName();
case 1:
case 2:
case 3:
case 4:
case 5:
return list.get(rowIndex).getNumber(columnIndex - 1);
default:
return null;
}
}
You could just use default as the pojo checks the range of the index, but this is a nice demonstration of the fall through nature of a switch statement.
Related
[UPDATE!!!!]
This is the finish product:
: )
So I am working on a program that helps me organize and print seatings for dinner. I have a student class with instance variables of their FirstName, LastName, etc. I also have a DinnerTable Class that has List of Student and String teacherName. I have created a GUI that so that it is easier to assign different seats. I already have one tab on JTabbedPane that organizes student information(if they are available or not) and randomizes the tables they sit. Now, to better visualize the tables and to make it easier to assign each student to a specific seat, I need to make something like this:
I want to use the actual DinnerTable objects in the TableModel so that whenever I edit something on this Frame, the changes are translated to the objects. However, I am not really sure about what to do. Should I:
1.Create tables(one JTable for each DinnerTable) nested in the cells of a bigger JTable? But how can I perform actions such as swiping students between DinnerTable? Or
2.Align JTables in GridLayout or GridBagLayout? But again, how can I swap students?
Thank you!
package DinnerList;
public class Student
{
private String lastName;
private String firstName;
private int grade;
private int table;
private boolean gender;//Male=true, female=false;
private boolean available; //true=available;
public Student()
{
lastName="";
firstName="";
grade=0;
table=0;
gender=true;
available=true;
}
public Student(String l, String f, int i, boolean g, boolean a)
{
lastName=l;
firstName=f;
grade=i;
gender=g;
available=a;
//table is not written back to the txt.
table=0;
}
//Getters
public String getLastName()
{
return lastName;
}
public String getFirstName()
{
return firstName;
}
public int getGrade()
{
return grade;
}
public int getTable()
{
return table;
}
public boolean getGender()
{
return gender;
}
public boolean getAvailable()
{
return available;
}
//Setters
public void setLastName(String s)
{
this.lastName=s;
}
public void setFirstName(String s)
{
firstName=s;
}
public void setGrade(int i)
{
grade=i;
}
public void setTable(int hiahia)
{
table=hiahia;
}
public void setGender(boolean b)
{
gender=b;
}
public void setAvailable(boolean b)
{
available=b;
}
//Miscellaneous
public String toString()
{
String a="";
a=lastName+","+firstName+","+Integer.toString(grade)+","+Boolean.toString(gender)+","+Boolean.toString(available);
return a;
}
}
///////////////////////////////////
package DinnerList;
import java.util.ArrayList;
import java.util.List;
public class DinnerTable
{
private List<Student> members= new ArrayList<Student>();
private int tableNumber=0;
private int capacity=0;
private String teacherName="";
private boolean available=true;
public DinnerTable(int a, int b, String c, boolean d)
{
tableNumber=a;
capacity=b;
teacherName=c;
available=d;
}
public void setTableNumber(int a) {tableNumber=a;}
public void setCapacity(int a) {capacity=a;}
public void setTeacherName(String a) {teacherName=a;}
public void setAvailable(boolean b) {available=b;}
public void add(Student s)
{
if(available&&(members.size()<capacity))
{ this.members.add(s); }
else if(!available)
{ System.out.println("Adding Student failed, table "+tableNumber+" not available");}
else
{ System.out.println("Adding Student failed, table "+tableNumber+" is full");}
}
public int getTableNumber()
{return tableNumber;}
public int getCapacity() {return this.capacity;}
public String getTeacherName() {return teacherName;}
public boolean getAvailable() {return available;}
public List<Student> getMembers(){return members;}
public void remove(Student s)
{
if(members.contains(s))
{
members.remove(s);
}
else
{
System.out.println("Failed to remove student from table because it wasn't there");
}
}
}
/////////////////////
package DinnerList;
import java.awt.Component;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
public class DinnerTableCellRenderer extends DefaultTableCellRenderer implements TableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column)
{
Object huahua =table.getModel().getValueAt(row, column);
String ppp="";
if(huahua!=null)
{
if(huahua instanceof Student)
{
ppp=((Student) huahua).getLastName()+", "+((Student)huahua).getFirstName();
}
else if(huahua instanceof String)
{
ppp=(String)huahua;
}
else
{
System.out.println("Error: DinnerTableCellRenderer intakes unknown data type");
}
}
else
{
ppp="";
}
JLabel label = (JLabel)super.getTableCellRendererComponent(table, ppp,isSelected, hasFocus,row, column);
return label;
}
}
//////////
package DinnerList;
import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
public class DinnerTableModel extends AbstractTableModel implements TableModel
{
private final String[] columnNames={"","","",""};
private List<DinnerTable> tableCollection= new ArrayList<DinnerTable>();
public DinnerTableModel(List<DinnerTable> huhu)
{
tableCollection.addAll(huhu);
}
public int getColumnCount()
{
return columnNames.length;
}
public int getRowCount()
{
if(tableCollection.size()%4==0)
{
return tableCollection.size()/4;
}
else
{
return (int)(tableCollection.size()/4)+1;
}
}
public String getColumnName(int col)
{
return columnNames[col];
}
public DinnerTable getTableAt(int row, int column)
{
if(tableCollection.size()>=(Integer)((row)/8)+column+1)
{
return tableCollection.get((Integer)((row)/8)+column);
}
else
{
return null;
}
}
public Object getValueAt(int rowIndex, int colIndex)
{
DinnerTable dd= this.getTableAt(rowIndex, colIndex);
String ss= "";
if(dd==null)
{
return "";
}
else if(rowIndex%8==0)
{
return (dd.getTableNumber()+". "+dd.getTeacherName());
}
else if(dd.getMembers().size()>=rowIndex%8)
{
return dd.getMembers().get(rowIndex%8);
}
else
{
return "";
}
}
public Class getColumnClass(int c)
{
return getValueAt(0, c).getClass();
}
public boolean isCellEditable(int row, int col)
{
if(this.getValueAt(row, col) instanceof Student)
{
return true;
}
else
{
return false;
}
}
public void setValueAt(Object aValue, int rowIndex, int columnIndex)
{
if(aValue instanceof Student)
{
if(rowIndex%8!=0)
{
if(null!=this.getTableAt(rowIndex,columnIndex))
{
this.getTableAt(rowIndex,columnIndex).getMembers().set(rowIndex%8-1, (Student)aValue);
}
else
{
System.out.println("error: Attempting to put student in nonexistent table in table list gui");
}
}
else
{
System.out.println("error: Attempting to put student in a string in table list gui");
}
}
else if(aValue instanceof String)
{
System.out.println("error: Attempting to change teacher name in tablelist gui");
}
else
{
System.out.println("error: Attempting to set unknown object type in tablelist gui");
}
}
}
////****************////
JTable tableTable= new JTable(new DinnerTableModel(tables));
for(int hihihi=0;hihihi<tableTable.getColumnCount();hihihi++)
{
tableTable.getColumnModel().getColumn(hihihi).setCellRenderer(new DinnerTableCellRenderer());
}
JScrollPane scrollpaneB1= new JScrollPane();
scrollpaneB1.add(tableTable);
panelB.add(scrollpaneB1);
I am new to programming and have a lot of questions. It is very nice of you to be so patient! : ) However, I have another JTable that intakes another TableModel class. I ran tests and it seems that the model does change whenever the original objects change, even though I didn't use any propertychangelisteners. This is very confusing to me...
JTable is among one of the more complex components in the API (JTree and text components been the next), if you can become comfortable with it, you will be a long way to becoming comfortable with the overall API.
There are any number of ways you could notify the TableModel that an object has changed, but one of the best ways is to do it in a decoupled way, so you don't have to maintain a reference to the TableModel every where the Student object might change.
This suggests that the Student object itself should generate some kind of change event, which interested parties (like the TabelModel) can listen for and take action when they occur.
In this way, you can change the Student object anywhere in your code without caring about who might need to know that the object has changed.
Now, this basically boils down to an observer pattern, Swing implements this kind of functionality in it's listeners, ChangeListener springs to mind as a possible candidest, but PropertyChangeListener is a more powerful option, as it generates events based on the property that has changed.
In some cases, you probably won't care what property has changed, but in the case of TableModel, it's very useful.
This is a simple demonstration of the concept, using two tables. You can edit any value in either table and the opposing table will be updated when the value is committed. Now, you could also modify the instance of Student in your code and you'd get the same result, but this was a simple example to create.
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.AbstractTableModel;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Student student = new Student("Skywalker", "Luke", 0, true, true);
StudentTabelModel leftModel = new StudentTabelModel(student);
StudentTabelModel rightModel = new StudentTabelModel(student);
JTable leftTable = new JTable(leftModel);
leftTable.setGridColor(Color.GRAY);
JTable rightTable = new JTable(rightModel);
rightTable.setGridColor(Color.GRAY);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(0, 2));
frame.add(new JScrollPane(leftTable));
frame.add(new JScrollPane(rightTable));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class StudentTabelModel extends AbstractTableModel {
private List<Student> students = new ArrayList<>(25);
private PropertyChangeListener propertyChangeListener;
public StudentTabelModel(Student... students) {
propertyChangeListener = new StudentPropertyChangeListener();
add(students);
}
public void add(Student... students) {
if (students != null && students.length > 0) {
int startRow = this.students.size();
for (Student student : students) {
student.addPropertyChangeListener(propertyChangeListener);
this.students.add(student);
}
fireTableRowsInserted(startRow, this.students.size() - 1);
}
}
public void remove(Student ...students) {
if (students != null && students.length > 0) {
for (Student student : students) {
int index = this.students.indexOf(student);
if (index != -1) {
student.removePropertyChangeListener(propertyChangeListener);
this.students.remove(student);
fireTableRowsDeleted(index, index);
}
}
}
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
#Override
public int getRowCount() {
return students.size();
}
#Override
public int getColumnCount() {
return 6;
}
#Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
case 1:
return String.class;
case 2:
case 3:
return Integer.class;
case 4:
case 5:
return Boolean.class;
}
return Object.class;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Student student = students.get(rowIndex);
switch (columnIndex) {
case 0:
return student.getLastName();
case 1:
return student.getFirstName();
case 2:
return student.getGrade();
case 3:
return student.getTable();
case 4:
return student.getGender();
case 5:
return student.getAvailable();
}
return "??";
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
Student student = students.get(rowIndex);
switch (columnIndex) {
case 0:
student.setLastName(aValue == null ? null : aValue.toString());
break;
case 1:
student.setFirstName(aValue == null ? null : aValue.toString());
break;
case 2:
if (aValue instanceof Integer) {
student.setGrade((Integer) aValue);
}
break;
case 3:
if (aValue instanceof Integer) {
student.setTable((Integer) aValue);
}
break;
case 4:
if (aValue instanceof Boolean) {
student.setGender((Boolean) aValue);
}
break;
case 5:
if (aValue instanceof Boolean) {
student.setAvailable((Boolean) aValue);
}
break;
}
}
protected class StudentPropertyChangeListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getSource() instanceof Student) {
Student student = (Student) evt.getSource();
int row = students.indexOf(student);
if (row != -1) {
switch (evt.getPropertyName()) {
case "lastName":
fireTableCellUpdated(row, 0);
break;
case "firstName":
fireTableCellUpdated(row, 1);
break;
case "grade":
fireTableCellUpdated(row, 2);
break;
case "table":
fireTableCellUpdated(row, 3);
break;
case "gender":
fireTableCellUpdated(row, 4);
break;
case "avaliable":
fireTableCellUpdated(row, 5);
break;
}
}
}
}
}
}
public class Student {
private String lastName;
private String firstName;
private int grade;
private int table;
private boolean gender;//Male=true, female=false;
private boolean available; //true=available;
private PropertyChangeSupport propertyChangeSupport;
public Student() {
this("", "", 0, false, true);
}
public Student(String l, String f, int i, boolean g, boolean a) {
lastName = l;
firstName = f;
grade = i;
gender = g;
available = a;
//table is not written back to the txt.
table = 0;
propertyChangeSupport = new PropertyChangeSupport(this);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(listener);
}
//Getters
public String getLastName() {
return lastName;
}
public String getFirstName() {
return firstName;
}
public int getGrade() {
return grade;
}
public int getTable() {
return table;
}
public boolean getGender() {
return gender;
}
public boolean getAvailable() {
return available;
}
//Setters
public void setLastName(String s) {
String old = lastName;
this.lastName = s;
propertyChangeSupport.firePropertyChange("lastName", old, lastName);
}
public void setFirstName(String s) {
String old = firstName;
firstName = s;
propertyChangeSupport.firePropertyChange("firstName", old, firstName);
}
public void setGrade(int i) {
int old = grade;
grade = i;
propertyChangeSupport.firePropertyChange("grade", old, grade);
}
public void setTable(int hiahia) {
int old = table;
table = hiahia;
propertyChangeSupport.firePropertyChange("table", old, table);
}
public void setGender(boolean b) {
boolean old = gender;
gender = b;
propertyChangeSupport.firePropertyChange("gender", old, gender);
}
public void setAvailable(boolean b) {
boolean old = available;
available = b;
propertyChangeSupport.firePropertyChange("available", old, available);
}
//Miscellaneous
#Override
public String toString() {
String a = "";
a = lastName + "," + firstName + "," + Integer.toString(grade) + "," + Boolean.toString(gender) + "," + Boolean.toString(available);
return a;
}
}
}
Remember, this relies on the INSTANCE of the Student been shared, if you create two different instances of the Student object and expect that changes in one instance will be reflected in the other, then you will be disappointed
My problem is:
I have a button that will add components to a JList when it is clicked. Each row of the list is composed by two jtextFields. The first is the ID of the row. Every time I press the "Add button", a new row appears, the ID is incremented, and the person who is using the application will write whatever he want on the second jTextField (forward the ID field).
Then it will have a scroll pane for when there are more than 4 rows.
And I want a Remove Button too. To be possible to remove some rows.
Can you help me with this? I don't know how to create a list like this...
Thanks!
Simply use JTable with two columns. This will allow you to establish two columns, one for the ID and one for the value. This will allow you make the second column editable.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.AbstractTableModel;
public class TestTable04 {
public static void main(String[] args) {
new TestTable04();
}
private int id = 0;
public TestTable04() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
final RecordTableModel model = new RecordTableModel();
JTable table = new JTable(model);
JButton add = new JButton("Add");
add.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
model.add(new Record(++id));
}
});
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(add, BorderLayout.SOUTH);
frame.add(new JScrollPane(table));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Record {
private int id;
private String value;
public Record(int id) {
this.id = id;
}
public int getID() {
return id;
}
public void setValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
public class RecordTableModel extends AbstractTableModel {
private List<Record> lstRecords;
public RecordTableModel() {
lstRecords = new ArrayList<>(24);
}
public void add(Record record) {
lstRecords.add(record);
fireTableRowsInserted(lstRecords.size() - 1, lstRecords.size() - 1);
}
public void remove(Record record) {
if (lstRecords.contains(record)) {
int index = lstRecords.indexOf(record);
remove(index);
}
}
public void remove(int index) {
lstRecords.remove(index);
fireTableRowsDeleted(index, index);
}
#Override
public int getRowCount() {
return lstRecords.size();
}
#Override
public int getColumnCount() {
return 2;
}
#Override
public Class<?> getColumnClass(int columnIndex) {
Class clazz = String.class;
switch (columnIndex) {
case 0:
clazz = Integer.class;
break;
}
return clazz;
}
#Override
public String getColumnName(int column) {
String name = null;
switch (column) {
case 0:
name = "ID";
break;
case 1:
name = "Value";
break;
}
return name;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Record record = lstRecords.get(rowIndex);
Object value = null;
switch (columnIndex) {
case 0:
value = record.getID();
break;
case 1:
value = record.getValue();
break;
}
return value;
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 1;
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
Record record = lstRecords.get(rowIndex);
switch (columnIndex) {
case 1:
record.setValue(aValue == null ? null : aValue.toString());
fireTableCellUpdated(rowIndex, columnIndex);
break;
}
}
}
}
Check out How to use tables for more details
You can try creating a custom ListCellRenderer and use JList's setRenderer method to assign it. Override the getListCellRenderer() method of ListCellRenderer to return a JPanel containing two components, a JLabel for the id, and a JTextfield for the user input. You may need to keep a reference to the JTextField elsewhere so that you can retrieve the user input.
To implement the add and remove methods, I would recommend backing the JList with a ListModel. Add and remove to the ListModel will also update the JList UI.
Okay, so what I have is a GUI with a table set up, (mostly, there are still a few problems) but what I need to know is this. Will the following code:
public void removeSelectedRows(JTable table)
{
DefaultTableModel model = (DefaultTableModel) table.getModel();
int[] rows = table.getSelectedRows();
for (int x=0;x<rows.length;++x){
model.removeRow(rows[x]-x);
}
for (int x=0;x<animals;++x)
{
if (Pets[x][0].equalsIgnoreCase(table.getValueAt(table.getSelectedRow(),0)+""))
{
Pets[x][0]=null;
Pets[x][1]=null;
Pets[x][2]=null;
Pets[x][3]=null;
Pets[x][4]=null;
}
}
animals=animals-1;
}
Delete the row that the user has selected? (By that I mean simply clicking on the row and then clicking the delete button). I don't want the row itself to be deleted but I want the values contained within the row the user has selected to be deleted.
Get ready to get you hands dirty.
At some point, DefaultTableModel will no longer meet your needs and you should be prepared to roll your own implementation.
First things first. You're working in an Object Orientated language, you should take advantage of this fact and represent your data as objects.
Secondly, when deleting multiple values from a table, it becomes really tricky quickly. Once you remove the first row, the indices no longer match, you need some way to map the values back to the index that they appear within the model.
Thirdly, the visible row indices may not be the same as those of the model, this is especially true when the table is sorted.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.AbstractTableModel;
public class TestJTable {
public static void main(String[] args) {
new TestJTable();
}
public TestJTable() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
List<Pet> pets = new ArrayList<>(25);
pets.add(new Pet("Tyrannosauridae", "TYRANNOSAURUS", 20, 35));
pets.add(new Pet("Dromaeosauridae", "VELOCIRAPTOR", 45, 90));
pets.add(new Pet("Ceratopsidae", "TRICERATOPS", 15, 30));
pets.add(new Pet("Stegosauridae", "STEGOSAURUS", 22, 25));
pets.add(new Pet("Titanosauridae", "MALAWISAURUS", 22, 25));
pets.add(new Pet("Compsognathidae", "COMPSOGNATHUS", 8, 25));
pets.add(new Pet("Brachiosauridae", "BRACHIOSAURUS", 8, 25));
pets.add(new Pet("Diplodocidae", "DIPLODOCUS", 8, 25));
final PetTableModel model = new PetTableModel(pets);
final JTable table = new JTable(model);
InputMap im = table.getInputMap(JTable.WHEN_FOCUSED);
ActionMap am = table.getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "delete");
am.put("delete", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
int[] indices= table.getSelectedRows();
// Convert the view's row indices to the models...
int[] mapped = new int[indices.length];
for (int index = 0; index < indices.length; index++) {
mapped[index] = table.convertRowIndexToModel(indices[index]);
}
model.removePets(mapped);
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(table));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PetTableModel extends AbstractTableModel {
private List<Pet> pets;
public PetTableModel() {
pets = new ArrayList<>(25);
}
public PetTableModel(List<Pet> pets) {
this.pets = pets;
}
#Override
public int getRowCount() {
return pets.size();
}
public void removePets(int... indicies) {
// Build a tempory list of Pet objects based
// on the supplied indices...
List<Pet> old = new ArrayList<>(indicies.length);
for (int index : indicies) {
old.add(pets.get(index));
}
// For each pet, get it's index in the model
// remove it from the model
// notify any listeners of the change to the model...
for (Pet pet : old) {
int index = pets.indexOf(pet);
pets.remove(pet);
fireTableRowsDeleted(index, index);
}
}
#Override
public Class<?> getColumnClass(int columnIndex) {
Class clazz = String.class;
switch (columnIndex) {
case 2:
case 3:
clazz = Float.class;
}
return clazz;
}
#Override
public String getColumnName(int column) {
String name = "??";
switch (column) {
case 0:
name = "Breed";
break;
case 1:
name = "Category";
break;
case 2:
name = "Buy Price";
break;
case 3:
name = "Sell Price";
break;
}
return name;
}
#Override
public int getColumnCount() {
return 4;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Pet pet = pets.get(rowIndex);
Object value = null;
switch (columnIndex) {
case 0:
value = pet.getBreed();
break;
case 1:
value = pet.getCategory();
break;
case 2:
value = pet.getBuyPrice();
break;
case 3:
value = pet.getSellPrice();
break;
}
return value;
}
public void add(Pet pet) {
pets.add(pet);
fireTableRowsInserted(getRowCount() - 1, getRowCount() - 1);
}
}
public class Pet {
private String breed;
private String category;
private float buyPrice;
private float sellPrice;
public Pet(String breed, String category, float buyPrice, float sellPrice) {
this.breed = breed;
this.category = category;
this.buyPrice = buyPrice;
this.sellPrice = sellPrice;
}
public String getBreed() {
return breed;
}
public float getBuyPrice() {
return buyPrice;
}
public String getCategory() {
return category;
}
public float getSellPrice() {
return sellPrice;
}
}
}
I have a jtable that show a text file contain on own.
Each line in text file is a user record.
I add a edit button to edit each selected row on table.
I use this code, But i don't understand how to do this:
public class AllUser extends AbstractTableModel {
UserInformation uiS = new UserInformation();
String[] col = {"ID", "Fname", "Lname", "Gender", "Date"};
List<UserInformation> Udata = new ArrayList<UserInformation>();
public AllUser() {
BufferedReader br = null;
try {
FileReader fr = new FileReader("xxx.txt");
br = new BufferedReader(fr);
String line;
while ((line = br.readLine()) != null) {
if (line.trim().length() == 0) {
continue;
}
Udata.add(initializeUserInfos(line));
}
} catch (IOException e) {
} finally {
if (br != null) {
try {
br.close();
} catch (IOException ioe) {
}
}
}
}
private UserInformation initializeUserInfos(String str) {
UserInformation Uinit = new UserInformation();
String[] CellArray = str.split(" ");
Uinit.setID(CellArray[0]);
Uinit.setFname(CellArray[1]);
Uinit.setLname(CellArray[2]);
Uinit.setGender(CellArray[3]);
Uinit.setDate(CellArray[4]);
return Uinit;
}
#Override
public String getColumnName(int colu) {
return col[colu];
}
#Override
public int getRowCount() {
return Udata.size();
}
#Override
public int getColumnCount() {
return col.length;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
UserInformation uinfoS = Udata.get(rowIndex);
Object value = null;
switch (columnIndex) {
case 0:
value = uinfoS.getID();
break;
case 1:
value = uinfoS.getFname();
break;
case 2:
value = uinfoS.getLname();
break;
case 3:
value = uinfoS.getGender();
break;
case 4:
value = uinfoS.getDate();
break;
default:
value = "...";
}
return value;
}
#Override
public void setValueAt(Object value, int rowIndex, int columnIndex) {
UserInformation userInfo = new UserInformation();
switch (columnIndex) {
case 0:
userInfo.setID((String) value);
break;
case 1:
userInfo.setFname((String) value);
break;
case 2:
userInfo.setLname((String) value);
break;
case 3:
userInfo.setGender((String) value);
break;
case 4:
userInfo.setDate((String) value);
break;
}
}
public Object getSelectedMember(int row){
UserInformation userInf=new UserInformation();
Object fname=userInf.getFname();
Object lname=userInf.getLname();
Object gender=userInf.getGender();
Object date=userInf.getDate();
return // ?
}
}
I add This getSelectedMember(int row) method to do this, But incorrect!
public class UserPage extends JFrame implements ActionListener {
private AllUser userModel;
private JTable uTable;
private JButton editButton;
public UserPage() {
userModel = new AllUser();
uTable = new JTable(userModel);
add(new JScrollPane(uTable), BorderLayout.CENTER);
add(buttonPanels(), BorderLayout.PAGE_START);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(800, 600);
}
public final JPanel buttonPanels() {
JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
editButton=new JButton("Edit");
editButton.addActionListener(this);
buttonsPanel.add(editButton);
return buttonsPanel;
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()== editButton){
int selectedRow=uTable.getSelectedRow();
if(selectedRow>0){
editUser(selectedRow);
}
else{
JOptionPane.showMessageDialog(null, "Select a user");
}
}
}
public void editUser(int row){
userModel.getSelectedMember(row);
new NewUserFrame_Edit().setVisible(true);
}
}
UserInformation Class:
public class UserInformation {
private String Fname;
private String Lname;
private String ID;
private String Gender;
private String Date;
public String getFname() {
return Fname;
}
public void setFname(String fname) {
this.Fname = fname;
}
public String getLname() {
return Lname;
}
public void setLname(String lname) {
this.Lname = lname;
}
public String getID() {
return ID;
}
public void setID(String i_d) {
this.ID = i_d;
}
public String getGender() {
return Gender;
}
public void setGender(String gndr) {
this.Gender = gndr;
}
public String getDate() {
return Date;
}
public void setDate(String date) {
this.Date = date;
}
#Override
public String toString() {
return ID + " " + Fname + " "
+ Lname + " " + Gender + " " + Date + "\n";
}
}
Sorry for long code.
It sould be like this: when user click a row in jtable and clicked a new page should open and then each old data should insert in own textfiled
Add a MouseListener to the table.
On a double click you create a JDialog that contains the text fields required to edit the data.
You then get the data from the table using the getValueAt(...) method.
the user then edits the data in the text fields.
When the user clicks the "Save" button on the dialog you get the data from each text field and update the table using the setValueAt(...) method.
if you want to save the data in your text file you then need to recreate the enitre file by writing out all the data from the table.
Create an extra column in table and fill the cell value with Edit. Then render the Edit cell with appropriate TableCellRenderer . Add MouseListener to table. Get the row and column number of the cell clicked on table. If the cell clicked contains value Edit , retrieve value at each column of that row and display it in a Panel containing JTextFields . Show that Panel using JOptionpane or in a JDialog. Here is the brief code demo for achieving this task:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.Component;
import java.awt.Color;
import java.awt.Point;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;
import java.awt.Cursor;
import javax.swing.BorderFactory;
import javax.swing.border.BevelBorder;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import javax.swing.JOptionPane;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.event.TableModelListener;
import javax.swing.event.TableModelEvent;
import javax.swing.table.TableModel;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.DefaultTableCellRenderer;
class TableRowEdit extends JFrame
{
private JTable table;
private JScrollPane jsPane;
private TableModel myModel;
private JPanel dialogPanel;
private JTextField tf[];
private JLabel lbl[];
public void prepareAndShowGUI()
{
myModel = new MyModel();
table = new JTable(myModel);
jsPane = new JScrollPane(table);
table.getColumnModel().getColumn(2).setCellRenderer(new LabelCellRenderer());
table.addMouseListener(new MyMouseAdapter());
getContentPane().add(jsPane);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
prepareDialogPanel();
pack();
setVisible(true);
}
private void prepareDialogPanel()
{
dialogPanel = new JPanel();
int col = table.getColumnCount() - 1;
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]);
}
}
private void populateTextField(String[] s)
{
for (int i = 0 ; i < s.length ; i++ )
{
tf[i].setText(s[i]);
}
}
public class LabelCellRenderer extends DefaultTableCellRenderer
{
public Component getTableCellRendererComponent(JTable table,Object oValue, boolean isSelected, boolean hasFocus, int row, int column)
{
Component c = super.getTableCellRendererComponent(table, oValue,isSelected, hasFocus,row, column);
String value = (String)oValue;
JLabel label =(JLabel)c;
label.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
label.setBackground(Color.lightGray);
label.setHorizontalTextPosition(SwingUtilities.CENTER);
label.setHorizontalAlignment(SwingUtilities.CENTER);
label.setText(value);
return label;
}
}
private class MyMouseAdapter extends MouseAdapter
{
#Override
public void mousePressed(MouseEvent evt)
{
int x = evt.getX();
int y = evt.getY();
int row = table.rowAtPoint(new Point(x,y));
int col = table.columnAtPoint(new Point(x,y));
if (col == 2)
{
String arr[] = new String[table.getColumnCount() - 1];
for (int i = 0 ; i < arr.length ; i++)
{
arr[i] = (String)table.getValueAt(row,i);
}
populateTextField(arr);
JOptionPane.showMessageDialog(TableRowEdit.this,dialogPanel,"Information",JOptionPane.INFORMATION_MESSAGE);
//Write here the code to save changed values to file and update to JTable also.
}
}
}
private class MyModel extends AbstractTableModel
{
String[] columns = {
"Roll No.",
"Name",
"Action"
};
String[][] inData = {
{"1","Huge Jackman","Edit"},
{"2","Thomas Andrews","Edit"},
{"3","Shiney","Edit"}
};
#Override
public void setValueAt(Object value, int row, int col)
{
inData[row][col] = (String)value;
}
#Override
public Object getValueAt(int row, int col)
{
return inData[row][col];
}
#Override
public int getColumnCount()
{
return columns.length;
}
#Override
public int getRowCount()
{
return inData.length;
}
#Override
public String getColumnName(int col)
{
return columns[col];
}
}
public static void main(String st[])
{
SwingUtilities.invokeLater( new Runnable()
{
#Override
public void run()
{
TableRowEdit td = new TableRowEdit();
td.prepareAndShowGUI();
}
});
}
}
The following code does not work on Mac OS X 10.6.8 but does on everything else I test, Mac OS X Lion and Windows 7. The obvious explanation would be differences in Apple's java. The table data does not show properly, if at all, on Mac. Here is the code
package com.dramble.dance;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.List;
public class TableDemo extends JPanel {
public TableDemo() {
super(new GridLayout(1,0));
TableModel tableModel = new TableModel();
JTable table = new JTable(tableModel);
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);
for(int i = 0 ; i <= 1900 ; i ++) {
DataRow row = new DataRow(i,"Firstname"+i,"Lastname"+i);
tableModel.appendRow(row);
tableModel.fireTableRowsInserted(i, i);
}
}
private static void createAndShowGUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TableDemo newContentPane = new TableDemo();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private class DataRow {
private String fname, lname;
private Integer id;
public String getFname() {
return fname;
}
public String getLname() {
return lname;
}
public Integer getId() {
return id;
}
public DataRow(Integer id, String fname, String lname) {
super();
this.fname = fname;
this.lname = lname;
this.id = id;
}
}
private class TableModel extends AbstractTableModel {
List<DataRow> data;
private String[] columnNames = {"ID #","First Name","Last Name"};
private Class[] columnTypes = {int.class, String.class, String.class};
public TableModel() {
this.data = new ArrayList<DataRow>();
}
#Override
public int getColumnCount() {
return columnNames.length;
}
#Override
public String getColumnName(int col) {
return columnNames[col];
}
#Override
public int getRowCount() {
return this.data.size();
}
#Override
public Object getValueAt(int row, int col) {
DataRow dataRow = this.data.get(row);
Object returnValue = null;
switch (col) {
case 0:
returnValue = dataRow.getId();
break;
case 1:
returnValue = dataRow.getFname();
break;
case 2:
returnValue = dataRow.getLname();
break;
}
return returnValue;
}
public void appendRow(DataRow row) {
this.data.add(row);
}
#Override
public boolean isCellEditable(int rowIndex, int vColIndex) {
return false;
}
#Override
public Class getColumnClass(int col) {
return columnTypes[col];
}
}
}
Here is an image of the expected behavior as exhibited in Windows
Here is the same code on Mac OS X 10.6.8
The problem lies in the AbstractTableModel, which came as a surprise to me for some reason, I figured it would be EDT and thread related for sure. The problem is in my array for the columnTypes and using int.class. Changing this to Integer.class fixed my issue.
Absent a complete example, it's hard to guess. What you have looks OK, but two thing stand out:
I'm wary of frame.setContentPane(newContentPane), which replaces the frame's content pane with your TableDemo. As TableDemo is a JPanel, it inherits a UI delegate that varies by platform. Instead, consider frame.add(newContentPane), which forwards to the content pane.
Your appendRowData() method in DanceTableModel should fireTableRowsInserted(), so callers can't forget to do so.