将滚动项动态添加到JscrollPane上的特定位置

时间:2015-01-01 03:42:22

标签: java swing jscrollpane

问题的简短版本:我有一个JScrollPane,其中滚动了大量项目。在某些时候,我想在JScrollPane中添加一些项目,并将它们显示在列表的末尾,但是在(例如)第17项之后。

通常,如果有问题的代码在JScrollPane派生类中,我只说这个.add();但我相信这已经到了列表的末尾。

理由:案例1:我滚动的基础数据是一个有序的项目列表,但在列表的任何一点都允许添加。当我将内容添加到列表中间时,我想避免将整个列表再次加载到JScrollPane中。

案例2:我正在模拟具有扩展子类别的滚动列表。因此,如果用户选择具有扩展子类别的项目,我的Action代码会识别这种情况,查看程序数据以查找子类别,然后将它们添加到所选类别下的JScrollPane。不要担心它,但也会有一些视觉指示它是一个子类别,由我的动作代码提供。

我可以编写所有这些代码。我希望学习的是如何在不将其添加到列表末尾的情况下向JScrollPane添加内容。

1 个答案:

答案 0 :(得分:1)

答案取决于您要将商品添加到此组件的内容。如果您使用JList,则可以使用DefaultListModel#add(int, Object)之类的内容将项目添加到特定位置。

如果您使用的是基于JComponent的内容(例如JPanel),则可以使用JComponent#add(Component, int)指定应添加该组件的位置,这假定存在位置(即,如果容器仅包含单个组件,则无法将组件添加到位置100。)

以下示例生成一个随机数,确定应插入该数字的位置,以便维护有序列表并在该点插入一个组件。它还会尝试滚动JScrollPane以使项目可见

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test10 {

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

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

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JPanel numbers;
        private List<Integer> values;

        public TestPane() {
            values = new ArrayList<>(25);
            setLayout(new BorderLayout());
            numbers = new JPanel(new GridLayout(0, 1));
            add(new JScrollPane(numbers));

            Timer timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    int next = (int) (Math.random() * Integer.MAX_VALUE);
                    int insertion = Collections.binarySearch(values, next);
                    if (insertion < 0) {
                        insertion = (Math.abs(insertion)) - 1;
                    }
                    values.add(insertion, next);
                    JLabel label = new JLabel(Integer.toString(next));
                    numbers.add(label, insertion);
                    numbers.revalidate();
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            Point p = label.getLocation();
                            JViewport vp = (JViewport) numbers.getParent();
                            JScrollPane sp = (JScrollPane) vp.getParent();
                            vp.setViewPosition(p);
                        }
                    });
                }
            });
            timer.start();
        }

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

    }

}