Getting Updated JTable Values - java

I'm trying to use a JTable in order to update users in a Java SWING application, currently when I edit a cell the results of the edit can only be obtained if I click a different cell thus firing the tableModelListener. I want to be able to get these changed values on a button event without clicking other cells.
My table definitions:
DefaultTableModel tableModel = new DefaultTableModel();
table = new JTable(tableModel);
tableModel.addColumn("Key");
tableModel.addColumn("Value");
if (PatientView.getSelected() != null){
tableModel.addRow(new Object[]{"Name", PatientView.getSelected().getName()});
tableModel.addRow(new Object[]{"Age", PatientView.getSelected().getAge()});
tableModel.addRow(new Object[]{"Height", PatientView.getSelected().getHeight()});
tableModel.addRow(new Object[]{"Weight", PatientView.getSelected().getWeight()});
tableModel.addRow(new Object[]{"BMI", PatientView.getSelected().getCalculatedBMI()});
}
Table Listener
tableModel.addTableModelListener(new TableModelListener(){
#Override
public void tableChanged(TableModelEvent arg0) {
int row = arg0.getFirstRow();
int column = arg0.getColumn();
Object data = tableModel.getValueAt(0, 1);
System.out.println(data);
}
});
Button Action Listener
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Vector data = tableModel.getDataVector();
System.out.println(table.getValueAt(0, 1));
System.out.println(data);
}
});

I want to be able to get these changed values on a button event without clicking other cells.
See Table Stop Editing.

Related

JCombobox - change value in JTable

first post here.
How to write method which can change values in JTable when app is on running? getValIn() returns me values in english (i used ResourceBundle for that and its work), but if i change the combobox I want have this value in french in JTable.
It's a piece of code.
public void show(){
String[] lang = {"en", "fr"};
List<String> columns = new ArrayList<String>();
Object[][] obj;
JComboBox combobox = new JComboBox(lang);
combobox.setSelectedIndex(0);
combobox.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
if(combobox.getSelectedItem().toString().equals("en")){
selectedLang ="en";
}else{
selectedLang = "fr";
}
}
});
obj = getValIn(selectedLang);
TableModel tb= new DefaultTableModel(obj, columns.toArray());
JTable table = new JTable(tb);
It's not necessary to be in JCombobox.
Thanks, have a nice day!

Java Swing: JTable tableChanged does not work after model is updated

On load, my JTable has 2 columns - . So its a string in the first column and a checkbox in the second column. When I click on the checkbox tableChanged is fired and I can print the row data that was selected.
I need to change the table data when user selects a new category in the dropdown.
When the table data is updated, and I click on the checkbox the tableChanged is no longer fired.
This is what I have:
This is how I am updating the table data:
comboBox.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String t = (String) comboBox.getSelectedItem();
if (t.equals("survey2")) {
String[] columnNames = { "Volume Name", "Select" };
Object[][] data = { { "pt1", false }, { "pt2", false },
{ "pt3", false }, { "pt4", false },
};
model = new DefaultTableModel(data, columnNames);
table.setModel(model);
}
}
});
This is my tableChanged:
table.getModel().addTableModelListener(new TableModelListener() {
#Override
public void tableChanged(TableModelEvent e) {
if ((Boolean)table.getModel().getValueAt(table.getSelectedRow(), 1)) {
System.out.println(">\t"
+ table.getValueAt(table.getSelectedRow(), 0));
} else {
System.out.println(">\t"
+ table.getValueAt(table.getSelectedRow(), 0));
}
}
});
I do not understand why the event is not fired after updating the model. Am I updating the table incorrectly?
You area creating a new TableModel but you added the ChangeListener to the old TableModel.
Don't create a new TableModel!
You can clear the data by using setRowCount(0).
The you can add the new data back to the DefaultTableModel by using:
the setDataVector(...) method, or
by adding data back to the model one row at a time using the addRow(...) method.
So there is no need to create a new TableModel. If you want to create a new TableModel then you also need to add your ChangeListener to this new model.

remove a selected row from jtable on button click

