JScrollPane和JViewport的最大滚动大小小于内容的限制 [英] Scrolling limitation with JScrollPane and JViewport maximum sizes smaller than contents

查看:116
本文介绍了JScrollPane和JViewport的最大滚动大小小于内容的限制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个JFrame包含一个JScrollPane包含一个JPanel. JPanel包含一堆JTextArea. 我正在其中加载很多文本(大约8k-10k个字符).

I have a JFrame containing a JScrollPane containing a JPanel. The JPanel contains a bunch of JTextAreas. I'm loading a lot of text into them (about 8k-10k characters).

尽管滚动有点滞后,但布局工作正常.

The layout works fine, though the scrolling is a bit laggy.

真正的问题是,JPanelJScrollPaneJViewport似乎有严格的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设计器,因此它可能有点冗长,但是我从默认值更改的唯一一件事是JTextAreaJPanel的直接子代,滚动条策略以及稍大的字体大小:

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 JTextAreas 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.

我已经尝试在JPanelJScrollPane及其JViewport上使用setMaximumSizesetSize,但是没有任何改变.我也有些困惑,即使有一万行文本,其中的一些可以滚动到足以查看的程度,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 JScrollPanes but the limit makes it unavoidable.

JPanel的内容移动到自己的单独JscrollPane中可以解决此问题.由于我不知道的原因,滚动仍然有些滞后.

Moving the contents of the JPanel into their own individual JscrollPanes resolved the issue. The scrolling is still a bit laggy for reasons unknown to me.

这篇关于JScrollPane和JViewport的最大滚动大小小于内容的限制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