调整列时,在JScrollPane中保持JTable固定

时间:2018-01-27 04:03:53

标签: java swing jtable jscrollpane

JTable内有JScrollPane。用户向右滚动。然后我按x像素放大用户正在查看的位置左侧的列。这会导致表格向左滚动。如何调整JScrollPaneJScrollBarJViewport以保持桌面静止?换句话说,如何在屏幕上保持表格的相同可见部分?

我尝试按JScrollBar调整水平x的值。我还尝试按JViewport调整x的观看位置。问题是该表最终向右滚动。

以下是显示问题的代码,我没有试图让表保持静止。

package oracle.psr.ndr.guiclient.util.table;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

public final class StableColumnResizing extends JFrame
{
   private static final long serialVersionUID = 738732002168497075L;

   private final TableColumnModel m_model;
   private final JScrollBar       m_bar;
   private       int              m_colIndex;

   public static void main(String args[])
   {
      SwingUtilities.invokeLater(StableColumnResizing::create);
   }

   private static void create()
   {
      StableColumnResizing frame;
      Timer timer;

      frame = new StableColumnResizing();

      frame.setVisible(true);
      SwingUtilities.invokeLater(frame::moveRight);

      timer = new Timer(1000, frame::adjust);

      timer.start();
   }

   private StableColumnResizing()
   {
      JScrollPane pane;
      JTable table;
      Object rowData[][], columnNames[];

      columnNames = new Object[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29};
      rowData     = new Object[][]{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}};

      table   = new JTable(rowData, columnNames);
      m_model = table.getColumnModel();
      pane    = new JScrollPane();
      m_bar   = pane.getHorizontalScrollBar();

      table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

      pane.setViewportView(table);

      add(pane, BorderLayout.CENTER);
      setSize(1024, 768);
      setLocationByPlatform(false);
      setLocationRelativeTo(null);
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   }

   private void moveRight()
   {
      m_bar.setValue(m_bar.getMaximum() / 3);
   }

   private void adjust(@SuppressWarnings("unused") ActionEvent event)
   {
      TableColumn column;
      int count;

      count = m_model.getColumnCount();

      if (m_colIndex >= count)
         return;

      column = m_model.getColumn(m_colIndex);

      column.setPreferredWidth(200);
      m_colIndex++;
   }
}

1 个答案:

答案 0 :(得分:0)

应其他人的要求,我创建了一些简单的代码来显示问题。使用这个简单的代码,可以很容易地创建解决方案。

该解决方案添加了一种新方法adjust(),并为getX()添加了更多代码。 x在更改任何列大小之前计算列的最左侧位置。该值存储在局部变量JScrollBar.getValue()中。

在进行任何列大小更改之前,该解决方案还会捕获value。该值存储在局部变量x中。

更改列大小后,再比较value< value。如果列的最左侧位置不在视图的左侧,则为true。如果为true,则将列宽的差异添加到JScrollBar.setValue()并调用TableColumn.getMaxWidth()。因此,视图左侧的列将导致滚动条移动到足以使可见列保持在视图中。右边的列将被简单调整。

渴望getMaxWidth()。设置列的宽度时,列的宽度将遵循此宽度。处理TableColumn.setMaxWidth()的代码在下面,即使它对用户界面没有任何影响,因为原始帖子不会调用private void adjust(@SuppressWarnings("unused") ActionEvent event) { TableColumn column; int count, old, next, value, x, max; count = m_model.getColumnCount(); if (m_colIndex >= count) return; x = getX(m_colIndex); value = m_bar.getValue(); column = m_model.getColumn(m_colIndex); old = column.getPreferredWidth(); max = column.getMaxWidth(); next = 200; column.setPreferredWidth(next); m_colIndex++; if (x < value) m_bar.setValue(value + Math.min(next, max) - old); } private int getX(int colIndex) { TableColumn column; int result; result = 0; while (--colIndex >= 0) { column = m_model.getColumn(colIndex); result += column.getPreferredWidth(); } return(result); }

public class Maze {
private static int N=8;
private static int [][] maze = {
        {0,0,0,0,0,0,0,1}, // 미로 라고 봄
        {0,1,1,0,1,1,0,1},
        {0,0,0,1,0,0,0,1},
        {0,1,0,0,1,1,0,0},
        {0,1,1,1,0,0,1,1},
        {0,1,0,0,0,1,0,1},
        {0,0,0,1,0,0,0,1},
        {0,1,1,1,0,1,0,0}
};

private static final int PATHWAY_COLOUR = 0; // white
private static final int WALL_COLOUR = 1; // blue
private static final int BLOCKED_COLOUR = 2; // red
private static final int PATH_COLOUR = 3; // green

public static boolean findMazePath(int x, int y){
    if (x<0 || y<0 || x>=N) // 유효한 좌표 범위 확인
        return false;
    else if (maze[x][y] != PATHWAY_COLOUR)
        return false;
    else if (x==N-1 && y==N-1){ // 출구
        maze[x][y] = PATH_COLOUR;
        return true;
    }
    else {
        maze[x][y] = PATH_COLOUR;
        if (findMazePath(x-1,y) || findMazePath(x,y+1)
                ||findMazePath(x+1,y) || findMazePath(x,y-1)){
            return true;
        } // 북 동 남 서 방향 순으로 확인
        maze[x][y] = BLOCKED_COLOUR; // dead end
        return false;
    }
}

public static void main(String[] args) {
//      printMaze();
    findMazePath(0,0); // 시작
//      printMaze();
    }
}