【问题标题】:A JPanel in JScrollPane, How to prevent Auto ScrollJScrollPane 中的 JPanel,如何防止自动滚动
【发布时间】:2014-08-03 14:25:48
【问题描述】:

我遇到了 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);
    }
}

【问题讨论】:

  • @DavidPostill 一点也不,那是 JScrollPane 中的 JTextArea。 JTextArea 有一个“getCaret()”。但是 JPanel 有不一样的东西。

标签: java swing jscrollpane


【解决方案1】:

我不知道如何防止滚动,但是您可以将滚动条重置回原来的位置:

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() 会将代码添加到事件调度线程的末尾,以便在所有自动滚动发生后执行,因此看起来滚动条从未移动过。

【讨论】:

  • 您好,谢谢您的回答,但对我来说还不够。因为对于我的程序,有一次,有100多个对象被改变,所以框架在闪烁。我想防止这种闪烁。不过还是谢谢大家的回答。
  • @RobyCat 为什么要同时更新 100 多个对象?为什么要使用 JTextArea?使用 JLabel 甚至 JTextField 怎么样?
  • 非常感谢!我使用了 JTextField,这个问题就解决了。但是您能向您解释一下为什么 JTextField 有效但 JTextArea 无效吗?非常感谢!
  • @RobyCat,一个 JTextField 永远不会有超过一行的文本,所以我猜你不需要逻辑来滚动文本以使其可见。
【解决方案2】:

接受的答案对我的情况并不可靠。

我目前正在使用可以阻止自动滚动请求的 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;
});

【讨论】:

    猜你喜欢
    • 2010-11-25
    • 2014-12-06
    • 1970-01-01
    • 2016-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-17
    相关资源
    最近更新 更多