JTextArea с JScrollPAne внутри кадра с нулевой разметкой


Я пытаюсь добавить эту область JTextArea с JScrollPane (с вертикальной, но не горизонтальной полосой прокрутки) в мой фрейм, но результат-просто серая область с полосой прокрутки справа... Я, вероятно, делаю что-то действительно глупое, но я сделал то же самое с JPanel, и это сработало

public class Chats {

     public static int height = 600;
     public static int length = 400;

     public static void init(String me, String you){

         JFrame frame = new JFrame ("Chat");
         frame.setSize(larguraframe, alturaframe);
         frame.setLocation(620, 100);
         frame.setResizable(false);
         frame.setLayout(null);
         frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);

         JTextArea chat = new JTextArea();
         chat.setColumns(10);
         chat.setLineWrap(true);
         chat.setWrapStyleWord(true);
         JScrollPane scrollpane = new JScrollPane(chat, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER;  
         scrollpane.setBounds(length/8 - 27, height/9 + 27, 350, 380);
         chat.setPreferredSize(new Dimension(lenght-15, 7*height/8-27));

         frame.add(chat);
         frame.add(scrollpane);
         frame.setVisible(true);
     }

 }

Я не возражаю против изменения макета моего фрейма, но я действительно хочу, чтобы он позволял мне помещать вещи именно там, где я хочу. Спасибо


Править

Хорошо, теперь это видно на моем кадре, но текстовая область по-прежнему не может быть изменена. Когда я пишу что-то в нем, используя JTextfield и JButton со слушателем, который добавляет текст JTextfield в JTextArea, а затем устанавливает текст в JTextField в"", он принимает только до определенного количества строк. После этого все выглядит точно так же.

4 2

4 ответа:

Я знаю, что вы уже "приняли" ответ, но я чувствую, что был бы упущен, если бы я не дал ответ, который дал бы важные моменты, которые в конечном счете позволили бы вам создать лучшее и более надежное (т. е. более легко отлаживаемое, модифицируемое и улучшаемое) приложение.

Опять же,

  1. никогда не устанавливайте предпочитаемый размер JTextArea, так как это создаст JTextArea, размер которого жестко задан, что не добавит дополнительные строки, когда это необходимо. Вместо этого установите Свойства строки и столбца JTextArea.
  2. в то время как нулевые макеты и setBounds() могут показаться новичкам Swing самым простым и лучшим способом создания сложных графических интерфейсов, чем больше вы создаете Swing GUI, тем более серьезные трудности вы столкнетесь при их использовании. Они не изменят размер ваших компонентов при изменении размера графического интерфейса, они являются королевской ведьмой для улучшения или поддержания, они полностью отказывают при размещении в scrollpanes, они выглядят gawd-ужасно при просмотре на всех платформах или разрешениях экрана, которые являются отличается от оригинала.
  3. лучше использовать JPanel, или чаще несколько вложенных JPanels, каждый из которых использует свой собственный менеджер макетов, что позволяет более просто создавать гибкие и мощные сложные, но красивые графические интерфейсы.
  4. при использовании менеджеров макетов вы захотите pack() Ваш JFrame после добавления всех компонентов, чтобы все менеджеры макетов выполняли свою работу и компоненты макета соответствующим образом.

У меня есть пример программы ниже, я показываю,

  • заголовок JLabel с большим центрированным текстом
  • JTextArea, называемая chatViewArea, заданного размера строки и столбца, удерживаемого в JScrollPane и предназначенного для просмотра чата. Он не фокусируется, так что пользователь не может непосредственно взаимодействовать с ним.
  • Еще одна JTextArea, называемая textEntryArea, для ввода текста. Вы можете использовать простое поле JTextField для этого и дать ему ActionListener, чтобы он реагировал на клавишу enter, однако если вы хотите многострочный текстовый компонент, который действует аналогично, вам нужно будет измените привязки клавиш для ключа ввода JTextArea. Я сделал это здесь, чтобы клавиша enter "отправляла" текст, хранящийся в textEntryArea JTextArea, а комбинация клавиш control-enter действовала так же, как клавиша enter, используемая для создания новой строки.
  • Основная JPanel использует просто BorderLayout для размещения заголовка вверху, представления чата JTextArea в центре и ввода текста JTextArea внизу. Обратите внимание, что если вам нужно увидеть больше компонентов, таких как JList показывает другие чаты, это можно сделать, вложив JPanels и используя больше макетов, если это необходимо.

Например:

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

