Thursday, December 21, 2017

Java JScrollpane not visible

Leave a Comment

I'm trying to display a series of buttons in a JScrollpane. Reading around, I managed to exit with this code, but nothing is displayed. I do not understand a possible mistake. Thank you for help

As suggested I made some changes, I edited but not works

EDITED or I'm stupid, or here is some other problem. Here is my complete code with the output image

public class Main extends javax.swing.JFrame {     private final JPanel gridPanel;      public Main() {         initComponents();         // EXISTING PANEL         gridPanel = new JPanel();         JScrollPane scrollPane = new JScrollPane(gridPanel);         scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);         JPanel borderLayoutPanel = new JPanel(new BorderLayout());         borderLayoutPanel.add(scrollPane, BorderLayout.CENTER);          this.Avvio();     }      private void Avvio() {         JPanel pane = new JPanel(new GridBagLayout());         pane.setBorder(BorderFactory.createLineBorder(Color.BLUE));         pane.setLayout(new GridBagLayout());          for (int i = 0; i < 10; i++) {             JButton button;             GridBagConstraints c = new GridBagConstraints();             c.fill = GridBagConstraints.HORIZONTAL;             c.anchor = GridBagConstraints.PAGE_START;              button = new JButton("Button 1");             c.weightx = 0.5;             c.gridx = 0;             c.gridy = i;             pane.add(button, c);              button = new JButton("Button 2");             c.gridx = 1;             c.gridy = i;             pane.add(button, c);              button = new JButton("Button 3");             c.gridx = 2;             c.gridy = i;             pane.add(button, c);          }         gridPanel.add(pane);         gridPanel.revalidate();         gridPanel.repaint();      } } 

enter image description here

4 Answers

Answers 1

Problems noted:

