您好我正在使用 JTable 来显示文件中的数据。为此,我喜欢有行标题和列标题。由于行标题不存在,我为它实现了一个单独的 JTable。
但现在我喜欢调整行标题和行网格的大小。无论如何我可以实现这样的excel功能。
我从 url 遵循行标题功能:- http://tips4java.wordpress.com/2008/11/18/row-number-table/并从 url 调整网格大小:- http://www.jroller.com/ santhosh/entry/make_jtable_resiable_better_than
现在,在整合了这两个代码之后,我成功地得到了行标题和可拖动的网格。
但是现在在调整网格大小后,我没有找到使行标题可拖动的方法。
请提出一些使行头可拖动的建议。
**SimpleTableDemo.java**
package com.swing.table;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.*;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.table.*;
import java.util.*;
import java.awt.*;
public class SimpleTableDemo extends JPanel {
private boolean DEBUG = false;
private int spacing = 6;
private Map columnSizes = new HashMap();
String[] columnNames = { "First Name", "Last Name", "Sport", "# of Years",
"Vegetarian" };
Object[][] data = {
{
"Kathy",
"Smith",
"SnowboardingXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
new Integer(5), new Boolean(false) },
{ "John", "Doe", "Rowing", new Integer(3), new Boolean(true) },
{ "Sue", "Black", "Knitting", new Integer(2), new Boolean(false) },
{ "Jane", "White", "Speed reading", new Integer(20),
new Boolean(true) },
{ "Joe", "Brown", "Pool", new Integer(10), new Boolean(false) } };
final JTable table = new JTable(data, columnNames);
Panel1 panel;
public SimpleTableDemo() {
super(new GridLayout(0, 1));
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
// table.setFillsViewportHeight(true);
if (DEBUG) {
table.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
printDebugData(table);
}
});
}
// Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
JTable rowTable = new RowNumberTable(table);
scrollPane.setRowHeaderView(rowTable);
scrollPane.setCorner(JScrollPane.UPPER_LEFT_CORNER,
rowTable.getTableHeader());
// Add the scroll pane to this panel.
add(scrollPane);
/*
* panel = new Panel1(); Rectangle rect = table.getCellRect(0,0,true);
*
* panel.setX(table.getWidth()); panel.setY(0);
* panel.setWidth(rect.width); panel.setHeight(rect.height);
* panel.setStr(table.getModel().getValueAt(0,0).toString());
* panel.setModel(table);
*
* add(panel);
*/
/*
* final JComboBox jNumberComboBoxSize = new JComboBox();
* jNumberComboBoxSize.setModel(new javax.swing.DefaultComboBoxModel(new
* String[] { "11", "12", "14", "16", "18", "20", "24", "30", "36",
* "48", "72" })); jNumberComboBoxSize.addActionListener(new
* java.awt.event.ActionListener() { public void
* actionPerformed(java.awt.event.ActionEvent evt) {
* jNumberComboBoxSizeActionPerformed(jNumberComboBoxSize); } });
*
* JPanel panel2 = new JPanel(); panel2.add(jNumberComboBoxSize);
*
* add(panel2);
*/
TableRowResizer rowResizer = new TableRowResizer(table);
adjustColumns();
}
private void jNumberComboBoxSizeActionPerformed(
JComboBox jNumberComboBoxSize) {
int fontSize = Integer.parseInt(jNumberComboBoxSize.getSelectedItem()
.toString());
table.setRowHeight(fontSize);
table.setFont(new Font("Serif", Font.BOLD, fontSize));
Rectangle rect = table.getCellRect(0, 0, true);
panel.setX(0);
panel.setY(0);
// panel.setWidth(rect.width);
panel.setHeight(rect.height);
panel.setStr(table.getModel().getValueAt(0, 0).toString());
panel.setModel(table);
panel.repaint();
table.revalidate();
}
private void printDebugData(JTable table) {
int numRows = table.getRowCount();
int numCols = table.getColumnCount();
javax.swing.table.TableModel model = table.getModel();
System.out.println("Value of data: ");
for (int i = 0; i < numRows; i++) {
System.out.print(" row " + i + ":");
for (int j = 0; j < numCols; j++) {
System.out.print(" " + model.getValueAt(i, j));
}
System.out.println();
}
System.out.println("--------------------------");
}
/*
* Adjust the widths of all the columns in the table
*/
public void adjustColumns() {
TableColumnModel tcm = table.getColumnModel();
for (int i = 0; i < tcm.getColumnCount(); i++) {
adjustColumn(i);
}
}
/*
* Adjust the width of the specified column in the table
*/
public void adjustColumn(final int column) {
TableColumn tableColumn = table.getColumnModel().getColumn(column);
if (!tableColumn.getResizable())
return;
int columnHeaderWidth = getColumnHeaderWidth(column);
int columnDataWidth = getColumnDataWidth(column);
int preferredWidth = Math.max(columnHeaderWidth, columnDataWidth);
panel.setWidth(preferredWidth);
updateTableColumn(column, preferredWidth);
}
/*
* Calculated the width based on the column name
*/
private int getColumnHeaderWidth(int column) {
TableColumn tableColumn = table.getColumnModel().getColumn(column);
Object value = tableColumn.getHeaderValue();
TableCellRenderer renderer = tableColumn.getHeaderRenderer();
if (renderer == null) {
renderer = table.getTableHeader().getDefaultRenderer();
}
Component c = renderer.getTableCellRendererComponent(table, value,
false, false, -1, column);
return c.getPreferredSize().width;
}
/*
* Calculate the width based on the widest cell renderer for the given
* column.
*/
private int getColumnDataWidth(int column) {
int preferredWidth = 0;
int maxWidth = table.getColumnModel().getColumn(column).getMaxWidth();
for (int row = 0; row < table.getRowCount(); row++) {
preferredWidth = Math.max(preferredWidth,
getCellDataWidth(row, column));
// We've exceeded the maximum width, no need to check other rows
if (preferredWidth >= maxWidth)
break;
}
return preferredWidth;
}
/*
* Get the preferred width for the specified cell
*/
private int getCellDataWidth(int row, int column) {
// Inovke the renderer for the cell to calculate the preferred width
TableCellRenderer cellRenderer = table.getCellRenderer(row, column);
Component c = table.prepareRenderer(cellRenderer, row, column);
int width = c.getPreferredSize().width
+ table.getIntercellSpacing().width;
return width;
}
/*
* Update the TableColumn with the newly calculated width
*/
private void updateTableColumn(int column, int width) {
final TableColumn tableColumn = table.getColumnModel()
.getColumn(column);
if (!tableColumn.getResizable())
return;
width += spacing;
// Don't shrink the column width
width = Math.max(width, tableColumn.getPreferredWidth());
columnSizes.put(tableColumn, new Integer(tableColumn.getWidth()));
table.getTableHeader().setResizingColumn(tableColumn);
tableColumn.setWidth(width);
}
/**
* Create the GUI and show it. For thread safety, this method should be
* invoked from the event-dispatching thread.
*/
private static void createAndShowGUI() {
// Create and set up the window.
JFrame frame = new JFrame("SimpleTableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create and set up the content pane.
SimpleTableDemo newContentPane = new SimpleTableDemo();
newContentPane.setOpaque(true); // content panes must be opaque
frame.setContentPane(newContentPane);
// Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
class Panel1 extends JPanel {
int x;
int y;
int width;
int height;
String str;
JTable model;
public void setModel(JTable model) {
this.model = model;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setWidth(int w) {
this.width = w;
}
public void setHeight(int h) {
this.height = h;
}
public void setStr(String s) {
this.str = s;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
int initX = 0;
for (int row = 0; row < 5; ++row) {
initX = x;
for (int col = 0; col < 5; ++col) {
g.drawRect(x, y, width, height);
g.drawString(model.getModel().getValueAt(row, col).toString(),
x + 10, y + 10);
x = x + width;
}
x = initX;
y = y + height;
}
}
};
**TableRowResizer.java**
package com.swing.table;
import java.awt.Cursor;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import javax.swing.JTable;
import javax.swing.event.MouseInputAdapter;
// @author Santhosh Kumar T - santhosh@in.fiorano.com
public class TableRowResizer extends MouseInputAdapter {
public static Cursor resizeCursor = Cursor
.getPredefinedCursor(Cursor.N_RESIZE_CURSOR);
private int mouseYOffset, resizingRow;
private Cursor otherCursor = resizeCursor;
private JTable table;
public TableRowResizer(JTable table) {
this.table = table;
table.addMouseListener(this);
table.addMouseMotionListener(this);
}
private int getResizingRow(Point p) {
return getResizingRow(p, table.rowAtPoint(p));
}
private int getResizingRow(Point p, int row) {
if (row == -1) {
return -1;
}
int col = table.columnAtPoint(p);
if (col == -1)
return -1;
Rectangle r = table.getCellRect(row, col, true);
r.grow(0, -3);
if (r.contains(p))
return -1;
int midPoint = r.y + r.height / 2;
int rowIndex = (p.y < midPoint) ? row - 1 : row;
return rowIndex;
}
public void mousePressed(MouseEvent e) {
Point p = e.getPoint();
resizingRow = getResizingRow(p);
mouseYOffset = p.y - table.getRowHeight(resizingRow);
}
private void swapCursor() {
Cursor tmp = table.getCursor();
table.setCursor(otherCursor);
otherCursor = tmp;
}
public void mouseMoved(MouseEvent e) {
if ((getResizingRow(e.getPoint()) >= 0) != (table.getCursor() == resizeCursor)) {
swapCursor();
}
}
public void mouseDragged(MouseEvent e) {
int mouseY = e.getY();
if (resizingRow >= 0) {
int newHeight = mouseY - mouseYOffset;
if (newHeight > 0)
table.setRowHeight(resizingRow, newHeight);
}
}
}
**RowNumberTable.java**
package com.swing.table;
import java.awt.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
/*
* Use a JTable as a renderer for row numbers of a given main table.
* This table must be added to the row header of the scrollpane that
* contains the main table.
*/
public class RowNumberTable extends JTable implements ChangeListener,
PropertyChangeListener {
private final JTable table;
public RowNumberTable(JTable table) {
this.table = table;
table.addPropertyChangeListener(this);
setFocusable(false);
setAutoCreateColumnsFromModel(false);
updateRowHeight();
updateModel();
updateSelectionModel();
TableColumn column = new TableColumn();
column.setHeaderValue("");
addColumn(column);
column.setCellRenderer(new RowNumberRenderer());
getColumnModel().getColumn(0).setPreferredWidth(50);
setPreferredScrollableViewportSize(getPreferredSize());
getTableHeader().setReorderingAllowed(false);
}
@Override
public void addNotify() {
super.addNotify();
Component c = getParent();
// Keep scrolling of the row table in sync with the main table.
if (c instanceof JViewport) {
JViewport viewport = (JViewport) c;
viewport.addChangeListener(this);
}
}
/*
* Delegate method to main table
*/
@Override
public int getRowCount() {
return table.getRowCount();
}
@Override
public int getRowHeight(int row) {
return table.getRowHeight(row);
}
/*
* This table does not use any data from the main TableModel, so just return
* a value based on the row parameter.
*/
@Override
public Object getValueAt(int row, int column) {
return Integer.toString(row + 1);
}
/*
* Don't edit data in the main TableModel by mistake
*/
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
// implements ChangeListener
public void stateChanged(ChangeEvent e) {
// Keep the scrolling of the row table in sync with main table
JViewport viewport = (JViewport) e.getSource();
JScrollPane scrollPane = (JScrollPane) viewport.getParent();
scrollPane.getVerticalScrollBar()
.setValue(viewport.getViewPosition().y);
}
// implements PropertyChangeListener
public void propertyChange(PropertyChangeEvent e) {
// Keep the row table in sync with the main table
if ("rowHeight".equals(e.getPropertyName())) {
updateRowHeight();
}
if ("selectionModel".equals(e.getPropertyName())) {
updateSelectionModel();
}
if ("model".equals(e.getPropertyName())) {
updateModel();
}
}
private void updateRowHeight() {
setRowHeight(table.getRowHeight());
}
private void updateModel() {
setModel(table.getModel());
}
private void updateSelectionModel() {
setSelectionModel(table.getSelectionModel());
}
/*
* Borrow the renderer from JDK1.4.2 table header
*/
private static class RowNumberRenderer extends DefaultTableCellRenderer {
public RowNumberRenderer() {
setHorizontalAlignment(JLabel.CENTER);
}
@Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
if (table != null) {
JTableHeader header = table.getTableHeader();
if (header != null) {
setForeground(header.getForeground());
setBackground(header.getBackground());
setFont(header.getFont());
}
}
if (isSelected) {
setFont(getFont().deriveFont(Font.BOLD));
}
setText((value == null) ? "" : value.toString());
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
return this;
}
}
}