@SuppressWarnings("serial")
public class Chat2 extends JPanel {
    private static final int ROWS = 25; // rows in the chat view JTextArea
    private static final int COLS = 40; // columns in the chat view JTextArea
                                        // and text entry area
    private static final int ENTRY_ROWS = 4; // rows in the text entry JTextArea
    private static final int BL_HGAP = 10; // horizontal gap for our
                                           // BorderLayout
    private static final int BL_VGAP = 5; // vertical gap for our BorderLayout
    private static final int EB_GAP = 15; // gap for empty border that goes
                                          // around entire app
    private static final String TITLE_TEXT = "My Chat Application";
    private static final float TITLE_POINTS = 32f; // size of the title jlabel
                                                   // text
    private JTextArea chatViewArea = new JTextArea(ROWS, COLS);
    private JTextArea textEntryArea = new JTextArea(ENTRY_ROWS, COLS);

    public Chat2() {
        // label to display the title in bold large text
        JLabel titleLabel = new JLabel(TITLE_TEXT, SwingConstants.CENTER);
        titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, TITLE_POINTS));

        // set up the chat view JTextArea to have word wrap
        // and to not be focusable
        chatViewArea.setWrapStyleWord(true);
        chatViewArea.setLineWrap(true);
        chatViewArea.setFocusable(false);

        // add it to a JScrollPane, and give the scrollpane vertical scrollbars
        JScrollPane viewScrollPane = new JScrollPane(chatViewArea);
        viewScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        // set up the text entry JTextArea
        textEntryArea.setWrapStyleWord(true);
        textEntryArea.setLineWrap(true);

        // key bindings so that control-enter will act as enter and the enter key will "submit"
        // the user input to the chat window and the chat server
        // will allow us to use a multilined text entry area if desired instead
        // of a single lined JTextField
        setEnterKeyBinding(textEntryArea);

        JScrollPane entryScrollPane = new JScrollPane(textEntryArea);
        entryScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        // add an empty border around entire application
        setBorder(BorderFactory.createEmptyBorder(EB_GAP, EB_GAP, EB_GAP, EB_GAP));
        // make the main layout a BorderLayout
        setLayout(new BorderLayout(BL_HGAP, BL_VGAP));
        // add our components to the GUI
        add(titleLabel, BorderLayout.PAGE_START);
        add(viewScrollPane, BorderLayout.CENTER);
        add(entryScrollPane, BorderLayout.PAGE_END);
    }

    // Again, use key bindings so that control-enter JTextArea will act as enter key
    // and the enter key will "submit" the user input to the chat window and the chat server.
    // When ctrl-enter is pushed the Action originally bound to the enter key will be called
    // and when enter is pushed a new Action, the EnterKeyAction, will be called
    private void setEnterKeyBinding(JTextArea textArea) {
        int condition = JComponent.WHEN_FOCUSED; // only for focused entry key
        InputMap inputMap = textArea.getInputMap(condition);
        ActionMap actionMap = textArea.getActionMap();

        KeyStroke entryKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
        KeyStroke ctrlEntryKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, KeyEvent.CTRL_DOWN_MASK);

        // first give ctrl-enter the action held by enter
        Object entryKey = inputMap.get(entryKeyStroke);
        Action entryAction = actionMap.get(entryKey);
        inputMap.put(ctrlEntryKeyStroke, ctrlEntryKeyStroke.toString());
        actionMap.put(ctrlEntryKeyStroke.toString(), entryAction);

        // now give enter key a new Action
        EnterKeyAction enterKeyAction = new EnterKeyAction();
        inputMap.put(entryKeyStroke, entryKeyStroke.toString());
        actionMap.put(entryKeyStroke.toString(), enterKeyAction);
    }

    public void appendToChatArea(final String text) {
        if (SwingUtilities.isEventDispatchThread()) {
            chatViewArea.append(text + "\n");
        } else {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    chatViewArea.append(text + "\n");
                }
            });
        }
    }

    private class EnterKeyAction extends AbstractAction {
        @Override
        public void actionPerformed(ActionEvent e) {
            String text = textEntryArea.getText();
            textEntryArea.setText("");

            chatViewArea.append("User: " + text + "\n");

            // TODO send text to the chat server!

        }
    }

    private static void createAndShowGui() {
        Chat2 mainPanel = new Chat2();

        JFrame frame = new JFrame("My Chat Window");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);

        // pack the JFrame so that it will size itself to its components
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

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

Попробуйте настроить макет следующим образом:

frame.setLayout(new BorderLayout());

И добавление полосы прокрутки к центру:

frame.add(scrollpane, BorderLayout.CENTER);

Также удалите линию, на которую указал Джайр в своем ответе.

Вам не нужно добавлять chat, потому что он адаптирован scrollPane.

Уберите эту строку: frame.add(chat);

Добавить

chat.setBounds(length/8 - 27, height/9 + 27, 330, 360);

И увидеть, как происходит волшебство... но вы должны подправить аргументы здесь, чтобы получить правильные размеры.

Для изменяемого кадра просто сделайте frame.setResizable(true); вместо frame.setResizable(false);