gpt4 book ai didi

java - JScrollPane 和自动滚动 : Disturbing scrolling behavior

转载 作者:行者123 更新时间:2023-11-29 06:59:10 25 4
gpt4 key购买 nike

我正在编写一个使用 JScrollPane 的应用程序。在这个 JScrollPane 中,我想自动显示搜索结果,这意味着我必须在 JScrollPane 中动态添加和删除结果。结果实现为 JTextArea,它嵌入在 GridBagLayout 中。

当有大量搜索结果时,JScrollPane 会自动滚动到底部(它应该在顶部)。我已经用我在这里找到的解决方案解决了它。这里的问题是,你可以看到,它是如何滚动回到顶部的。是否可以消除这种行为?

我发现了以下事情:

  • 我必须删除以前的搜索结果才能显示新的搜索结果。如果我不删除以前的,它会正确显示。
  • 它既没有解决我在添加行后每次调整 JScrollPane 时更新 JScrollPane 的问题,也没有解决仅在添加所有行后才更新的问题。

最好的办法就是禁用自动滚动。我创建了一个可执行示例来演示此行为。单击“添加行”按钮时,将添加 500 行。多点几次,就很清楚了。

非常感谢您的帮助!

import java.awt.GridBagConstraints;
import javax.swing.JTextArea;

public class ScrollPaneTest extends javax.swing.JFrame {
private javax.swing.JButton jButton1;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JScrollPane jScrollPane1;


/**
* Creates new form ScrollPaneTest
*/
public ScrollPaneTest() {
initComponents();
}

/**
* Adds a new row.
* @param index The index of the new row.
*/
private void addRow(int index) {
JTextArea row = new JTextArea("Area " + index);
row.setEditable(false);
row.setBorder(null);

GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = index;
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 0);
jPanel2.add(row, gridBagConstraints);
}


/**
* Initializes the components.
*/
private void initComponents() {

jScrollPane1 = new javax.swing.JScrollPane();
jPanel1 = new javax.swing.JPanel();
jPanel2 = new javax.swing.JPanel();
jButton1 = new javax.swing.JButton();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jScrollPane1.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
jScrollPane1.setPreferredSize(new java.awt.Dimension(400, 400));

jScrollPane1.setViewportView(jPanel1);

jPanel1.setLayout(new java.awt.BorderLayout());

jPanel2.setLayout(new java.awt.GridBagLayout());
jPanel1.add(jPanel2, java.awt.BorderLayout.NORTH);

jScrollPane1.setViewportView(jPanel1);

jButton1.setText("Create Rows");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGap(148, 148, 148)
.addComponent(jButton1)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 245, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jButton1)
.addGap(0, 21, Short.MAX_VALUE))
);

pack();
}

/**
* Creates 500 new rows.
* @param evt
*/
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
jPanel2.removeAll();

for(int i = 0; i < 1000; i++) {
addRow(i);
}

javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
jScrollPane1.getVerticalScrollBar().setValue(0);
}

});
jPanel2.validate();
jPanel2.repaint();
}

public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new ScrollPaneTest().setVisible(true);
}
});
}
}

更新 1

我删除了 lambda 表达式。希望它现在也可以用

更新 2

令人不安的滚动行为问题已通过替换解决

jPanel2.validate();
jPanel2.repaint();

jScrollPane1.validate();
jScrollPane1.repaint();

尽管如此,这个问题的两个答案在其他一些情况下都可能非常有用,应该引起注意。

最佳答案

实现此目的的一种方法是为您的滚动 Pane 自定义 JViewPort。此自定义视口(viewport)覆盖 setViewPosition 并使用标志来阻止滚动或不滚动。

这是此类代码的示例,在更改文本区域的内容之前,我们“锁定”视口(viewport)以防止滚动,稍后再解锁:

import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class TestNoScrolling {

private int lineCount = 0;
private LockableViewPort viewport;
private JTextArea ta;

private final class LockableViewPort extends JViewport {

private boolean locked = false;

@Override
public void setViewPosition(Point p) {
if (locked) {
return;
}
super.setViewPosition(p);
}

public boolean isLocked() {
return locked;
}

public void setLocked(boolean locked) {
this.locked = locked;
}
}

protected void initUI() {
JFrame frame = new JFrame("test");
ta = new JTextArea(5, 30);
JScrollPane scrollpane = new JScrollPane();
viewport = new LockableViewPort();
viewport.setView(ta);
scrollpane.setViewport(viewport);
frame.add(scrollpane);
frame.pack();
frame.setVisible(true);
Timer t = new Timer(1000, new ActionListener() {

@Override
public void actionPerformed(ActionEvent e) {
viewport.setLocked(true);
ta.append("Some new line " + lineCount++ + "\n");
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
viewport.setLocked(false);
}
});
}
});
t.setRepeats(true);
t.start();
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {

@Override
public void run() {
new TestNoScrolling().initUI();
}
});
}
}

关于java - JScrollPane 和自动滚动 : Disturbing scrolling behavior,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29087376/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com