Why is my JPanel inside JScrollPane not scrolling?

I have a JPanel (yellow) located in a JScrollPane .

pic1

When you type some text in JTextPane it changes, but the vertical scrollbar is still not active. yelowPanel.getSize() returns the same value as before. `(You can see it on redPanel).

pic2

So how can I update yellowPanel ? I want to scroll the panel vertically. I tried:

 panelCreating.revalidate(); panelCreating.invalidate(); panelCreating.repaint(); 

Only panelCreating.setPreferredSize(new Dimension(333, 777)); works panelCreating.setPreferredSize(new Dimension(333, 777)); but I don’t know what size to set. It depends on the content.

There is a small example:

 package swingtest; import java.awt.Color; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextPane; public class SwingTest extends JFrame { public SwingTest() { initComponents(); } public static void main(String[] args) { java.awt.EventQueue.invokeLater(new Runnable() { @Override public void run() { new SwingTest().setVisible(true); } }); } private JPanel panelCenter, panelCreating; private JScrollPane scrollPaneCreating, scrollPaneCenter; private JTextPane textPane1, textPane2; private JButton button1; private void initComponents() { setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setMinimumSize(new Dimension(300, 300)); panelCreating = new JPanel(); panelCreating.setMinimumSize(new Dimension(160, 200)); panelCreating.setPreferredSize(new Dimension(160, 200)); scrollPaneCreating = new JScrollPane(panelCreating, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); textPane1 = new JTextPane(); textPane1.setText("a\na"); textPane2 = new JTextPane(); textPane2.setText("b\nb"); button1 = new JButton("+++"); panelCenter = new JPanel(); panelCenter.setBackground(Color.blue); scrollPaneCenter = new JScrollPane(panelCenter); // ----------------- Left Panel Init ----------------------- panelCreating.setLayout(new GridBagLayout()); panelCreating.setBackground(Color.ORANGE); panelCreating.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); GridBagConstraints c = new GridBagConstraints(); c.insets = new Insets(0, 0, 4, 4); c.anchor = GridBagConstraints.FIRST_LINE_START; c.weightx = c.weighty = 0; c.gridx = 0; c.gridy = GridBagConstraints.RELATIVE; c.gridwidth = GridBagConstraints.REMAINDER; c.gridheight = 1; c.fill = GridBagConstraints.BOTH; panelCreating.add(textPane1, c); button1.addActionListener(new ActionListener() { int height = 50; @Override public void actionPerformed(ActionEvent e) { textPane1.setText(textPane1.getText() + "\na"); textPane1.setPreferredSize(new Dimension(150, height)); textPane2.setText(textPane2.getText() + "\nb"); textPane2.setPreferredSize(new Dimension(150, height)); height += 30; panelCreating.revalidate(); panelCreating.repaint(); scrollPaneCreating.revalidate(); } }); panelCreating.add(button1, c); panelCreating.add(textPane2, c); // ------------------------------------------------------- getContentPane().setLayout(new GridBagLayout()); c = new GridBagConstraints(); c.ipadx = c.ipady = 0; c.insets = new Insets(0, 0, 0, 0); c.weighty = 0; c.gridheight = 1; c.gridx = 0; c.gridy = 1; c.gridwidth = 1; c.weightx = 0; c.fill = GridBagConstraints.BOTH; getContentPane().add(scrollPaneCreating, c); c.gridx = 1; c.gridy = 1; c.fill = GridBagConstraints.BOTH; c.weightx = 1; c.weighty = 1; getContentPane().add(scrollPaneCenter, c); } } 

The yellow bar also uses the GridBagLayout. sorry for my English

+7
source share
3 answers

Instead of setting your preferred size on panelCreating , set it to scrollPaneCreating . And do not set the preferred size of the text components, they will grow as you add new lines of text to them. The idea is for the panel inside the scroll panel to grow as much as necessary, and simply limit the size of the scroll area itself.

  // [...] panelCreating = new JPanel(); //panelCreating.setMinimumSize(new Dimension(160, 200)); //panelCreating.setPreferredSize(new Dimension(160, 200)); scrollPaneCreating = new JScrollPane(panelCreating, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); scrollPaneCreating.setMinimumSize(new Dimension(160, 200)); scrollPaneCreating.setPreferredSize(new Dimension(160, 200)); // [...] @Override public void actionPerformed(ActionEvent e) { textPane1.setText(textPane1.getText() + "\na"); //textPane1.setPreferredSize(new Dimension(150, height)); textPane2.setText(textPane2.getText() + "\nb"); //textPane2.setPreferredSize(new Dimension(150, height)); //height += 30; // This isn't necessary either //panelCreating.revalidate(); //panelCreating.repaint(); //scrollPaneCreating.revalidate(); } 

Edited to add: another alternative is to set dimensions on JViewport , which is attached to the scroll bar. The viewport displays the contents. You might think of the scroll bar as consisting of a viewport and scroll bars. If a fixed size is set in the scroll area, the size of the viewport is determined by subtracting the size of the scroll bar. But if the viewport is set to a fixed size, the size of the scroll area is determined by adding the size of the scrollbar to the size of the viewport. Setting a fixed size in the viewport is preferable if you want to precisely control how much content should be displayed on the screen, since the scroll sizes may vary depending on the operating system.

 scrollPaneCreating.getViewport().setMinimumSize(new Dimension(160, 200)); scrollPaneCreating.getViewport().setPreferredSize(new Dimension(160, 200)); 
+5
source

The default layout for JPanel is FlowLayout . Instead, try GridLayout . Here is an example here . For example,

 panelCreating = new JPanel(new GridLayout()); scrollPaneCreating = new JScrollPane(panelCreating); 

Addendum: Also consider nested layouts. The example below uses BoxLayout for the left pane.

enter image description here

 import java.awt.Color; import java.awt.EventQueue; import java.awt.GridLayout; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextPane; /** @see https://stackoverflow.com/questions/9184476 */ public class SwingTest extends JFrame { private static final int N = 8; public SwingTest() { initComponents(); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { new SwingTest().setVisible(true); } }); } private JPanel panelCenter, panelCreating; private JScrollPane scrollPaneCreating, scrollPaneCenter; private void initComponents() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); panelCreating = new JPanel(); scrollPaneCreating = new JScrollPane(panelCreating, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); panelCenter = new JPanel(); panelCenter.setBackground(Color.blue); scrollPaneCenter = new JScrollPane(panelCenter); // ----------------- Left Panel Init ----------------------- panelCreating.setLayout(new BoxLayout(panelCreating, BoxLayout.Y_AXIS)); panelCreating.setBackground(Color.orange); panelCreating.setBorder(BorderFactory.createEmptyBorder(N, N, N, N)); panelCreating.add(createTextPane()); panelCreating.add(Box.createVerticalStrut(N)); panelCreating.add(createTextPane()); panelCreating.add(Box.createVerticalStrut(N)); panelCreating.add(createTextPane()); // ------------------------------------------------------- setLayout(new GridLayout(1, 0)); add(scrollPaneCreating); add(scrollPaneCenter); pack(); } private JTextPane createTextPane() { JTextPane pane = new JTextPane(); pane.setText("" + "Twas brillig and the slithy toves\n" + "Did gyre and gimble in the wabe;\n" + "All mimsy were the borogoves,\n" + "And the mome raths outgrabe."); pane.setBorder(BorderFactory.createEmptyBorder(N, N, N, N)); return pane; } } 
+4
source

I fixed your problem by adding 1 line.

 panelCreating.setPreferredSize(new Dimension((int) panelCreating.getPreferredSize().getWidth(), (int)(panelCreating.getPreferredSize().getHeight()+30))); 

The line should be inserted after the following lines:

 @Override public void actionPerformed(ActionEvent e) { textPane1.setText(textPane1.getText() + "\na"); textPane1.setPreferredSize(new Dimension(150, height)); textPane2.setText(textPane2.getText() + "\nb"); textPane2.setPreferredSize(new Dimension(150, height)); height += 30; 

Explanation: The location of the mesh bag does not set its preferred panel size when you set the preferred size of the text panels inside it, but scrollPane only scrolls based on the preferred panel size in it. Therefore, you must set a new preferred panel size each time you resize components in it, then scrollPane knows exactly what it should do. What I did, add a line that increased the preferred size of createPanel, which is the one inside scrollPanel

0
source

All Articles