JScrollPane中的JPanel,如何防止自动滚动

时间:2014-08-03 14:25:49

标签: java swing jscrollpane

我有JScrollPane的自动滚动问题。例如,在以下代码中,如果我们更改Spinner的值,则所有TextAreas的值都将更改。然后JScrollPane自动滚动到最新更改的JComponent。

我可以阻止这种自动滚动吗?

有人认为这个问题是“重复”但根本没有。这个问题Java / Swing : JTextArea in a JScrollPane, how to prevent auto-scroll?是JScrollPane中的JTextArea,所以我们可以使用DefaultCaret来解决这个问题,因为JTextArea有DefaultCaret。但在我的问题中,它是JScrollPane中的JPanel,JPanel没有DefaultCaret。所以我们不能用同样的方法来解决这个问题。

import java.awt.BorderLayout

import javafx.scene.layout.Pane;

import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class ScrollControl {
    static JFrame main_frame = new JFrame();
    static JScrollPane scroll_pane = new JScrollPane();
    static JPanel pane = new JPanel();
    static JSpinner spinner = new JSpinner();
    static JTextArea text1 = new JTextArea();
    static JTextArea text2 = new JTextArea();
    static JTextArea text3 = new JTextArea();
    static JTextArea text4 = new JTextArea();
    static JTextArea text5 = new JTextArea();
    static JTextArea text6 = new JTextArea();
    static JTextArea text7 = new JTextArea();

    public static void main(String args[]){
        main_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
        spinner.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent arg0) {
                text1.setText(spinner.getValue().toString());
                text2.setText(spinner.getValue().toString());
                text3.setText(spinner.getValue().toString());
                text4.setText(spinner.getValue().toString());
                text5.setText(spinner.getValue().toString());
                text6.setText(spinner.getValue().toString());
                text7.setText(spinner.getValue().toString());
            }
        });
        pane.add(spinner);
        pane.add(text1);
        pane.add(text2);
        pane.add(text3);
        pane.add(text4);
        pane.add(text5);
        pane.add(text6);
        pane.add(text7);
        scroll_pane = new JScrollPane(pane);
        main_frame.setSize(300, 100);
        main_frame.getContentPane().add(scroll_pane, BorderLayout.CENTER);

        main_frame.setVisible(true);
    }
}

2 个答案:

答案 0 :(得分:0)

我不知道如何阻止滚动,但您可以将滚动条重置回其原始位置:

spinner.addChangeListener(new ChangeListener()
{
    @Override
    public void stateChanged(ChangeEvent arg0)
    {
        final JScrollBar vertical = scroll_pane.getVerticalScrollBar();
        final int value = vertical.getValue();

        text1.setText(spinner.getValue().toString());
        text2.setText(spinner.getValue().toString());
        text3.setText(spinner.getValue().toString());
        text4.setText(spinner.getValue().toString());
        text5.setText(spinner.getValue().toString());
        text6.setText(spinner.getValue().toString());
        text7.setText(spinner.getValue().toString());

        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                vertical.setValue( value );
            }
        });
    }
});

invokeLater()会将代码添加到Event Dispatch Thread的末尾,这样它将在所有自动滚动发生后执行,因此看起来滚动条从未移动过。

答案 1 :(得分:0)

对于我的情况,接受的答案无法可靠地起作用。

我当前正在使用JPanel子类,它可以防止自动滚动请求作为解决方法:

class AutoScrollSafeJPanel extends JPanel {
  boolean preventAutroscroll;   

  @Override
  public void scrollRectToVisible(Rectangle rect) {
    if (!preventAutoscroll) {
      super.scrollRectToVisible(rect);
    }
  }
}

在调整组件大小的地方,请执行以下操作:

container.preventAutoscroll = true;
container.setSize(Math.round(width), Math.round(height));
container.setPreferredSize(container.getSize());
container.revalidate();

SwingUtilities.invokeLater(() -> {
  container.preventAutoscroll = false;
});