Search code examples
javaswinglayoutdemo

JFrame: How to make a simple layout with linebreak-like behavior?


I have tried to make a JFrame containing 3 elements using Swing in Java 1.6: One a the start of the page, a second at the same line with some spacing to the left, a third on a new line. But failed after several aproaches:

BorderLayout.[SOUTH|WEST|EAST|NORTH]
BorderLayout.[LINE_START|LINE_END|AFTER_LINE_END|AFTER_LAST_LINE]
FlowLayout.LEFT
BoxLayout.[X_AXIS|Y_AXIS]

The only way it displayed about right was when using:

container.add(firstElement, BorderLayout.WEST);
container.add(secondElement, BorderLayout.EAST);
container.add(thirdElement, BorderLayout.SOUTH); 

Here is the current version of my program:

import javax.swing.*;
import java.awt.*;
//import java.awt.event.*;
//import java.lang.reflect.*;

public class MainClass {
    public static void main(String[] args) {

        JFrame frame = new JFrame("JFrame Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Container container = frame.getContentPane();

        JTextField field = new JTextField();
        JButton button = new JButton("Enter");
        JTextArea outputarea = new JTextArea("Outputtext before input.");
        outputarea.setEditable(false);

        container.add(field, BoxLayout.X_AXIS);
        container.add(button, BoxLayout.X_AXIS);
        container.add(outputarea, BoxLayout.Y_AXIS);

        field.setPreferredSize(new Dimension(600, 30));
        button.setPreferredSize(new Dimension(100, 30));
        //button.setMargin(new Insets(0, 10, 0, 0)); //left-margin
        outputarea.setPreferredSize(new Dimension(700, 300));

        container.setPreferredSize(new Dimension(800, 400));

        frame.pack();
        frame.setVisible(true);
    }
}

While I want to achive something like this:
https://dl.dropboxusercontent.com/u/72032667/JFrame_Demo.html
Source:

<!doctype html>
<html lang="en">
<head>
<title>JFrame Demo</title>
<style type="text/css">
  body {width:800px; min-height:400px;}
  * {float:left; margin:0; color:inherit;}
  #input {width:600px;}
  #button {margin-left:10px; background:#AAA; padding:2px 5px; border:1px solid black;}
  #textarea {width:700px; height:300px; resize:none; white-space:nowrap;}
</style>
<script type="text/javascript">
  function myAction() {
    var inputElement = document.getElementById('input');
    var outputElement = document.getElementById('textarea'); 
    outputElement.innerHTML = myMethod(inputElement.value);

    function myMethod(str) {
      // Do something more useful than this:
      return "You wrote: "+str;
    }
  }
</script>
</head>
<body>
  <input id="input" />
  <a href="#" onclick="myAction()"><p id="button">Enter</p></a>
  <br>
  <textarea id="textarea" readonly spellcheck="false" warp="off"></textarea>
</body>
</html>

I have seen some examples when they give the constructor for JFrame a Component as argument to choose a layout, but have not understood how that works.
EDIT: I won't accept a nested solution to these 3 elements.


Solution

  • Ok, I know this is not the answer you wanted, sorry. But I just want to show you what I meant with my comment and how to do it. This is not a direct answer, but maybe you will change your mind after seeing it :P (especially about setPreferredSize(), because this not really recommended to do). This will work properly on nearly any frame size:

    Code:

    import javax.swing.*;
    import javax.swing.border.Border;
    import javax.swing.border.CompoundBorder;
    import javax.swing.border.EmptyBorder;
    import javax.swing.border.LineBorder;
    
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    public class MainClass {
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new MainClass();
                }
            });
        }
    
        public MainClass() {
    
            JFrame frame = new JFrame("JFrame Demo");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            JTextArea outputarea = new JTextArea();
            outputarea.setBorder(new LineBorder(Color.GRAY));
            outputarea.setWrapStyleWord(true);
            outputarea.setLineWrap(true);
            outputarea.setEditable(false);
    
            JTextField field = new JTextField();
            field.setBorder(new CompoundBorder(new EmptyBorder(0, 0, 3, 0), field.getBorder()));
    
            JButton button = new JButton("Enter");
            button.setBackground(Color.LIGHT_GRAY);
            button.setFocusPainted(false);
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    outputarea.setText("You wrote: " + field.getText());
                }
            });
    
            // This panel is just needed in order to set a border for the button
            // without losing it's margin.
            BorderPanel buttonPanel = new BorderPanel();
            buttonPanel.setBorder(new CompoundBorder(new EmptyBorder(0, 10, 0, 30), new LineBorder(Color.BLACK)));
            buttonPanel.add(button);
    
            BorderPanel northPanel = new BorderPanel();
            northPanel.add(field);
            northPanel.add(buttonPanel, BorderLayout.EAST);
    
            BorderPanel mainPanel = new BorderPanel();
            mainPanel.add(outputarea);
            mainPanel.add(northPanel, BorderLayout.NORTH);
    
            frame.setContentPane(mainPanel);
            frame.setSize(600, 300);
            frame.setVisible(true);
    
        }
    
        public class BorderPanel extends JPanel {
    
            public BorderPanel() {
                setLayout(new BorderLayout());
                setBackground(Color.WHITE);
            }
    
        }
    
    }
    

    End result:

    enter image description here