Home > Software design >  Java Swing GridLayout Change Grid Sizes
Java Swing GridLayout Change Grid Sizes

Time:02-23

I'm trying to create a program that lists movies in a Netflix style to learn Front-End coding.

How I want it to look in the end:

Example Image How it should look

My guess is that every movie is a button component with an image a name label and a release year label.

I'm struggling to recreate this look. This is how it looks when I try it:

How it looks when I try it

The navigationbar in my image is at the page start of a border layout. Below the navigationbar the movie container is in the center of the border layout.

My idea was creating a GridLayout and then create a button for each movie and adding it to the GridLayout.

You can recreate this with this code:

public class Main {
private static JFrame frame;

public static void main(String[] args) throws HeadlessException {
    frame = new JFrame();
    frame.setLayout(new BorderLayout());
    frame.setBackground(new Color(32, 32, 32));
    
    JPanel navigationPanel = createNavigationBar();
    frame.add(navigationPanel, BorderLayout.PAGE_START);
    
    JPanel moviePanel = createMoviePanel();
    frame.add(moviePanel, BorderLayout.CENTER);
    
    frame.setPreferredSize(new Dimension(1920, 1080));
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setTitle("Example App");
    frame.pack();
    frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
    frame.setVisible(true);
}

public static JPanel createMoviePanel() {
    JPanel moviePanel = new JPanel();
    
    GridLayout layout = new GridLayout(0, 10);
    layout.setHgap(3);
    layout.setVgap(3);
    moviePanel.setLayout(layout);
    moviePanel.setBackground(new Color(32, 32, 32));
    
    ArrayList<String> exampleList = new ArrayList<>();
    
    // Add stuff to the example list
    for(int i = 0; i < 120; i  ) {
        exampleList.add(Integer.toString(i));
    }
    
    final File root = new File("");
    
    for(final String movie : exampleList) {
        JLabel picLabel = new JLabel();
        
        try {
            File imageFile = new File(root.getAbsolutePath()   "\\src\\images\\"   "imageName.jpg"); // Try to find the cover image
            
            if(imageFile.exists()) {
                BufferedImage movieCover = ImageIO.read(imageFile);
                picLabel = new JLabel(new ImageIcon(movieCover));
            } else {
                BufferedImage movieCover = ImageIO.read(new File(root.getAbsolutePath()   "\\src\\images\\temp.jpg")); // Get a temp image
                picLabel = new JLabel(new ImageIcon(movieCover));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        JLabel movieName = new JLabel("New Movie");
        movieName.setForeground(Color.WHITE);;
        
        JButton movieButton = new JButton();
        movieButton.setLayout(new GridLayout(0, 1));
        //movieButton.setContentAreaFilled(false);
        //movieButton.setBorderPainted(false);
        //movieButton.setFocusPainted(false);
        
        movieButton.add(picLabel);
        movieButton.add(movieName);
        
        moviePanel.add(movieButton);
    }
    
    return moviePanel;
}

public static JPanel createNavigationBar() {
    JPanel navBar = new JPanel();
    navBar.setLayout(new FlowLayout(FlowLayout.LEFT, 30, 20));
    navBar.setBackground(new Color(25, 25, 25));
    
    JButton homeButton = new JButton("Home");
    homeButton.setContentAreaFilled(false);
    homeButton.setBorderPainted(false);
    homeButton.setFocusPainted(false);
    
    JButton movieButton = new JButton("Movies");
    movieButton.setContentAreaFilled(false);
    movieButton.setBorderPainted(false);
    movieButton.setFocusPainted(false);
    
    // Add all the buttons to the navbar
    navBar.add(homeButton);
    navBar.add(movieButton);
    
    return navBar;
}
}

I noticed that the GridLayout always tries to fit everything onto the window.

CodePudding user response:

That code was a mess. All that's needed is a properly configured JButton in a GridLayout

E.G.

enter image description here

public static JPanel createMoviePanel() {
    JPanel movieLibraryPanel = new JPanel(new GridLayout(0, 10, 3, 3));
    movieLibraryPanel.setBackground(new Color(132, 132, 132));

    int m = 5;
    BufferedImage image = new BufferedImage(9 * m, 16 * m, BufferedImage.TYPE_INT_RGB);
    for (int ii = 1; ii < 21; ii  ) {
        JButton picButton = new JButton("Mov "   ii, new ImageIcon(image));
        picButton.setMargin(new Insets(0,0,0,0));
        picButton.setForeground(Color.WHITE);
        picButton.setContentAreaFilled(false);
        picButton.setHorizontalTextPosition(JButton.CENTER);
        picButton.setVerticalTextPosition(JButton.BOTTOM);
        movieLibraryPanel.add(picButton);
    }

    return movieLibraryPanel;
}

CodePudding user response:

Same idea's from Andrew Thompson answer but with some minor text alignment changes and hover effect

final class Testing 
{
 public static void main(String[] args)
 {
  JFrame frame=new JFrame("NEFLIX");
  
  frame.setContentPane(new GridDisplay()); 
  frame.pack();
  frame.setResizable(false);
  
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setVisible(true);
 }
 
 private static final class GridDisplay extends JPanel implements ActionListener
 {
  private GridDisplay()
  {
   super(new GridLayout(0,5,20,20));
   
   setBackground(new Color(0,0,0,255));
   
   BufferedImage image=new BufferedImage(150,200,BufferedImage.TYPE_INT_RGB); 
   Graphics2D g2d=(Graphics2D)image.getGraphics();  
   g2d.setColor(Color.BLUE);  
   g2d.fillRect(0,0,image.getWidth(),image.getHeight());
   
   HoverPainter painter=new HoverPainter();  
   for(int i=0;i<10;i  )
   {
    TVShowCard card=new TVShowCard(image,"Show " i,"199" i);   
    card.addMouseListener(painter);   
    add(card);
   }
  }

  //highlight only on hover
  private final class HoverPainter extends MouseAdapter
  {
   @Override
   public void mouseExited(MouseEvent e) {
    ((TVShowCard)e.getSource()).setBorderPainted(false);
   }

   @Override
   public void mouseEntered(MouseEvent e) {
    ((TVShowCard)e.getSource()).setBorderPainted(true);
   }  
  } 
  
  private final class TVShowCard extends JButton
  {
   private TVShowCard(BufferedImage preview,String name,String year)
   {
    super();
       
    setContentAreaFilled(false);
    setBackground(new Color(0,0,0,0));
    setFocusPainted(false);  
    setBorderPainted(false);

    //I didn't use image icon & text horizontal allignment because the text always horizontally centered aligned but from the expected output it was left  so created 2 labels for the job            

    setLayout(new GridBagLayout());
    addIcon(preview);  
    addLabel(name,year);
      
    addActionListener(GridDisplay.this);
   }
   
   private void addIcon(BufferedImage preview)
   {
    JLabel icon=new JLabel();   
    icon.setIcon(new ImageIcon(preview));  
    add(icon,new GridBagConstraints(0,0,1,1,1.0f,0.0f,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(0,0,0,0),0,0));
   }
   
   private void addLabel(String name,String year)
   {
    JLabel label=new JLabel("<html><body>" name "<br>" year "</body></html>");   
    label.setForeground(Color.white);  
    label.setBackground(new Color(0,0,0,0));
    add(label,new GridBagConstraints(0,1,1,1,1.0f,1.0f,GridBagConstraints.SOUTHWEST,GridBagConstraints.NONE,new Insets(5,0,0,0),0,0));
   }
  } 
  
  @Override
  public void actionPerformed(ActionEvent e)
  {
   TVShowCard card=(TVShowCard)e.getSource();
   
   //do stuff with it
  }
 } 
}

enter image description here

  • Related