【发布时间】:2015-03-16 21:35:29
【问题描述】:
我正在编写一个使用 JScrollPane 的应用程序。在这个 JScrollPane 中,我想自动显示搜索结果,这意味着我必须在 JScrollPane 中动态添加和删除结果。结果实现为 JTextArea,嵌入在 GridBagLayout 中。
当有大量搜索结果时,JScrollPane 会自动滚动到底部(它应该在顶部)。我已经用我在这里找到的解决方案解决了这个问题。这里的问题是,你可以看到,它是如何滚动回顶部的。是否可以消除这种行为?
我发现了以下几点:
- 我必须删除以前的搜索结果才能显示新的搜索结果。如果我不删除以前的,它会正确显示。
- 它既不能解决 wgeb 的问题,我在添加 arow 后每次调整时更新 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();
尽管如此,这个问题的两个答案在其他一些情况下都非常有帮助,应该引起注意。
【问题讨论】:
-
you can see, how it scrolls back to the top.- 我不能,因为我不使用 Java 8 并且您的代码无法编译。 -
亲爱的camickr,我更新了代码。感谢您的关注和帮助!
-
你不能将插入符号的位置设置为视图的开头吗?
标签: java swing jscrollpane autoscroll