如何让JScrollPane中可动态调整大小的JPanel正常工作
问题排查与修复方案
核心错误点
- 给
JScrollPane添加内部滚动组件不能调用add()方法,必须调用setViewportView()把组件放到滚动视口中,直接add()的组件不会被滚动逻辑渲染,自然不可见 - Swing组件只能绑定一个父容器,你初始已经把
panel添加到了JFrame中,后续要转移到JScrollPane之前,需要先把它从原父容器中移除 - 不需要每次点击按钮都重复把
JScrollPane添加到JFrame中,初始布局阶段就可以把JScrollPane添加到窗口,仅动态修改内部panel的尺寸即可,反复添加组件会导致层级混乱 - 空布局(
null layout)下修改组件层级或尺寸后,必须调用repaint()触发窗口重绘,否则会出现显示残留
修正后可运行代码
import javax.swing.*; import java.awt.*; import java.awt.event.*; public class Frame extends JFrame implements ActionListener{ int scrollBarSize; JButton button; JPanel buttonPanel; JPanel panel = new JPanel(); JScrollPane pane = new JScrollPane( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); JTextField text; int bigPanelPos = 495, bigPanelSize = 55 , smallPanelPos; Frame(){ this.setSize(700,700); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setResizable(false); this.setLayout(null); scrollBarSize = ((Integer)UIManager.get("ScrollBar.width")) + 1; pane.setBounds(0,0,700,550); // 初始就把滚动面板添加到窗口 this.add(pane); panel.setBackground(Color.yellow); panel.setBounds(0,495,700,55); panel.setAlignmentX(Component.CENTER_ALIGNMENT); panel.setAlignmentY(Component.CENTER_ALIGNMENT); button = new JButton("Click me!"); button.setPreferredSize(new Dimension(50,15)); button.setFont(new Font("Didot",Font.BOLD, 15)); button.addActionListener(this); buttonPanel = new JPanel(); buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS)); buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT); buttonPanel.setAlignmentY(Component.CENTER_ALIGNMENT); buttonPanel.setBorder(BorderFactory.createTitledBorder("ButtonPanel")); buttonPanel.setBounds(0, 550, 700, 150 ); buttonPanel.add(button); this.add(panel); this.add(buttonPanel); this.setVisible(true); } public void actionPerformed(ActionEvent e) { if (e.getSource() == button) { bigPanelPos -= 55; bigPanelSize +=55; int n = scrollBarSize; panel.setPreferredSize(new Dimension(700 - n,bigPanelSize)); // 仅首次点击时转移panel到滚动视口 if (panel.getParent() != pane.getViewport()) { if (panel.getParent() != null) { panel.getParent().remove(panel); } pane.setViewportView(panel); } pane.revalidate(); this.repaint(); System.out.println(pane.getBounds()); System.out.println(panel.getBounds()); } } public static void main(String[] args) { new Frame(); } }
内容的提问来源于stack exchange,提问作者ItsSilver
相关产品推荐
相关产品推荐

