java - 如何选择 JList 中每个单元格包含包含 JTextArea 的 JPanel 的行

标签 java swing jlist

我的代码目前是这样编写的,因为我的目的是将文本包装在 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;
    }
  }
}

最佳答案

如果您决定使用 ListCellRender 接口(interface),您必须实现所有效果,因此为了澄清起见,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;
    }
  }

结果是

enter image description here

How could I get make each row to be selectable? or Would you suggest to use a different component to wrap texts inside JList?

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

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

关于java - 如何选择 JList 中每个单元格包含包含 JTextArea 的 JPanel 的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58270489/

相关文章:

java - 如何在mongodb中获取两个用户之间的共同点

java - mongoDB 将数据添加到没有 _id 字段的集合

java - 如何在我的 Java 程序中使用 CardLayout 来实现登录和菜单项

java - 检查现有文本时自定义控制台 nullPointerException

没有滚动条的java jcombobox?

java - 通过 Regex 表达式的 Hibernate 查询过滤器

java - 具有初始化变量的 NPE

Java ArrayList的正确使用

java - 尝试将 txt 文件中的项目添加到 jList

java - Scala 等价于 Java 的静态 block 是什么?