Java 多页多行JTable

Java 多页多行JTable,java,swing,jtable,Java,Swing,Jtable,我想制作一个JTable,它可以显示在多个页面中(如果行超过最大行数),并且它还有一个可以包装多行文本的列(或单元格)。问题是,当为多页设置它时,它的表模型已经用于AbstractTableModel,并且不能(再次)通过包装多行文本所需的DefaultTableModel设置它。我可以单独运行多页表或多行文本列表,但当我将两者结合使用时,问题就会出现。我已经在互联网上搜索过了,但我的问题没有答案。有人能帮我吗 这是我用于多页表的AbstractTableModel的代码: class MyTa

我想制作一个
JTable
,它可以显示在多个页面中(如果行超过最大行数),并且它还有一个可以包装多行文本的列(或单元格)。问题是,当为多页设置它时,它的表模型已经用于
AbstractTableModel
,并且不能(再次)通过包装多行文本所需的
DefaultTableModel设置它。我可以单独运行多页表或多行文本列表,但当我将两者结合使用时,问题就会出现。我已经在互联网上搜索过了,但我的问题没有答案。有人能帮我吗

这是我用于多页表的
AbstractTableModel
的代码:

class MyTableModel extends AbstractTableModel {
    private String[] columnNames = {"No.","Kode","Produk","Jasa","satuan", "harga", "qty", "jml"};
    private Vector data = new Vector();
    public final Object[] longValues = {"", "", "", false, "", new Double(20), new Integer(20), new Double(20)};

    @Override
    public int getColumnCount() {
        return columnNames.length;
    }
    @Override
    public int getRowCount() {
        return data.size();
    }
    @Override
    public Object getValueAt(int row, int col) {
        return ((Vector) data.get(row)).get(col);
    }           

    public String getColumnName(int col){
        return columnNames[col];
    }
    public void setEmpty(int rows) {    
        int i = rows-1;
        while (i > -1) {
            data.removeElementAt(i); 
            i--;
        }

        fireTableDataChanged();
    }
    public Class getColumnClass(int col){
        switch (col) {
            case 0:
                return String.class;
            case 1:
                return String.class;
            case 2:
                return String.class;
            case 3:
                return Boolean.class;   
            case 4:
                return String.class; 
            case 5:
                return Double.class; 
            case 6:
                return Integer.class; 
            case 7:
                return Double.class; 
            default:
                return String.class;
        }
    }        
    public void setValueAt(Object value, int row, int col){
        ((Vector) data.get(row)).setElementAt(value, col);
        fireTableCellUpdated(row,col);
    }
    public boolean isCellEditable(int row, int col){            
        return true;            
    }
    public void insertData(Object[] values){
        data.add(new Vector());
        for(int i = 0; i < values.length; i++){
            ((Vector) data.get(data.size()-1)).add(values[i]);
        }
        fireTableDataChanged();
    }
    public void removeRow(int row){
        data.removeElementAt(row);
        fireTableDataChanged();
    }
}
initPagination()

Zebra
是一个制作Zebra stripe表的
类,我将其用于多行单元格表:

