当滚动条出现时,Java动态更改组件

当滚动条出现时,Java动态更改组件

问题描述:

我试图实现一个功能,(在我的测试项目中)按下按钮后,它会向我的JPanel添加一个随机数。 (我使用了我的布局,因为在我的真实程序中,我有更多的项目,它显示正确)。但是我需要我的程序来识别滚动条何时可见(这是我实现的,但有点延迟。我的意思是延迟是我按下按钮添加一个数字,如果滚动条变得可见,则什么也没有发生。下一次按下按钮就会像我想要的那样移动)。我有的另一个问题(我现在关注的一个)是当我动态更改JPanel的大小时,如果滚动条可见,则设置为将宽度更改为我的宽度 - 滚动条的宽度。但是看起来好像当滚动条可见时,新输入的数字移动了滚动条宽度的两倍而不是一次。我一直在我的计划的这一部分一整天,无法弄清楚。我将添加我的完整代码和一些截图。当滚动条出现时,Java动态更改组件

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.Font; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.ArrayList; 
import java.util.Random; 

import javax.swing.BorderFactory; 
import javax.swing.BoxLayout; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.UIManager; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 


public class Main { 
    JFrame frame; 
    JPanel topPanel; 
    JPanel memoryPanel; 
    JScrollPane sPane; 
    JButton button; 
    ArrayList<Integer> list = new ArrayList<>(); 
    boolean isVScrollVisible = false; 
    int scrollBarSize = 0; 

    public class MyChangeListener implements ChangeListener { 
     @Override 
     public void stateChanged(ChangeEvent e) { 
      isVScrollVisible = (sPane.getVerticalScrollBar().isVisible()); 
     } 
    } 

    public class ButtonListener implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      Random random = new Random(); 
      int r = random.nextInt(10); 

      list.add(r); 

      int n; 
      if (isVScrollVisible) { 
       n = scrollBarSize; 
      } else { 
       n = 0; 
      } 

      JPanel nextPanel = new JPanel(); 
      nextPanel.setName("" + r); 
      nextPanel.setForeground(Color.BLACK); 
      nextPanel.setPreferredSize(new Dimension(200 - n, 55)); 
      nextPanel.setMinimumSize(new Dimension(200 - n, 55)); 
      nextPanel.setMaximumSize(new Dimension(200 - n, 55)); 

      JPanel labelPanel = new JPanel(); 
      labelPanel.setLayout(new BorderLayout()); 

      JLabel label = new JLabel(); 
      label.setText("" + r); 
      label.setPreferredSize(new Dimension(200 - n, 55)); 
      label.setMinimumSize(new Dimension(200 - n, 55)); 
      label.setMaximumSize(new Dimension(200 - n, 55)); 
      label.setHorizontalAlignment(JLabel.RIGHT); 
      label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 17)); 
      label.setFont(new Font("Sans-Serif", Font.BOLD, 20)); 
      labelPanel.add(label); 

      nextPanel.add(labelPanel, BorderLayout.LINE_START); 

      for (int i = 0; i < memoryPanel.getComponents().length; i++) { 
       memoryPanel.getComponent(i).setPreferredSize(new Dimension(200 - n, 55)); 
       memoryPanel.getComponent(i).revalidate(); 
       memoryPanel.getComponent(i).repaint(); 
      } 


      memoryPanel.add(nextPanel, 0); 

      memoryPanel.revalidate(); 
      memoryPanel.repaint(); 
      sPane.revalidate(); 
      sPane.repaint(); 
     } 
    } 

    public Main() { 
     frame = new JFrame(); 

     topPanel = new JPanel(); 
     memoryPanel = new JPanel(); 
     memoryPanel.setLayout(new BoxLayout(memoryPanel, BoxLayout.Y_AXIS)); 

     sPane = new JScrollPane(memoryPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 
     sPane.setPreferredSize(new Dimension(200, 300)); 
     sPane.getViewport().addChangeListener(new MyChangeListener()); 

     scrollBarSize = ((Integer)UIManager.get("ScrollBar.width")) + 1; 

     button = new JButton("Add Random Number"); 
     button.addActionListener(new ButtonListener()); 

     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLayout(new BorderLayout()); 

     topPanel.add(button); 

     frame.add(topPanel, BorderLayout.PAGE_START); 
     frame.add(sPane, BorderLayout.CENTER); 

     frame.setResizable(false); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

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

enter image description here

enter image description here

我需要他们看起来完全一样。在我拥有现在的代码之前,滚动条会出现在看起来很丑的数字上。而我的框架可调整大小错误的原因是因为在我的真实程序中,我硬编码了所有尺寸,将来我会根据框架的尺寸计算正确的尺寸,所以现在将可调整尺寸设置为true已经超出这个问题。有什么建议做什么?

enter image description here

这就是我想要accompolish。

+0

1)看起来这个用例更适合于具有ListCellRenderer的JScrollPane中的JList。2)当存在定义的常量时不要猜测字体名称,例如'new Font(“Sans-Serif”,Font.BOLD,20)'应该是'new Font(Font.SANS_SERIF,Font.BOLD,20)' –

+0

我没有使用JList,因为在我的真实程序中,我有按钮为每个标签。 – Vince

+0

按钮有什么作用? –

摆脱所有设置首选/最小/最大尺寸的逻辑。每个组件都知道它的大小应该是多少。每个布局管理器将依次知道面板的首选大小应该是多少。让布局经理使用这些信息来完成它的工作。

用于动态地添加组件的基本逻辑是:

panel.add(...); 
panel.revalidate(); 
panel.repaint(); 

然后在需要时滚动条会自动出现。不需要听众或任何东西。

编辑:

我将所有大小的原因是因为如果我带他们出去,那么一切都居中显示

了解如何正确和有效地使用布局管理器。

例如使用当BoxLayout可以通过使用控制部件的对准:

component.setAlignmentX(JLabel.RIGHT_ALIGNMENT); 

和成分将被对准以提供给该部件的空间的右边缘。

使用JLabel时,您可能还需要在JLabel上设置一个属性,以将文本与标签的右边缘对齐。阅读JLabel API以获取适当的方法。

+0

我设置所有尺寸的原因是因为如果我将它们取出,那么所有内容都显示为中心 – Vince

+0

@Vince,请参阅编辑。 – camickr