4

After reading this answer, I came to using getPreferredSize instead of setPreferredSize. But I still can't use the @Override getPreferredSize, but that's not the main problem I'm facing right now.

I have a CardLayout application which calls a class called HiraganaData

HiraganaData is a class which extends a JPanel so it can be used by the CardLayout, but it also has 2 more JPanels on it, one for a "back" button and one for the rest of buttons, before using this idea I was using a JTable, but faced problems on making cells as buttons, so I dropped the idea and came with this new one using GridLayout. Some of the buttons will be disabled, anyway I can do that and won't include that code since it's not relevant.

So my actual question or problem is:

  • How can I add a JScrollPane only to buttonsPanel, did my best trying to add it even to the whole "global" pane w/o success.

This is the most aproximate GUI I can do with the same code of my class I just added a JFrame to it.

Not sure if relevant, but I'm using a CardLayout with different sizes, in the way @MadProgrammer suggested on this answer.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.*;
import javax.swing.table.TableCellRenderer;
import javax.swing.DefaultCellEditor;
import java.awt.Dimension;

public class HiraganaPage extends JPanel {
    JFrame frame = new JFrame("Hello");
    JButton kanas[][] = new JButton[26][5];
    JButton backButton = new JButton("back");
    JPanel backPanel = new JPanel();
    JPanel buttonsPanel = new JPanel();
    
    public static void main(String args[]) {
        new HiraganaPage();
    }
    
    public HiraganaPage() {
        JPanel pane = new JPanel();
        backPanel.add(backButton);
        buttonsPanel.setLayout(new GridLayout(0, 5));
        pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
        pane.add(backPanel);
        
        //pane.setPreferredSize(new Dimension(500, 500));
        
        for (int i = 0; i < 26; i++) {
            for (int j = 0; j < 5; j++) {
                kanas[i][j] = new JButton("1");
                buttonsPanel.add(kanas[i][j]);
            }
        }
        
        JScrollPane scroll = new JScrollPane(buttonsPanel);
        pane.add(buttonsPanel);
        this.add(pane, BorderLayout.CENTER);
        frame.add(this);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocation(50, 50);
        frame.setSize(300, 300);
    }
}

This is how it looks like in my complete application

enter image description here

And this is how it looks like in the MCVE.

enter image description here

Community
  • 1
  • 1
Frakcool
  • 10,915
  • 9
  • 50
  • 89
  • 2
    The short answer is, don't screw with the preferred size of the panel... – MadProgrammer Jul 28 '14 at 02:52
  • @MadProgrammer you mean `pane.setPreferredSize(new Dimension(500, 500));` that line? commented ok, looks better but scroll doesn't appear that way either. – Frakcool Jul 28 '14 at 02:54
  • Check answer, you're not actually adding anything to the scroll pane nor are you adding the scroll pane to anything...By convention, you should always avoid using `setPreferred/Minimum/MaximumSize` as it will cause more problems than it will solve, instead, override the appropriate method instead ... as required ... – MadProgrammer Jul 28 '14 at 02:59
  • MCVE, clear problem description, evidence of research, two pertinent screenshots. +1(thousand). Great question. – Andrew Thompson Jul 28 '14 at 03:18
  • 1
    Oh thanks @AndrewThompson, there are some people I see in here on SO like you, MadProgrammer, Kleopatra, thrashgod and a couple of more people that I would love to become as good as you, I always see answers from all of you and make me show more effort on each Q & A I write. – Frakcool Jul 28 '14 at 03:23
  • 1
    Glad to see that your efforts paid off in a swift answer from @MadProgrammer. :) – Andrew Thompson Jul 28 '14 at 03:26

1 Answers1

4

The main problem you've facing is the fact that you removing the buttonsPane from the scroll pane when you add it to the pane...

JScrollPane scroll = new JScrollPane(buttonsPanel);
pane.add(buttonsPanel);
this.add(pane, BorderLayout.CENTER);

And the fact that you never actually add the scroll pane to anything doesn't help either.

A component may only have a single parent, so when you add buttonsPane to pane, it is effectively removed from the scroll pane

Instead, set the layout manager of the HiraganaPage to BorderLayout, add the buttonsPanel to the scroll pane and add the scroll pane to the CENTER position of the HiraganaPage then add the pane to the NORTH position of the HiraganaPage

Buttons

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestScrollPane {

    public static void main(String[] args) {
        new TestScrollPane();
    }

    public TestScrollPane() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new HiraganaPage());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class HiraganaPage extends JPanel {

        JFrame frame = new JFrame("Hello");
        JButton kanas[][] = new JButton[26][5];
        JButton backButton = new JButton("back");
        JPanel backPanel = new JPanel();
        JPanel buttonsPanel = new JPanel();

        public HiraganaPage() {
            setLayout(new BorderLayout());

            JPanel pane = new JPanel();
            backPanel.add(backButton);
            buttonsPanel.setLayout(new GridLayout(0, 5));
            pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
            pane.add(backPanel);

//            pane.setPreferredSize(new Dimension(500, 500));

            for (int i = 0; i < 26; i++) {
                for (int j = 0; j < 5; j++) {
                    kanas[i][j] = new JButton("1");
                    buttonsPanel.add(kanas[i][j]);
                }
            }

            add(pane, BorderLayout.NORTH);
            add(new JScrollPane(buttonsPanel));
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(500, 500);
        }
    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • yeah I noticed that part of the scroll while I was editing post too... but the part on the parents is interesting... and now I see how you use the `@Override` part too I was doing it in a wrong way (inside the constructor instead of as a method). Let me analize it a bit. – Frakcool Jul 28 '14 at 03:02
  • Thanks, I knew it was something simple but even by doing the MCVE didn't noticed about the add of scroll. You solved more than one of my questions by this :) – Frakcool Jul 28 '14 at 03:16