-1

I am trying to work with grid layout, and im trying to put few panels there that has some data, but nothing gets rendered at all.

Here is the current code that I have:

package main.cache.test;

import java.awt.EventQueue;
import java.awt.GridLayout;
import java.io.File;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class ImageView {

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    ImageView window = new ImageView();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public ImageView() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        JFrame frmSpitePicker = new JFrame("Title");

        frmSpitePicker.setSize(658, 395);
        frmSpitePicker.setResizable(false);
        frmSpitePicker.setLocationRelativeTo(null);
        frmSpitePicker.getContentPane().setLayout(null);
        frmSpitePicker.setVisible(true);

        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setBounds(12, 35, 620, 303);
        frmSpitePicker.getContentPane().add(scrollPane);

        JPanel panel = new JPanel();
        scrollPane.setViewportView(panel);

        File file = new File("images/");
        panel.setLayout(new GridLayout((file.listFiles().length / 6), 6));

        int i = 0;

        // getting files name from folder
        for (String name : file.list()) {

            JPanel panel_1 = new JPanel();
            panel_1.setBounds(209, 362, 82, 87);
            frmSpitePicker.getContentPane().add(panel_1);
            panel_1.setLayout(null);

            // create label
            JLabel lblNewLabel = new JLabel((i++) + "");
            lblNewLabel.setBounds(12, 13, 56, 16);
            lblNewLabel.setIcon(new ImageIcon(new ImageIcon("images/" + name).getImage().getScaledInstance(8, 8, 1)));
            lblNewLabel.setHorizontalTextPosition(JLabel.CENTER);
            lblNewLabel.setVerticalTextPosition(JLabel.BOTTOM);
            panel_1.add(lblNewLabel);

            // create button
            JButton btnNewButton = new JButton("btn");
            btnNewButton.setBounds(12, 42, 58, 25);
            panel_1.add(btnNewButton);

            // add to the panel
            panel.add(panel_1);

        }
    }
}

I don't know what is wrong with this, and why Jpanel when being added, it doesn't get rendered but when adding a JLabel would work.

Thanks in advance!

albertos
  • 47
  • 5
  • 3
    `setLayout(null);` would be you first mistake, `JPanel panel = new JPanel();` would be your next oversight – MadProgrammer Oct 21 '19 at 21:34
  • `JScrollPane` relies on the viewports `preferredSize` information in order to make determinations about how and when it should display its scroll bars, to start with. `JPanel` by default, uses a `FlowLayout`. `panel_1` is no longer providing sizing hints (through `getPreferredSize`, which is `0x0` by default) and the whole thing is just one large code crash – MadProgrammer Oct 21 '19 at 21:37
  • The only answer to your question is to start making use of appropriate layout managers, any answer which tries to salvage your code while still using `null` layouts is a hack and will explode in your face unexpectedly. Start by having a look at [Laying Out Components Within a Container](https://docs.oracle.com/javase/tutorial/uiswing/layout/index.html) – MadProgrammer Oct 21 '19 at 21:39
  • @MadProgrammer worked after using preferred size, but I still have the null layout. I don't know why you don't recommend it since I can simply position my elements freely, and neither the frame, nor the panels are re-sizable, so I don't think it will affect. – albertos Oct 21 '19 at 22:04
  • 1
    Increase the font size, run in on a Mac, change the DPI, change the text dynamically at run time - these are all issues you are going to run into. Layouts on a GUI are more complicated then you think and require an enormous amount of effort to get right - which is why we recommending using the API(s) which have been developed to do this work for you. I recommend (using the layout managers) as it will reduce the number of questions you post about "why did my UI fall apart on me" and have people repeatedly tell you the same thing - sorry if that smacks – MadProgrammer Oct 21 '19 at 23:39
  • Also, as generally side effect, we also recommend against setting the preferred size of components. The calculations need to make this work are really complicated and involved – MadProgrammer Oct 21 '19 at 23:41
  • You should avoid been worried about "pixel" perfect layouts and focus more on the "user flow" through your UIs, you will loose less hair this way ;). As some one who has done VB coding, I can assure you, the layout managers are a blessing – MadProgrammer Oct 21 '19 at 23:43

1 Answers1

0

Using layouts correctly, we can easily get something like this:

enter image description here

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

public class ImageView {

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            try {
                ImageView window = new ImageView();
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    public ImageView() {
        initialize();
    }

    private void initialize() {
        int num = 32; // number of images to show..
        JFrame frmSpitePicker = new JFrame("Title");
        frmSpitePicker.setResizable(false);
        JPanel panel = new JPanel(new GridLayout(0, 6));
        JScrollPane scrollPane = new JScrollPane(panel, 
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        frmSpitePicker.getContentPane().add(scrollPane);

        for (int ii = 1; ii <= num; ii++) {

            JPanel panel_1 = new JPanel(new BorderLayout());

            // create label
            JLabel lblNewLabel = new JLabel(ii + "");
            lblNewLabel.setIcon(new ImageIcon(getImage()));
            lblNewLabel.setHorizontalTextPosition(JLabel.CENTER);
            lblNewLabel.setVerticalTextPosition(JLabel.BOTTOM);
            panel_1.add(lblNewLabel, BorderLayout.CENTER);

            // create button
            JButton btnNewButton = new JButton("btn");
            panel_1.add(btnNewButton, BorderLayout.PAGE_END);

            // add to the panel
            panel.add(panel_1);
            // hack to ensure our scroll bar is active 
            // we require 3 rows to be visible..
            if (ii==18) frmSpitePicker.pack();

        }
        frmSpitePicker.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        // Normally we'd call pack() here!
        //frmSpitePicker.pack();
        frmSpitePicker.setLocationRelativeTo(null);
        frmSpitePicker.setVisible(true);
    }

    java.util.Random r = new java.util.Random();

    private BufferedImage getImage() {
        int s = 16;
        BufferedImage bi = new BufferedImage(
                s, s, BufferedImage.TYPE_INT_RGB);
        Graphics g = bi.getGraphics();
        g.setColor(new Color(
                r.nextInt(255), r.nextInt(255), r.nextInt(255)));
        g.fillRect(0, 0, s, s);
        g.dispose();
        return bi;
    }
}

Note that I would tend to use a JList for this type of case. The panel_1 would become a renderer for a POJO what encapsulates the label and button. But the button might not be needed, in that a list can have listeners for selection and activation. If that's what the button does, it'd be redundant in a list, and lblNewLabel could replace the entire panel_1.

BTW - please make sure all resources needed, are available to run the code. When it comes to images, we might hot link (load by URL) to images available on the net1 or generate them in the code (as done here).

  1. One way to get image(s) for an example is to hot link to images seen in this Q&A. E.G. This answer hot links to an image embedded in this question.
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433