I am new to JTable.
I want to update the jtable data at runtime in button press event.
Here is my code.
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.*;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
public class SetEditableTableCell extends JPanel {
JPanel top = new JPanel();
JPanel bottom = new JPanel();
JButton update = new JButton("Update");
JTable table;
Vector<String> rowOne;
Vector<String> rowTwo;
DefaultTableModel tablemodel;
public SetEditableTableCell() {
this.setLayout(new BorderLayout());
rowOne = new Vector<String>();
rowOne.addElement("Row1-1");
rowOne.addElement("Row1-2");
rowOne.addElement("Row1-3");
rowTwo = new Vector<String>();
rowTwo.addElement("Row2-2");
rowTwo.addElement("Row2-3");
rowTwo.addElement("Row2-4");
Vector<Vector> rowData = new Vector<Vector>();
rowData.addElement(rowOne);
rowData.addElement(rowTwo);
Vector<String> columnNames = new Vector<String>();
columnNames.addElement("Column One");
columnNames.addElement("Column Two");
columnNames.addElement("Column Three");
tablemodel = new DefaultTableModel(rowData, columnNames);
table = new JTable(tablemodel);
// table.setValueAt("aa", 0, 0);
update.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
updatedata();
}
private void updatedata() {
rowOne = new Vector<String>();
rowOne.addElement("updated Row1-1");
rowOne.addElement("updated Row1-2");
rowOne.addElement("updated Row1-3");
rowTwo = new Vector<String>();
rowTwo.addElement("updated Row2-2");
rowTwo.addElement("updated Row2-3");
rowTwo.addElement("updated Row2-4");
// tablemodel.addRow(rowTwo);
tablemodel.fireTableDataChanged();
table.setModel(tablemodel);
System.out.println("button pressed");
// table.setValueAt("aa", 0, 0);
}
});
JScrollPane scrollPane = new JScrollPane(table);
top.add(scrollPane);
bottom.add(update);
add(top, BorderLayout.NORTH);
add(bottom, BorderLayout.SOUTH);
}
public static void main(String args[]) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SetEditableTableCell obj = new SetEditableTableCell();
frame.add(obj);
//frame.setSize(400, 300);
frame.pack();
frame.setVisible(true);
}
}
But it is not updating after pressing update button.
Can anybody solve my problem?
Thanks in advance..
It is not updated because you do not modify the values in your TableModel. By assigning a new Vector to rowOne and rowTwo in your updateData method, you are altering other Vector instances then the ones your TableModel knows about.
A possible solution is to reconstruct the data vector and use the setDataVector method
Construct your own table model using the AbstractTableModel and use it's "event" triggers to notify the JTable of changes to the underlying model
Related
I am running a program with two frames. First one has a table, the second one has a form which allows adding a new user to the table. I think the problem is I didn't add a reference from the mainframe. I was trying different methods to refresh the mainframe programmatically, but it did not help so much. I read many articles on how to to it but I could find a solution. My table usually changes when I close my app and open it again. But I don't think is the right way to do it. I tried to delete elements from DefaultTableModel and populated jtable again, but did not get any results. Here is my code:
public Vector vector_jtable = new Vector();
public MainApp() {
initComponents();
Database b = new Database();
b.getAmountOfRows(getCount);
this.setLocationRelativeTo(null);
printResultDB();
}
//add function that is responsible for addding data to the table
public void postDataJtable() {
System.out.println("The vector is: " + vector_jtable);
Vector<String> header = new Vector<String>();
header.add("Number");
header.add("Name");
header.add("First Payment");
header.add("Next Payment");
header.add("Picture");
header.add("Phone");
header.add("Amount");
header.add("Age");
model = (DefaultTableModel)jTable2.getModel();
model.setDataVector(vector_jtable,header);
}
I created a vector that allows putting data from the second frame.
MainApp app;
public AddStudents(MainApp a) {
initComponents();
app = a;
this.setLocationRelativeTo(null);
jDateChooser1.setDateFormatString("yyyy-MM-dd");
jDateChooser2.setDateFormatString("yyyy-MM-dd");
}
After that, I push the button to send it out and update the mainframe, but nothing happened:
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
app.vector_jtable.add(name);
app.vector_jtable.add(first_p);
app.vector_jtable.add(next_p);
app.vector_jtable.add(picture);
app.vector_jtable.add(phone);
app.vector_jtable.add(amount);
app.vector_jtable.add(age);
app.postDataJtable();
My question. How to add a row in jtable and refresh it. I really stuck in this topic. I need your help.
Don't update the Vector.
When you want to change the data in the table you need to change the data in the TableModel.
You can use the addRow(...) method of the DefaultTableModel to add a new row of data.
So the basic logic is:
Vector<Object> row = new Vector<Object>();
row.add( someVariable1 );
row.add( someVariable2 );
...
modal.addRow( row ):
The model will then tell the table to repaint itself.
Edit:
There is no trick all you need is a reference to the model. Then you update the model.
Here is a simple example to prove the concept works:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
public class SSCCE extends JPanel
{
private DefaultTableModel model;
SSCCE()
{
setLayout( new BorderLayout() );
model = new DefaultTableModel(0, 2);
JTable table = new JTable( model );
add(new JScrollPane( table ));
JButton button = new JButton( "Add Row" );
add(button, BorderLayout.PAGE_END);
button.addActionListener( new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
Vector<Object> row = new Vector<Object>();
row.add( "" + model.getRowCount() );
row.add( new Date().toString() );
model.addRow( row );
}
});
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SSCCE());
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args) throws Exception
{
java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
If it doesn't work for you then you need to debug your code. Maybe you have two "model" variables? Maybe you have to "table" variables. Maybe your code isn't even executed. Did you add any debug statements to the code to make sure it is executed.
We can't solve your problem only point you in the right direction.
You can try some aspects from this example below. The example has two JFrame's - one with a JTable and the other the data entry fields. When the data is entered and the "UpdateTable" button is pressed (in the data entry class) the table is updated.
The example uses java.util.Observer and Observable to achieve this functionality.
The class with table:
import java.awt.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.util.Observer;
import java.util.Observable;
public class TableUpdateTester implements Observer {
private JTable table;
private static final Object[] TABLE_COLUMNS = {"Book", "Author"};
private static final Object [][] TABLE_DATA = {
{"Book 1", "author 1"}, {"Book 2", "author 1"}
};
public static void main(String [] args) {
TableUpdateTester tester = new TableUpdateTester();
new DataEntryClass(tester);
}
public TableUpdateTester() {
JFrame frame = new JFrame("Table Update Tester");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(getTablePanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JPanel getTablePanel() {
table = new JTable(new DefaultTableModel(TABLE_DATA, TABLE_COLUMNS));
JScrollPane scrollpane = new JScrollPane(table);
scrollpane.setPreferredSize(new Dimension(400, 150));
scrollpane.setViewportView(table);
JPanel panel = new JPanel();
panel.add(scrollpane);
return panel;
}
// This is Observer's override method.
#Override public void update(Observable o, Object arg) {
String [] data = (String []) arg;
System.out.println("Data recieving: " + java.util.Arrays.toString(data));
DefaultTableModel model = (DefaultTableModel) table.getModel();
model.addRow(data);
}
}
The data entry class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Observable;
public class DataEntryClass {
public DataEntryClass(TableUpdateTester observer) {
final DataObservable observable = new DataObservable();
observable.addObserver(observer);
JLabel label = new JLabel("Book: ");
final JTextField text = new JTextField(15);
JLabel label2 = new JLabel("Author: ");
final JTextField text2 = new JTextField(15);
JButton button = new JButton("Update Table");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String data1 = text.getText().isEmpty() ? "empty" : text.getText();
String data2 = text2.getText().isEmpty() ? "empty" : text2.getText();
String [] data = {data1, data2};
System.out.println("Data sent: " + java.util.Arrays.toString(data));
observable.changeData(data);
}
});
JPanel panel = new JPanel();
GridLayout grid = new GridLayout(3, 2);
panel.setLayout(grid);
panel.add(label);
panel.add(text);
panel.add(label2);
panel.add(text2);
panel.add(new JLabel(""));
panel.add(button);
JFrame frame = new JFrame();
frame.setTitle("Data Entry");
frame.add(panel);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.pack();
}
}
class DataObservable extends Observable {
DataObservable() {
super();
}
void changeData(Object data) {
// the two methods of Observable class
setChanged();
notifyObservers(data);
}
}
Finally, I found a solution to my problem. I will post my code here.
The Mainframe. I know the app with two frames is not a good option, because it's hard to fix the problem and it usually takes a lot of time to debug it.
/**
* Create the application.
*/
public MainApp() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 689, 345);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
//add table in DefaultTableModel
model = new DefaultTableModel(0,2);
table = new JTable(model);
table.setBounds(58, 38, 524, 197);
frame.getContentPane().add(table);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(0, 0, 4, 4);
frame.getContentPane().add(scrollPane);
JButton btnNewButton = new JButton("Add");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//Call a second frame
//add reference for DefaultTableModel and send it to another frame
AddData frame = new AddData(model);
frame.setVisible(true);
}
});
btnNewButton.setBounds(239, 269, 117, 29);
frame.getContentPane().add(btnNewButton);
}
The second frame, that is responsible for adding a new row in a table.
/**
* Create the frame.
*/
public AddData(DefaultTableModel model) {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JDateChooser dateChooser = new JDateChooser();
dateChooser.setBounds(115, 71, 188, 41);
contentPane.add(dateChooser);
JButton btnNewButton = new JButton("Send");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//MainApp app = new MainApp();
Vector<Object> row = new Vector<Object>();
row.add(""+model.getRowCount());
row.add(dateChooser.getDate().toString());
model.addRow(row);
}
});
btnNewButton.setFont(new Font("Lucida Grande", Font.PLAIN, 20));
btnNewButton.setBounds(165, 192, 117, 41);
contentPane.add(btnNewButton);
}
I found my mistake. I did not send a link of DefaultTableModel into the second frame. That's why it was null every time. It was a really painful experience, but I learned from my mistakes. Thanks, everyone for your help. I really appriciate.
How to update data to JTable from a vector after a button click? I have the code to add data to a JTable but it displays the same data for all the rows. Here's the following code:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import mygui.MainParent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Test {
Vector<String> row;
DefaultTableModel DFMO;
Vector<Vector> rowData;
JFrame frame;
private int count = 0;
public static void main(String arg[]){
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Test window = new Test();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Test() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton mybtn = new JButton("Click Me");
frame.getContentPane().add(mybtn, BorderLayout.SOUTH);
row = new Vector<String>();
rowData = new Vector<Vector>();
Vector<String> columnNames = new Vector<String>();
columnNames.addElement("Column One");
columnNames.addElement("Column Two");
columnNames.addElement("Column Three");
DFMO = new DefaultTableModel(rowData, columnNames);
JTable table = new JTable(DFMO);
JScrollPane scrollPane = new JScrollPane(table);
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
frame.setSize(300, 150);
frame.setVisible(true);
mybtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
datachange();
}
});
datachange();
}
public void datachange(){
count++;
row.addElement("Row"+count+"-Column1");
row.addElement("Row"+count+"-Column2");
row.addElement("Row"+count+"-Column3");
rowData.addElement(row);
DFMO.fireTableDataChanged();
}
}
However, when I execute this code it doesn't show the updated row, even if the count value changes. The following image shows the output of the code.
Try this. You kept adding the same Vector
public void datachange(){
count++;
Vector<String> newRow = new Vector<>();
newRow.addElement("Row"+count+"-Column1");
newRow.addElement("Row"+count+"-Column2");
newRow.addElement("Row"+count+"-Column3");
DFMO.addRow(newRow);
//rowData.addElement(row);
DFMO.fireTableDataChanged();
}
You are adding the data to the Vector object (rowData).
What you should do is add the data directly to the DefaulTableModel object.
Replace
rowData.addElement(row);
with
DMFO.addRow(row);
in your datachange() method.
I get an error when I remove a row a sorted row in a JTable.
The error appears only when the table is sorted, and I know where the error source is:
the method updateRowHeights() in the tableChanged causes an Exception java.lang.ArrayIndexOutOfBoundsException.
I guess that the line int rowHeight = table.getRowHeight(); causes the problem,
but I don't know why.
Here is my code:
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.*;
public class TableExample {
String [] title = new String [] {"Title A", "Title B"};
Object [][] data = new String [][] {{"aaaaaaaaaaaa aaaaaa aaaaaaa", "bbbbbbbb bbbb bbbbbb bbbbbb"},
{"cccccccccc cccccccc ccccccc", "ddddddd ddd dddddddd dddddd"},
{"eeeeeeeeee eeeeeeee eeeeeee", "fffffff ffff ffffff fffffff"}};
private JTable table;
private JFrame frame;
private DefaultTableModel model;
private JScrollPane pane1;
TableExample() {} //constructor
public JPanel createTable() {
JPanel panel = new JPanel();
//creating tables and table models
model = new DefaultTableModel(data, title);
table = new JTable(model);
table.getModel().addTableModelListener(new TableModelListener() {
#Override
public void tableChanged(TableModelEvent e) {
updateRowHeights();
}
});
//enable table sorting
table.setAutoCreateRowSorter(true);
pane1 = new JScrollPane(table);
pane1.setPreferredSize(new Dimension(300,300));
updateRowHeights();
panel.add(pane1);
//delete a row after del keystroke
keyBindings();
return panel;
}
void showTable() {
//create and show frame
JPanel testPanel = createTable();
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(testPanel);
frame.pack();
frame.setVisible(true);
}//showTable
void updateRowHeights() {
for (int row = 0; row < table.getRowCount(); row++) {
int rowHeight = table.getRowHeight();
Component comp = table.prepareRenderer(table.getCellRenderer(row, 1), row, 1);
rowHeight = Math.max(rowHeight, comp.getPreferredSize().height);
table.setRowHeight(row, rowHeight);
}
}
void keyBindings() {
int condition = JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;
InputMap inputMap = table.getInputMap(condition);
ActionMap actionMap = table.getActionMap();
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "delete");
actionMap.put("delete", new AbstractAction() {
public void actionPerformed(ActionEvent e) {
int row = table.getSelectedRow();
model.removeRow(row);
}
});
}
public static void main(String[] args) {
TableExample example = new TableExample();
example.showTable();
}//main
}//TableExample
How can I solve this problem?
As noted here, "When using a sorter, always remember to translate cell coordinates." In your delete action, for example,
row = table.convertRowIndexToModel(row);
A similar problem afflicts updateRowHeights(), although I did not pursue this.
Also consider overriding getPreferredScrollableViewportSize(), instead of calling setPreferredSize(); more details here.
As tested:
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.*;
public class TableExample {
String[] title = new String[]{"Title A", "Title B"};
Object[][] data = new String[][]{
{"aaaaaaaaaaaa aaaaaa aaaaaaa", "bbbbbbbb bbbb bbbbbb bbbbbb"},
{"cccccccccc cccccccc ccccccc", "ddddddd ddd dddddddd dddddd"},
{"eeeeeeeeee eeeeeeee eeeeeee", "fffffff ffff ffffff fffffff"}};
private JTable table;
private JFrame frame;
private DefaultTableModel model;
private JScrollPane pane1;
public JPanel createTable() {
JPanel panel = new JPanel();
//creating tables and table models
model = new DefaultTableModel(data, title);
table = new JTable(model);
//enable table sorting
table.setAutoCreateRowSorter(true);
pane1 = new JScrollPane(table);
panel.add(pane1);
//delete a row after del keystroke
keyBindings();
return panel;
}
void showTable() {
//create and show frame
JPanel testPanel = createTable();
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(testPanel);
frame.pack();
frame.setVisible(true);
}//showTable
void keyBindings() {
int condition = JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;
InputMap inputMap = table.getInputMap(condition);
ActionMap actionMap = table.getActionMap();
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "delete");
actionMap.put("delete", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
int row = table.getSelectedRow();
row = table.convertRowIndexToModel(row);
model.removeRow(row);
}
});
}
public static void main(String[] args) {
TableExample example = new TableExample();
example.showTable();
}//main
}//TableExample
I am working on a the GUI of a piece of code that I have been patching together. I am stuck at this part of the program where I would like a datafile the user chooses to be displayed in a JTable in a preview manner (i.e. the user should not be able to edit the data on the table).
With a button click from Experiment Parameters tab (see screenshot below), I create and run a "PreviewAction" which creates a new tab, and fills it up with the necessary components. Below is the code for DataPreviewAction. EDIT: I also posted a self-contained, minimal version of this that mimics the conditions in the real project, and exhibits the same behaviour.
import java.awt.BorderLayout;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
public class MyFrame extends JFrame {
private JPanel panel1;
private JTabbedPane tabs;
private JButton runButton;
public MyFrame() {
tabs = new JTabbedPane();
panel1 = new JPanel();
runButton = new JButton("go!");
runButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
runButtonActionPerformed(evt);
}
});
panel1.add(runButton);
tabs.addTab("first tab", panel1);
this.add(tabs);
pack();
}
public static void main(String args[]) {
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager
.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(
java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(
java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(
java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(
java.util.logging.Level.SEVERE, null, ex);
}
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
MyFrame frame = new MyFrame();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
private void runButtonActionPerformed(java.awt.event.ActionEvent evt) {
/*
* Normally there is more stuff happening here but this much will do for
* the sake of example
*/
List<String[]> data = new LinkedList<String[]>();
for (int i = 1; i < 1000; i++)
data.add(new String[] { "entry1", "value1", "value2", "value3" });
SwingUtilities.invokeLater(new DataPreviewAction(data, tabs));
}
public class DataPreviewAction implements Runnable {
private JTabbedPane contentHolder;
private List<String[]> data;
public DataPreviewAction(List<String[]> data, JTabbedPane comp) {
this.contentHolder = comp;
this.data = data;
}
#Override
public void run() {
DefaultTableModel previewModel = new DefaultTableModel() {
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
for (String[] datarow : data) {
previewModel.addRow(Arrays.copyOf(datarow, datarow.length,
Object[].class));
}
JTable table = new JTable(previewModel);
JPanel buttonPanel = new JPanel();
buttonPanel.add(new JButton("A button"));
buttonPanel.add(new JLabel(
"Some description for the awesome table below "));
buttonPanel.add(new JButton("another button"));
JScrollPane tablePanel = new JScrollPane(table);
JPanel container = new JPanel();
container.setLayout(new BorderLayout());
container.add(buttonPanel, BorderLayout.NORTH);
container.add(tablePanel, BorderLayout.CENTER);
contentHolder.addTab("Preview", container);
contentHolder.validate();
contentHolder.repaint();
}
}
}
There are at least two problems here:
The JTable (or the JScrollPane) does not render at all
The JScrollPane is not as wide as the frame itself, I have no idea why
I am not all that good in Swing so I might be missing something fundamental. I have checked that the datafile is read properly, and the data model contains the right amount of rows (1000+). SO the table should not be empty.
Suggestions?
JPanel buttonPanel = new JPanel();
buttonPanel.add(new JButton("A button"));
buttonPanel.add(new JLabel("Some description for the awesome table below "));
buttonPanel.add(new JButton("another button"));
JScrollPane tablePanel = new JScrollPane(table);
JPanel container = new JPanel();
container.add(buttonPanel,BorderLayout.NORTH);
container.add(tablePanel,BorderLayout.SOUTH);
contentHolder.addTab("Preview", container);
//contentHolder.validate(); <- NO good
//contentHolder.repaint(); <- --"---
}
JPanel uses FlowLayout (implemented in API, acceptiong only PreferredSize, by default isn't resizable), correct output as is demonstrated in attn image, you have to change default LayoutManager for JPanel to BorderLayout, then code lines
.
container.add(buttonPanel,BorderLayout.NORTH);
container.add(tablePanel,BorderLayout.SOUTH);
will expands JComponents and can be works as you expecting, but I think tablePanel should be placed in CENTER area
EDIT:
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
public class MyFrame extends JFrame {
private JPanel panel1;
private JTabbedPane tabs;
private JButton runButton;
private JFrame frame = new JFrame();
private String[] columnNames = {"Nama", "Nim", "IP", "Hapus Baris ke"};
private Object[][] data = {
{"igor", "B01_125-358", "1.124.01.125", true},
{"lenka", "B21_002-242", "21.124.01.002", true},
{"peter", "B99_001-358", "99.124.01.001", false},
{"zuza", "B12_100-242", "12.124.01.100", true},
{"jozo", "BUS_011-358", "99.124.01.011", false},
{"nora", "B09_154-358", "9.124.01.154", false},
{"xantipa", "B01_001-358", "1.124.01.001", false},};
private DefaultTableModel model = new DefaultTableModel(data, columnNames) {
private static final long serialVersionUID = 1L;
#Override
public boolean isCellEditable(int row, int column) {
switch (column) {
case 3:
return true;
default:
return false;
}
}
#Override
public Class getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
};
public MyFrame() {
tabs = new JTabbedPane();
panel1 = new JPanel();
runButton = new JButton("go!");
runButton.addActionListener(new java.awt.event.ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
//
}
});
panel1.add(runButton);
tabs.addTab("first tab", panel1);
JTable table = new JTable(model);
JPanel buttonPanel = new JPanel();
buttonPanel.add(new JButton("A button"));
buttonPanel.add(new JLabel("Some description for the awesome table below "));
buttonPanel.add(new JButton("another button"));
JScrollPane tablePanel = new JScrollPane(table);
JPanel container = new JPanel();
container.setLayout(new BorderLayout());
container.add(buttonPanel, BorderLayout.NORTH);
container.add(tablePanel, BorderLayout.CENTER);
tabs.addTab("Preview", container);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(tabs);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
MyFrame frame = new MyFrame();
}
});
}
}
EDIT 2nd. e.g.
from code (included your idea about to fill data to model)
import java.awt.BorderLayout;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
public class MyFrame extends JFrame {
private JPanel panel1;
private JTabbedPane tabs;
private JButton runButton;
private JFrame frame = new JFrame();
private String[] columnNames = {"Nama", "Nim", "IP", "Hapus Baris ke"};
private Object[][] data = {
{"igor", "B01_125-358", "1.124.01.125", "true"},
{"lenka", "B21_002-242", "21.124.01.002", "true"},
{"peter", "B99_001-358", "99.124.01.001", "false"},
{"zuza", "B12_100-242", "12.124.01.100", "true"},
{"jozo", "BUS_011-358", "99.124.01.011", "false"},
{"nora", "B09_154-358", "9.124.01.154", "false"},
{"xantipa", "B01_001-358", "1.124.01.001", "false"},};
private DefaultTableModel model = new DefaultTableModel(data, columnNames) {
private static final long serialVersionUID = 1L;
#Override
public boolean isCellEditable(int row, int column) {
switch (column) {
case 3:
return true;
default:
return false;
}
}
#Override
public Class getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
};
public MyFrame() {
tabs = new JTabbedPane();
panel1 = new JPanel();
runButton = new JButton("go!");
runButton.addActionListener(new java.awt.event.ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
List<String[]> data = new LinkedList<String[]>();
for (int i = 1; i < 10; i++) {
data.add(new String[]{"entry1", "value1", "value2", "value3"});
}
for (String[] datarow : data) {
model.addRow(Arrays.copyOf(datarow, datarow.length, Object[].class));
}
}
});
panel1.add(runButton);
tabs.addTab("first tab", panel1);
JTable table = new JTable(model);
JPanel buttonPanel = new JPanel();
buttonPanel.add(new JButton("A button"));
buttonPanel.add(new JLabel("Some description for the awesome table below "));
buttonPanel.add(new JButton("another button"));
JScrollPane tablePanel = new JScrollPane(table);
JPanel container = new JPanel();
container.setLayout(new BorderLayout());
container.add(buttonPanel, BorderLayout.NORTH);
container.add(tablePanel, BorderLayout.CENTER);
tabs.addTab("Preview", container);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(tabs);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
MyFrame frame = new MyFrame();
}
});
}
}
Following the footsteps of mKorbel I ended up doing some debugging. I am providing it here in case others run into the same problem.
It felt quite odd that the table looked OK when the underlying DataModel was supplied a data matrix upon initialisation
private DefaultTableModel model = new DefaultTableModel(data, columnNames)
but it would not show up properly when created with the empty constructor
private DefaultTableModel model = new DefaultTableModel()
and adding rows later with model.addRow(Object[] row);
I started look through the source code, and it turns out with the empty constructor the number of rows and columns for the model (private fields) is initiated to 0 and not updated properly afterwards. I noticed this while debugging since my tables had the dimension of 1370 x 0, which of course does not display properly.
Since I do not want to hardcode the number of rows/cols in advance the best course of action was to convert my "rows" to a matrix and provide the data to the model via constructor (much like mKorbel did). Here comes the fun part, if you want to supply the data then you need to supply the column names as well. THe fact that you have to have column names is counter-intuitive (IMHO), what happens if you dont have/need headers? The data is already in a table form, so I dont understand why column names is so important.
At any rate the following code renders the table at least:
String[] colNames = new String[data[1].length];
for(int i=0; i<colNames.length; i++)
colNames[i] = "C" + i;
DefaultTableModel model = new DefaultTableModel(data,colNames){
#Override
public boolean isCellEditable(int row, int column){
return false;
}};
I am accepting this because it points to the origin of the problem, but I would not be able to pinpoint the problem without mKorbel's answer, so give the upvote to his/her answer :)
i am working on a gui based project and i need to add a jtable in a jpanel.But i am not getting why the table is not being displayed when adding with a scrollpane.Also when adding without scrollpane,the table header is not displayed.
Thanks for any help...
Following is the code i am using..
import javax.swing.*;
import javax.swing.table.*;
import java.sql.*;
import java.awt.*;
import java.awt.event.*;
public class FrmAddEditDN extends JDialog{
JButton JBUpdate = new JButton(new ImageIcon("images/save.png"));
JButton JBReset = new JButton("Reset",new ImageIcon("images/reset.png"));
JButton JBCancel = new JButton("Cancel",new ImageIcon("images/cancel.png"));
JLabel JLPic1 = new JLabel();
JLabel JLBanner = new JLabel("Please fill-up all the required fields.");
public FrmAddEditDN(boolean ADD_STATE,JFrame OwnerForm,Connection srcCN,String srcSQL){
super(OwnerForm,true);
cnAEDN = srcCN;
ADDING_STATE = ADD_STATE;
JPanel JPContainer = new JPanel();
JPContainer.setLayout(null);
String[] columnNames = {
"Sr No","Invoice No","Invoice Date","Consignee","Description","Basic Amount","Invoice Amount","Payment Received",
"EFT Date","Payment Earlier Received","Comm. # %","Comm.Claim # %","Comm. Received","Date","Bank","Remarks"};
String[][] data = {
{"","","","","","","","","","","","","","","",""}
};
DefaultTableModel DTModel = new DefaultTableModel(data,columnNames);
JTable table = new JTable(5,16);
table.setBounds(15,295,screen.width-40,150);
table.setRowHeight(30);
table.setForeground(Color.black);
table.setBackground(Color.white);
JTableHeader header = table.getTableHeader();
header.setForeground(Color.red);
header.setBackground(Color.green);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getColumnModel().getColumn(0).setPreferredWidth(2);
table.getColumnModel().getColumn(1).setPreferredWidth(50);
JScrollPane tableContainer = new JScrollPane();
tableContainer.setViewportView(table);
JPContainer.add(tableContainer);
getContentPane().add(JPContainer);
setSize(screen.width-5,screen.height-45);
setResizable(false);
setLocation(0,0);
}
}
You need to pass Component while creating a JScrollPane.
JScrollPane scrollPane = new JScrollPane(table);
JPContainer.add(scrollPane);