JScrollPane和JViewport的最大滚动大小小于内容的限制 [英] Scrolling limitation with JScrollPane and JViewport maximum sizes smaller than contents
问题描述
我有一个JFrame
包含一个JScrollPane
包含一个JPanel
.
JPanel
包含一堆JTextArea
.
我正在其中加载很多文本(大约8k-10k个字符).
I have a JFrame
containing a JScrollPane
containing a JPanel
.
The JPanel
contains a bunch of JTextArea
s.
I'm loading a lot of text into them (about 8k-10k characters).
尽管滚动有点滞后,但布局工作正常.
The layout works fine, though the scrolling is a bit laggy.
真正的问题是,JPanel
,JScrollPane
和JViewport
似乎有严格的32767大小限制,因此,当任何JTextArea
变得更高时,就无法进一步滚动以显示文字的最后1/3.
The real issue is that it seems JPanel
, JScrollPane
and JViewport
have a hard 32767 size limit, so when any JTextArea
grows higher than that, it can't be scrolled any further to show the last 1/3 of the text.
在下面,您可以看到一个最小的问题示例.我使用了NetBeans JFrame
设计器,因此它可能有点冗长,但是我从默认值更改的唯一一件事是JTextArea
是JPanel
的直接子代,滚动条策略以及稍大的字体大小:
Below you can see a minimal example for the problem. I used the NetBeans JFrame
designer so it might be a bit lengthy but the only thing I have changed from the defaults is that the JTextArea
s are direct children of the JPanel
, the scrollbar policies, and slightly larger font size:
public class NewJFrame extends javax.swing.JFrame {
/**
* Creates new form NewJFrame
*/
public NewJFrame() {
initComponents();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
jPanel1 = new javax.swing.JPanel();
jTextArea1 = new javax.swing.JTextArea();
jTextArea2 = new javax.swing.JTextArea();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jScrollPane1.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
jTextArea1.setColumns(20);
jTextArea1.setFont(new java.awt.Font("Monospaced", 0, 14)); // NOI18N
jTextArea1.setRows(5);
jTextArea2.setColumns(20);
jTextArea2.setFont(new java.awt.Font("Monospaced", 0, 14)); // NOI18N
jTextArea2.setRows(5);
jTextArea2.setText("Some long text...");
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jTextArea1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jTextArea2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0))
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jTextArea1, javax.swing.GroupLayout.DEFAULT_SIZE, 342, Short.MAX_VALUE)
.addComponent(jTextArea2))
.addGap(0, 0, 0))
);
jScrollPane1.setViewportView(jPanel1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 96, Short.MAX_VALUE)
);
pack();
}// </editor-fold>
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
final NewJFrame f = new NewJFrame();
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for(javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels())
if("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}catch(ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}catch(InstantiationException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}catch(IllegalAccessException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}catch(javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
f.setVisible(true);
}
});
StringBuilder txt = new StringBuilder();
for(int i=0; i<10000; i++)
txt.append(i).append("\n");
f.jTextArea1.setText(txt.toString());
txt = new StringBuilder();
txt.append("JTextArea height: ").append(f.jTextArea1.getHeight()).append('\n');
txt.append("JTextArea rows: ").append(f.jTextArea1.getRows()).append('\n');
txt.append("JScrollPane height:").append(f.jScrollPane1.getHeight()).append('\n');
txt.append("JViewport height:").append(f.jScrollPane1.getViewport().getHeight()).append('\n');
txt.append("JPanel height:").append(f.jPanel1.getHeight()).append('\n');
f.jTextArea2.setText(txt.toString());
}
// Variables declaration - do not modify
private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextArea jTextArea1;
private javax.swing.JTextArea jTextArea2;
// End of variables declaration
}
如果运行此命令并滚动到底部,您会希望看到计数达到10,000,但仅达到1637,并且您几乎可以看到下一行的顶部像素.
If you run this and scroll to the bottom, you would expect to see the count reach 10 000 but it only goes to 1637, and you can see the top pixels from the next line just barely show up.
我已经尝试在JPanel
,JScrollPane
及其JViewport
上使用setMaximumSize
和setSize
,但是没有任何改变.我也有些困惑,即使有一万行文本,其中的一些可以滚动到足以查看的程度,getRows()
和getSize()
方法仍返回原始值.
I have already tried to setMaximumSize
and setSize
on the JPanel
, the JScrollPane
and its JViewport
but nothing has changed. I'm also somewhat confused that even though there's 10k lines of text, some of which can be scrolled far enough to be viewed, the getRows()
and getSize()
methods return the original values.
当我想让可滚动的JTextArea
大于32767时,解决这种情况的正确方法是什么?
What is the right way to handle this situation when I want to have a scrollable JTextArea
larger than 32767?
推荐答案
该问题与线程安全无关.经过大量挖掘之后,我发现JPanel
的外观的基础窗口管理器实现具有硬编码的32767大小限制,因此它位于JScrollPane
中并不重要.这样做的目的是避免对单个JScrollPane
进行过多的额外管理,但这种局限性使其不可避免.
The problem had nothing to do with thread safety. After much digging, I found that the underlying window manager implementation for the Look And Feel of JPanel
had a hardcoded 32767 size limit, so it didn't matter that it was sitting in a JScrollPane
. The idea was to avoid a lot of extra managing of individual JScrollPane
s but the limit makes it unavoidable.
将JPanel
的内容移动到自己的单独JscrollPane
中可以解决此问题.由于我不知道的原因,滚动仍然有些滞后.
Moving the contents of the JPanel
into their own individual JscrollPane
s resolved the issue. The scrolling is still a bit laggy for reasons unknown to me.
这篇关于JScrollPane和JViewport的最大滚动大小小于内容的限制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!