Java 如何使JTable列不包含JTextFields,而是包含JTextAreas?

Java 如何使JTable列不包含JTextFields,而是包含JTextAreas?,java,swing,jtable,textarea,awt,Java,Swing,Jtable,Textarea,Awt,请告诉我,如何制作包含JTextAreas的JTable列, 因此,当用户键入大量文本和内容时,单元格的高度将增加 我们可以看到多行(单元格被展开;因此,行也会展开)您需要基于JTextArea编写自己的单元格渲染器和编辑器: public class Start { public static class JTextPaneCellEditor extends AbstractCellEditor implements TableCellEditor, KeyListener

请告诉我,如何制作包含JTextAreas的JTable列, 因此,当用户键入大量文本和内容时,单元格的高度将增加
我们可以看到多行(单元格被展开;因此,行也会展开)

您需要基于JTextArea编写自己的单元格渲染器和编辑器:

    public class Start
{
    public static class JTextPaneCellEditor extends AbstractCellEditor implements TableCellEditor, KeyListener
    {
        private JViewport viewport;
        private JTable table;
        private int row;
        private JTextPane pane;

        public JTextPaneCellEditor(){
            viewport = new JViewport();
            pane = new JTextPane();
            viewport.add(pane);
            pane.addKeyListener(this);
        }

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

        @Override public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column){
            this.table = table;
            this.row = row;
            pane.setText(value.toString());
            int newHeight = (int)pane.getPreferredSize().getHeight();
            if(table.getRowHeight(row) < newHeight){
                table.setRowHeight(row, newHeight);
            }
            return pane;
        }

        @Override public boolean isCellEditable(EventObject e){
            if (e instanceof MouseEvent) {
                return ((MouseEvent)e).getClickCount() >= 2;
            }
            return true;
        }

        @Override public void keyTyped(KeyEvent e){
            table.setRowHeight(row, (int)pane.getPreferredSize().getHeight());
        }

        @Override public void keyPressed(KeyEvent e){
            if(e.getKeyCode() == KeyEvent.VK_ENTER){
                stopCellEditing();
            }
        }

        @Override public void keyReleased(KeyEvent e){
        }
    }

    private static class JTextPaneCellRenderer extends JViewport implements TableCellRenderer
    {
        JTextPane pane;
        JTextPaneCellRenderer(){
            pane = new JTextPane();
            add(pane);
        }

        @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column){
            pane.setText(value.toString());
            table.setRowHeight(row, (int)pane.getPreferredSize().getHeight());
            return this;
        }
    }

    public static void main(String[] args){
        JTable table = new JTable(new String[][]{{"String String String String StringString String String String StringString String String String StringString String String String StringString String String String String"}, {"String 2"}}, new String[]{"Column"});
        table.setDefaultRenderer(Object.class, new JTextPaneCellRenderer());
        table.setDefaultEditor(Object.class, new JTextPaneCellEditor());

        JFrame test = new JFrame();
        test.add(new JScrollPane(table));
        test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        test.setSize(300, 300);
        test.setLocationRelativeTo(null);
        test.setVisible(true);
    }
}
公共类启动
{
公共静态类JTextPaneCellEditor扩展AbstractCellEditor实现TableCellEditor、KeyListener
{
私有视口;
专用JTable表;
私人int row;
私人JTextPane;
公共JTextPaneCellEditor(){
viewport=newjviewport();
pane=新的JTextPane();
viewport.add(窗格);
pane.addKeyListener(这个);
}
@重写公共对象getCellEditorValue(){
return pane.getText();
}
@重写公共组件getTableCellEditorComponent(JTable表、对象值、布尔isSelected、int行、int列){
this.table=表格;
this.row=行;
setText(value.toString());
int newHeight=(int)pane.getPreferredSize().getHeight();
if(表.getRowHeight(行)=2;
}
返回true;
}
@重写公共void键类型(KeyEvent e){
table.setRowHeight(row,(int)窗格.getPreferredSize().getHeight());
}
@按下覆盖公共无效键(键事件e){
如果(例如getKeyCode()==KeyEvent.VK_ENTER){
stopCellEditing();
}
}
@覆盖公共无效密钥释放(密钥事件e){
}
}
私有静态类JTextPaneCellRenderer扩展了JViewport,实现了TableCellRenderer
{
JTextPane窗格;
JTextPaneCellRenderer(){
pane=新的JTextPane();
添加(窗格);
}
@重写公共组件GetTableCellRenderComponent(JTable表、对象值、布尔isSelected、布尔hasFocus、int行、int列){
setText(value.toString());
table.setRowHeight(row,(int)窗格.getPreferredSize().getHeight());
归还这个;
}
}
公共静态void main(字符串[]args){
JTable table=新JTable(新字符串[][{{“字符串”},{“字符串2”},新字符串[]{“列”});
setDefaultRenderer(Object.class,新的JTextPaneCellRenderer());
setDefaultEditor(Object.class,新的JTextPaneCellEditor());
JFrame测试=新JFrame();
添加(新的JScrollPane(表));
test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
测试设置尺寸(300300);
test.setLocationRelativeTo(空);
test.setVisible(真);
}
}
编辑:添加视口以更好地调整大小。但在第一次编辑时该行仍然没有展开。有人有什么想法吗

编辑2:我同意这些评论。您想要的东西是可能的,但您需要未经测试的、黑客式的自定义实现。如果您重新设计布局以排除此类JTable巫术,您的境况会更好。

@Jakub Zaverka

稍后我将删除此答案

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

public class AutoWrapTest {

    public JComponent makeUI() {
        String[] columnNames = {"TextAreaCellRenderer"};
        Object[][] data = {
            {"123456789012345678901234567890"},
            {"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddx"},
            {"----------------------------------------------0"},
            {">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>|"},};
        TableModel model = new DefaultTableModel(data, columnNames) {

            private static final long serialVersionUID = 1L;

            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };
        JTable table = new JTable(model) {

            private static final long serialVersionUID = 1L;

            @Override
            public void doLayout() {
                TableColumn col = getColumnModel().getColumn(0);
                for (int row = 0; row < getRowCount(); row++) {
                    Component c = prepareRenderer(col.getCellRenderer(), row, 0);
                    if (c instanceof JTextArea) {
                        JTextArea a = (JTextArea) c;
                        int h = getPreferredHeight(a) + getIntercellSpacing().height;
                        if (getRowHeight(row) != h) {
                            setRowHeight(row, h);
                        }
                    }
                }
                super.doLayout();
            }            //http://tips4java.wordpress.com/2008/10/26/text-utilities/

            private int getPreferredHeight(JTextComponent c) {
                Insets insets = c.getInsets();
                View view = c.getUI().getRootView(c).getView(0);
                int preferredHeight = (int) view.getPreferredSpan(View.Y_AXIS);
                return preferredHeight + insets.top + insets.bottom;
            }
        };
        table.setEnabled(false);
        table.setShowGrid(false);
        table.setTableHeader(null);
        table.getColumnModel().getColumn(0).setCellRenderer(new TextAreaCellRenderer());
        JScrollPane sp = new JScrollPane(table);
        sp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        JPanel p = new JPanel(new BorderLayout());
        p.add(sp);
        return p;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }

    public static void createAndShowGUI() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.getContentPane().add(new AutoWrapTest().makeUI());
        f.setSize(200, 200);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class TextAreaCellRenderer extends JTextArea implements TableCellRenderer {

    private static final long serialVersionUID = 1L;
    private final Color evenColor = new Color(230, 240, 255);

    public TextAreaCellRenderer() {
        super();
        setLineWrap(true);
        setWrapStyleWord(true);
        setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        if (isSelected) {
            setForeground(table.getSelectionForeground());
            setBackground(table.getSelectionBackground());
        } else {
            setForeground(table.getForeground());
            setBackground(table.getBackground());
            setBackground((row % 2 == 0) ? evenColor : getBackground());
        }
        setFont(table.getFont());
        setText((value == null) ? "" : value.toString());
        return this;
    }
}
import java.awt.*;
导入javax.swing.*;
导入javax.swing.table.*;
导入javax.swing.text.*;
公共类自动包装{
公共JComponent makeUI(){
String[]columnNames={“TextAreaCellRenderer”};
对象[][]数据={
{"123456789012345678901234567890"},
{“ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddx”},
{"----------------------------------------------0"},
{">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>|"},};
TableModel model=新的DefaultTableModel(数据、列名){
私有静态最终长serialVersionUID=1L;
@凌驾
公共布尔值可编辑(int行,int列){
返回false;
}
};
JTable表格=新JTable(型号){
私有静态最终长serialVersionUID=1L;
@凌驾
公共空间布局(){
TableColumn col=getColumnModel().getColumn(0);
对于(int row=0;row