简体   繁体   中英

Scrollbar not appearing on custom Panel

I have made a class RefreshablePanel that extends JPanel

public class RefreshablePanel extends JPanel {

static String description="";
static int x=10;
static int y=11;

protected void paintComponent(Graphics g){
       super.paintComponent(g);
    for (String line : description.split("\n"))
        g.drawString(line, x, y += g.getFontMetrics().getHeight());
}
void updateDescription(String dataToAppend){
        description = description.concat("\n").concat(dataToAppend);
        System.out.println("The description is "+description);
   }   
}

and then I am adding it into my GUI_class like this

JScrollPane scrollPane_2 = new JScrollPane();
scrollPane_2.setBounds(32, 603, 889, 90);
frmToolToMigrate.getContentPane().add(scrollPane_2);

descriptionPanel = new RefreshablePanel();
scrollPane_2.setViewportView(descriptionPanel);
descriptionPanel.setBackground(Color.WHITE);
descriptionPanel.setLayout(null);

I have added the scrollbar in the class where I am making an instance of RefreshablePanel but scrollbar is not appearing. I have tried adding

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

to refreshable Panel but then the string is disappearing like this 在此处输入图片说明

and nothing is appearing when I scroll down

  1. You're using null layouts, so nothing is going to work the way it should. Swing is designed at the core to utilise layout managers.

  2. You're RefreshablePanel has no discernible size, meaning that when you add to the scroll pane, the scroll pane is likely to simply think it's size should 0x0 . RefreshablePanel needs to provide some kind of size hint back to the scrollpane, preferably via the getPreferredSize method

  3. You could use a JLabel (with text wrapped in html) or a non-editable JTextArea to achieve the same results

Updated

Take a quick check of your code. You are declaring the x and y values as static and you are incrementing the y value in your paintComponent method

static int x=10;
static int y=11;

protected void paintComponent(Graphics g){
   super.paintComponent(g);
    for (String line : description.split("\n"))
        g.drawString(line, x, y += g.getFontMetrics().getHeight());
}

This means two things.

  1. If you have more than one instance of your RefreshablePanel they will ALL share the same x / y values AND update them
  2. y is constantly being update to a new position, so if the panel is painted twice, on the second paint, the y position will start from the position it was last at when the first call exited.

Remember, you don't control the paint process. A paint cycle may be executed at any time that the system decides it needs to...

Make the x / y values local variables to the paintComponent method...

Updated

The scroll pane will try and match the preferred size of the component if the available space allows for it. This may mean that the scroll bars may not appear until you resize the window...but you're using a null layout so that won't work for you...

To affect the size of the scroll pane, you can use the Scrollable interface instead...

在此处输入图片说明

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Scrollable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Scrollable01 {

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

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

                RefreshablePanel pane = new RefreshablePanel();
                pane.updateDescription("1. You're using null layouts, so nothing is going to work the way it should. Swing is designed at the core to utilise layout managers.");
                pane.updateDescription("2. You're RefreshablePanel has no discernible size, meaning that when you add to the scroll pane, the scroll pane is likely to simply think it's size should 0x0. RefreshablePanel needs to provide some kind of size hint back to the scrollpane, preferably via the getPreferredSize method");
                pane.updateDescription("3. You could use a JLabel (with text wrapped in html) or a non-editable JTextArea to achieve the same results");

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

    public class RefreshablePanel extends JPanel implements Scrollable {

        public String description = "";

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

        @Override
        protected void paintComponent(Graphics g) {
            int x = 10;
            int y = 11;
            super.paintComponent(g);
            for (String line : description.split("\n")) {
                g.drawString(line, x, y += g.getFontMetrics().getHeight());
            }
        }

        void updateDescription(String dataToAppend) {
            description = description.concat("\n").concat(dataToAppend);
            System.out.println("The description is " + description);
            repaint();
        }

        @Override
        public Dimension getPreferredScrollableViewportSize() {
            return new Dimension(400, 400);
        }

        @Override
        public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
            return 64;
        }

        @Override
        public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
            return 64;
        }

        @Override
        public boolean getScrollableTracksViewportWidth() {
            return false;
        }

        @Override
        public boolean getScrollableTracksViewportHeight() {
            return false;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM