Search code examples
javaswingspringlayout

JButton on JPanel with SpringLayout not visible


I've got a JPanel, containing an other JPanel, on which I wnat to place a JButton, using the SpringLayout. But for some reason the JButton is not drawn. However, the JButton gets drawn, if I use absolute positioning, instead of a layout manager. If I print out the bounds of the JButton after setting the constrains for the SpringLayout I get the position (0, 0) with a width and height of 0. By setting the size of the JButton manually (calling setSize()) I get the JButton to be drawn in the right size, but not in the right location.

This is a stripped down version of my code so far:

import java.awt.Dimension;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SpringLayout;


public class Panel extends JPanel {

    private JPanel innerPanel;

    public Panel(){
        innerPanel = new InnerPanel();
        this.setLayout(null);

        innerPanel.setBounds(30, 30, 100, 200);
        this.add(innerPanel);

        this.setOpaque(false);
    }


    public class InnerPanel extends JPanel {

        private SpringLayout layout;
        private JButton someButton;

        public InnerPanel() {
            layout = new SpringLayout();
            this.setLayout(layout);

            someButton = new JButton("X");
            someButton.setPreferredSize(new Dimension(45, 25));
            layout.putConstraint(SpringLayout.NORTH, someButton, +5, SpringLayout.NORTH, innerPanel);
            layout.putConstraint(SpringLayout.EAST, someButton, -5, SpringLayout.EAST, innerPanel);
            this.add(someButton);

            this.setOpaque(false);
        }

    }

    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.add(new Panel());

        f.setSize(800, 600);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        f.setVisible(true);
    }

}

A SpringLayout just to place one JButton on a JPanel might seem a bit overcomplicated, but I plan to add more components to the JPanel, for which I need the SpringLayout.

I'm using Eclipse (no Window Builder) and I'm running OpenSuse, if that is of any importance.


Solution

  • The innerPanel variable is obviously null in the constructor of InnerPanel.

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class Panel2 extends JPanel {
      private JPanel innerPanel;
    
      public Panel2() {
        super(new BorderLayout());
        innerPanel = new InnerPanel();
        //this.setLayout(null);
        //innerPanel.setBounds(30, 30, 100, 200);
        this.add(innerPanel);
        this.setOpaque(false);
      }
      private /* TEST static */ class InnerPanel extends JPanel {
        private SpringLayout layout;
        private JButton someButton;
    
        public InnerPanel() {
          super();
          layout = new SpringLayout();
          this.setLayout(layout);
    
          someButton = new JButton("X");
          //someButton.setPreferredSize(new Dimension(45, 25));
          System.out.println(innerPanel); //TEST
          //layout.putConstraint(SpringLayout.NORTH, someButton, +5, SpringLayout.NORTH, innerPanel);
          //layout.putConstraint(SpringLayout.EAST, someButton, -5, SpringLayout.EAST, innerPanel);
          layout.putConstraint(SpringLayout.NORTH, someButton, +5, SpringLayout.NORTH, this);
          layout.putConstraint(SpringLayout.EAST, someButton, -5, SpringLayout.EAST, this);
    
          this.add(someButton);
          this.setOpaque(false);
        }
      }
      public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
          @Override public void run() {
            createAndShowGUI();
          }
        });
      }
      public static void createAndShowGUI() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.add(new Panel2());
        f.setSize(800, 600);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
      }
    }