Java Swing GridLayout 更改网格大小

发布于 2025-01-09 09:53:35 字数 3756 浏览 1 评论 0原文

我正在尝试创建一个程序,以 Netflix 风格列出电影,以学习前端编码。

我希望它最终的样子:

示例图像它应该是什么样子

我的猜测是每部电影都是一个按钮组件,带有图像、名称标签和发行年份标签。

我正在努力重现这种外观。这是我尝试时的样子:

我尝试时的外观

我的图像中的导航栏位于边框布局的页面开头。在导航栏下方,影片容器位于边框布局的中心。

我的想法是创建一个 GridLayout,然后为每部电影创建一个按钮并将其添加到 GridLayout。

您可以使用以下代码重新创建它:

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;
}
}

我注意到 GridLayout 总是尝试将所有内容都放入窗口中。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

纵情客 2025-01-16 09:53:35

所需要的只是在GridLayout 中正确配置JButton

EG

enter图片描述在这里

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;
}

这里是上述内容的完整来源,并进行了调整,将年份放在新的一行。它使用 JButton 中的 HTML 将按钮文本分成两行。

输入焦点位于第一个按钮上,而鼠标悬停在“2009”电影上:

在此处输入图像描述

import java.awt.*;
import java.awt.image.*;
import javax.swing.*;

class MovieGrid {

    MovieGrid() {
        JFrame f = new JFrame("Movie Grid");
        f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        f.setLocationByPlatform(true);
        f.add(createMoviePanel());
        f.pack();
        f.setVisible(true);
    }

    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 = 2001; ii < 2021; ii++) {
            JButton picButton = new JButton(
                    "<html>Movie<br>" + 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;
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                new MovieGrid();
            }
        };
        SwingUtilities.invokeLater(r);
    }
}

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;
}

Here is a complete source for the above with a tweak to put the year on a new line. It uses HTML in the JButton to break the button text into two lines.

The input focus is on the first button, whereas the mouse hovers over the '2009' movie:

enter image description here

import java.awt.*;
import java.awt.image.*;
import javax.swing.*;

class MovieGrid {

    MovieGrid() {
        JFrame f = new JFrame("Movie Grid");
        f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        f.setLocationByPlatform(true);
        f.add(createMoviePanel());
        f.pack();
        f.setVisible(true);
    }

    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 = 2001; ii < 2021; ii++) {
            JButton picButton = new JButton(
                    "<html>Movie<br>" + 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;
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                new MovieGrid();
            }
        };
        SwingUtilities.invokeLater(r);
    }
}
雪花飘飘的天空 2025-01-16 09:53:35

Andrew Thompson 的回答也有同样的想法,但有一些小的文本对齐更改和悬停效果

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 alignment 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
  }
 } 
}

在此处输入图像描述

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 alignment 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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文