2
votes

I'm trying to add this JTextArea with a JScrollPane (with vertical but not horizontal scrollbar) to my frame but the result is just a grey area with a scrollbar on the right... I'm probably doing something really dumb but i've done that same exact thing to a JPanel and it worked

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);
     }

 }

I don't mind changing my frame's Layout but i really want one that allows me to put stuff exactly where i want it. Thanks


EDIT

Okay it now shows on my frame but the TextArea is still not resizable. When i write something in it using a JTextfield and a JButton with a Listener that appends the JTextfield's text to the JTextArea and then sets the text in the JTextField to "" it only accepts up to a certain ammount of lines. After that it just looks the same.

4
Please can you post a picture of your output... - ITguy
Your code contain several errors too... length is spelled wrong in one of the lines. - ITguy
@ITguy Thanks, but that's because I translated it before uploading it here. - Miguel Antunes
It's not resizable because of this line: frame.setResizable(false); - Paco Abato
1) Never set a JTextArea's preferredSize, not unless you want to create a JTextArea that will not add additional lines when needed. Instead set the JTextArea's row and column properties. - Hovercraft Full Of Eels

4 Answers

2
votes

Try setting a layout like this:

frame.setLayout(new BorderLayout());

And adding the scrollpane to the center:

frame.add(scrollpane, BorderLayout.CENTER);

Also remove the line pointed by Jire in his answer.

2
votes

I know that you've already "accepted" an answer, but I feel that I'd be remiss if I didn't give an answer that gave important points, ones that in the long run would allow you to create a better and more robust (i.e., a more easily debuggable, modifiable, and enhanceable) application.

Again,

  1. Never set a JTextArea's preferredSize, as this will create a JTextArea whose size is inflexibly set that will not add additional lines when needed. Instead set the JTextArea's row and column properties.
  2. While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
  3. Better to use a JPanel, or more often multiple nested JPanels, each using its own layout manager that allow you to more simply create agile and powerful complex yet beautiful GUI's.
  4. When using layout managers, you'll want to pack() your JFrame after adding all components so that all layout managers will do their jobs and layout components appropriately.

I've an example program below I show,

  • a title JLabel with large centered text
  • a JTextArea, called chatViewArea, of specified row and column size held within a JScrollPane and that is for viewing the chat. It is non-focusable so that the user cannot directly interact with it.
  • Another JTextArea, called textEntryArea, for entering text. You could use a simple JTextField for this and give it an ActionListener so that it responds to the enter key, however if you want a multi-lined text component that acts similar, you'll need to change the key bindings for the JTextArea's enter key. I've done that here so that the enter key "submits" the text held within the textEntryArea JTextArea, and the control-enter key combination acts the same as the enter key used to -- creating a new line.
  • The main JPanel uses simply a BorderLayout to allow placement of the title at the top, the chat view JTextArea in the center and the text entry JTextArea at the bottom. Note that if you needed to see more components, such as a JList showing other chatters, this can be done by nesting JPanels and using more layouts if need be.

For example:

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();
            }
        });
    }
}
1
votes

You don't need to add chat because it is adapted by scrollPane.

Remove this line: frame.add(chat);

0
votes

Add

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

And see the magic happen... but do tweek the arguments here in order to get the right dimensions.

For resizable frame just do frame.setResizable(true); instead of frame.setResizable(false);