I'm trying to create a multiple choice quiz, and I need the content pane to scroll. If you run the program I've attached you'll see what I mean. Each question and the answers are place in a JPanel and the JPanels are place on the content pane. Thanks in advance for any help.

/*********************************************
        Multiple Choice Quiz
*********************************************/
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.border.EtchedBorder;

public class Quiz extends JFrame {
    /*********************
      Instance variables
    **********************/

        // Label and answer choices for question1 and JPanel to place components
    private JLabel header, question1;
    private JRadioButton answer1, answer2, answer3, answer4;
    private ButtonGroup question1Group;
    private JPanel question1JPanel;

        // question2
    private JLabel question2;
    private JRadioButton answer5, answer6, answer7, answer8;
    private ButtonGroup question2Group;
    private JPanel question2JPanel;

        // question3
    private JLabel question3;
    private JRadioButton answer9, answer10, answer11, answer12;
    private ButtonGroup question3Group;
    private JPanel question3JPanel;

        // question4
    private JLabel question4;
    private JRadioButton answer13, answer14, answer15, answer16;
    private ButtonGroup question4Group;
    private JPanel question4JPanel;

    /***********************
            Constructor
    ************************/
    public Quiz() {

        // get content pane for attaching GUI components
       Container contentPane = getContentPane();

        // enable explicit positioning of GUI components and set background color
       contentPane.setLayout( null );
        contentPane.setBackground(new Color(77, 0, 64));

        // Label for header
        header = new JLabel( "Linear Equations Quiz" );
        header.setBounds( 10, 5, 980, 24 );
        header.setOpaque( true );                      // for some components you must setOpaque
        header.setBackground( new Color(51, 0, 77) );  // to true before you can change the background color
        header.setForeground(Color.white);
        header.setBorder( BorderFactory.createRaisedBevelBorder() );
        contentPane.add( header );

        // Label for question1
        question1 = new JLabel("1) This is the question");
        question1.setBounds( 1, 5, 272, 24 );
        question1.setForeground(Color.white);
        question1.setBorder( BorderFactory.createEtchedBorder(EtchedBorder.RAISED) );

        // Create answer radioButtons for question1
        answer1 = new JRadioButton("answer #1");
        answer1.setBounds( 1, 30, 200, 24 );
        answer1.setForeground(Color.white);
        answer2 = new JRadioButton("answer #2");
        answer2.setBounds( 1, 55, 200, 24 );
        answer2.setForeground(Color.white);
        answer3 = new JRadioButton("answer #3");
        answer3.setBounds( 1, 80, 200, 24 );
        answer3.setForeground(Color.white);
        answer4 = new JRadioButton("answer #4");
        answer4.setBounds( 1, 105, 200, 24 );
        answer4.setForeground(Color.white);

        // Group answers for question1 together
        question1Group = new ButtonGroup();
        question1Group.add(answer1);
        question1Group.add(answer2);
        question1Group.add(answer3);
        question1Group.add(answer4);

        // set up JPanel (line 84: set place of object on contentPane(first parameter)
        // and line 88: enable explicit placement of GUI components)
      question1JPanel = new JPanel();
      question1JPanel.setBounds( 25, 35, 950, 150 );
        question1JPanel.setBackground( new Color(77, 0, 26) );
        question1JPanel.setForeground(Color.white);
      question1JPanel.setBorder( BorderFactory.createRaisedBevelBorder() );
      question1JPanel.setLayout( null );


        // add question label and add individual JRadioButtons to JPanel
        // (can't add ButtonGroup object to JPanel)
        question1JPanel.add( question1 );
        question1JPanel.add( answer1 );
        question1JPanel.add( answer2 );
        question1JPanel.add( answer3 );
        question1JPanel.add( answer4 );

        // add the question JPanel to the content pane
      contentPane.add( question1JPanel );

        /*************************************************
                    QUESTION2
        *************************************************/
        // Label for question2
        question2 = new JLabel("1) This is the  second question");
        question2.setBounds( 1, 5, 272, 24 );
        question2.setForeground(Color.white);
        question2.setBorder( BorderFactory.createEtchedBorder(EtchedBorder.RAISED) );

        // Create answer radioButtons for question2
        answer5 = new JRadioButton("answer #5");
        answer5.setBounds( 1, 30, 200, 24 );
        answer5.setForeground(Color.white);
        answer6 = new JRadioButton("answer #6");
        answer6.setBounds( 1, 55, 200, 24 );
        answer6.setForeground(Color.white);
        answer7 = new JRadioButton("answer #7");
        answer7.setBounds( 1, 80, 200, 24 );
        answer7.setForeground(Color.white);
        answer8 = new JRadioButton("answer #8");
        answer8.setBounds( 1, 105, 200, 24 );
        answer8.setForeground(Color.white);

        // Group answers for question2 together
        question2Group = new ButtonGroup();
        question2Group.add(answer5);
        question2Group.add(answer6);
        question2Group.add(answer7);
        question2Group.add(answer8);

        // set up JPanel (line 84: set place of object on contentPane(first parameter)
        // and line 88: enable explicit placement of GUI components)
      question2JPanel = new JPanel();
      question2JPanel.setBounds( 25, 195, 950, 150 );
        question2JPanel.setBackground( new Color(77, 0, 26) );
        question2JPanel.setForeground(Color.white);
      question2JPanel.setBorder( BorderFactory.createRaisedBevelBorder() );
      question2JPanel.setLayout( null );


        // add question label and add individual JRadioButtons to JPanel
        // (can't add ButtonGroup object to JPanel)
        question2JPanel.add( question2 );
        question2JPanel.add( answer5 );
        question2JPanel.add( answer6 );
        question2JPanel.add( answer7 );
        question2JPanel.add( answer8 );

        // add the question JPanel to the content pane
      contentPane.add( question2JPanel );

        /*************************************************
                    QUESTION3
        *************************************************/
        // Label for question3
        question3 = new JLabel("1) This is the  third question");
        question3.setBounds( 1, 5, 272, 24 );
        question3.setForeground(Color.white);
        question3.setBorder( BorderFactory.createEtchedBorder(EtchedBorder.RAISED) );

        // Create answer radioButtons for question3
        answer9 = new JRadioButton("answer #9");
        answer9.setBounds( 1, 30, 200, 24 );
        answer9.setForeground(Color.white);
        answer10 = new JRadioButton("answer #10");
        answer10.setBounds( 1, 55, 200, 24 );
        answer10.setForeground(Color.white);
        answer11 = new JRadioButton("answer #11");
        answer11.setBounds( 1, 80, 200, 24 );
        answer11.setForeground(Color.white);
        answer12 = new JRadioButton("answer #12");
        answer12.setBounds( 1, 105, 200, 24 );
        answer12.setForeground(Color.white);

        // Group answers for question2 together
        question3Group = new ButtonGroup();
        question3Group.add(answer9);
        question3Group.add(answer10);
        question3Group.add(answer11);
        question3Group.add(answer12);

        // set up JPanel 
      question3JPanel = new JPanel();
      question3JPanel.setBounds( 25, 355, 950, 150 );
        question3JPanel.setBackground( new Color(77, 0, 26) );
        question3JPanel.setForeground(Color.white);
      question3JPanel.setBorder( BorderFactory.createRaisedBevelBorder() );
      question3JPanel.setLayout( null );

        question3JPanel.add( question3 );
        question3JPanel.add( answer9 );
        question3JPanel.add( answer10 );
        question3JPanel.add( answer11 );
        question3JPanel.add( answer12 );

      contentPane.add( question3JPanel );
        /*************************************************
                    QUESTION4
        *************************************************/
        // Label for question4
        question4 = new JLabel("1) This is the fourth question");
        question4.setBounds( 1, 5, 272, 24 );
        question4.setForeground(Color.white);
        question4.setBorder( BorderFactory.createEtchedBorder(EtchedBorder.RAISED) );

        // Create answer radioButtons for question3
        answer13 = new JRadioButton("answer #13");
        answer13.setBounds( 1, 30, 200, 24 );
        answer13.setForeground(Color.white);
        answer14 = new JRadioButton("answer #14");
        answer14.setBounds( 1, 55, 200, 24 );
        answer14.setForeground(Color.white);
        answer15 = new JRadioButton("answer #15");
        answer15.setBounds( 1, 80, 200, 24 );
        answer15.setForeground(Color.white);
        answer16 = new JRadioButton("answer #16");
        answer16.setBounds( 1, 105, 200, 24 );
        answer16.setForeground(Color.white);

        // Group answers for question2 together
        question4Group = new ButtonGroup();
        question4Group.add(answer13);
        question4Group.add(answer14);
        question4Group.add(answer15);
        question4Group.add(answer16);

        // set up JPanel 
      question4JPanel = new JPanel();
      question4JPanel.setBounds( 25, 515, 950, 150 );
        question4JPanel.setBackground( new Color(77, 0, 26) );
        question4JPanel.setForeground(Color.white);
      question4JPanel.setBorder( BorderFactory.createRaisedBevelBorder() );
      question4JPanel.setLayout( null );

        question4JPanel.add( question4 );
        question4JPanel.add( answer13 );
        question4JPanel.add( answer14 );
        question4JPanel.add( answer15 );
        question4JPanel.add( answer16 );

      contentPane.add( question4JPanel );

        // set properties of application's window
       setTitle( "Quiz" );   // set title bar string
       setSize( 1000, 575 );  // set window size
       setVisible( true );   // display window
        setDefaultCloseOperation(EXIT_ON_CLOSE);// closes program when user exits

    }

