JScrollPane 不会向下滚动以正确显示从 ActionListener 调用的 JTextPane
JScrollPane won't scroll down to properly display JTextPane called from ActionListener
我想刷新我的 ColorPane 定义如下:
public class ColorPane extends JTextPane{
/* FYI, The function below allows me to add text with ANSI Coloring */
public void appendANSI(String s) {
// ...
}
// ...
}
在接下来的 while
语句中,我以控制台样式 window 编写 line
。
因此,作为控制台,我想在 textPane
.
添加新行时刷新并 在底部自动向下滚动
我想通过按 mainButton
启动以下循环。
public class mainButton implements ActionListener {
public void actionPerformed (ActionEvent e) {
ColorPane textPane = new ColorPane();
/* FYI, in is a BufferedReader */
while ((line = in.readLine()) != null) {
/* Add automatically in the console window */
textPane.appendANSI(line+"\n");
/* Last possible workaround I tried
Which as the same effect than commenting these lines.. */
JScrollBar vertical = scrollPane.getVerticalScrollBar();
vertical.setValue(vertical.getMaximum());
/* I also tried : */
// textPane.setCaretPosition(textPane.getDocument().getLength());
/* Or this : */
// Rectangle rec = GenerationWindow.textPane.getVisibleRect();
// rec.setLocation((int) (rec.getX() + 1000), (int) rec.getY());
// textPane.scrollRectToVisible(rec);
/* Refresh the display */
textPane.update(textPane.getGraphics());
}
}
}
问题是,我的 window 向下滚动,但 仅在退出 actionPerformed
时才向下滚动。为什么?
一方面,我可以看到文本在每次循环时都会更新,但另一方面,JScrollPane scrollPane
在函数末尾向下滚动...
我想我在这里错过了一些摇摆哲学..
我已经在 Oracle 文档和 StackO 主题上漫游了几个小时,尝试了不同的 "solutions",但我现在有点绝望了..
不自动向下滚动的控制台是..好吧..不是控制台..
textPane.update(textPane.getGraphics());
不要在组件上手动调用 update(...)。 Swing 会判断组件何时需要重绘。
The thing is, my window is scrolled down, but only when exiting actionPerformed. Why ?
您的代码在一个循环中执行,该循环在事件调度线程上执行,该线程是绘制 GUI 的线程。在循环完成之前,GUI 无法重新绘制自身。
较长的 运行 代码需要在单独的线程上执行,然后当您更新文本窗格时,GUI 可以自行重新绘制。
我可能会为此线程使用 Swing Worker
,然后您可以 "publish" 结果可用时。阅读有关 Concurrency 的 Swing 教程部分,了解更多信息和使用 SwingWorker 的示例。
正如@camickr 所建议的,运行 SwingWorker 中的 actionPerformed() 的内容。其内容应包含如下内容:
Runnable runner = new Runnable() {
@Override
public void run() {
textPane.appendANSI(line+"\n");
textpane.setCaretPosition(textpane.getDocument().getLength());
}
}
while ((line = in.readLine()) != null) {
SwingUtilities.invokelater( runner );
}
我想刷新我的 ColorPane 定义如下:
public class ColorPane extends JTextPane{
/* FYI, The function below allows me to add text with ANSI Coloring */
public void appendANSI(String s) {
// ...
}
// ...
}
在接下来的 while
语句中,我以控制台样式 window 编写 line
。
因此,作为控制台,我想在 textPane
.
我想通过按 mainButton
启动以下循环。
public class mainButton implements ActionListener {
public void actionPerformed (ActionEvent e) {
ColorPane textPane = new ColorPane();
/* FYI, in is a BufferedReader */
while ((line = in.readLine()) != null) {
/* Add automatically in the console window */
textPane.appendANSI(line+"\n");
/* Last possible workaround I tried
Which as the same effect than commenting these lines.. */
JScrollBar vertical = scrollPane.getVerticalScrollBar();
vertical.setValue(vertical.getMaximum());
/* I also tried : */
// textPane.setCaretPosition(textPane.getDocument().getLength());
/* Or this : */
// Rectangle rec = GenerationWindow.textPane.getVisibleRect();
// rec.setLocation((int) (rec.getX() + 1000), (int) rec.getY());
// textPane.scrollRectToVisible(rec);
/* Refresh the display */
textPane.update(textPane.getGraphics());
}
}
}
问题是,我的 window 向下滚动,但 仅在退出 actionPerformed
时才向下滚动。为什么?
一方面,我可以看到文本在每次循环时都会更新,但另一方面,JScrollPane scrollPane
在函数末尾向下滚动...
我想我在这里错过了一些摇摆哲学..
我已经在 Oracle 文档和 StackO 主题上漫游了几个小时,尝试了不同的 "solutions",但我现在有点绝望了..
不自动向下滚动的控制台是..好吧..不是控制台..
textPane.update(textPane.getGraphics());
不要在组件上手动调用 update(...)。 Swing 会判断组件何时需要重绘。
The thing is, my window is scrolled down, but only when exiting actionPerformed. Why ?
您的代码在一个循环中执行,该循环在事件调度线程上执行,该线程是绘制 GUI 的线程。在循环完成之前,GUI 无法重新绘制自身。
较长的 运行 代码需要在单独的线程上执行,然后当您更新文本窗格时,GUI 可以自行重新绘制。
我可能会为此线程使用 Swing Worker
,然后您可以 "publish" 结果可用时。阅读有关 Concurrency 的 Swing 教程部分,了解更多信息和使用 SwingWorker 的示例。
正如@camickr 所建议的,运行 SwingWorker 中的 actionPerformed() 的内容。其内容应包含如下内容:
Runnable runner = new Runnable() {
@Override
public void run() {
textPane.appendANSI(line+"\n");
textpane.setCaretPosition(textpane.getDocument().getLength());
}
}
while ((line = in.readLine()) != null) {
SwingUtilities.invokelater( runner );
}