Bou Bou - 2 months ago 7
Java Question

Java Swing Layout block

I'm trying to learn about layouts as I've read things about bad practice to use null layout with absolute positioning in GUI. If takes away the flexibility to expand the GUI dynamically. So I'm trying out some combinations of GUI blocks and now I've encounter a problem. Below is the GUI block I intend to try out:

enter image description here

I start off by doing the top part (block 1, 2 & 3) of the GUI and it works with the following code:

enter image description here

public class LayoutTestGuiDelegate implements Observer{
private LayoutTestModel model;
private int totalScreenWidth;
private int totalScreenHeight;
private JFrame mainFrame;
private JPanel totalScreen;
private JPanel topScreen;
private JPanel botScreen;
private JPanel dateScreen;
private ImagePanelOne imagePanelOne;
private ImagePanelTwo imagePanelTwo;
private ImagePanelThree imagePanelThree;
private ImagePanelFour imagePanelFour;
private ImagePanelFive imagePanelFive;

public LayoutTestGuiDelegate(LayoutTestModel model){
this.model = model;
totalScreenWidth = model.GetScreenWidth();
totalScreenHeight = model.GetScreenHeight();
SetupComponents();
}

public void SetupComponents(){
// set it to full exclusive mode
final GraphicsDevice fullScreen = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
mainFrame = new JFrame("Video Clock Display");
mainFrame.setLayout(new GridLayout(1, 1, 0, 0));
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setUndecorated(true); // Remove title bar
mainFrame.setAlwaysOnTop(false); // Always on top
mainFrame.setResizable(false);
mainFrame.setVisible(true);

totalScreen = new JPanel(new GridLayout(2, 1, 0, 0));
mainFrame.setContentPane(totalScreen);

topScreen = new JPanel(new GridLayout(1, 2, 0, 0));
imagePanelOne = new ImagePanelOne(model, 1020, 280);
topScreen.add(imagePanelOne);

dateScreen = new JPanel(new GridLayout(2, 1, 0, 0));
imagePanelTwo = new ImagePanelTwo(model, 900, 150);
dateScreen.add(imagePanelTwo);
imagePanelThree = new ImagePanelThree(model, 900, 130);
dateScreen.add(imagePanelThree);
topScreen.add(dateScreen);
totalScreen.add(topScreen);

mainFrame.pack();
}

@Override
public void update(Observable arg0, Object arg1) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
imagePanelOne.repaint();
imagePanelTwo.repaint();
imagePanelThree.repaint();
imagePanelFour.repaint();
imagePanelFive.repaint();
}
});

}

}


When I try to add in the bottom part (block 4 & 5), everything just go wierd. It shows up like this with the following code:

enter image description here

public class LayoutTestGuiDelegate implements Observer{
private LayoutTestModel model;
private int totalScreenWidth;
private int totalScreenHeight;
private JFrame mainFrame;
private JPanel totalScreen;
private JPanel topScreen;
private JPanel botScreen;
private JPanel dateScreen;
private ImagePanelOne imagePanelOne;
private ImagePanelTwo imagePanelTwo;
private ImagePanelThree imagePanelThree;
private ImagePanelFour imagePanelFour;
private ImagePanelFive imagePanelFive;

public LayoutTestGuiDelegate(LayoutTestModel model){
this.model = model;
totalScreenWidth = model.GetScreenWidth();
totalScreenHeight = model.GetScreenHeight();
SetupComponents();
}

public void SetupComponents(){
// set it to full exclusive mode
final GraphicsDevice fullScreen = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
mainFrame = new JFrame("Video Clock Display");
mainFrame.setLayout(new GridLayout(1, 1, 0, 0));
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setUndecorated(true); // Remove title bar
mainFrame.setAlwaysOnTop(false); // Always on top
mainFrame.setResizable(false);
mainFrame.setVisible(true);

totalScreen = new JPanel(new GridLayout(2, 1, 0, 0));
mainFrame.setContentPane(totalScreen);

topScreen = new JPanel(new GridLayout(1, 2, 0, 0));
imagePanelOne = new ImagePanelOne(model, 1020, 280);
topScreen.add(imagePanelOne);

dateScreen = new JPanel(new GridLayout(2, 1, 0, 0));
imagePanelTwo = new ImagePanelTwo(model, 900, 150);
dateScreen.add(imagePanelTwo);
imagePanelThree = new ImagePanelThree(model, 900, 130);
dateScreen.add(imagePanelThree);
topScreen.add(dateScreen);
totalScreen.add(topScreen);

botScreen = new JPanel(new GridLayout(1, 2, 0, 0));
imagePanelFour = new ImagePanelFour(model, 1420, 800);
botScreen.add(imagePanelFour);
imagePanelFive = new ImagePanelFive(model, 500, 800);
botScreen.add(imagePanelFive);

totalScreen.add(botScreen);
mainFrame.pack();
}

@Override
public void update(Observable arg0, Object arg1) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
imagePanelOne.repaint();
imagePanelTwo.repaint();
imagePanelThree.repaint();
imagePanelFour.repaint();
imagePanelFive.repaint();
}
});

}

}


Can Anyone tell me what I'm doing wrong? Thanks.

Answer

I think you should use a BorderLayout. Put the first three components in the NORTH constraint area. Put 4 in the center, and put 5 in the EAST.

The example below doesn't look exactly like your picture, because the various panels I used have different borders and layouts by default, and the buttons I used as examples are pretty small. But overall I think this is going to be the easiest to work with if you have to do this by hand.

I'd also like to see you use smaller panels divided into smaller classes, and compose your GUI from those smaller components. The rather large blob of code you have above is kind of unwieldy and hard to read.

public class LayoutTest
{
   public static void main( String[] args )
   {
      SwingUtilities.invokeLater( new Runnable(){
         public void run()
         {
            JFrame frame = new JFrame();

            TopPanel top = new TopPanel();
            frame.add( top, BorderLayout.NORTH );
            frame.add( new JButton( "4" ) );
            frame.add( new JButton( "5" ), BorderLayout.EAST );

            frame.pack();
            frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
            frame.setLocationRelativeTo( null );
            frame.setVisible( true );
         }
      } );
   }
}

class CenterButtonPanel extends JPanel {
   public CenterButtonPanel( String name ) {
      JButton but = new JButton( name );
      add( but );
   }
}

class TopPanel extends JPanel {
  TopPanel() {
     Box right = Box.createVerticalBox();
     right.add( new CenterButtonPanel( "2" ) );
     right.add( new CenterButtonPanel( "3" ) );
     Box left = Box.createHorizontalBox();
     left.add( new CenterButtonPanel( "1" ) );
     left.add( right );
     add( left );
  }
}