    /************************
            Main Method
    *************************/
    public static void main( String[] args )
    {
        Quiz quiz = new Quiz();
    }

}
  1. there are two ways
  • by moving with derived JScrollBar from JScrollpane

  • by moving with JViewport to desired Rectangle

  1. both are based on Rectangle from JComponent.getBounds(), where JComponent.getBounds() is required JComponent to be visible in JViewport

  2. easiest of ways is moving with JViewport e.g. JScrollPane#scrollRectToVisible(JComponent.getBounds())

So, could I just add a JScrollPane to the contentPane, and then add my JPanels to the scrollPane?

  • correctly, but for code logics of this nature could be better to scrollRectToVisible on bottom,

  • because code posted here scrolling on top, can you live with that :-), otherise is required to (change centering to bottom) bothering with this logics

  • override getPreferrerdSize for JPanel this new Dimension(int, int)) must be larger than JScrollPane.setPreferredScrollableViewportSize(new Dimension(int, int));

So what would I add to the code above to provide the functionality to scroll. If you run the code above you'll see what I mean. I just need the container to be able to scroll. I have 4 JPanels in the container. Do you mean to overide the preferred size on all of them?

I tried adding all 4 JPanels for the questions to a main JPanel and then adding the main JPanel to a JScrollPane. Then, I tried to add the JScrollPane to the contentPane, but it's not working right.

            // new JPanel to add questionJPanel's to
            // then add mainJPanel to JScrollPane and add scrollPane to contentPane
        JPanel mainPanel = new JPanel();
        mainPanel.setBounds( 1, 1, 950, 665 );
        mainPanel.setLayout( new BoxLayout(mainPanel, BoxLayout.Y_AXIS) );
        mainPanel.add(question1JPanel);
        mainPanel.add(question2JPanel);
        mainPanel.add(question3JPanel);
        mainPanel.add(question4JPanel);
        JScrollPane scrollPane = new JScrollPane( mainPanel );
        scrollPane.setPreferredSize(new Dimension(950, 110));
        scrollPane.setBounds(10, 30, 950, 110);
        contentPane.add(scrollPane);

