Java JScrollpane中的JTable可调整显示组件的高度

Java JScrollpane中的JTable可调整显示组件的高度,java,swing,swingx,jgoodies,Java,Swing,Swingx,Jgoodies,我在jscrollpane中有一个jtable。我使用jgoodies表单布局,并将滚动窗格放在设置为“pref”的行中。这就是表格现在的样子: 顺便说一下,我正在使用swingx JXTable,并已将visibleRowCount设置为2。但仅显示半行 在制作SSCCE时,我意识到它不能正常工作,因为我有一个自定义的TextArea渲染器。我认为由于这个渲染器,行高度计算不正确。我想知道为什么,同时如果你们能发现它,那就太好了 public static void main(String[

我在jscrollpane中有一个jtable。我使用jgoodies表单布局,并将滚动窗格放在设置为“pref”的行中。这就是表格现在的样子:

顺便说一下,我正在使用swingx JXTable,并已将visibleRowCount设置为2。但仅显示半行

在制作SSCCE时,我意识到它不能正常工作,因为我有一个自定义的TextArea渲染器。我认为由于这个渲染器,行高度计算不正确。我想知道为什么,同时如果你们能发现它,那就太好了

public static void main(String[] args) {
    JFrame frame=new JFrame();
    JPanel panel=new FormDebugPanel();
    frame.setContentPane(panel);
    FormLayout layout=new FormLayout("1dlu:grow,200dlu:grow,1dlu:grow",
            "10dlu,pref,5dlu,pref,10dlu");
    panel.setLayout(layout);
    String[] columns= {"1st Column","2nd Column","3rd Column"};
    String[][] data= {
            {"Sethu","Data","Something\nis\nhere"},
            {"Sethu","Data","Something\nis\nhere"},

    };
    JXTable table=new JXTable(data,columns);
    table.setVisibleRowCount(2);

    TableColumnModel columnModel=table.getColumnModel();
    columnModel.getColumn(2).setCellRenderer(new TextAreaRenderer());

    JScrollPane scrlPan=new JScrollPane(table);
    CellConstraints cc=new CellConstraints();
    panel.add(scrlPan, cc.xy(2, 2));
    panel.add(new JLabel("Label After Table"),cc.xy(2,4));
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
  }
}
下面是渲染器:

class TextAreaRenderer extends JTextArea implements TableCellRenderer {

private final DefaultTableCellRenderer adaptee = new DefaultTableCellRenderer();

/** map from table to map of rows to map of column heights */
private final Map<JTable,Map<Integer,Map<Integer,Integer>>> cellSizes = new HashMap<JTable,Map<Integer,Map<Integer,Integer>>>();

public TextAreaRenderer() {
    setLineWrap(true);
    setWrapStyleWord(true);
}

public Component getTableCellRendererComponent(//
        JTable table, Object obj, boolean isSelected, boolean hasFocus, int row, int column) {
    // set the colours, etc. using the standard for that platform
    adaptee.getTableCellRendererComponent(table, obj, isSelected, hasFocus, row, column);
    setForeground(adaptee.getForeground());
    setBackground(adaptee.getBackground());
    setBorder(adaptee.getBorder());
    setFont(adaptee.getFont());
    setText(adaptee.getText());

    // This line was very important to get it working with JDK1.4
    TableColumnModel columnModel = table.getColumnModel();
    setSize(columnModel.getColumn(column).getWidth(), 100000);
    int height_wanted = (int) getPreferredSize().getHeight();
    addSize(table, row, column, height_wanted);
    height_wanted = findTotalMaximumRowSize(table, row);
    if (height_wanted != table.getRowHeight(row)) {
        table.setRowHeight(row, height_wanted);
    }
    return this;
}

private void addSize(JTable table, int row, int column, int height) {
    Map<Integer,Map<Integer,Integer>> rows = cellSizes.get(table);
    if (rows == null) {
        cellSizes.put(table, rows = new HashMap<Integer,Map<Integer,Integer>>());
    }
    Map<Integer,Integer> rowheights =  rows.get(new Integer(row));
    if (rowheights == null) {
        rows.put(new Integer(row), rowheights = new HashMap<Integer,Integer>());
    }
    rowheights.put(new Integer(column), new Integer(height));
}

/**
 * Look through all columns and get the renderer. If it is also a
 * TextAreaRenderer, we look at the maximum height in its hash table for
 * this row.
 */
private int findTotalMaximumRowSize(JTable table, int row) {
    int maximum_height = 0;
    Enumeration<TableColumn> columns = table.getColumnModel().getColumns();
    while (columns.hasMoreElements()) {
        TableColumn tc = (TableColumn) columns.nextElement();
        TableCellRenderer cellRenderer = tc.getCellRenderer();
        if (cellRenderer instanceof TextAreaRenderer) {
            TextAreaRenderer tar = (TextAreaRenderer) cellRenderer;
            maximum_height = Math.max(maximum_height, tar.findMaximumRowSize(table, row));
        }
    }
    return maximum_height;
}

private int findMaximumRowSize(JTable table, int row) {
    Map<Integer,Map<Integer,Integer>> rows = cellSizes.get(table);
    if (rows == null)
        return 0;
    Map<Integer,Integer> rowheights = rows.get(new Integer(row));
    if (rowheights == null)
        return 0;
    int maximum_height = 0;
    for (Iterator<Map.Entry<Integer, Integer>> it = rowheights.entrySet().iterator(); it.hasNext();) {
        Map.Entry<Integer,Integer> entry = it.next();
        int cellHeight = ((Integer) entry.getValue()).intValue();
        maximum_height = Math.max(maximum_height, cellHeight);
    }
    return maximum_height;
}
}
类TextAreaRenderer扩展JTextArea实现TableCellRenderer{
private final DefaultTableCellRenderer adaptee=新的DefaultTableCellRenderer();
/**从表映射到行映射到列高度映射*/
private final Map cellSizes=new HashMap();
公共文本区域渲染器(){
setLineWrap(真);
setWrapStyleWord(true);
}
公共组件GetTableCellRenderComponent(//
JTable表,Object obj,boolean isSelected,boolean hasFocus,int行,int列){
//使用该平台的标准设置颜色等
getTableCellRenderComponent(表、对象、isSelected、hasFocus、行、列);
set前台(adaptee.get前台());
挫折背景(adaptee.getBackground());
setboorder(adaptee.getBorder());
setFont(adaptee.getFont());
setText(adaptee.getText());
//这一行对于使用JDK1.4非常重要
TableColumnModel columnModel=table.getColumnModel();
setSize(columnModel.getColumn(column.getWidth(),100000);
int height_wanted=(int)getPreferredSize().getHeight();
addSize(需要表格、行、列、高度);
所需高度=findTotalMaximumRowSize(表格、行);
如果(需要高度)=table.getRowHeight(行)){
表.设置行高(行,所需高度);
}
归还这个;
}
私有void addSize(JTable表、int行、int列、int高度){
Map rows=cellSizes.get(表);
if(行==null){
put(table,rows=newhashmap());
}
Map rowheights=rows.get(新整数(行));
如果(行高==null){
put(新整数(row),rowheights=newhashmap());
}
put(新整数(列)、新整数(高度));
}
/**
*查看所有列并获取渲染器
*TextAreaRenderer,我们查看其哈希表中的最大高度
*这一排。
*/
私有int findTotalMaximumRowSize(JTable表,int行){
int最大_高度=0;
枚举列=table.getColumnModel().getColumns();
while(columns.hasMoreElements()){
TableColumn tc=(TableColumn)columns.nextElement();
TableCellRenderer-cellRenderer=tc.getCellRenderer();
if(cellRenderer instanceof TextAreaRenderer){
TextAreaRenderer tar=(TextAreaRenderer)cellRenderer;
最大_高度=Math.max(最大_高度,tar.find最大行大小(表,行));
}
}
返回最大高度;
}
私有int findMaximumRowSize(JTable表,int行){
Map rows=cellSizes.get(表);
if(行==null)
返回0;
Map rowheights=rows.get(新整数(行));
如果(行高==null)
返回0;
int最大_高度=0;
for(Iterator it=rowhights.entrySet().Iterator();it.hasNext();){
Map.Entry=it.next();
int cellHeight=((整数)entry.getValue()).intValue();
最大高度=数学最大值(最大高度,单元高度);
}
返回最大高度;
}
}

当我使用TextAreaRenderer时,setVisibleRowHeight()未正确执行。我认为这与渲染器中未正确设置行高有关。

我相信您可以使用JSCrollPane的preferredSize、minSize和maxSize属性来实现这一点。如果将preferredSize设置为所需的最小大小,将maxsize设置为所需的最大大小,则应该可以正常工作

setPreferredScrollableViewportSize(Dimension)

这是你应该调查的事情。这里有一个很好的教程:

使用JXTable,您可以配置最初显示多少行(或列):

    table.setVisibleRowCount(2)
下面是一个快速片段,展示了如何在TableModelListener中设置行的初始大小并动态更新pref高度

    final JXTable table = new JXTable(3, 5);
    table.setVisibleRowCount(table.getRowCount());
    TableModelListener l = new TableModelListener() {

        @Override
        public void tableChanged(TableModelEvent e) {
            if (!(e.getType() == TableModelEvent.INSERT)) return;
            table.setVisibleRowCount(((TableModel) e.getSource()).getRowCount());
            RootPaneContainer frame = (RootPaneContainer) SwingUtilities.windowForComponent(table);
            ((JComponent) frame.getContentPane()).revalidate();
        }
    };
    table.getModel().addTableModelListener(l);
    Action insert = new AbstractAction("add row") {

        @Override
        public void actionPerformed(ActionEvent e) {
            ((DefaultTableModel) table.getModel()).addRow(new Object[] {});
        }
    };
    new Timer(500, insert).start();
    JComponent comp = new JPanel(new MigLayout());
    comp.add(new JScrollPane(table));
    JXFrame frame = wrapInFrame(comp, "visibleRowCount");
    show(frame, frame.getPreferredSize().width, frame.getPreferredSize().height * 4);

不,永远不要使用任何setXXSize,原因见f.i.不,不比setXXSize好多少。。特别是不支持配置逻辑大小的组件(如JXTable,f.i.),谢谢。。对我来说,更简单的是,在构建面板时加载表中的数据,并且不会更改。所以我不需要听众。但是如果我已经用滚动窗格包装了JXTable,那么在设置visibleRowCount()的同时,我还需要正确设置滚动窗格的大小,对吗?你能帮我设置滚动窗格的大小吗?设置行计数的逻辑很简单。如果行数小于3,则将VisibleRowCount设置为行数。否则,请将设置VisibleRowCount保持为3,并滚动剩余的行。抱歉,我将其收回。。您没有设置滚动窗格的大小,而是在我使用的jgoodies表单布局中设置行的大小。我需要设置包含此scrollpane+jxtable的行的行大小。但是,在显示表格之前,我该如何计算呢?不要设置固定的大小,永远不要-让布局为您处理sscce的时间-看到您的评论,我不太确定我是否理解您的意图:-)没有查看渲染器,因此这与它无关:在SwingX中,您从未实现渲染器(您将失去自动高亮显示/字符串表示的所有细节,…)相反,实现一个ComponentProvider