Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
265 views
in Technique[技术] by (71.8m points)

recursive calls to AdjustmentListener - StackOverFlow Error Swing Java

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;
    }
} 
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

there are important issues as AdjustmentListener

hardcoded for last JScrollBar only (cant comment something works, better coud be know the value for all JScrollBars and recalculate the concrete value for another JScrollBars)

import java.awt.Color;
import java.awt.Dimension;
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;

public class ScrollableJTable {

    private JFrame frame = null;
    private JPanel panel = null;
    private JTable table = null;
    private JTableHeader header = null;
    private JScrollPane pane = null;
    private JTable table1 = null;
    private JTableHeader header1 = null;
    private JScrollPane pane1 = null;
    private JTable table2 = null;
    private JTableHeader header2 = null;
    private 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.setPreferredSize(new Dimension(400, 200));
        table1 = new JTable(data, col);
        table1.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        header1 = table1.getTableHeader();
        header1.setBackground(Color.yellow);
        pane1 = new JScrollPane(table1);
        pane1.setPreferredSize(new Dimension(400, 200));
        table2 = new JTable(data, col);
        table2.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        header2 = table2.getTableHeader();
        header2.setBackground(Color.yellow);
        pane2 = new JScrollPane(table2);
        pane2.setPreferredSize(new Dimension(200, 200));
        panel.setSize(500, 500);
        panel.add(pane);
        panel.add(pane1);
        panel.add(pane2);
        frame.add(panel);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        final JScrollBar bar = pane.getHorizontalScrollBar();
        final JScrollBar bar1 = pane1.getHorizontalScrollBar();
        final JScrollBar bar2 = pane2.getHorizontalScrollBar();
        bar2.addAdjustmentListener(new AdjustmentListener() {

            @Override
            public void adjustmentValueChanged(AdjustmentEvent e) {
                bar.setValue(e.getValue());
                bar1.setValue(e.getValue());
            }
        });
    }
}
  1. don't use setSize, most of LayoutManagers accepting PreferredSize (hardcoded in my code example)

  2. FlowLayout (built_in LayoutManager for JPanel) accepting only PreferredSize

  3. use JFrame#pack() rether than JFrame#setSize(int, int)

  4. have look at InitialThread

  5. (event everybody can tell you that) output from AdjustmentListener is done on EDT, wrap output to the invokeLater() in the case that you hare to calculate value for different JScrollBars with different size on the screen, output should be delayed and then nicer, without jumping of JScrollPanes contens on the screen

EDIT

whatever, anything I tried no exception, only in the case that ColumnModel doesn't equals RowModel, rest is only to calculate the ratio for every ScrollBars Models

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
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;

public class ScrollableJTable {

    private JFrame frame = null;
    private JPanel panel = null;
    private JTable table = null;
    private JTableHeader header = null;
    private JScrollPane pane = null;
    private JTable table1 = null;
    private JTableHeader header1 = null;
    private JScrollPane pane1 = null;
    private JTable table2 = null;
    private JTableHeader header2 = null;
    private JScrollPane pane2 = null;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                ScrollableJTable scrollableJTable = 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 data1[][] = {
            {"001", "vinod", "Bihar", "India", "Biology", "65", "First",
                "001", "vinod", "Bihar", "India", "Biology", "65", "First",
                "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",
                "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",
                "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",
                "004", "Ranjan", "Bangloor", "India", "chemestry", "90", "Dictontion",
                "001", "vinod", "Bihar", "India", "Biology", "65", "First"}
        };
        String data2[][] = {
            {"001", "vinod", "Bihar", "India", "Biology", "65", "First",
                "001", "vinod", "Bihar", "India", "Biology", "65", "First",
                "001", "vinod", "Bihar", "India", "Biology", "65", "First",
                "001", "vinod", "Bihar", "India", "Biology", "65", "First",
                "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",
                "002", "Raju", "ABC", "Kanada", "Geography", "58", "second",
                "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",
                "003", "Aman", "Delhi", "India", "computer", "98", "Dictontion",
                "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",
                "004", "Ranjan", "Bangloor", "India", "chemestry", "90", "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"};
        String col1[] = {"Roll", "Name", "State", "country", "Math", "Marks",
            "Grade", "Roll", "Name", "State", "country", "Math", "Marks", "Grade",
            "Roll", "Name", "State", "country", "Math", "Marks", "Grade",
            "Roll", "Name", "State", "country", "Math", "Marks", "Grade"};
        String col2[] = {"Roll", "Name", "State", "country", "Math", "Marks",
            "Grade", "Roll", "Name", "State", "country", "Math", "Marks", "Grade",
            "Roll", "Name", "State", "country", "Math", "Marks", "Grade",
            "Roll", "Name", "State", "country", "Math", "Marks", "Grade",
            "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);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        header = table.getTableHeader();
        header.setBackground(Color.yellow);
        pane = new JScrollPane(table);
        pane.setPreferredSize(new Dimension(400, 200));
        table1 = new JTable(data1, col1);
        table1.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        table1.setPreferredScrollableViewportSize(table1.getPreferredSize());
        header1 = table1.getTableHeader();
        header1.setBackground(Color.yellow);
        pane1 = new JScrollPane(table1);
        pane1.setPreferredSize(new Dimension(400, 200));
        table2 = new JTable(data2, col2);
        table2.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        table2.setPreferredScrollableViewportSize(table2.getPreferredSize());
        header2 = table2.getTableHeader();
        header2.setBackground(Color.yellow);
        pane2 = new JScrollPane(table2);
        pane2.setPreferredSize(new Dimension(200, 200));
        panel.setSize(500, 500);
        panel.add(pane);
        panel.ad

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...