Как изменить размер строки JTable при вводе пользователем? - PullRequest
2 голосов
/ 23 января 2012

У меня есть редактируемый JTable.По мере того, как пользователь печатает, если текст длиннее ширины, мне нужна высота для увеличения.Я установил для linewrap значение true, но он изменяет высоту только после того, как пользователь нажмет ввод.Что мне не хватает?Я посмотрел на ответы, которые решают проблему изменения размера (например, this в cellRenderer, но мне нужно настроить высоту как пользовательские типы, а не после того, как они закончили печатать.

public class EndCycleCellEditor extends AbstractCellEditor implements TableCellEditor, KeyListener  {
    JComponent component;

    private ArrayList<ArrayList<Integer>> rowColHeight = new ArrayList<ArrayList<Integer>>();

    public EndCycleCellEditor(){
        component  = new JTextArea();
        ((JTextArea) component).setWrapStyleWord(true);
        ((JTextArea) component).setLineWrap(true);
        component.addKeyListener(this);
    }

    @Override
    public Object getCellEditorValue() {
        return ((JTextArea) component).getText();
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value,
            boolean isSelected, int row, int column) {
        ((JTextArea)component).setText(value.toString());
        return component;
    }

    @Override
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyPressed(KeyEvent e) {
        // TODO Auto-generated method stub

            }

    @Override
    public void keyReleased(KeyEvent e) {
        if(((JTextArea) component).getText().length() >= 200){
            Toolkit.getDefaultToolkit().beep();
            ((JTextArea)component).setText(((JTextArea)component).getText().substring(0,200) );
        }

    }



}

Ответы [ 2 ]

4 голосов
/ 23 января 2012

1) изменение размера возможно, но безобразно и не user_friendly

2) не используйте нестандартный хак в качестве диапазона MultiLines в JTable

3) put JTextArea *От 1006 * до JScrollPane , но затем необходимо переопределить прокрутку JScrollPane внутри другого JScrollPane

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

class JTableMultiLineSupport extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {

    private static final long serialVersionUID = 1L;
    private JTextArea editor = new JTextArea(4, 10);
    private JScrollPane jsp = new JScrollPane(editor);
    private JTable table;
    private int row;
    private int col;
    private JTextArea renderer = new JTextArea(4, 10);

    public static void main(String[] args) {
        JTable table = new JTable(new String[][]{
                    {"1\n2\n3\n4\n5\n6\n7", "1\n2\n3\n4\n5\n6\n7", "1\n2\n3\n4\n5\n6\n7"},
                    {"1\n2\n3\n4\n5\n6\n7", "1\n2\n3\n4\n5\n6\n7", "1\n2\n3\n4\n5\n6\n7"}},
                new String[]{"First Column", "Second Column", "Third Column"});
        JTableMultiLineSupport mls = new JTableMultiLineSupport();
        table.setDefaultEditor(Object.class, mls);
        table.setDefaultRenderer(Object.class, mls);
        table.setRowHeight(0, 30);
        table.setRowHeight(1, 70);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JFrame frame = new JFrame("Test");
        frame.add(new JScrollPane(table));
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value,
            boolean isSelected, int row, int col) {
        this.table = table;
        this.row = row;
        this.col = col;
        editor.setText(value.toString());
        return jsp;
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
        renderer.setText(value == null ? "" : value.toString());
        renderer.setEnabled(false);
        return renderer;
    }

    @Override
    public Object getCellEditorValue() {
        return editor.getText();
    }

    @Override
    public boolean stopCellEditing() {
        table.getModel().setValueAt(editor.getText(), row, col);
        return true;
    }
}
0 голосов
/ 07 марта 2013

[РЕДАКТИРОВАТЬ: мой первоначальный ответ имел некоторые ошибки и последствия.Между тем я нашел более элегантное решение, основанное на различных примерах.]

Это решение основано на http://www.coderanch.com/t/336033/GUI/java/MultiLine-JTable - хотя я исправил некоторые ошибки (в основном: удалил вычисление rowHeights из Editor,добавлено вычисление rowHeight для Renderer).

Предложения по http://blog.botunge.dk/post/2009/10/09/JTable-multiline-cell-renderer.aspx хороши для того, чтобы сделать его более красивым (например, добавление цветов и шрифтов для таблицы).

Соберите вместеЭто решение отображает ячейки JTable с несколькими строками.Редактор автоматически обновляет высоту строки, когда текст вводится или удаляется.Вычисление высоты строки оставлено для предпочитаемого размера TextArea.

Шаг первый: CellRenderer

public class MultiLineCellRenderer extends JTextArea implements
    TableCellRenderer {

public MultiLineCellRenderer() {
    setEditable(false);
    setLineWrap(true);
    setWrapStyleWord(true);
}

public Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int column) {

    if (value instanceof String) {
        setText((String) value);
        // We set the width and force textarea to recompute the preferred height
        setSize(table.getColumnModel().getColumn(column).getWidth(), 1000);

        // we should not do the following in this method.
        // it seems to create an endless loop
        // int rowHeight = table.getRowHeight(row);
        // int cellHeight = getPreferredSize().height;
        // if (cellHeight > rowHeight)
        //  table.setRowHeight(row, cellHeight);
    } else
        setText("");
    return this;
}

