I have to synchronize the horizontal scrolling of tables. The columns would be the same only property that can be changed for the columns is their size. Now the following code shows 3 tables with synchronised scrolling. But as i change size of any one column in any of the table and then try to scroll, i get an Stack Overflow error and the gui is distorted.
I am trying to achieve it by setting the viewport position of rest of the tables to the column which comes first on the left hand side. If the size of the columns are different then then from the percentage scrolled for that column i am reconstructing the position of other table.
import java.awt.Color;
import java.awt.Point;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
public class ScrollableJTable implements AdjustmentListener{
JFrame frame = null;
JPanel panel = null;
JTable table = null;
JTableHeader header = null;
JScrollPane pane = null;
JTable table1 = null;
JTableHeader header1 = null;
JScrollPane pane1 = null;
JTable table2 = null;
JTableHeader header2 = null;
JScrollPane pane2 = null;
public static void main(String[] args) {
new ScrollableJTable();
}
public ScrollableJTable() {
frame = new JFrame("Creating a Scrollable JTable!");
panel = new JPanel();
String data[][] = {
{"001", "vinod", "Bihar", "India", "Biology", "65", "First","001", "vinod", "Bihar", "India", "Biology", "65", "First"},
{"002", "Raju", "ABC", "Kanada", "Geography", "58", "second","001", "vinod", "Bihar", "India", "Biology", "65", "First"},
{"003", "Aman", "Delhi", "India", "computer", "98", "Dictontion","001", "vinod", "Bihar", "India", "Biology", "65", "First"},
{"004", "Ranjan", "Bangloor", "India", "chemestry", "90", "Dictontion","001", "vinod", "Bihar", "India", "Biology", "65", "First"}
};
String col[] = {"Roll", "Name", "State", "country", "Math", "Marks", "Grade","Roll", "Name", "State", "country", "Math", "Marks", "Grade"};
table = new JTable(data, col);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
header = table.getTableHeader();
header.setBackground(Color.yellow);
pane = new JScrollPane(table);
pane.getHorizontalScrollBar().addAdjustmentListener(this);
pane.setSize(100, 100);
table1 = new JTable(data, col);
table1.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
header1 = table1.getTableHeader();
header1.setBackground(Color.yellow);
pane1 = new JScrollPane(table1);
pane1.getHorizontalScrollBar().addAdjustmentListener(this);
pane1.setSize(100, 100);
table2 = new JTable(data, col);
table2.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
header2 = table2.getTableHeader();
header2.setBackground(Color.yellow);
pane2 = new JScrollPane(table2);
pane2.getHorizontalScrollBar().addAdjustmentListener(this);
pane2.setSize(100, 100);
panel.setSize(500, 500);
panel.add(pane);
panel.add(pane1);
panel.add(pane2);
frame.add(panel);
frame.pack();
frame.setSize(1000, 1000);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public void adjustmentValueChanged(AdjustmentEvent e) {
JScrollPane scrollPane = null, scroll = null;
JScrollBar bar = null;
int position[] = null;
bar = (JScrollBar) e.getAdjustable();
scroll = (JScrollPane) bar.getParent();
position = this.getFirstVisibleColumnIndex(scroll);
for (int j = 0; j < panel.getComponentCount(); j++) {
scrollPane = (panel.getComponent(j) instanceof JScrollPane) ? (JScrollPane) panel.getComponent(j) : null;
if (scrollPane != null && scrollPane != scroll) this.setFirstColumnVisiblePosition(position, scrollPane);
}
}
private int[] getFirstVisibleColumnIndex(JScrollPane scroll) {
JTable table = null;
TableColumnModel model = null;
Object obj = null;
int retval[] = null, index = -1, position = -1, relpos = -1;
if (scroll == null) return null;
obj = scroll.getViewport().getView();
table = (obj instanceof JTable ? (JTable)obj : null);
if (table == null) return null;
model = table.getColumnModel();
if (model == null) return null;
position = scroll.getViewport().getViewPosition().x;
for (int column = 0; index == -1 && column < model.getColumnCount(); column++) {
position = position - model.getColumn(column).getWidth();
if (position < 0) {
index = column;
relpos = ((position + model.getColumn(column).getWidth()) * 100) / model.getColumn(column).getWidth();
}
}
retval = new int[2];
retval[0] = index;
retval[1] = relpos;
return retval;
}
private boolean setFirstColumnVisiblePosition(int position[], JScrollPane scroll) {
JTable table = null;
TableColumnModel model = null;
Object obj = null;
int pos = 0, width = 0;
if (scroll == null || position == null) return false;
obj = scroll.getViewport().getView();
table = (obj instanceof JTable ? (JTable)obj : null);
if (table == null) return false;
model = table.getColumnModel();
if (model == null) return false;
if (position[0] == -1 || position [1] == -1) return false;
for (int column = 0; column < position[0]; column++) {
pos = pos + model.getColumn(column).getWidth();
}
width = model.getColumn(position[0]).getWidth();
pos = pos + ((position[1] * width) / 100);
scroll.getViewport().setViewPosition(new Point(pos, scroll.getViewport().getViewPosition().y));
return true;
}
}
I am trying to achieve it by setting the viewport position of rest of the tables to the column
don't use Integer value for calculating, change that to the percents and to use percentage ratio, – Callboy