有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java动态更改文本框JTextArea的大小

我是Java新手,我一直在尝试构建一个简单的即时消息程序。我希望文本框(在发送消息之前键入消息的位置)在用户输入大消息时动态更改大小(有最大高度限制),有点像WhatsApp或iMessage上发生的情况

我试图计算文本框中的文本行数(考虑到文本环绕的效果),然后根据文本环绕的行数增加/减少文本框的高度。我使用getScrollableUnitIncrement()方法确定了1行文本的高度

另外,正如我正在学习的,有没有比我上面概述的更好的动态更改文本框大小的方法

我使用嵌入在JScrollPane中的JTextArea,并在JTextArea上使用componentListener根据需要调整文本框的大小

请检查组件侦听器方法中的while循环,因为我认为程序的这部分工作不正常

下面是一段代码:

public class clienterrors extends JFrame {
    private JTextArea userText;
    private JTextPane chatWindow;
    private String userName="testName";
    private Document doc;

    // Automatic resizing of the text box
    private static Dimension textBoxSize = new Dimension(20, 20);
    public static int numRows = 1;
    private static final int rowHeight = 20;
    private final int maxHeight = 80;


    public static void main(String[] args) {
        clienterrors george = new clienterrors();
        george.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    }

    public clienterrors(){
        super("Client instant messaging platform");

        // Chat window initialisation
        chatWindow = new JTextPane();
        chatWindow.setEditable(false);
        doc = chatWindow.getDocument();
        add(new JScrollPane(chatWindow), BorderLayout.CENTER);


        // Text box initialisation
        userText = new JTextArea();
        userText.setLineWrap(true);
        userText.setWrapStyleWord(true);

        JScrollPane jsp = new JScrollPane(userText);
        jsp.setPreferredSize(textBoxSize);
        jsp.setMaximumSize(new Dimension(20, 40));


        // Gets the text box to resize as appropriate
        userText.addComponentListener(
                new ComponentAdapter() {
                    @Override
                    public void componentResized(ComponentEvent e) {

                        // Needs to cater for when removing & pasting large messages into the text box
                        while (countLines(userText) > numRows && textBoxSize.getHeight() < maxHeight) {
                            textBoxSize.setSize(20, (int) textBoxSize.getHeight() + rowHeight);
                            revalidate();
                            numRows++;  // numRows is used as an update to see which
                        }

                        while (countLines(userText) < numRows && textBoxSize.getHeight() > 20){
                            textBoxSize.setSize(20, (int)textBoxSize.getHeight() - rowHeight);
                            revalidate();
                            numRows--;
                        }
                    }
                }
        );

        // Allows u to send text from text box to chat window
        userText.addKeyListener(
                new KeyAdapter() {
                    @Override
                    public void keyTyped(KeyEvent e) {
                        if(e.getKeyChar() == '\n' && enterChecker(userText.getText())){
                            // returns the text (-1 on the substring to remove the \n escape character when pressing enter)
                            showMessage("\n" + userName + ": " + userText.getText().substring(0, userText.getText().length() - 1));
                            userText.setText("");
                        }
                    }
                }
        );
        add(jsp, BorderLayout.SOUTH);


        //JFrame properties
        setSize(300, 400);
        setVisible(true);
    }

    // shows message on the chat window
    private void showMessage(final String text){
        SwingUtilities.invokeLater(
                new Runnable() {
                    @Override
                    public void run() {
                        try{
                            doc.insertString(doc.getLength(), text, null);
                        }catch(BadLocationException badLocationException){
                            badLocationException.printStackTrace();
                        }
                        // place caret at the end (with no selection), so the newest message can be automatically seen by the user
                        chatWindow.setCaretPosition(chatWindow.getDocument().getLength());
                    }
                }
        );
    }

    // Prevents the user from sending empty messages that only contain whitespace or \n
    private static boolean enterChecker(String t){
        for(int i=0; i<t.length(); i++)
            if (t.charAt(i) != '\n' && t.charAt(i) != ' ')
                return true;
        return false;
    }

    // This counts the number of wrapped lines in the text box to compare to numRows - only used to resize the text box
    // (got this off the internet)
    private static int countLines(JTextArea textArea) {
        if(!enterChecker(textArea.getText())) return 0; // this prevents getting an error when you're sending an empty message
        AttributedString text = new AttributedString(textArea.getText());
        FontRenderContext frc = textArea.getFontMetrics(textArea.getFont())
                .getFontRenderContext();
        AttributedCharacterIterator charIt = text.getIterator();
        LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(charIt, frc);
        float formatWidth = (float) textArea.getSize().width;
        lineMeasurer.setPosition(charIt.getBeginIndex());

        int noLines = 0;
        while (lineMeasurer.getPosition() < charIt.getEndIndex()) {
            lineMeasurer.nextLayout(formatWidth);
            noLines++;
        }

        return noLines;
    }

}

共 (1) 个答案

  1. # 1 楼答案

    JTextArea自动更新其首选大小,以便可以显示所有文本。如果不将其包装在滚动窗格中,则BorderLayout将自动显示所需内容,而无需任何其他逻辑:

    public class ClientErrors extends JFrame {
        private JTextArea userText;
        private JTextPane chatWindow;
        private String userName = "testName";
    
        // Automatic resizing of the text box
        public static int numRows = 1;
        private static final int rowHeight = 20;
        private final int maxHeight = 80;
        private Document doc;
    
        public static void main(String[] args) {
            ClientErrors george = new ClientErrors();
            george.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }
    
        public ClientErrors() {
            super("Client instant messaging platform");
    
            // Chat window initialisation
            chatWindow = new JTextPane();
            chatWindow.setEditable(false);
            doc = chatWindow.getDocument();
            add(new JScrollPane(chatWindow), BorderLayout.CENTER);
    
            // Text box initialisation
            userText = new JTextArea();
            userText.setLineWrap(true);
            userText.setWrapStyleWord(true);
    
            // Allows u to send text from text box to chat window
            userText.addKeyListener(new KeyAdapter() {
                @Override
                public void keyTyped(KeyEvent e) {
                    if (e.getKeyChar() == '\n' && enterChecker(userText.getText())) {
                        // returns the text (-1 on the substring to remove the \n
                        // escape character when pressing enter)
                        showMessage("\n"
                                + userName
                                + ": "
                                + userText.getText().substring(0,
                                        userText.getText().length() - 1));
                        userText.setText("");
                    }
                }
            });
            add(userText, BorderLayout.SOUTH);
    
            // JFrame properties
            setSize(300, 400);
            setVisible(true);
        }
    
        // shows message on the chat window
        private void showMessage(final String text) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        doc.insertString(doc.getLength(), text, null);
                    } catch (BadLocationException badLocationException) {
                        badLocationException.printStackTrace();
                    }
                    // place caret at the end (with no selection), so the newest
                    // message can be automatically seen by the user
                    chatWindow.setCaretPosition(chatWindow.getDocument()
                            .getLength());
                }
            });
        }
    
        // Prevents the user from sending empty messages that only contain
        // whitespace or \n
        private static boolean enterChecker(String t) {
            for (int i = 0; i < t.length(); i++)
                if (t.charAt(i) != '\n' && t.charAt(i) != ' ')
                    return true;
            return false;
        }
    }
    

    编辑:如果您还需要输入JTextArea的最大高度,该区域在达到最大高度后滚动,我建议将其包装在滚动窗格中,并在文本区域更改时更新其首选大小