我无法调整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?我以为我可以使用默认的。我可以添加列,更改背景颜色等,但不能调整大小。我正在添加一张图片,展示它现在的样子。我想要显示整个文本。
任何帮助都会非常感激。我现在花了很多时间。
答案 0 :(得分:4)
在TimeLine.addColumn()
表结构中,使用SwingUtilities.invokeLater
触发通知。一旦处理完所有其他待处理事件,通知将在EDT上异步执行。
诀窍是fireTableStructureChanged()
可能会触发重建表的列。您可以在此answer中找到有关fireTableStructureChanged
的更多详细信息。因此,可能发生的是您设置首选大小然后执行fireTableStructureChanged()
并将大小重置为默认值。
不确定该方法中的预期逻辑是什么(即注释“修复了一个讨厌的java矢量错误”),但是如果你执行fireTableStructureChanged()
和fireTableDataChanged()
没有SwingUtilities.invokeLater
您应该看到已调整大小的列。
当然,您必须使用EDT,因此如果无法修复,您可以使用SwingUtilities.invokeLater()
执行列宽设置。
另请注意,列从0开始。您提到您调整了第0列的大小,但事实上在代码中您访问了第1列。