2

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.

Cedric
  • 55
  • 1
  • 6
  • `for which I need the SpringLayout.` - you are never forced to use a single LayoutManager. Usually for more complicated layouts you create multiple panels which each panel using an appropriate LayoutManager and then combine all the panels into a layout. I have never used a SpringLayout because I find to too confusing. – camickr Mar 09 '15 at 20:51
  • I am already using multiple panels with different LayoutManagers. And for this one I think the SpringLayout fits best. Besides that, the SpringLayout is the one I am most familiar with. – Cedric Mar 10 '15 at 07:35

1 Answers1

1

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);
  }
}
aterai
  • 9,658
  • 4
  • 35
  • 44
  • It was definitively one of the mistakes I've made. And it fixes my example code. But even with this fix the JButton in my actual code doesn't get drawn. It seems like there are even more mistakes in my code. But anyway, this narrows the case quite a bit. – Cedric Mar 10 '15 at 11:59
  • I found the other problem. The Problem was, that I've added the JPanel to the surrounding container after calling setVisible(). The Solution is calling revalidate() after adding the JPanel. – Cedric Mar 10 '15 at 13:58