如何使行标题可拖动

时间:2012-10-07 07:55:19

标签: java swing jtable

您好我正在使用JTable来显示文件中的数据。为此,我喜欢有行标题和列标题。由于行标题不存在,我为它实现了一个单独的JTable。

但现在我想调整行标题和行网格的大小。无论如何,我可以实现这样的excel功能。

我按照网址中的行标题功能: - 来自网址的http://tips4java.wordpress.com/2008/11/18/row-number-table/和网格调整大小: - 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;
        }
    }
}

0 个答案:

没有答案