I'm getting nowhere with this. It seems like it would be simple to add a scroll bar to a container object. Isn't there a way to just add the scrolling funcionality to the code above, without placing each quiz question in one main JPanel?

very simple example

import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;

public class FollowFocus {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                final int ROWS = 100;
                final JPanel content = new JPanel();
                content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));
                content.add(new JLabel(
                        "Thanks for helping out. Use tab to move around."));
                for (int i = 0; i < ROWS; i++) {
                    JTextField field = new JTextField("" + i);
                    field.setName("field#" + i);
                    content.add(field);
                }
                final JScrollPane scroll = new JScrollPane(content);
                KeyboardFocusManager.getCurrentKeyboardFocusManager().
                        addPropertyChangeListener("focusOwner", new PropertyChangeListener() {
                    @Override
                    public void propertyChange(PropertyChangeEvent evt) {
                        if (!(evt.getNewValue() instanceof JComponent)) {
                            return;
                        }
                        JViewport viewport = (JViewport) content.getParent();
                        JComponent focused = (JComponent) evt.getNewValue();
                        if (content.isAncestorOf(focused)) {
                            System.out.println("Scrolling to " + focused.getName());
                            Rectangle rect = focused.getBounds();
                            Rectangle r2 = viewport.getVisibleRect();
                            content.scrollRectToVisible(new Rectangle(rect.x, rect.y, (int) r2.getWidth(), (int) r2.getHeight()));
                        }
                    }
                });

                JFrame window = new JFrame("Follow focus");
                window.setContentPane(new JScrollPane(content));
                window.setSize(200, 200);
                window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                window.setVisible(true);
            }
        });
    }
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.