java - 多页和多行 JTable

标签 java swing jtable

我想制作一个可以在多个页面中显示的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();
    }
}

我从 setGrid() 方法调用它:

public void setGrid() {
...
tabelItem = new Zebra();
btnRight.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                nomorHalaman++;
                initPagination();
            }
 });
 panelNavigasi.add(btnRight);
...
}

initPagination() 使用上面的 MyTableModel 从 MySQL 数据库的表中加载记录,可以设置每次用户单击导航按钮(第一、左、右、最后)时一页中的行数:

private void initPagination(){
    totalData=getItemRecNum();         
    jumlahBarisPerhalaman=Integer.valueOf(txtPagesize.getText());
    Double totalHalamanD=Math.ceil((double)totalData/(double)jumlahBarisPerhalaman);
    totalHalaman=totalHalamanD.intValue();        
    String HEADER[]={"No.","Kode","Produk","Jasa","satuan", "harga", "qty", "jml"};
    if(nomorHalaman.equals(1)){
        btnOne.setEnabled(false);
        btnLeft.setEnabled(false);
    }   else {
        btnOne.setEnabled(true);
        btnLeft.setEnabled(true);
    }

    if(nomorHalaman.equals(totalHalaman)){
        btnEnd.setEnabled(false);
        btnRight.setEnabled(false);
    }   else    {
        btnEnd.setEnabled(true);
        btnRight.setEnabled(true);
    }    
    if(nomorHalaman>totalHalaman){
        nomorHalaman=1;
    }        

    model = new MyTableModel();
  // Get records from MySQL DB according to page(offset) and rows per page      
    show(nomorHalaman, jumlahBarisPerhalaman);
    tabelItem.setModel(model);   

    lblPage.setText("p." + nomorHalaman + "/" + totalHalaman + "     ");
}

Zebra 是一个制作斑马条纹表的,我将它用于多行单元格表:

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;
    }
}

最佳答案

我已经找到了解决我的问题的方法。也许还有其他方法,但目前这对我来说已经足够了。我对旧源代码做了一些修改,并将其限制为三行,因为项目名称不太长,不需要超过三行。 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);
          }
    }       
}

关于java - 多页和多行 JTable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29889313/

相关文章:

c# - 在 C# 中访问 java 编译器的输出

java - 如何指定Spring应该使用哪个子类

Java - jpanel 未显示所有组件

java - 绘制还是使用 JLabel 更好

java - 如何在 JTable 顶部添加新行并更改 Java 中新插入行的颜色?

java - 无法在 JTable 中返回 Double 值

java - 问 : Updating a ProgressBar with real results (includes code)

java - twitter4j 程序上出现 "unexpected token: int"错误

Java:获取一个/所有可用显示器(而不是整个桌面)的分辨率?

java - 如何在 NetBeans 的对话框中显示 JTable?