无法调整JTable列的大小

时间:2012-09-29 22:41:59

标签: java swing jtable jframe

我无法调整JTable中的列(时间轴相似)。我复制了时间线课程。我自己写了timelineUI。感觉就像我已经尝试了一切来调整列的大小但似乎不可能。

这是TimelineUI类,重要部分位于我试图调整第0列的底部。

package group4;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.TableColumn;

public class TimelineUI extends JFrame {

    TimeLine timeline;
    JScrollPane scrollpane;
    public TimelineUI() {
        initTimeline();
    }

    public final void initTimeline() {
            try {                                       
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());            
            } catch (Exception e) {
                e.printStackTrace();
            }   
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setLayout(new BorderLayout());
            this.setTitle("Timeline");

            timeline = new TimeLine(5,3);
            scrollpane = new JScrollPane();
            scrollpane.setViewportView(timeline);
            this.add(scrollpane,BorderLayout.CENTER);

            addData();

            this.pack();
            this.setSize(1200,200);
            this.setVisible(true);
    }
    public JTable getTable () {
        return timeline;
    }
    private void addData(){
        ArrayList<String> columndata = new ArrayList<String>();
        columndata.add("Blig (1)");
        columndata.add("Workbench (2)");
        timeline.addColumn("", columndata);

        columndata = new ArrayList<String>();
        columndata.add("Making spunks");
        columndata.add("Service bligs");
        timeline.addColumn(0, columndata);

        columndata = new ArrayList<String>();
        columndata.add("Finding plonks");
        columndata.add("Finding plonks");
        timeline.addColumn(60, columndata);

        columndata = new ArrayList<String>();
        columndata.add("Finding plonks");
        columndata.add("Finding plonks");
        timeline.addColumn(90, columndata);

        columndata = new ArrayList<String>();
        columndata.add("Finding plonks");
        columndata.add("Finding plonks");
        timeline.addColumn(120, columndata);


        columndata = new ArrayList<String>();
        columndata.add("Finding plonks");
        columndata.add("Finding plonks");
        timeline.addColumn(150, columndata);

        columndata = new ArrayList<String>();
        columndata.add("Finding plonks");
        columndata.add("Finding plonks");
        timeline.addColumn(180, columndata);


        timeline.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        timeline.getColumnModel().getColumn(1).setMinWidth(200);
        timeline.getColumnModel().getColumn(1).setMaxWidth(200);
        timeline.getColumnModel().getColumn(1).setPreferredWidth(200);

    }
}

然后我们有一个Timeline.class,我是从一个网上好人那里得到的:

package group4;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;


public class TimeLine extends JTable{
    private final int ROW_DISTANCE = 5;
    private final int TIME_ROW_HEIGHT = 20;
    private ImageTableModel itm;
    private int maxRowHeight = 20;

    /**
     * Generates a new TimeLine object
     * @param rows  - number of rows of the default grid
     * @param columns - number of columns of the default grid
     */
    public TimeLine(int rows, int columns){
        setTimeLineLookAndFeel();
        itm = initModel();
        itm.initGrid(rows, columns);
        setModel(itm);  // set the table model
        System.out.println(itm.getValueAt(2, 1));

    }

    /**
     * @return ImageTableModel - a new ImageTableModel
     */
    private ImageTableModel initModel(){
        return new ImageTableModel();
    }

    /**
     * Adds a new column to the table
     * @param date - The column name as java.util.Date
     * @param columndata - The row values for this column. 
     */
    public void addColumn(int time, ArrayList<String> columndata){
        itm.addColumn(time+"", columndata);
    }

    /**
     * Adds a new column to the table
     * @param columnName - The column name
     * @param columndata - The row values for this column. 
     */
    public void addColumn(String columnName, ArrayList<String> columndata){
        itm.addColumn(columnName, columndata);
    }

    /**
     * Utility function to set the scroll pane
     */
    public int getRowCount(){
        return itm.getRowCount();
    }

    /**
     * Utility function to set the scroll pane
     */
    public int getColumnCount(){
        return itm.getColumnCount();
    }

