我有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);
}
}
答案 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;
});