I want to remove a Selected row from a table in java.
The event should be performed on button click.
I will be thank full if someone helps...
For example there is a table named sub_table with 3 columns i.e sub_id, sub_name,class.
when I select one of the rows from that table and click delete button that particular row should be deleted..
It's very simple.
Add ActionListener on button.
Remove selected row from the model attached to table.
Sample code: (table having 2 columns)
Object[][] data = { { "1", "Book1" }, { "2", "Book2" }, { "3", "Book3" },
{ "4", "Book4" } };
String[] columnNames = { "ID", "Name" };
final DefaultTableModel model = new DefaultTableModel(data, columnNames);
final JTable table = new JTable(model);
table.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
JButton button = new JButton("delete");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// check for selected row first
if (table.getSelectedRow() != -1) {
// remove selected row from the model
model.removeRow(table.getSelectedRow());
}
}
});

Remove JTable row that read file records

I am New in java, I have a JTable that can read records from a txt file and show they perfectly.
I want to add a new book to my JFrame that when user select a row on table and clicked the "delete" button, that row should delete and that deleted row records must delete from txt file,too.
my code is this, but it has errors and not seen JTable! :
public class CopyOfAllUserTable extends AbstractTableModel {
Vector data;
Vector column;
public static void main(String[] args){
new CopyOfAllUserTable();
}
public CopyOfAllUserTable() {
String line;
data = new Vector();
column = new Vector();
try {
FileInputStream fis = new FileInputStream("D:\\AllUserRecords.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
StringTokenizer st1 = new StringTokenizer(br.readLine(), " ");
while (st1.hasMoreTokens())
column.addElement(st1.nextToken());
while ((line = br.readLine()) != null) {
StringTokenizer st2 = new StringTokenizer(line, " ");
while (st2.hasMoreTokens())
data.addElement(st2.nextToken());
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
final JFrame frame1=new JFrame();
JTable table=new JTable(data,column);
JButton button1=new JButton("Delete");
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DefaultTableModel model=new DefaultTableModel(data, column);
JTable table=new JTable(model);
}
});
JPanel panel=new JPanel();
panel.add(table);
panel.add(button1);
frame1.add(panel);
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.setBounds(200, 80, 600, 500);
frame1.setVisible(true);
frame1.setEnabled(true);
}
public int getRowCount() {
return data.size() / getColumnCount();
}
public int getColumnCount() {
return column.size();
}
public Object getValueAt(int rowIndex, int columnIndex) {
return (String) data.elementAt((rowIndex * getColumnCount())
+ columnIndex);
}
}
My problem is in delete row, and read records from file to jtable are perfectly successful.
Firstly you're not adding your JTable to the content of the frame.
For containers like: frame.getContentPane() and JPanel you should add the child components by using their #add(...) method.
For example:
final JPanel panel=new JPanel(new BorderLayout());
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DefaultTableModel model=new DefaultTableModel(data, column);
JTable table=new JTable(model);
panel.add(new JScrollPane(table));
panel.revalidate();
}
});
Note that JPanel default layout is FlowLayout. Second thing - if you want to have headers and scrolling in your JTable you need to wrap it with JScrollPane.
Next - you should revalidate the panel after adding/removing/etc.
The second issue is removing rows from JTable. I usually write a method to handle it:
protected void removeRows(final int[] rows) {
int modelRows[] = new int[rows.length];
for(int i = 0; i < rows.length; ++i) {
modelRows[i] = table.convertRowIndexToModel(rows[i]);
}
Arrays.sort(modelRows);
for(int i = modelRows.length - 1; i >= 0; --i) {
int row = modelRows[i];
model.removeRow(row);
}
model.fireTableDataChanged();
}
The convertRowIndexToModel method converts index returned by JTable#getSelectedRows() or JTable#getSelectedRow() (which are the visible indices) to the model indices. If you set RowSorter for your JTable or you leave it to standard implementation:
table.setAutoCreateRowSorter(true);
You are adding table directly to the panel with out using the JScrollPane. Your table header will not be visible if you do like this,
So instead of this,
JPanel panel=new JPanel();
panel.add(table);
Do this,
JPanel panel=new JPanel();
panel.add(new JScrollPane(table));
Why to use JScrollPane? Read this.
When user selects a row and clicks on delete, then get the selected row and remove it from the table list. As you are using AbstractTableModel then you have to write your custom removeRow(..) method to perform this.
Example:
private boolean removeSelectedRow(int row) {
// Remove the row from the list that the table is using.
dataList.remove(row);
// You need to call fireXXX method to refresh the table model.
fireTableDataChanged();
return true;
// If fail return false;
}
If delete is the action then first get the selected row and then call removeSelectedRow(int) like the following,
private void deleteRow() {
int selectedRow = table.getSelectedRow();
boolean deleteStatus = removeSelectedRow(selectedRow);
// Only if the deletion is success then delete from the file.
if(deleteStatus) {
// Delete it from the file too.
}
}
first you have to make sure that something has been selected: when there is something selected than enable the delete button. please look up the JTable java source code #
http://developer.classpath.org/doc/javax/swing/JTable-source.html
and the following code:
1331: /**
1332: * Receives notification when the row selection changes and fires
1333: * appropriate property change events.
1334: *
1335: * #param event the list selection event
1336: */
1337: public void valueChanged(ListSelectionEvent event)
1338: {
1339: firePropertyChange(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY,
1340: Boolean.FALSE, Boolean.TRUE);
1341: int r = getSelectedRow();
1342: int c = getSelectedColumn();
1343: if (r != lastSelectedRow || c != lastSelectedColumn)
1344: {
1345: Accessible o = getAccessibleAt(lastSelectedRow,lastSelectedColumn);
1347: Accessible n = getAccessibleAt(r, c);
1348: firePropertyChange(AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY, o, n);
1350: lastSelectedRow = r;
1351: lastSelectedColumn = c;
1352: }
1353: }
You need to register for the last event to be notified when the selected rows have been changed. Add your own listener to enable the deletebutton based on whether or not a row has been selected which is as you can see in the event itself.
Please use to start with the DefaultTableModel because it will work in 90% of the cases.
And any change is applied to the tabledatamodel which will automatically propogate to the JTable View: normally you never change the view because all selection and scroll information is lost which is something you don't want.
When the delete button is fired the approach is straight forward: there is a row selected, otherwise it is impossible to click it: remove that selected row number from the defaultTableModel, and last but not least I would write simply the entire contents of the datamodel model to the designated file because the table's model hold the actual rows that are indeed displayed in the View.
So please think in terms of models models and models: Views are instantiated only once, packed scrolled etc and than you leave them as is. Models are normally also never changed: you change the contents of the models by adding and or deleting rows. One other tip: use always renderers: those that don't don't, in my humble opinion, don't understand how to work with JTables.
And yes you can leave out the first part to listen for selection changes: sure and pop up a warning to indicate the problem. And in a later stage add the functionality that listens for selection changes to enable and or disable the JButton delete row.
Hope this helps.