/*
 * Make sure to call this method, whenever the table changes.
 * Call it from appropriate TableCellRenderer, TableModelListener, 
 * ComponentListener, TableColumnModelListener.
 */
public void updateRowHeights() {
    for (int row = 0; row < table.getRowCount(); row++) {
        int rowHeight = 0;
        for (int col = 0; col < table.getColumnCount(); col++) {
            Object value = table.getValueAt(row, col);
            if (value != null)
                setText(value.toString());
            else
                setText("");
            setSize(table.getColumnModel().getColumn(col).getWidth(), 1000);
            int cellHeight = getPreferredSize().height;
            if (cellHeight > rowHeight)
                rowHeight = cellHeight;
        }
        table.setRowHeight(row, rowHeight);
    }
}
}

Шаг 2: CellEditor (я предполагаю, что возможно более короткое решение, без переопределения JTextArea).

public class MultiLineCellEditor extends AbstractCellEditor implements
    TableCellEditor {
MyTextArea textArea;
JTable table;

public MultiLineCellEditor(JTable ta) {
    super();
    table = ta;
    // this component relies on having this renderer for the String
    // class
    MultiLineCellRenderer renderer = new MultiLineCellRenderer();
    table.setDefaultRenderer(String.class, renderer);
    textArea = new MyTextArea();
    textArea.setLineWrap(true);
    textArea.setWrapStyleWord(true);
}

public Object getCellEditorValue() {
    return textArea.getText();
}

public Component getTableCellEditorComponent(JTable table, Object value,
        boolean isSelected, int row, int column) {
    textArea.setText(table.getValueAt(row, column).toString());
    textArea.rowEditing = row;
    textArea.columnEditing = column;
    textArea.lastPreferredHeight = textArea.getPreferredSize().height;
    return textArea;
}

/**
 * This method determines the height in pixel of a cell given the text it
 * contains
 */
private int cellHeight(int row, int col) {
    if (row == table.getEditingRow() && col == table.getEditingColumn())
        return textArea.getPreferredSize().height;
    else
        return table
                .getDefaultRenderer(String.class)
                .getTableCellRendererComponent(table,
                        table.getModel().getValueAt(row, col), false,
                        false, row, col).getPreferredSize().height;
}

void cellGrewEvent(int row, int column) {
    updateRow(row);
}

void cellShrankEvent(int row, int column) {
    updateRow(row);
}

void updateRow(int row) {
    int maxHeight = 0;
    for (int j = 0; j < table.getColumnCount(); j++) {
        int ch;
        if ((ch = cellHeight(row, j)) > maxHeight) {
            maxHeight = ch;
        }
    }
    table.setRowHeight(row, maxHeight);
}

class MyTextArea extends JTextArea implements KeyListener {
    private static final long serialVersionUID = 1L;
    int lastPreferredHeight = 0;
    int rowEditing;
    int columnEditing;

    MyTextArea() {
        addKeyListener(this);
        // This is a fix to Bug Id 4256006
        addAncestorListener(new AncestorListener() {
            public void ancestorAdded(AncestorEvent e) {
                requestFocus();
            }

            public void ancestorMoved(AncestorEvent e) {
            }

            public void ancestorRemoved(AncestorEvent e) {
            }
        });
    }

    public void keyPressed(KeyEvent e) {
    }

    public void keyReleased(KeyEvent e) {
    }

    public void keyTyped(KeyEvent e) {
        if (getPreferredSize().getHeight() > lastPreferredHeight) {
            lastPreferredHeight = getPreferredSize().height;
            cellGrewEvent(rowEditing, columnEditing);
            // this will trigger the addition of extra lines upon the
            // cell growing and prevent all the text being lost when 
            // the cell grows to the point of requiring scrollbars
            table.setValueAt(getText(), rowEditing, columnEditing);
        } else if (getPreferredSize().getHeight() < lastPreferredHeight) {
            lastPreferredHeight = getPreferredSize().height;
            cellShrankEvent(rowEditing, columnEditing);
        } else if (table.getValueAt(rowEditing, columnEditing).equals(""))
            table.setValueAt(getText(), rowEditing, columnEditing);
    }
}
}

А вот код для его тестирования.

public class MultiLineCellExample extends JFrame {

private static final long serialVersionUID = 1L;

public MultiLineCellExample() {
    DefaultTableModel dm = new DefaultTableModel() {
        private static final long serialVersionUID = 1L;

        public Class<?> getColumnClass(int columnIndex) {
            return String.class;
        }
    };
    dm.setDataVector(
            new Object[][] {
                    { "aa TEST TEST TEST TEST TEST TEST TEST TEST END",
                            "bb", "cc" }, { "A\nA", "B\nB", "C\nC" } },
            new Object[] { "1", "2", "3" });
    JTable table = new JTable(dm);
    MultiLineCellEditor editor = new MultiLineCellEditor(table);
    table.setDefaultEditor(String.class, editor);
    dm.fireTableRowsInserted(0, 0);
    JScrollPane scroll = new JScrollPane(table);
    getContentPane().add(scroll);
}

public static void main(String[] args) {
    MultiLineCellExample mlce = new MultiLineCellExample();

    mlce.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mlce.setSize(400, 400);
    mlce.pack();
    mlce.setVisible(true);
}

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...