I am using the following code to create JTable inside JScrollPane to show column headers
JTable won't show column headers
String[] columnNames = {"header1", "header2", "header2", "header3"};
Object[][] data = new Object[num][4];
//feed values into data using for
JTable chart = new JTable(data, columnNames);
chart.setShowVerticalLines(false);
chart.setEnabled(false);
chart.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
JScrollPane sp = new JScrollPane(chart);
sp.setPreferredSize(new Dimension(width, chart.getHeight() + 5));
panel.add(sp);
The problem is that I need to compute a height for JScrollPane so the whole JTable can be visible and JScrollBars won't appear. How can I do that?
num changes from 2 to 4 and if it is 4 then scroll bars appear. width is fixed.
The basic approach is
JTable is-a Scrollable which unfortunately doesn't do too well in calculating a prefScrollable, so you have to do it yourself
either use a LayoutManager which lays out all at their pref (f.i. FlowLayout), or implement max in JTable (if you use a resizing but max-respecting manager like BoxLayout)
JScrollPane is-a validationRoot, so the revalidate must happen on the parent of the scrollPane
Something like:
final JTable table = new JTable(10, 5) {
#Override
public Dimension getPreferredScrollableViewportSize() {
Dimension dim = super.getPreferredScrollableViewportSize();
// here we return the pref height
dim.height = getPreferredSize().height;
return dim;
}
};
final JComponent content = new JPanel();
content.add(new JScrollPane(table));
Action add = new AbstractAction("add row") {
#Override
public void actionPerformed(ActionEvent e) {
((DefaultTableModel) table.getModel()).addRow(new Object[]{});
content.revalidate();
}
};
converting my comments here to the answer, crazy, crazy, really crazy, everything could be complicating the simple things, by assuming that every rows have got the same size, long methods for columnmodel, expanding methods, have to add column renderer/editor, etc..
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.TableColumn;
public class TablePreferredSize {
private String[] head = {"One", "Two", "Three", "Four", "Five", "Six"};
private String[][] data = new String[25][6];
private JTable table = new JTable(data, head);
private DefaultTableColumnModel columnModel = new DefaultTableColumnModel();
private TableColumn column = new TableColumn();
private int rowHeight = 23;
private int rowWidth = 0;
public TablePreferredSize() {
table.setRowHeight(23);
table.setIntercellSpacing(new Dimension(1, 1));
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
column = new TableColumn();
column.setModelIndex(0);
column.setHeaderValue("One");
column.setPreferredWidth(250);
columnModel.addColumn(column);
rowWidth += column.getPreferredWidth();
column = new TableColumn();
column.setModelIndex(1);
column.setHeaderValue("Two");
column.setPreferredWidth(120);
columnModel.addColumn(column);
rowWidth += column.getPreferredWidth();
column = new TableColumn();
column.setModelIndex(2);
column.setHeaderValue("Three");
column.setPreferredWidth(80);
columnModel.addColumn(column);
rowWidth += column.getPreferredWidth();
column = new TableColumn();
column.setModelIndex(3);
column.setHeaderValue("Four");
column.setPreferredWidth(120);
columnModel.addColumn(column);
column = new TableColumn();
column.setModelIndex(4);
column.setHeaderValue("Five");
column.setPreferredWidth(70);
columnModel.addColumn(column);
column = new TableColumn();
column.setModelIndex(5);
column.setHeaderValue("Six");
column.setPreferredWidth(30);
columnModel.addColumn(column);
table.setColumnModel(columnModel);
table.setPreferredScrollableViewportSize(new Dimension(rowWidth, 12 * rowHeight));
JScrollPane scrollPane = new JScrollPane(table);
JFrame frame = new JFrame("Table PreferredSize");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(scrollPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
TablePreferredSize t = new TablePreferredSize();
}
});
}
}
What if you call ?
sp.getColumnHeader().getHeight()
Related
I created a JScrollPane with a JTable on it. When the table's height is larger than the height of the scroll pane, a scroll bar appears. If minimize the JFrame although I didn't change the size of it, the scroll bar vanishes and the scroll pane extends downwards.
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class Main {
static String columns[] = {"Date", "Price", "URL", "Expired"};
static String data[][] = new String[8][4];
/*
* The data that should be provided to the JTable is
* replaced with some example data because the method
* of getting this data is complicated and doesn't
* change anything at the outcome.
*/
public static void main(String[] args) {
loadGui();
}
public static void loadGui() {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 4; j++) {
data[i][j] = "Example data " + i + " " + j;
}
}
JFrame mainFrame = new JFrame();
mainFrame.setSize(800, 300);
mainFrame.setResizable(false);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setVisible(true);
JTable table = new JTable(data, columns);;
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane pane = new JScrollPane(table);
pane.setViewportView(table);
pane.setSize(785, 100);
mainFrame.add(pane);
table.getTableHeader().setReorderingAllowed(false);
table.setDefaultEditor(Object.class, null);
table.setFocusable(false);
table.setRowSelectionAllowed(false);
}
}
I search for a way to stop the scroll pane to extend downwards and keeping it in its size.
You can use BorderLayout layout manager to make your scroll pane stick to the top
You can use setPreffered size to suggest to the layout manager what dimensions element should have if possible
Use setVisible when all components are already added
public class Main {
static String columns[] = {"Date", "Price", "URL", "Expired"};
static String data[][] = new String[8][4];
/*
* The data that should be provided to the JTable is
* replaced with some example data because the method
* of getting this data is complicated and doesn't
* change anything at the outcome.
*/
public static void main(String[] args) {
loadGui();
}
public static void loadGui() {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 4; j++) {
data[i][j] = "Example data " + i + " " + j;
}
}
JFrame mainFrame = new JFrame();
mainFrame.setSize(800, 300);
mainFrame.setResizable(false);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//set our layour manager
mainFrame.setLayout(new BorderLayout());
JTable table = new JTable(data, columns);;
table.setPreferredScrollableViewportSize(table.getPreferredSize());
table.getTableHeader().setReorderingAllowed(false);
table.setDefaultEditor(Object.class, null);
table.setFocusable(false);
table.setRowSelectionAllowed(false);
JScrollPane pane = new JScrollPane(table);
pane.setViewportView(table);
// we would like to have its height at 100px, width does not matter thus 0
pane.setPreferredSize(new Dimension(0,100));
//using NORTH will "stick" the component to the top
mainFrame.add(pane,BorderLayout.NORTH);
//all the calculation will be done now. The same happens when you minimize/restore the frame.
mainFrame.setVisible(true);
}
}
Happy new year everyone, i've a problem chaning the height of a JTable header, I appreciate if someone can help. The Method I'am using is changing also the backgroundcolor etc.
Thanks
public static void ChangeJTableBackgroundColor(JTable InTable){
JTable mytable = InTable;
Color mycolor = new Color(248, 201, 171);
mytable.setOpaque(true);
mytable.setFillsViewportHeight(true);
mytable.setBackground(mycolor);
Color mycolorhead = new Color(249, 168, 117);
mytable.getTableHeader().setBackground(mycolorhead);
mytable.getTableHeader().setPreferredSize(new Dimension(1,50));
}
There are lots of ways you "might" increase the height of the header, which you choose will depend on what you want to achieve. One thing to keep in mind though, is trying to find a solution which respects the diverse rendering environments which you program might need to run in.
You could...
Simple change the font size. This might sound silly, but you'd be surprised at how simple it really is, for example...
DefaultTableModel model = new DefaultTableModel(10, 10);
JTable table = new JTable(model);
JTableHeader header = table.getTableHeader();
header.setFont(header.getFont().deriveFont(30f));
You could...
Take advantage of Swing's inbuilt HTML support. This example sets up a HTML table with a defined cell height
DefaultTableModel model = new DefaultTableModel(10, 10);
JTable table = new JTable(model);
TableColumnModel columnModel = table.getColumnModel();
String prefix = "<html><body><table><tr><td height=100>";
String suffix = "</td></tr></table></body><html>";
for (int col = 0; col < columnModel.getColumnCount(); col++) {
TableColumn column = columnModel.getColumn(col);
String text = prefix + Character.toString((char)('A' + col)) + suffix;
System.out.println(text);
column.setHeaderValue(text);
}
You could...
Just supply your own TableCellRenderer as the default cell renderer for the table header. This is a little tricky, as it's difficult to mimic the default renderer used by the current look and feel and the UIManager doesn't help. Instead, you need to consider using a "proxy" approach, where by you apply the changes you need to the existing header renderer instead.
DefaultTableModel model = new DefaultTableModel(10, 10);
JTable table = new JTable(model);
JTableHeader header = table.getTableHeader();
TableCellRenderer proxy = header.getDefaultRenderer();
header.setDefaultRenderer(new TableCellRenderer() {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component comp = proxy.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (comp instanceof JLabel) {
JLabel label = (JLabel) comp;
label.setBorder(new CompoundBorder(label.getBorder(), new EmptyBorder(50, 0, 50, 0)));
}
return comp;
}
});
As far as solutions go, this is probably my preferred, as it takes into account more of the variables involved in determine the preferred size of the column header itself
import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.Arrays;
import javax.swing.*;
import javax.swing.table.*;
public class TableHeaderHeightTest {
private static int HEADER_HEIGHT = 32;
private JTable makeTable() {
JTable table = new JTable(new DefaultTableModel(2, 20));
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
return table;
}
public JComponent makeUI() {
JPanel p = new JPanel(new GridLayout(2,1));
JTable table1 = makeTable();
//Bad: >>>>
JTableHeader header = table1.getTableHeader();
//Dimension d = header.getPreferredSize();
//d.height = HEADER_HEIGHT;
//header.setPreferredSize(d); //addColumn case test
header.setPreferredSize(new Dimension(100, HEADER_HEIGHT));
p.add(makeTitledPanel("Bad: JTableHeader#setPreferredSize(...)", new JScrollPane(table1)));
//<<<<
JTable table2 = makeTable();
JScrollPane scroll = new JScrollPane(table2);
scroll.setColumnHeader(new JViewport() {
#Override public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
d.height = HEADER_HEIGHT;
return d;
}
});
// //or
// table2.setTableHeader(new JTableHeader(table2.getColumnModel()) {
// #Override public Dimension getPreferredSize() {
// Dimension d = super.getPreferredSize();
// d.height = HEADER_HEIGHT;
// return d;
// }
// });
p.add(makeTitledPanel("Override getPreferredSize()", scroll));
final List<JTable> list = Arrays.asList(table1, table2);
JPanel panel = new JPanel(new BorderLayout());
panel.add(p);
panel.add(new JButton(new AbstractAction("addColumn") {
#Override public void actionPerformed(ActionEvent e) {
for(JTable t: list) {
t.getColumnModel().addColumn(new TableColumn());
JTableHeader h = t.getTableHeader();
Dimension d = h.getPreferredSize();
System.out.println(d);
}
}
}), BorderLayout.SOUTH);
panel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
return panel;
}
private static JComponent makeTitledPanel(String title, JComponent c) {
JPanel p = new JPanel(new BorderLayout());
p.add(c);
p.setBorder(BorderFactory.createTitledBorder(title));
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new TableHeaderHeightTest().makeUI());
f.setSize(320, 320);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
Try this
I have to program that takes ip Addresses from a file and outputs the country its in onto a JTable. I have no errors but when i click the button the JTable doesn't open up. How do i make the JTable open up?
package org.koushik.javabrains;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.io.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import net.webservicex.GeoIP;
import net.webservicex.GeoIPService;
import net.webservicex.GeoIPServiceSoap;
public class IPLocationFinder {
public static void main(String[] args) {
final JFileChooser filechooser = new JFileChooser();
filechooser.setVisible(false);
final JTable jt;
final String[] columns= {"IP address","Country"};
final String[][] data = {{}};
final DefaultTableModel model = new DefaultTableModel(data, columns);
jt = new JTable(model);
jt.setPreferredScrollableViewportSize(new Dimension(450, 60));
jt.setFillsViewportHeight(true);
JScrollPane jps = new JScrollPane();
jt.add(jps);
final JFrame frame = new JFrame();
frame.setSize(500,500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new GridBagLayout());
frame.getContentPane().add(panel, BorderLayout.CENTER);
GridBagConstraints c = new GridBagConstraints();
JButton b1 = new JButton("Start");
c.gridx = 0;
c.gridy = 0;
c.insets = new Insets(10,10,10,10);
panel.add(b1, c);
frame.setBounds(400,150,600,200);
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
new IPLocationFinder();
BufferedReader inputStream = null;
try {
inputStream = new BufferedReader(new FileReader("C:/IP Addresses/ip.txt"));
String l;
try {
while ((l = inputStream.readLine()) != null) {
String ipAddress = l;
GeoIPService ipService = new GeoIPService();
GeoIPServiceSoap geoIPServiceSoap = ipService.getGeoIPServiceSoap();
GeoIP geoIp = geoIPServiceSoap.getGeoIP(ipAddress);
model.addRow(new String[][]{{"Column 1", geoIp.getCountryName()}});
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
};
b1.addActionListener(actionListener);
}
}
You have several problems:
You never add the JTable to your panel.
You're adding a JScrollPane to your JTable when it should be the other way around. The JScrollPane should have its view set to the scrollable component, which in this case is the JTable. Otherwise, as your table's rows increase, the elements above it are simply going to be pushed up.
You've added an empty row to your table by saying final String[][] data = { {} };. When you start adding rows, you'll have a blank row to start. Therefore, you should remove the inner curly braces.
You should be aware that your JTable data is being prescribed as a 2D String array and although you're technically adding the data correctly, it's going to show up as an address in your first column:
To fix the above issue, change your addRow data to a 2D array such as model.addRow(new String[] { "Column 1", "Country 1" });
Below is a simplified, corrected version:
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class IPLocationFinder {
public static void main(String[] args) {
final String[] columns = { "IP address", "Country" };
final String[][] data = {};
final DefaultTableModel model = new DefaultTableModel(data, columns);
final JTable jt = new JTable(model);
final JFrame frame = new JFrame();
final JScrollPane jps = new JScrollPane(jt);
final JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
JButton b1 = new JButton("Start");
c.gridx = 0;
c.gridy = 0;
c.insets = new Insets(10, 10, 10, 10);
panel.add(b1, c);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel, BorderLayout.NORTH);
frame.getContentPane().add(jps, BorderLayout.CENTER);
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
model.addRow(new String[] { "Column 1", "Country 1" });
}
};
b1.addActionListener(actionListener);
frame.pack();
frame.setVisible(true);
}
}
I'm gessing you're using a panel to show the jtable, however as you can notice, there's no a panel.add(jt); line.
So, go ahead and add that line inside the Action
EDIT
As #Braj comment, the jt must be added to the scroll. Then instead add the JTable, add the JScroll.
panel.add(jsp);
I have a JPanel with GridBagLayout. The panel contains 2 rows, first row has a JLabel and second row has a JScrollPane with JTable inside. The table does not fill 100% of the scrollpane. Even I resize my frame, the scrollpane resizes but the table inside always has fixed width.
JTable table=new JTable(myModel);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
JScrollPane scroll=new JScrollPane(table);
JPanel panel=new JPanel(new GridBagLayout());
// component add details skipped
And the following are the grid bag constraints applied to scroll pane while adding to panel.
GridBagConstraints gbc=new GridBagConstraints();
gbc.gridx=0; // first column
gbc.gridy=1; // second row
gbc.gridwidth=1;
gbc.gridheight=1;
gbc.fill=GridBagConstraints.BOTH;
gbc.anchor=GridBagConstraints.NORTHEAST;
gbc.weightx=1.0;
gbc.weighty=1.0;
What went wrong? Problem is with scroll pane or table?
I think that only (notice rows never will be resized by using any of LayoutManager, only columns)
c.fill = GridBagConstraints.BOTH;
c.weightx = 1;
c.weighty = 0;
GBC isn't proper LayoutManager for JComponents implements Scrollable, use BorderLayout(ev GridLayout) for these JComponents
for example
import java.awt.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
public class JTableAndGBC {
private String[] columnNames = {"Source", "Hit", "Last", "Ur_Diff"};
private JTable table;
private Object[][] data = {{"Swing Timer", 2.99, 5, 1.01},
{"Swing Worker", 7.10, 5, 1.010}, {"TableModelListener", 25.05, 5, 1.01}};
private DefaultTableModel model = new DefaultTableModel(data, columnNames);
public JTableAndGBC() {
JPanel panel = new JPanel(new GridBagLayout());
table = new JTable(model);
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
panel.add(table, gbc);
JFrame frame = new JFrame();
frame.add(panel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
public static void main(String args[]) throws Exception {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new JTableAndGBC();
}
});
}
}
EDIT 1
JTable, JScollPane, JComboBox can't returns reasonable PreferredSize, see my code in the edit, then wokrs for all LayoutManagers,
notice carefully with table.setPreferredScrollableViewportSize(table.getPreferredSize());, I'd suggest to test if Dimension overload desired coordinates or screen resolution or not overload :-),
otherwise to shrink with new Dimension(int, int) instead of table.getPreferredSize()
.
import java.awt.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
public class JTableAndGBC {
private String[] columnNames = {"Source", "Hit", "Last", "Ur_Diff"};
private JTable table;
private Object[][] data = {{"Swing Timer", 2.99, 5, 1.01},
{"Swing Worker", 7.10, 5, 1.010}, {"TableModelListener", 25.05, 5, 1.01}};
private DefaultTableModel model = new DefaultTableModel(data, columnNames);
public JTableAndGBC() {
JPanel panel = new JPanel(new GridBagLayout());
table = new JTable(model);
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
JScrollPane pane = new JScrollPane(table);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
panel.add(pane, gbc);
JFrame frame = new JFrame();
frame.add(panel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
public static void main(String args[]) throws Exception {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new JTableAndGBC();
}
});
}
}
EDIT 2
I'm strongly to suggest to use BorderLayout, GridLayout
.
instead of GBC (JTable, JScollPane, JComboBox can't returns reasonable PreferredSize, required to override GBC, brrrr, not why bothering)
.
code for BorderLayout
import java.awt.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
public class JTableAndGBC {
private String[] columnNames = {"Source", "Hit", "Last", "Ur_Diff"};
private JTable table;
private Object[][] data = {{"Swing Timer", 2.99, 5, 1.01},
{"Swing Worker", 7.10, 5, 1.010}, {"TableModelListener", 25.05, 5, 1.01}};
private DefaultTableModel model = new DefaultTableModel(data, columnNames);
public JTableAndGBC() {
JPanel panel = new JPanel(new BorderLayout()/*(new GridBagLayout()*/);
table = new JTable(model);
//GridBagConstraints gbc = new GridBagConstraints();
//gbc.weightx = 1.0;
//gbc.fill = GridBagConstraints.HORIZONTAL;
JScrollPane pane = new JScrollPane(table,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
/*TableColumn firstColumn = table.getColumnModel().getColumn(0);
firstColumn.setMinWidth(150);
firstColumn.setMaxWidth(200);
TableColumn secondColumn = table.getColumnModel().getColumn(1);
secondColumn.setMinWidth(200);
secondColumn.setMaxWidth(250);
TableColumn thirdColumn = table.getColumnModel().getColumn(1);
thirdColumn.setMinWidth(50);
thirdColumn.setMaxWidth(100); */
table.setRowHeight(30);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
panel.add(pane/*, gbc*/);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
public static void main(String args[]) throws Exception {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new JTableAndGBC();
}
});
}
}
Thanks for giving valuable suggestions. I found the exact solution for this problem. Size the table at its preferred size or view port size whichever is greater. Regardless of whatever layout manager you use it is working fine!
The solution is have table defined with getScrollableTracksViewportWidth() method, as example given below:
JTable table=new JTable(myModel){
public boolean getScrollableTracksViewportWidth() {
return getPreferredSize().width < getParent().getWidth();
}
};
JScrollPane scroll=new JScrollPane(table);
Remove the
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
line. It causes the fixed table size.
I have a problem with JTable/JScrollPane. My data table is not refreshing/updating. I am using DefultTableModel and according to the code everything is fine and I don't have any errors. Also I have a table with paging and that's why I am using action listeners and buttons "prev" and "next". I am passing from other function to function that is coded in class where is JTable. Problem is that I fill arrays which contains data for table but table won't update/refresh it. Here is my code. Thanks advance.
BIG EDIT Old code was removed. I added new codes that will help you guys/girls to understand problem that I have. Hope that this will help. Regards.
First here is class that show gui:
import javax.swing.*;
public class Glavni {
public static void main(String[] args) {
// TODO Auto-generated method stub
SwingUtilities.invokeLater(new Runnable() {
public void run() {
gui Scanner = new gui();
Scanner.setVisible(true);
}
});
}
}
Second here is class that pass String to gui class that contains jtable
public class passDatatoTable {
public void passData(){
String str1,str2,str3,str4;
gui SendStringsToGUI = new gui();
for (int i =0;i<=10;i++){
str1="Column 1 of row: "+i;
str2="Column 2 of row: "+i;
str3="Column 3 of row: "+i;
str4="Column 4 of row: "+i;
SendStringsToGUI.WriteMonitorData(str1, str2, str3, str4);
}
}
}
Next here is declaration of gui (contructor):
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class gui extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
String[][] data = new String[100][4];
String[] columnNames = new String[]{
"IP", "PC_NAME", "ttl", "db"
};
DefaultTableModel model = new DefaultTableModel(data,columnNames);
JTable table = new JTable(model);
JScrollPane scrollPane = new JScrollPane(table);
int i=0;
public void WriteMonitorData (String IP, String PC_NAME, String ttl, String gw)
{
System.out.println(IP);//just for testing (check if data was passed)
model.setValueAt(IP, i, 0);
model.setValueAt(PC_NAME, i, 1);
model.setValueAt(ttl, i, 2);
model.setValueAt(gw, i, 3);
i++;
model.fireTableDataChanged();
table.repaint();
scrollPane.repaint();
}
gui(){
JButton addData= new JButton("Add Data");
JButton next = new JButton("next");
JButton prev = new JButton("prev");
addData.addActionListener(this);
next.addActionListener(this);
prev.addActionListener(this);
JPanel panel = new JPanel(new BorderLayout());
JPanel buttonPanel = new JPanel();
buttonPanel.add(addData);
buttonPanel.add(prev);
buttonPanel.add(next);
panel.add(buttonPanel, BorderLayout.SOUTH);
panel.add(table.getTableHeader(), BorderLayout.PAGE_START);
panel.add(scrollPane, BorderLayout.CENTER);
getContentPane().add(panel);
}
Here is actionListeners:
public void actionPerformed(ActionEvent e) {
if ("Add Data".equals(e.getActionCommand())){
passDatatoTable passSomeData = new passDatatoTable();
passSomeData.passData();
}
if ("next".equals(e.getActionCommand())) {
Rectangle rect = scrollPane.getVisibleRect();
JScrollBar bar = scrollPane.getVerticalScrollBar();
int blockIncr = scrollPane.getViewport().getViewRect().height;
bar.setValue(bar.getValue() + blockIncr);
scrollPane.scrollRectToVisible(rect);
}
if ("prev".equals(e.getActionCommand())) {
Rectangle rect = scrollPane.getVisibleRect();
JScrollBar bar = scrollPane.getVerticalScrollBar();
int blockIncr = scrollPane.getViewport().getViewRect().height;
bar.setValue(bar.getValue() - blockIncr);
scrollPane.scrollRectToVisible(rect);
}
}
Your first snippet shows this:
JTable table = new JTable(model);
but your gui() constructor shows:
JTable table = new JTable(data, columnNames);
You initiate the table twice. Once using the TableModel (JTable(TableModel tm)) the next using JTable(int rows,int cols) this is not good, initiate the JTable once in the constructor:
gui() {
DefaultTableModel model = new DefaultTableModel(data,columnNames);
JTable table = new JTable(model);
JScrollPane scrollPane = new JScrollPane(table);
JButton next = new JButton("next");
JButton prev = new JButton("prev");
next.addActionListener(this);
prev.addActionListener(this);
JPanel panel = new JPanel(new BorderLayout());
JPanel buttonPanel = new JPanel();
buttonPanel.add(prev);
buttonPanel.add(next);
panel.add(buttonPanel, BorderLayout.SOUTH);
panel.add(table.getTableHeader(), BorderLayout.PAGE_START);
panel.add(scrollPane, BorderLayout.CENTER);
getContentPane().add(panel);
}
UPDATE:
Here is an example that has a thread which will start 2.5 secinds after the UI is visible and change a value of the JTable:
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
public class Test extends JFrame {
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test().createAndShowUI();
}
});
}
private void createAndShowUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initComponents(frame);
frame.pack();
frame.setVisible(true);
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(2500);
} catch (InterruptedException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
model.setValueAt("hello", 0, 0);
}
});
}
}).start();
}
static DefaultTableModel model;
private void initComponents(JFrame frame) {
String data[][] = {
{"1", "2", "3"},
{"4", "5", "6"},
{"7", "8", "9"},
{"10", "11", "12"}
};
String col[] = {"Col 1", "Col 2", "Col 3"};
model = new DefaultTableModel(data, col);
JTable table = new JTable(model);
frame.getContentPane().add(new JScrollPane(table));
}
}
From what I understand from the comments and the question, you have first created a DefaultTableModel by passing the data as arrays in the constructor
String[][] data = new String[100][4];
String[] columnNames = new String[]{
"IP", "PC_NAME", "ttl", "db"};
DefaultTableModel model = new DefaultTableModel(data,columnNames);
and you try to modify the table afterwards by adjusting those arrays. That will never ever have any effect, as the DefaultTableModel does not use those arrays. This can be seen in the source code of that class
public DefaultTableModel(Object[][] data, Object[] columnNames) {
setDataVector(data, columnNames);
}
which in the end comes down to
protected static Vector convertToVector(Object[][] anArray) {
if (anArray == null) {
return null;
}
Vector<Vector> v = new Vector<Vector>(anArray.length);
for (Object[] o : anArray) {
v.addElement(convertToVector(o));
}
return v;
}
So all the elements of the array are copied into an internal Vector and the array is no longer used.
Solution: do not update the arrays but update the DefaultTableModel. That class provides all the API you need to add/remove data to/from it.