    /**
     * Set some JTable properties to make it 
     * look more like a timeline
     */
    private void setTimeLineLookAndFeel(){
        this.getTableHeader().setReorderingAllowed(false);
        this.setCellSelectionEnabled(true); 
        this.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        this.setIntercellSpacing(new Dimension(0,0));
        this.setShowGrid(false);        
        this.setTableHeader(null);
    }

    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.setColor( Color.BLACK );
        int y = getRowHeight(0) * (itm.getRowCount() - 1) - 1;      
        g.drawLine(0, y, getSize().width, y);
    }

    @Override
    public Component prepareRenderer(TableCellRenderer renderer, int row, int column){
        Component c = super.prepareRenderer(renderer, row, column);

        if(row == itm.getRowCount()-1){
            c.setBackground(java.awt.SystemColor.control);
        }
        else if( !this.isCellSelected(row, column)) {
            c.setBackground(column % 2 != 0 ? new Color(241, 245, 250) : null);
        }       
        return c;
    }   


    @Override
    /**
     * makes the date column look like a table header
     */ 
    public void changeSelection(int row, int column, boolean toggle, boolean extend){
        Object o = getValueAt(row, column); 
        if (o != null && row != itm.getRowCount()-1){
            super.changeSelection(row, column, toggle, extend); 
        }
    }


    /**
     * The table model for this timeline     *
     */
    class ImageTableModel extends AbstractTableModel {
        private ArrayList<String> columnnames; // holds the column names
        private ArrayList<ArrayList<String>> data; // holds the table data
        private int maxRowCount;    
        private int columnCursor; // points on the current column

        public ImageTableModel(){
            columnnames = new ArrayList<String>();
            data = new ArrayList<ArrayList<String>>();
            maxRowCount = 0;
            columnCursor = 0;
        }

        public Object getValueAt(int row, int column) {
            if (data.get(column).size()-1<row) {
                return null;
            }
            else{
                return data.get(column).get(row);
            }           
        } 

        public int getRowCount(){
            return maxRowCount;
        } 

        public int getColumnCount(){
            return columnnames.size();
        }

        public String getColumnName( int columnIndex ){
            return columnnames.get(columnIndex);
        }

        /**
         * Adds a new column to the table
         * @param columnName - The column name
         * @param columndata - The row values for this column.
         */
        public void addColumn(String columnName, ArrayList<String> columndata) {
            if(columnCursor >= columnnames.size()){
                columnnames.add(columnName);
                data.add(rotateFillList(columnName,columndata));

            }
            else{
                columnnames.set(columnCursor, columnName);
                data.set(columnCursor, rotateFillList(columnName,columndata));
            }
            SwingUtilities.invokeLater (new Runnable(){     // fixes a nasty java vector bug
                public void run ()  {
                    fireTableStructureChanged();
                    fireTableDataChanged(); 
                }
            });
            columnCursor++;
        }

        public void initGrid(int rows, int columns){
            for(int i = 0; i < columns+100; i++){
                ArrayList<String> newdata = new ArrayList<String>();
                for(int j = 0; j < rows; j++){
                    newdata.add(null);
                }
                columnnames.add(String.valueOf(i));
                data.add(newdata);
                maxRowCount = rows;
            }
            SwingUtilities.invokeLater (new Runnable(){     // fixes a nasty java vector bug
                public void run ()  {
                    fireTableStructureChanged();
                    fireTableDataChanged(); 
                }
            });
        }

        /**
         * Rotates the list. If list.size() is smaller than
         * maxRowCount the list if filled with null values
         * This generates the bottom up effect
         * @param columnName - The column name
         * @param list
         * @return list
         */
        private ArrayList<String> rotateFillList(String columnName, ArrayList<String> list){
            list.add(0,columnName); // set column name to be on the bottom 

            if(maxRowCount < list.size()){
                // adjust all rows to the new maxRowCount
                maxRowCount = list.size();
                for(int i = 0; i < data.size(); i++){
                    int diff = maxRowCount - data.get(i).size();
                    for(int j = 0; j < diff; j++){
                        data.get(i).add(0,null);
                    }
                }               
            }
            else {  // fill with null values
                int diff = maxRowCount - list.size();
                for(int i = 0; i < diff; i++){
                    list.add(null);
                }
            }

            ArrayList<String> rotatedList = new ArrayList<String>();
            for(int i= list.size()-1;i>=0;i--){     // rotate list
                rotatedList.add(list.get(i));
            }

            return rotatedList;
        }
    }   
}

这似乎是一个非常简单的问题,但我无法弄明白。我是否需要自己定义ColumnModel?我以为我可以使用默认的。我可以添加列,更改背景颜色等,但不能调整大小。我正在添加一张图片,展示它现在的样子。我想要显示整个文本。

Image of the timeline

任何帮助都会非常感激。我现在花了很多时间。

1 个答案:

答案 0 :(得分:4)

TimeLine.addColumn()表结构中,使用SwingUtilities.invokeLater触发通知。一旦处理完所有其他待处理事件,通知将在EDT上异步执行。

诀窍是fireTableStructureChanged()可能会触发重建表的列。您可以在此answer中找到有关fireTableStructureChanged的更多详细信息。因此,可能发生的是您设置首选大小然后执行fireTableStructureChanged()并将大小重置为默认值。

不确定该方法中的预期逻辑是什么(即注释“修复了一个讨厌的java矢量错误”),但是如果你执行fireTableStructureChanged()fireTableDataChanged()没有SwingUtilities.invokeLater您应该看到已调整大小的列。

当然,您必须使用EDT,因此如果无法修复,您可以使用SwingUtilities.invokeLater()执行列宽设置。

另请注意,列从0开始。您提到您调整了第0列的大小,但事实上在代码中您访问了第1列。