【问题标题】:Make ArrayList<JTextArea> to JScrollPane使 ArrayList<JTextArea> 为 JScrollPane
【发布时间】:2020-12-19 17:31:38
【问题描述】:

我有一个包含“n”个不同聊天的数组列表,下面用宽度包裹是 TextArea 块的代码

JTextArea chat2 = new JTextArea();
 chat2.setText("this is chat 2"); 
 chat2.setWrapStyleWord(true);
 chat2.setLineWrap(true);
 chat.setColumns(20); 
 chat2.setEditable(false);
 chat2.setBorder(borderLine);   
 chat2.setVisible(true);

还有一个看起来像的数组列表

ArrayList<JTextArea> c = new ArrayList<JTextArea>();
c.add(chat2)

已经试过了

Vector itemsVector = new Vector(c);
JList chats = new JList(itemsVector);
 //CHAT PANEL SCROLLABLE
 JScrollPane scrollChats = new JScrollPane(chats);
 scrollChats.setBounds(0,60,1100,600);
 main.add(scrollChats); 

它没有得到这个输出:

【问题讨论】:

  • JList 是要走的路,但您似乎将模型与显示混淆了。该模型应该包含聊天字符串或字符串列表,并且显示(或列表渲染器)将是 JTextAreas 可能所在的位置
  • 所以我将字符串列表发送到 Jlist 而不是 JTextArea 列表。我可以这样做,但是我以后如何添加包装或其他 UI 属性?@HovercraftFullOfEels
  • 您声明您正在显示多个聊天集合,这表明您的 JList 模型将包含 List&lt;List&lt;String&gt;&gt; 或类似的东西。然后,您必须使用在渲染的 JTextArea 中显示每个 List&lt;String&gt; 的列表渲染器。这只是考虑这样做的一种方式。
  • 那可能很简单——创建一个DefaultListModel&lt;String&gt;,用聊天文本填充它,然后将其添加到您的列表中。完成。
  • 如果你想根据谁发布聊天来更改显示,这会变得更加困难,但这可以通过正确使用渲染器来完成。

标签: java list swing user-interface scroll


【解决方案1】:

所以,想象一个 Chat 类,它包含一个 String ,该 String 表示 chatter(或者更好的是,一个明确定义的 User 类型对象)以及该用户正在发送的文本:

public class Chat {
    String name;
    String text;

    public Chat(String name, String text) {
        super();
        this.name = name;
        this.text = text;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

}

然后你可以创建一个列表模型和一个 JList 来保存这种类型的对象:

private DefaultListModel<Chat> chatListModel = new DefaultListModel<Chat>();
private JList<Chat> chatList = new JList<Chat>(chatListModel);

然后您可以创建一个渲染器,将 Chatter 的文本显示为默认渲染器文本,并在单个渲染器周围的标题边框中显示 Chatter 的名称(默认渲染器是 JLabel):

private class ChatRenderer extends DefaultListCellRenderer {
    @Override
    public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected,
            boolean cellHasFocus) {
        Chat chat = (Chat) value;
        String text = chat.getText();
        String name = chat.getName();
        JLabel rendererComponent = (JLabel) super.getListCellRendererComponent(list, text, index, isSelected, cellHasFocus);
        rendererComponent.setBorder(BorderFactory.createTitledBorder(name));
        return rendererComponent;
    }
}

整个事情可能看起来像:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.*;

@SuppressWarnings("serial")
public class FooGui01 extends JPanel {
    private DefaultListModel<Chat> chatListModel = new DefaultListModel<Chat>();
    private JList<Chat> chatList = new JList<Chat>(chatListModel);
    private JTextField inputField = new JTextField(20);
    private JButton submitButton = new JButton("Submit");
    
    public FooGui01() {
        chatList.setCellRenderer(new ChatRenderer());
        chatList.setPrototypeCellValue(new Chat("John", "abc def ghi jkl abc def ghi jkl abc def ghi jkl abc def ghi jkl abc def ghi jkl abc def ghi jkl "));
        chatList.setVisibleRowCount(10);
        JScrollPane scrollPane = new JScrollPane(chatList);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        
        ActionListener listener = new SubmitListener();
        inputField.addActionListener(listener);
        submitButton.addActionListener(listener);
        submitButton.setMnemonic(KeyEvent.VK_S);
        
        JPanel submitPanel = new JPanel();
        submitPanel.setLayout(new BoxLayout(submitPanel, BoxLayout.LINE_AXIS));
        submitPanel.add(inputField);
        submitPanel.add(submitButton);
        
        setLayout(new BorderLayout());
        add(scrollPane);
        add(submitPanel, BorderLayout.PAGE_END);
    }
    
    // public method called by outside code that is wanting to pass chat to you
    public void submitChat(Chat chat) {
        if (SwingUtilities.isEventDispatchThread()) {
            chatListModel.addElement(chat);
        } else {
            SwingUtilities.invokeLater(() -> chatListModel.addElement(chat));
        }
    }

    private class SubmitListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            String text = inputField.getText();
            chatListModel.addElement(new Chat("Me", text));
            inputField.selectAll();
            inputField.requestFocusInWindow();
            
            // here you would send the chat text or object to a socket's output stream
        }
    }
    
    private class ChatRenderer extends DefaultListCellRenderer {
        @Override
        public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected,
                boolean cellHasFocus) {
            Chat chat = (Chat) value;
            String text = chat.getText();
            String name = chat.getName();
            JLabel rendererComponent = (JLabel) super.getListCellRendererComponent(list, text, index, isSelected, cellHasFocus);
            rendererComponent.setBorder(BorderFactory.createTitledBorder(name));
            return rendererComponent;
        }
    }
    
    public static void main(String[] args) {        
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("Foo");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
            FooGui01 gui = new FooGui01();
            frame.add(gui);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }
}

【讨论】:

  • 这非常有用,谢谢。所以我只是为了测试目的而传递字符串,制作了很多与urs相同的代码我对ChatRenderer有疑问。我实现了ListCellRenderer并返回了一个jtextarea,但它没有包装它创建的足够高度来包装的文本,但是文字是一长串...有什么建议吗?我尝试将其添加到面板并返回面板但没有工作:(。它只是包装文本我遇到了 rn 问题
  • @JaisonThomas:在您的问题中显示您的minimal reproducible example 代码(就像我发布的一样)。您是否在渲染器中的 JTextArea 上调用了 setLineWrap(true)setWrapStyleWord(true)
  • 是的,我设置了setLineWrap(true);setWrapStyleWord(true);,并给定尺寸为setSize(100,getPreferredSize().height);,它为它不换行的高度留出了适当的空间
  • 我今天太麻烦你了,我试图构建一个更多与whatsapp相关的ui,但我编译了你的代码,它看起来比我能构建的任何东西都要好,我将使用你提供的ui和坚持这一点。再次,非常感谢
  • @JaisonThomas:从this question的答案中可以尝试一些有趣的事情
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-05
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多