【问题标题】:Expand JList row height depending on content根据内容展开 JList 行高
【发布时间】:2011-10-17 14:04:48
【问题描述】:

我有一个简单的问题让我发疯。

我有一个 JList,并希望它的单元格根据其内容(可变长度的文本)进行扩展。

所以我像这样创建了一个 CustomCellRenderer:

@Override
public Component getListCellRendererComponent(final JList list, final Object value, final int index, final boolean isSelected, final boolean hasFocus)
{
    final String text = (String) value;

    final JTextArea ta = new JTextArea();
    ta.setText(text);
    ta.setFont(new Font("Dialog", Font.PLAIN, (int) Theme.FONTSIZE_TEXT));
    ta.setForeground(Theme.FONTCOLOR_CONTENT);
    ta.setLineWrap(true);
    ta.setWrapStyleWord(true);
    ta.setColumns(0);
    ta.setBorder(BorderFactory.createEmptyBorder(10, Theme.PADDING, 0, 0));
    return ta;
}

但单元格只有一个文本行高,而 JTextArea 的其余部分被截断。如果我添加

ta.setPreferredSize(new Dimension(0, 70));

我得到了 70 的行高,我可以看到更多 JTextArea 的文本,但仍然不是全部。

有什么办法可以让JList展开它的单元格,让JTextArea的全部内容都显示出来?

【问题讨论】:

  • sscce 可能会澄清问题。

标签: java swing height row jlist


【解决方案1】:

尝试使用 JList 的 setFixedCellHeight() 方法。

【讨论】:

  • 这是 4 年前,但我今天遇到了同样的问题,发现这个答案会更改所有 jlists 行,而不是内容特别长或短的特定行。
  • 我不同意你的建议。 Swing a 是很棒的前端框架,您可以在其中开发出色的跨平台应用程序。是一个非常成熟的框架,并且有很好的文档记录。确实还有其他一些跨平台选项,例如 JavaFX、SWT、Qt……但我认为 Swing 是一个不错的选择。例如,IntelliJ (Android Studio) 对我来说是有史以来最好的商业 Swing 应用程序,在每个操作系统(Linux、Mac 和 Windows)中都带来了出色的用户体验。
【解决方案2】:

不确定是否有优雅的方式。 我知道的一种方法如下: 在getListCellRendererComponent()

  • 为渲染器使用 JLabel
  • 将相关文本转换为 HTML 和 使用一些逻辑将<br> 插入到需要的文本中。
  • 然后将文本设置为JLabel组件的文本并返回。

【讨论】:

    【解决方案3】:

    也许有最简单和最好的方法,我认为JTable 有一个 TableColumn(并且没有 TableHeader)在所有情况下都比JList 更好,这是你的Render MacOX version

    那么输出应该是

    import java.awt.*;
    import javax.swing.*;
    import javax.swing.table.*;
    import javax.swing.text.*;
    //http://tips4java.wordpress.com/2008/10/26/text-utilities/
    public class AutoWrapTest {
    
        public JComponent makeUI() {
            String[] columnNames = {" Text Area Cell Renderer "};
            Object[][] data = {
                {"123456789012345678901234567890"},
                {"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddx"},
                {"----------------------------------------------0"},
                {">>>>>>>>>>>>>dddddddddddddddddddddddddddddddddddddddddddddddddd"
                    + "dddddddxdddddddddddddddddddddddddddddddddddddddddddddd"
                    + "dddddddddddx>>>>>>>>>>>>>>>>>>>>>>>>>|"},
                {">>>>>>>>>>>>ddddddddddddddddddddddddddddddddddddddddddddddddddd"
                    + "ddddddx>>>>>>>>>>>>>>>>>>>>>>>>>>|"},
                {"a|"},
                {">>>>>>>>bbbb>>>>>>>>>>>>>>>>>>>|"},
                {">>>>>>>>>>>>>>>>>>|"},
                {">>>>>>>>>>>>>dddddddddddddddddddddddddddddddddddddddddddddddddd"
                    + "dddddddxdddddddddddddd123456789012345678901234567890dddddd"
                    + "dddddddddddddddddddddddddddddddddddddx>>>>>>>>>>>>>>>>>>>>"
                    + ">>>>>|"},
                {">>>>>>>>>>>>>dddddddddddddd123456789012345678901234567890dddddd"
                    + "dddddddddddddddddddddddddddddddddddddxdddddddddddddd123456"
                    + "789012345678901234567890dddddddddddddddddddddddddddddddddd"
                    + "ddddd123456789012345678901234567890ddddx>>>>>>>>>>>>>>>>>>"
                    + ">>>>>>>|"},};
            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();
                }
    
                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());
            //table.setPreferredScrollableViewportSize(table.getPreferredSize());
            JScrollPane sp = new JScrollPane(table);
            sp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
            sp.setPreferredSize(new Dimension(250, 533));
            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.setLocation(100, 100);
            f.pack();
            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);
            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;
        }
    }
    

    【讨论】:

    • 太棒了。但这似乎只适用于 JTextArea (我所要求的)。现在,如果我想将 TextArea 放在 Panel 中并将 Panel 用作单元格组件,该怎么办。我怎样才能实现,包含 Textarea 的面板仍然扩展单元格的高度?一般来说,有没有机会实现可扩展的单元格高度,不管单元格的内容是什么。
    • @haferblues 关于PreferredSize,不管是否有JPanel 的JTexArea,确保JPanel 会更好的JComponents 作为普通的JTextArea,例如stackoverflow.com/questions/6355544/…
    猜你喜欢
    • 2021-12-20
    • 2018-02-18
    • 2018-11-13
    • 1970-01-01
    • 1970-01-01
    • 2018-01-13
    • 2014-07-24
    • 2021-07-15
    • 1970-01-01
    相关资源
    最近更新 更多