Adding actionlistener of column in a jtable

Hi everyone..
I need some help again. :)
How to do this? When I click the column t1, another form must pop-up explaining what happens to column t1, say, at time 1, Instruction 1 is in fetch stage. Then, when I click naman t2 column, Instruction 2 is in fetch stage and Instruction 1 is in Decode stage., so on and so forth.
Thank you in advance. I really need your help..
Regards.. :)
You need to add following chunk of code,
table.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
// This is for double click event on anywhere on JTable
if (e.getClickCount() == 2) {
JTable target = (JTable) e.getSource();
int row = target.getSelectedRow();
int column = target.getSelectedColumn();
// you can play more here to get that cell value and all
new DialogYouWantToOpen(row, Column);
}
}
});
A Dialog which will be opened on double click.
class DialogYouWantToOpen extends JDialog{
JLabel testLabel = new JLable();
public DialogYouWantToOpen(int row, int column){
setSize(200,200)
setLayout(new FlowLayout());
testLabel.setText("User double clicked at row "+row+" and column "+ column);
add(testLabel);
}
}
Generaly it should go something like this
Listener listener = new Listener() {
public void handleEvent(Event e) {
TableColumn column = (TableColumn) e.widget;
System.out.println(column);
}
};
you get the column out of event and then do what you want with it.

Categories