当滚动条出现时,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();
}
}
我需要他们看起来完全一样。在我拥有现在的代码之前,滚动条会出现在看起来很丑的数字上。而我的框架可调整大小错误的原因是因为在我的真实程序中,我硬编码了所有尺寸,将来我会根据框架的尺寸计算正确的尺寸,所以现在将可调整尺寸设置为true已经超出这个问题。有什么建议做什么?
这就是我想要accompolish。
摆脱所有设置首选/最小/最大尺寸的逻辑。每个组件都知道它的大小应该是多少。每个布局管理器将依次知道面板的首选大小应该是多少。让布局经理使用这些信息来完成它的工作。
用于动态地添加组件的基本逻辑是:
panel.add(...);
panel.revalidate();
panel.repaint();
然后在需要时滚动条会自动出现。不需要听众或任何东西。
编辑:
我将所有大小的原因是因为如果我带他们出去,那么一切都居中显示
了解如何正确和有效地使用布局管理器。
例如使用当BoxLayout
可以通过使用控制部件的对准:
component.setAlignmentX(JLabel.RIGHT_ALIGNMENT);
和成分将被对准以提供给该部件的空间的右边缘。
使用JLabel时,您可能还需要在JLabel上设置一个属性,以将文本与标签的右边缘对齐。阅读JLabel API以获取适当的方法。
1)看起来这个用例更适合于具有ListCellRenderer的JScrollPane中的JList。2)当存在定义的常量时不要猜测字体名称,例如'new Font(“Sans-Serif”,Font.BOLD,20)'应该是'new Font(Font.SANS_SERIF,Font.BOLD,20)' –
我没有使用JList,因为在我的真实程序中,我有按钮为每个标签。 – Vince
按钮有什么作用? –