首页 > 解决方案 > 如何在 JList 中选择行,其中每个单元格包含包含 JTextArea 的 JPanel

问题描述

我的代码目前是这样编写的,因为我的目的是将文本包装在 JList 的每个单元格中。现在,这部分在 JList 呈现的面板中的 JTextArea 上是成功的,但我有一个不同的问题。我似乎无法像简单的 JList 实现那样让每一行都可选择。

我怎样才能让每一行都可以选择?或者您会建议使用不同的组件在 JList 中包装文本吗?

import java.awt.BorderLayout;
import java.awt.Component;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public class JListPractice3 {

public static void main(final String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            new JListPractice3();
        }
    });
}

public JListPractice3() {
    JFrame f = new JFrame("JList Practice");
    f.setResizable(true);
    f.setVisible(true);
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().setLayout(new BorderLayout());

    JPanel listPanel = this.buildJListPanel();

    f.add(listPanel);

    f.pack();
}

/**
 * Build JList panel
 * @return JPanel
 */
private JPanel buildJListPanel() {
    JPanel listPanel = new JPanel();
    listPanel.setLayout(new BorderLayout());

    JList jList = new JList(getData());
    jList.setVisibleRowCount(1);
    jList.setFixedCellHeight(50);
    jList.setFixedCellWidth(250);
    jList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    jList.setCellRenderer(new MyCellRenderer());

    JScrollPane scrollPane = new JScrollPane();
    scrollPane.getViewport().setView(jList);
    listPanel.add(scrollPane, BorderLayout.CENTER);
    return listPanel;
}

/**
 * Get Alias data
 * @return String[]
 */
private String[] getData() {
    //TODO: remove hard code
    String[] data = {"123456789012345678901234567890123456789012345678901234567890123456789"
            + "012345678901234567890123456789012345678901234567890123456789012",
            "two two two two two two two two two two two twotwo two two two two two two two two two two twotwo two two end",
            "two two two two two two two two two two two twotwo two two two two two two two end",
            "five", "six"};
    return data;
}

private class MyCellRenderer implements ListCellRenderer {
    private JPanel p;
    private JPanel linePanel;
    private JLabel lineLabel;
    private JTextArea textArea;

    public MyCellRenderer() {
        p = new JPanel();
        p.setLayout(new BorderLayout());

        linePanel = new JPanel(new BorderLayout());
        linePanel.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 3));
        lineLabel = new JLabel("Test");
        linePanel.add(lineLabel, BorderLayout.NORTH);
        p.add(linePanel, BorderLayout.WEST);

        textArea = new JTextArea();
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        p.add(textArea, BorderLayout.CENTER);
    }

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

        textArea.setText((String) value);
        int width = list.getWidth();
        // this is just to lure the ta's internal sizing mechanism into action
        if (width > 0) {
            textArea.setSize(width, Short.MAX_VALUE);
        }
        return p;
    }
  }
}

标签: javaswingjlist

解决方案


如果您决定使用 ListCellRender 接口,则必须实现所有效果,因此为了澄清,ListCellRender 是一个用于设置值和所有侦听器的组件(示例 JLabel)(在这种情况下,您已在组件内添加侦听器)

因此,在您的解决方案中,组件是可选的,但您的代码不会绘制它,这是我对 CellRender 的实现

private class MyCellRenderer extends JTextArea implements ListCellRenderer{
    private JPanel p;
    private JPanel linePanel;
    private JLabel lineLabel;

    public MyCellRenderer() {
        p = new JPanel();
        p.setLayout(new BorderLayout());

        linePanel = new JPanel(new BorderLayout());
        linePanel.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 3));
        lineLabel = new JLabel("Test");
        linePanel.add(lineLabel, BorderLayout.NORTH);
        p.add(linePanel, BorderLayout.WEST);

        this.setLineWrap(true);
        this.setWrapStyleWord(true);
        p.add(this, BorderLayout.CENTER);
    }

    public Component getListCellRendererComponent(final JList list,
            final Object value, final int index, final boolean isSelected,
            final boolean hasFocus) {
        if(isSelected){
            this.setBackground(Color.BLUE);
        }else{
            this.setBackground(Color.GRAY);
        }
        this.setText((String) value);
        int width = list.getWidth();
        // this is just to lure the ta's internal sizing mechanism into action
        if (width > 0) {
            this.setSize(width, Short.MAX_VALUE);
        }
        return this;
    }
  }

结果是

在此处输入图像描述

我怎样才能让每一行都可以选择?或者您会建议使用不同的组件在 JList 中包装文本吗?

为了回应我们的要求,我的回应取决于

如果您只需要视觉效果,我认为这是一个很好的解决方案,而DefaultListCellRenderer不是管理多条线路。


推荐阅读