public class Zebra extends JTable {
@Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int col) {
    Component cell = super.prepareRenderer(renderer, row, col);
    cell.setForeground(Color.BLACK);
    if (row % 2 == 0) {
        cell.setBackground(Color.ORANGE);            
    } else {
        cell.setBackground(Color.WHITE);            
    }
    return cell;
}
@Override public void doLayout() {
    TableColumn col = getColumnModel().getColumn(2);
    for(int row=0; row<getRowCount(); row++) {
      Component c = prepareRenderer(col.getCellRenderer(), row, 2);
      if(c instanceof JTextArea) {
        JTextArea a = (JTextArea)c;
        int h = getPreferredHeight(a) + getIntercellSpacing().height;
        if(getRowHeight(row)!=h) setRowHeight(row, h);
      }
    }
    super.doLayout();
  }

  private int getPreferredHeight(JTextComponent c) {
    Insets insets = c.getInsets();
    View view = c.getUI().getRootView(c).getView(0);
    int preferredHeight = (int)view.getPreferredSpan(View.Y_AXIS);
    return preferredHeight + insets.top + insets.bottom;
  }

  class TextAreaCellRenderer extends JTextArea implements TableCellRenderer {
    private final Color evenColor = new Color(230, 240, 255);
    public TextAreaCellRenderer() {
      super();
      setLineWrap(true);
      setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
    }
    @Override public Component getTableCellRendererComponent(
      JTable table, Object value, boolean isSelected,
      boolean hasFocus, int row, int column) {
      if(isSelected) {
        setForeground(table.getSelectionForeground());
        setBackground(table.getSelectionBackground());
      } else {
        setForeground(table.getForeground());
        setBackground(table.getBackground());
        setBackground((row%2==0)?evenColor:getBackground());
      }
      setFont(table.getFont());
      setText((value ==null) ? "" : value.toString());
      return this;
    }
}
公共类Zebra扩展JTable{
@凌驾
公共组件预渲染器(TableCellRenderer渲染器,int行,int列){
组件单元=super.prepareRenderer(渲染器、行、列);
单元格。设置前景(颜色。黑色);
如果(第%2行==0){
细胞。挫折背景(颜色。橙色);
}否则{
细胞。挫折背景(颜色。白色);
}
返回单元;
}
@覆盖公共void doLayout(){
TableColumn col=getColumnModel().getColumn(2);

对于(int row=0;row我已经找到了问题的解决方案。也许还有其他方法,但现在对我来说已经足够了。我从旧的源代码中做了一些修改,并将其限制为三行,因为项目名称不太长,不需要超过三行。Aaron Digulla是对的,它应该来自渲染器,没有什么需要修改的用这个模型吧……谢谢你的建议

private int getPreferredHeight(JTextComponent c) {
    Insets insets = c.getInsets();
    View view = c.getUI().getRootView(c).getView(2);
    int preferredHeight = (int)view.getPreferredSpan(View.Y_AXIS);
    return preferredHeight + insets.top + insets.bottom;
} 
private void setMultiLine(JTable table, TableColumn col, int row) {    
    int tableRowHeight = table.getRowHeight();
    col.setCellRenderer(new TextAreaCellRenderer());
    Component c = table.prepareRenderer(col.getCellRenderer(), row, 2);
    if(c instanceof JTextArea) {
          JTextArea a = (JTextArea) c;
          int h = getPreferredHeight(a) +     table.getIntercellSpacing().height;               
          if(h > tableRowHeight) {
              if (tableRowHeight * 3 < h) 
                  table.setRowHeight(row, tableRowHeight * 3);
              else
                  table.setRowHeight(row, h);
          }
    }       
}
private int getPreferredHeight(jtextc组件){
Insets Insets=c.getInsets();
视图视图=c.getUI().getRootView(c).getView(2);
int preferredHeight=(int)view.getPreferredSpan(view.Y_轴);
返回首选高度+insets.top+insets.bottom;
} 
私有void setMultiLine(JTable table,TableColumn col,int row){
int tableRowHeight=table.getRowHeight();
col.setCellRenderer(新的TextAreaCellRenderer());
组件c=table.prepareRenderer(列getCellRenderer(),第2行);
if(JTextArea的c实例){
JTextArea=(JTextArea)c;
int h=getPreferredHeight(a)+table.getIntercellSpacing().height;
如果(h>表格行高){
if(表格行高*3
我“建议”多行线支持应该来自渲染器,它应该与模型无关。这和/或您可能需要使用一个或多个代理模型来“过滤”先前存在的模型以满足您的新需求。我尝试了您的建议,但我遇到错误:“线程中的异常”AWT-EventQueue-0“java.lang.ArrayIndexOutOfBoundsException:2>=0”。这是因为我为第2列调用了渲染器(该列尚未由DeafultTableModel初始化):这是对表的调用:tabelItem.getColumnModel().getColumn(2).setCellRenderer(new TextAreaCellRenderer());…我对代理模型没有任何概念……对不起,“页面”是什么“在GUI术语中?您通常将
JTable
放在
JScrollPane
中。
public class Zebra extends JTable {
@Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int col) {
    Component cell = super.prepareRenderer(renderer, row, col);
    cell.setForeground(Color.BLACK);
    if (row % 2 == 0) {
        cell.setBackground(Color.ORANGE);            
    } else {
        cell.setBackground(Color.WHITE);            
    }
    return cell;
}
@Override public void doLayout() {
    TableColumn col = getColumnModel().getColumn(2);
    for(int row=0; row<getRowCount(); row++) {
      Component c = prepareRenderer(col.getCellRenderer(), row, 2);
      if(c instanceof JTextArea) {
        JTextArea a = (JTextArea)c;
        int h = getPreferredHeight(a) + getIntercellSpacing().height;
        if(getRowHeight(row)!=h) setRowHeight(row, h);
      }
    }
    super.doLayout();
  }

  private int getPreferredHeight(JTextComponent c) {
    Insets insets = c.getInsets();
    View view = c.getUI().getRootView(c).getView(0);
    int preferredHeight = (int)view.getPreferredSpan(View.Y_AXIS);
    return preferredHeight + insets.top + insets.bottom;
  }

  class TextAreaCellRenderer extends JTextArea implements TableCellRenderer {
    private final Color evenColor = new Color(230, 240, 255);
    public TextAreaCellRenderer() {
      super();
      setLineWrap(true);
      setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
    }
    @Override public Component getTableCellRendererComponent(
      JTable table, Object value, boolean isSelected,
      boolean hasFocus, int row, int column) {
      if(isSelected) {
        setForeground(table.getSelectionForeground());
        setBackground(table.getSelectionBackground());
      } else {
        setForeground(table.getForeground());
        setBackground(table.getBackground());
        setBackground((row%2==0)?evenColor:getBackground());
      }
      setFont(table.getFont());
      setText((value ==null) ? "" : value.toString());
      return this;
    }
}
private int getPreferredHeight(JTextComponent c) {
    Insets insets = c.getInsets();
    View view = c.getUI().getRootView(c).getView(2);
    int preferredHeight = (int)view.getPreferredSpan(View.Y_AXIS);
    return preferredHeight + insets.top + insets.bottom;
} 
private void setMultiLine(JTable table, TableColumn col, int row) {    
    int tableRowHeight = table.getRowHeight();
    col.setCellRenderer(new TextAreaCellRenderer());
    Component c = table.prepareRenderer(col.getCellRenderer(), row, 2);
    if(c instanceof JTextArea) {
          JTextArea a = (JTextArea) c;
          int h = getPreferredHeight(a) +     table.getIntercellSpacing().height;               
          if(h > tableRowHeight) {
              if (tableRowHeight * 3 < h) 
                  table.setRowHeight(row, tableRowHeight * 3);
              else
                  table.setRowHeight(row, h);
          }
    }       
}