  • Avvio - the pane layout was reset during each loop. Set it once before the loop.
  • Avvio - the pane was added to the grid pane in each loop. Add it once after the loop.
  • Avvio - the constraints place the buttons in the same grid locations. With the previous two issues fixed, only the last three buttons placed appear.

I'm assuming you want three buttons in a row, so I changed the loop to use the counter as a row counter. The code below will create ten rows of three buttons.

What appears: enter image description here

import java.awt.BorderLayout; import java.awt.Color; import java.awt.GridBagConstraints; import java.awt.GridBagLayout;  import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.WindowConstants;   public class Main extends javax.swing.JFrame {     private JPanel gridPanel;      public Main() {          this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);         this.setSize(600,400);          //EXISTING PANEL         gridPanel = new JPanel();         JScrollPane scrollPane = new JScrollPane(gridPanel);         scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);         JPanel borderLayoutPanel = new JPanel(new BorderLayout());         borderLayoutPanel.add(scrollPane, BorderLayout.CENTER);          this.Avvio();         this.add(borderLayoutPanel, BorderLayout.CENTER);         this.setVisible(true);     }      private void Avvio() {         JPanel pane = new JPanel(new GridBagLayout());         pane.setBorder(BorderFactory.createLineBorder(Color.BLUE));         pane.setLayout(new GridBagLayout());             for (int i = 0; i < 10; i++) {                JButton button;                GridBagConstraints c = new GridBagConstraints();                c.fill = GridBagConstraints.HORIZONTAL;                c.anchor = GridBagConstraints.PAGE_START;                 button = new JButton("Button 1");                c.weightx = 0.5;                c.gridx = 0;                c.gridy = i;                pane.add(button, c);                 button = new JButton("Button 2");                c.gridx = 1;                c.gridy = i;                pane.add(button, c);                 button = new JButton("Button 3");                c.gridx = 2;                c.gridy = i;                pane.add(button, c);             }            gridPanel.add(pane);            gridPanel.revalidate();            gridPanel.repaint();      }      public static void main(String args[]) {        new Main();     }       } 

Answers 2

Alright, from your comments in another answer:

No problem for compile , simply the Jpanel is empty. The buttons does not appear.

After calling this.Avvio(); you must call:

this.add(scrollPane); this.pack(); 

This will produce the following outputs (before and after resizing it):

enter image description hereenter image description here

But there's still no JScrollPanel

This at least solves the first problem, however you have more errors in your code, some of which have already been commented in other answers:

  1. You're extending JFrame, this isn't needed as you can create a JFrame instance / object and use it later. You're never changing the JFrame's behavior and that's why it's not needed to extend it. See Extends JFrame vs. creating it inside the program for more information about this.

  2. You're not calling pack() nor setSize(...) this creates a tiny window, which you need to manually resize. Call pack() recommended before making your JFrame visible. (As suggested at the beginning of this answer).

  3. You're calling .invokeLater() method twice. You need to call it just once, I prefer this way:

    SwingUtilities.invokeLater(() -> new Main()); //Note there is no call to .setVisible(true); as per point #1. It should go later in the program like:  frame.setVisible(true); 
  4. You're calling gridPanel.revalidate(); and gridPanel.repaint() while it doesn't affect your program, it's not needed as your GUI is still not visible, and thus those calls have no effect on your program, you can safely remove them.

  5. You're creating a new GridBagConstraints object on each iteration of the for loop, you can just change its properties inside it and declaring it outside the for loop, which will make your program better.

After following the above recommendations, you can end up with a code like this one:

import java.awt.BorderLayout; import java.awt.Color; import java.awt.GridBagConstraints; import java.awt.GridBagLayout;  import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.SwingUtilities;  public class Main {     private final JPanel gridPanel;     private JFrame frame;      public Main() {         // EXISTING PANEL         gridPanel = new JPanel();         JScrollPane scrollPane = new JScrollPane(gridPanel);         scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);         JPanel borderLayoutPanel = new JPanel(new BorderLayout());         borderLayoutPanel.add(scrollPane, BorderLayout.CENTER);          this.Avvio();          frame.add(scrollPane);         frame.pack();         frame.setVisible(true);     }      private void Avvio() {         JPanel pane = new JPanel(new GridBagLayout());         pane.setBorder(BorderFactory.createLineBorder(Color.BLUE));         pane.setLayout(new GridBagLayout());          for (int i = 0; i < 10; i++) {             JButton button;             GridBagConstraints c = new GridBagConstraints();             c.fill = GridBagConstraints.HORIZONTAL;             c.anchor = GridBagConstraints.PAGE_START;              button = new JButton("Button 1");             c.weightx = 0.5;             c.gridx = 0;             c.gridy = i;             pane.add(button, c);              button = new JButton("Button 2");             c.gridx = 1;             c.gridy = i;             pane.add(button, c);              button = new JButton("Button 3");             c.gridx = 2;             c.gridy = i;             pane.add(button, c);          }         gridPanel.add(pane);     }      public static void main(String args[]) {         /* Create and display the form */         SwingUtilities.invokeLater(() -> {             new Main();         });     } } 

Which still produces this output:

enter image description here

BUT... We still can improve it a little more!

We may have two nested for loops, for the GridBagConstraints properties as well as the generation of the buttons:

import java.awt.BorderLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.GridLayout;  import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.SwingUtilities;  public class ScrollablePaneWithButtons {     private static final int ROWS = 10;     private static final int COLS = 3;      private JFrame frame;     private JPanel pane;     private JButton[][] buttons;     private GridBagConstraints gbc;     private JScrollPane scroll;     private JButton[] menuButtons;     private JPanel menuPane;      public static void main(String[] args) {         SwingUtilities.invokeLater(new ScrollablePaneWithButtons()::createAndShowGui);     }      private void createAndShowGui() {         frame = new JFrame(this.getClass().getSimpleName());          pane = new JPanel();         pane.setLayout(new GridBagLayout());          menuPane = new JPanel();         menuPane.setLayout(new GridLayout(1, 3));          buttons = new JButton[ROWS][COLS];          menuButtons = new JButton[] {new JButton("Edit"), new JButton("Delete"), new JButton("Sort Fields")};          gbc = new GridBagConstraints();          gbc.fill = GridBagConstraints.HORIZONTAL;         gbc.anchor = GridBagConstraints.PAGE_START;         gbc.weightx = 0.5;          for (int i = 0; i < ROWS; i++) {             for (int j = 0; j < COLS; j++) {                 buttons[i][j] = new JButton("Button " + (j + 1));                  gbc.gridx = j;                 gbc.gridy = i;                  pane.add(buttons[i][j], gbc);             }         }          scroll = new JScrollPane(pane, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);          for (JButton b : menuButtons) {             menuPane.add(b);         }         frame.add(scroll);         frame.add(menuPane, BorderLayout.SOUTH);          frame.pack();         frame.setVisible(true);         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);     } } 

And this example is (in my opinion) easier to read and follow up. And this is the output the above code is generating:

enter image description here

You can still choose which code to use, either doing the modifications at the first part of this answer, the second one following the recommendations above or the last one which is shorter.

Answers 3

There are several things to do to make it work:

  1. Add a main method
  2. This main method is the entry point. This makes sure the swing-code runs in the AWT-thread. This is what the SwingUtilities.invokeLater is for
  3. Instantiate, pack and display the frame. The size setting is only for experimenting with the scrollpane
  4. Declare the gridPanel as an instance variable
  5. wrap the gridPanel with the scrollPane
  6. Optionally, wrap the scrollPane with the borderLayoutPanel
  7. Invoke the Avvio method because this is the one that adds the buttons
  8. Add the outmost element to the frame

Here is the fixed code:

public class MyFrame extends javax.swing.JFrame {      public static void main(String[] args) {         SwingUtilities.invokeLater(() -> {             MyFrame frame = new MyFrame();             frame.pack();             frame.setSize(600, 300);             frame.setVisible(true);         });     }      private JPanel gridPanel;      public MyFrame() {         this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);          gridPanel = new JPanel(new GridLayout(0, 1));         JScrollPane scrollPane = new JScrollPane(gridPanel);         scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);         JPanel borderLayoutPanel = new JPanel(new BorderLayout());         borderLayoutPanel.add(scrollPane, BorderLayout.CENTER);         this.Avvio();         this.add(borderLayoutPanel, BorderLayout.CENTER);     }       private void Avvio() {...} } 

Answers 4

I have simplified the program and removed all the mistakes and bad practices. (Missing package, unnecessary panels, calling invokeLater() twice and others.)

Here is a working example:

package com.zetcode;  import java.awt.BorderLayout; import java.awt.EventQueue; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane;  public class JavaScrollPaneEx extends JFrame {      public JavaScrollPaneEx() {          initUI();     }      private void initUI() {          JPanel panel = new JPanel(new BorderLayout());          JPanel buttonPanel = createButtonPanel();         JScrollPane scrollPane = new JScrollPane(buttonPanel);          panel.add(scrollPane, BorderLayout.CENTER);         add(panel);          setTitle("Buttons in JScrollBar");         setSize(350, 250);         setLocationRelativeTo(null);         setDefaultCloseOperation(EXIT_ON_CLOSE);      }      private JPanel createButtonPanel() {          JPanel panel = new JPanel(new GridBagLayout());          GridBagConstraints c = new GridBagConstraints();         c.fill = GridBagConstraints.HORIZONTAL;         c.anchor = GridBagConstraints.PAGE_START;         c.insets = new Insets(5, 5, 5, 5);          for (int i = 0, j = 0; i < 5; i++) {              JButton btn = new JButton("Button " + (j + 1));             c.weightx = 0.5;             c.gridx = i;             c.gridy = 0;             panel.add(btn, c);              btn = new JButton("Button " + (j + 2));             c.gridx = i;             c.gridy = 1;             panel.add(btn, c);              btn = new JButton("Button " + (j + 3));             c.gridx = i;             c.gridy = 2;             panel.add(btn, c);              j += 3;         }          return panel;     }      public static void main(String args[]) {          EventQueue.invokeLater(() -> {             JavaScrollPaneEx ex = new JavaScrollPaneEx();             ex.setVisible(true);         });     } } 

And this is the screenshot.

enter image description here

And since I consider GridBagLayout to be a very bad layout manager, I have created a similar example with MigLayout manager.

We need the following Maven dependency for this example:

<dependency>     <groupId>com.miglayout</groupId>     <artifactId>miglayout-swing</artifactId>     <version>5.0</version> </dependency> 

The source:

package com.zetcode;  import java.awt.BorderLayout; import java.awt.EventQueue; import javax.swing.JButton; import javax.swing.JFrame; import static javax.swing.JFrame.EXIT_ON_CLOSE; import javax.swing.JPanel; import javax.swing.JScrollPane; import net.miginfocom.swing.MigLayout;  public class JavaScrollPaneEx2 extends JFrame {      public JavaScrollPaneEx2() {          initUI();     }      private void initUI() {          JPanel panel = new JPanel(new BorderLayout());          JPanel buttonPanel = createButtonPanel();         JScrollPane scrollPane = new JScrollPane(buttonPanel);          panel.add(scrollPane, BorderLayout.CENTER);         add(panel);          setTitle("Buttons in JScrollBar");         setSize(350, 250);         setLocationRelativeTo(null);         setDefaultCloseOperation(EXIT_ON_CLOSE);      }      private JPanel createButtonPanel() {          JPanel panel = new JPanel(new MigLayout());          for (int i = 0, j = 0; i < 5; i++) {              JButton btn1 = new JButton("Button " + (j + 1));             JButton btn2 = new JButton("Button " + (j + 2));             JButton btn3 = new JButton("Button " + (j + 3));             JButton btn4 = new JButton("Button " + (j + 4));             JButton btn5 = new JButton("Button " + (j + 5));              panel.add(btn1, "sgx");             panel.add(btn2, "sgx");             panel.add(btn3, "sgx");             panel.add(btn4, "sgx");             panel.add(btn5, "sgx, wrap");              j += 5;         }          return panel;     }      public static void main(String args[]) {          EventQueue.invokeLater(() -> {             JavaScrollPaneEx2 ex = new JavaScrollPaneEx2();             ex.setVisible(true);         });     } } 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment