I am making a GUI in which i tried to indent the column name.I am also pasting my source code. I am using the GridBagConstraints. This my code where i create a GridBagConstraints but nothing seems to happen
private final static Dimension VOLUME_FIELD_DIMENSION = new Dimension(200, 25);
private final static Dimension NAME_FIELD_DIMENSION = new Dimension(200, 25);
private final static Dimension IMAGE_FIELD_DIMENSION = new Dimension(200, 25);
private final static Dimension DATE_FIELD_DIMENSION = new Dimension(150, 25);
private final static Dimension STATUS_FIELD_DIMENSION = new Dimension(100, 25);
private final static Dimension IMAGE_PANEL_DIMENSION = new Dimension(1000,250);
private static void ImagePanel(ArrayList<ResourceListObject> arr, JPanel imagelist)
{
for(int i=0 ; i < arr.size();i++)
{
try {
// column 1: name
JTextField t1 = createTextField(arr.get(i).getName(), NAME_FIELD_DIMENSION);
// column 2: Created At
JTextField t2 = createTextField(arr.get(i).getCreatedDate(), DATE_FIELD_DIMENSION);
// column 3: Status
JTextField t3 = createTextField(arr.get(i).getStatus(), STATUS_FIELD_DIMENSION);
// column 4: Image Id
JTextField t4 = createTextField(arr.get(i).getID(), IMAGE_FIELD_DIMENSION);
//column 5:Volume Id
JTextField t5 = createTextField(arr.get(i).getVolume_id(), VOLUME_FIELD_DIMENSION);
// construct the row (panel), and then add it to the list panel
JPanel rowPanel = new JPanel();
rowPanel.setLayout(new BoxLayout(rowPanel, BoxLayout.X_AXIS));
rowPanel.add(t1);
rowPanel.add(t2);
rowPanel.add(t3);
rowPanel.add(t4);
rowPanel.add(t5);
imagelist.add(rowPanel);
} catch (Exception e) {
}
}
}
private static JTextField createTextField(String text, Dimension d) {
JTextField tf = new JTextField(text);
tf.setPreferredSize(d);
tf.setBackground(Color.WHITE);
tf.setEditable(false);
return tf;
}
private static JPanel getColumnHeadings() {
GridBagConstraints regularFieldConstraints = new GridBagConstraints();
regularFieldConstraints.fill = GridBagConstraints.BOTH;
String nameColumn = "Image Name";
String secondColumn = "Created At";
String thirdColumn = "Status";
String fourthColumn = "Image Id";
String fifthColumn = "Volume Id";
JLabel name = new JLabel(nameColumn);
JLabel created_at = new JLabel(secondColumn);
JLabel status = new JLabel(thirdColumn);
JLabel id = new JLabel(fourthColumn);
JLabel volume_id = new JLabel(fifthColumn);
name.setPreferredSize(NAME_FIELD_DIMENSION);
created_at.setPreferredSize(DATE_FIELD_DIMENSION);
status.setPreferredSize(STATUS_FIELD_DIMENSION);
id.setPreferredSize(IMAGE_FIELD_DIMENSION);
volume_id.setPreferredSize(VOLUME_FIELD_DIMENSION);
JPanel headingsPanel = new JPanel(new GridBagLayout());
headingsPanel.add(name, regularFieldConstraints);
headingsPanel.add(created_at, regularFieldConstraints);
headingsPanel.add(status, regularFieldConstraints);
headingsPanel.add(id, regularFieldConstraints);
headingsPanel.add(volume_id, regularFieldConstraints);
return headingsPanel;
}
The class sun.swing.table.DefaultTableCellHeaderRenderer is not part of the published API. If you are reluctant to depend on it, consider these alternative options:
Use the existing renderer, as shown here and below.
Use Darryl Burke's Default Table Header Cell Renderer.
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
public class Demo {
/** #see https://stackoverflow.com/a/6644956/230513 */
private static class HeaderRenderer implements TableCellRenderer {
TableCellRenderer renderer;
public HeaderRenderer(JTable table) {
renderer = table.getTableHeader().getDefaultRenderer();
}
#Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int col) {
// assumes JLabel
JLabel label = (JLabel) renderer.getTableCellRendererComponent(
table, value, isSelected, hasFocus, row, col);
label.setHorizontalAlignment(JLabel.LEADING);
return label;
}
}
private void initGUI() {
Object[] columnNames = new Object[]{
"Image Name", "Created At", "Status", "Image Id", "Volume Id"};
DefaultTableModel dtm = new DefaultTableModel(columnNames, 0);
dtm.addRow(new Object[]{"Some picture's name", "2013-10-05",
"Status unknown", "0123456789", "9876543210"});
JTable table = new JTable(dtm);
table.getTableHeader().setDefaultRenderer(new HeaderRenderer(table));
JScrollPane scrollPane = new JScrollPane(table);
JPanel content = new JPanel(new BorderLayout());
content.setPreferredSize(new Dimension(600, 250));
content.add(scrollPane);
JFrame frame = new JFrame("Demo");
frame.setContentPane(content);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Demo().initGUI();
}
});
}
}
I want that all the column name are indents like Image Id
If I'm understanding right, you want column header labels left-aligned just as Image ID. If so, you can use a TableCellRenderer to achive that using JTable.getHeader() method. (if not so, sorry for misunderstand your question)
For instance you can use a sun.swing.table.DefaultTableCellHeaderRenderer which extends from DefaultTableCellRenderer.
Sample Code
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import sun.swing.table.DefaultTableCellHeaderRenderer;
public class Demo{
private void initGUI(){
Object[] columnNames = new Object[]{"Image Name", "Created At", "Status", "Image Id", "Volume Id"};
DefaultTableModel dtm = new DefaultTableModel(columnNames, 0);
dtm.addRow(new Object[]{"Some picture's name", "2013-10-05", "Status unknown", "0123456789", "9876543210"});
/*
* Create your own TableCellRender
*/
TableCellRenderer headerRenderer = new DefaultTableCellHeaderRenderer(){
#Override
public Component getTableCellRendererComponent(JTable jtable, Object o, boolean bln, boolean bln1, int i, int i1) {
super.getTableCellRendererComponent(jtable, o, bln, bln1, i, i1);
setHorizontalAlignment(SwingConstants.LEADING);
return this;
}
};
JTable table = new JTable(dtm);
table.getTableHeader().setDefaultRenderer(headerRenderer);
JScrollPane scrollPane = new JScrollPane(table);
JPanel content = new JPanel(new BorderLayout());
content.setPreferredSize(new Dimension(600,250));
content.add(scrollPane);
JFrame frame = new JFrame("Demo");
frame.setContentPane(content);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.updateComponentTreeUI(frame);
}
catch(ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex){
ex.printStackTrace();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Demo().initGUI();
}
});
}
}
Related
I have the following code:
package view;
import base.BaseView;
import contoller.EvaluatePropertyController;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.util.List;
import java.util.Vector;
public class EvaluatePropertyWindow extends JFrame implements BaseView {
private EvaluatePropertyController controller = new EvaluatePropertyController();
private JLabel queryLB = new JLabel("Запрос: ");
private JTextArea queryTA = new JTextArea();
private JTable table = new JTable();
private Vector<String> columnNames = new Vector<>();
private JButton backBtn = new JButton("Назад");
private JButton executeBtn = new JButton("Выполнить");
private int id;
private MenuWindow window;
EvaluatePropertyWindow(int id, MenuWindow window) {
super("Конструктор отчетов");
setDefaultCloseOperation(EXIT_ON_CLOSE);
this.id = id;
this.window = window;
controller.attachView(this);
controller.setId(id);
initWindow();
}
public void onDataSaved() {
JOptionPane.showMessageDialog(this, "Info saved", "Saved!", JOptionPane.INFORMATION_MESSAGE);
}
#Override
public void initWindow() {
SpringLayout springLayout = new SpringLayout();
getContentPane().setLayout(springLayout);
getContentPane().add(new JScrollPane(table));
springLayout.putConstraint(SpringLayout.HORIZONTAL_CENTER, table, 0, SpringLayout.HORIZONTAL_CENTER, getContentPane());
springLayout.putConstraint(SpringLayout.NORTH, table, 20, SpringLayout.NORTH, getContentPane());
getContentPane().add(queryLB);
springLayout.putConstraint(SpringLayout.WEST, queryLB, 20, SpringLayout.WEST, table);
springLayout.putConstraint(SpringLayout.NORTH, queryLB, 20, SpringLayout.NORTH, getContentPane());
getContentPane().add(queryTA);
queryTA.setPreferredSize(new Dimension(200, 200));
springLayout.putConstraint(SpringLayout.WEST, queryTA, 20, SpringLayout.EAST, queryLB);
springLayout.putConstraint(SpringLayout.NORTH, queryTA, 20, SpringLayout.NORTH, getContentPane());
getContentPane().add(executeBtn);
executeBtn.addActionListener(e -> {
String query = queryTA.getText().replace('\n', ' ');
controller.executeQueries(query);
//System.out.println(query);
});
springLayout.putConstraint(SpringLayout.HORIZONTAL_CENTER, executeBtn, 0, SpringLayout.HORIZONTAL_CENTER, queryTA);
springLayout.putConstraint(SpringLayout.NORTH, executeBtn, 20, SpringLayout.SOUTH, queryTA);
getContentPane().add(backBtn);
backBtn.addActionListener(e -> {
this.setVisible(false);
window.setVisible(true);
});
springLayout.putConstraint(SpringLayout.HORIZONTAL_CENTER, backBtn, 0, SpringLayout.HORIZONTAL_CENTER, executeBtn);
springLayout.putConstraint(SpringLayout.NORTH, backBtn, 20, SpringLayout.SOUTH, executeBtn);
setSize(900, 800);
}
public void setColumnNames(List<String> columns) {
columnNames.clear();
columnNames.addAll(columns);
}
public void onLoaded(Vector<Vector> data) {
table = new JTable(data, columnNames);
System.out.println(data);
System.out.println(columnNames);
}
}
So, there's onLoaded method in the window class, which sets column Names and table data. But when I run the app I got the following output:
The result of
System.out.println(data);
System.out.println(columnNames);
is [[1, nick, 123, #mail.ru, 1]] [u_id, u_login, u_password, u_email, u_role], so data is received correctly. So, why there's no data loaded to JTable?
UPD
Modified code in this way:
public void onLoaded(Vector<Vector> data) {
data.forEach(it -> {
((DefaultTableModel) table.getModel()).addRow(it);
});
System.out.println(data);
System.out.println(columnNames);
String name = "output" + System.currentTimeMillis()+".txt";
}
Still shows nothing, but the output of data is an array of an empty object: [[]]
So there are 2 issues:
You create a new JTable instance on each call of onLoaded and set the data to the new instance, which doesn't help as you should really be modifying the current JTable you have added
In order to completely update/refresh a JTables data (which I assume is what you want as when a query is run you wouldn't want to append new data to old) you would need to extend the DefaultTableModel and create a method which accepts and sets the new data and then fires fireTableDataChanged().
Here is an example of the below:
CustomTableModel.java:
import javax.swing.table.DefaultTableModel;
public class CustomTableModel extends DefaultTableModel {
public CustomTableModel(Object[][] data, String[] columnNames) {
super(data, columnNames);
}
public void setData(Object[][] data) {
this.setDataVector(convertToVector(data), this.columnIdentifiers);
fireTableDataChanged();
}
}
TestApp.java:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.border.EmptyBorder;
public class TestApp {
private JTable table;
public TestApp() {
initComponents();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(TestApp::new);
}
private void initComponents() {
JFrame frame = new JFrame("TestApp");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.setBorder(new EmptyBorder(10, 10, 10, 10));
// setup refresh data button
JButton refreshButton = new JButton("Refresh data");
refreshButton.addActionListener((ActionEvent e) -> {
// lets update the data using a swing worker to not freeze the UI
new SwingWorker<Object[][], Void>() {
#Override
protected Object[][] doInBackground() throws Exception {
return getRandomData();
}
#Override
protected void done() {
try {
// get the data and update the table
Object[][] data = get();
((CustomTableModel) table.getModel()).setData(data);
} catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(TestApp.class.getName()).log(Level.SEVERE, null, ex);
}
}
}.execute();
});
table = new JTable() {
private static final long serialVersionUID = 1L;
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
// setup JTable and custom table model with intial data
Object[][] data = getRandomData();
String[] columnNames = {"Random Data"};
CustomTableModel model = new CustomTableModel(data, columnNames);
table.setModel(model);
// add components to the panel
JScrollPane pane = new JScrollPane(table);
panel.add(pane, BorderLayout.CENTER);
panel.add(refreshButton, BorderLayout.SOUTH);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
private Object[][] getRandomData() {
Object[][] data = {{UUID.randomUUID()}, {UUID.randomUUID()}, {UUID.randomUUID()}, {UUID.randomUUID()}, {UUID.randomUUID()}, {UUID.randomUUID()}};
return data;
}
}
onLoaded is called, but you just asign a value and do not add to the screen
table = new JTable(data, columnNames); // this creates instance and nothing else
your solution is put this new created JTable on the screen or use the old one reference and set the data there trough its TableModel
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 :)
Here is an example table of what I have been using:
JScrollPane scrollPane = new JScrollPane();
contentPane.add(scrollPane);
table = new JTable();
DefaultTableModel tableModel = new DefaultTableModel(new Object[]{"Row 1","Row 2"},0);
table.setModel(tableModel);
scrollPane.setViewportView(table);
I've attempted to use the following autoscrolling methods both with the same result.
// Method 1
JScrollBar vertical = scrollPane.getVerticalScrollBar();
vertical.setValue(vertical.getMaximum());
// Method 2
table.scrollRectToVisible(table.getCellRect(table.getRowCount(), 0, true));
Both examples go to the near-bottom of the table, up until the last (bottom) row that the user has to scroll down to see, only to happen again when another row is added.
EDIT: Example code to replicate the problem
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JScrollPane;
import javax.swing.table.DefaultTableModel;
public class ScrollTableEx extends JFrame {
private static final long serialVersionUID = 1L;
public int i = 100;
public JScrollPane scrollPane;
public JPanel contentPane;
public JTable table;
public JButton add;
public DefaultTableModel model = new DefaultTableModel(new Object[] { "Int (+)", "Int (-)" }, 0);
public static void main(String[] args) {
ScrollTableEx frame = new ScrollTableEx();
frame.setVisible(true);
}
public ScrollTableEx() {
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
setSize(500,400);
scrollPane = new JScrollPane();
table = new JTable();
table.setCellSelectionEnabled(true);
table.setModel(model);
scrollPane.setViewportView(table);
for (int i = 0; i < 100; i++) {
model.addRow(new Object[] { i, i * -1 });
Rectangle goodRect = table.getCellRect(model.getRowCount() - 1, 0, true);
table.scrollRectToVisible(goodRect);
}
JButton add = new JButton("Add");
add.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Rectangle goodRect = table.getCellRect(model.getRowCount() - 1, 0, true);
table.scrollRectToVisible(goodRect);
model.addRow(new Object[] { i, i * -1 });
i++;
}
});
add(add, BorderLayout.NORTH);
add(scrollPane, BorderLayout.CENTER);
}
}
The problem is, JTable and TableModel are both 0 indexed. That is, the last value is actually rowCount - 1.
So when you use table.getCellRect(table.getRowCount(), 0, true), it's actually returning a Rectangle of the right position, just with a 0 height, because the row doesn't actually exist.
Instead you want to use table.getCellRect(table.getRowCount() - 1, 0, true)
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
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.DefaultTableModel;
public class ScrollTable {
public static void main(String[] args) {
new ScrollTable();
}
public ScrollTable() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
final DefaultTableModel model = new DefaultTableModel(new Object[]{"Test"}, 0);
for (int index = 0; index < 100; index++) {
model.addRow(new Object[]{index});
}
final JTable table = new JTable(model);
JButton add = new JButton("Add");
add.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
model.addRow(new Object[]{model.getRowCount()});
Rectangle badRect = table.getCellRect(model.getRowCount(), 0, true);
Rectangle goodRect = table.getCellRect(model.getRowCount() - 1, 0, true);
System.out.println("bad = " + badRect);
System.out.println("goodRect = " + goodRect);
table.scrollRectToVisible(goodRect);
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(table));
frame.add(add, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
I would avoid using .setBounds where possible. It does not take into consideration the variety of differences that exist between different computers and OS's and while it might look perfectly fine when you are developing, when you move it another system, it could produce undeseriable results - IMHO
I am trying to make one column from JTable, invisible by setting width to zero but it could not happen and it remain visible to width = 15. Here is code -
public void restoreColumnWithWidth(int column, int width) {
try {
TableColumn tableColumn = table.getColumnModel().getColumn(column);
table.getTableHeader().setResizingColumn(tableColumn);
tableColumn.setWidth(width);
tableColumn.setMaxWidth(width);
tableColumn.setMinWidth(width);
tableColumn.setPreferredWidth(width);
} catch (Exception ex) {
}
}
What is wrong with the code ?
not, never to remove TableColumn from TableModel, this is wrong suggestion, instead of to use built-in method JTable#removeColumn(TableColumn aColumn),
notice, this method remove column only from View, in the model is removed column still presents, and you can revert that, visible the removed column by using JTable#addColumn(TableColumn aColumn)
EDIT
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Stack;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.WindowConstants;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class TableRowHeight {
private static final long serialVersionUID = 1L;
private JFrame frame = new JFrame("p*s*s*s*s*t*t");
private String[] columnNames = {"one", "two", "Playing with", "four", "five",};
private String[][] data = {
{"aaaaaa", "bbbbbb", "cccccc", "dddddd", "eeeeeee",},
{"bbbbbb", "cccccc", "dddddd", "eeeeeee", "aaaaaa",},
{"cccccc", "dddddd", "eeeeeee", "aaaaaa", "bbbbbb",},
{"dddddd", "eeeeeee", "aaaaaa", "bbbbbb", "cccccc",},
{"eeeeeee", "aaaaaa", "bbbbbb", "cccccc", "dddddd",}};
private JTable table = new JTable(new DefaultTableModel(data, columnNames));
private TableColumnModel tcm = table.getColumnModel();
private Stack<TableColumn> colDeleted = new Stack<TableColumn>();
private JButton restoreButton = new JButton("Restore Column Size");
private JButton hideButton = new JButton("Set Column Size to Zero");
private JButton deleteButton = new JButton("Delete Column");
private JButton addButton = new JButton("Restore Column");
public TableRowHeight() {
table.setRowMargin(4);
table.setRowHeight(30);
table.setFont(new Font("SansSerif", Font.BOLD + Font.PLAIN, 20));
JScrollPane scrollPane = new JScrollPane(table);
for (int i = 0; i < (tcm.getColumnCount()); i++) {
tcm.getColumn(i).setPreferredWidth(100);
}
table.setPreferredScrollableViewportSize(table.getPreferredSize());
restoreButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
tcm.getColumn(2).setPreferredWidth(100);
}
});
hideButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
tcm.getColumn(2).setPreferredWidth(000);
}
});
deleteButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (table.getColumnCount() > 0) {
TableColumn colToDelete = table.getColumnModel().getColumn(table.getColumnCount() - 1);
table.removeColumn(colToDelete);
table.validate();
colDeleted.push(colToDelete);
addButton.setEnabled(true);
} else {
deleteButton.setEnabled(false);
}
}
});
addButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (colDeleted.size() > 0) {
table.addColumn(colDeleted.pop());
table.validate();
deleteButton.setEnabled(true);
} else {
addButton.setEnabled(false);
}
}
});
JPanel btnPanel = new JPanel();
btnPanel.add(hideButton);
btnPanel.add(restoreButton);
btnPanel.add(deleteButton);
btnPanel.add(addButton);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(scrollPane, BorderLayout.CENTER);
frame.add(btnPanel, BorderLayout.SOUTH);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
TableRowHeight frame = new TableRowHeight();
}
});
}
}
EDIT2
you have to check too
JTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
JTable.getTableHeader().setReorderingAllowed(false);
If it should be removed, and not just hidden: Remove it from the table-model.
If it only should be hidden and later shown, you can remove the TableColumn from the TableColumnModel
Making the column height 0 is a bit bogus.