1

状況:複数の「itemPanel」をJScrollPane含む「mainPanel」を含む「scrollPane」があります(データベースから読み取られた情報とそれに応じて作成されたオブジェクト)。ユーザーは、既存のエントリの間に新しいエントリを挿入できます。この場合、新しいエントリがデータベースに追加され、すべてのコンポーネント (「itemPanels」) が再度生成され、新しい「mainPanel」に追加されます。最後に、新しい「mainPanel」が setViewPortView で scrollPane に設定されます。JPanelJPanel

Vector<JPanel> itemPanels = generateMyPanelsFromDB();
JPanel mainPanel = new JPanel(new GridBagLayout());
//.. layout stuff
for(JPanel itemPanel: itemPanels) mainPanel.add(itemPanel,<gridbagconstraintsvar>);
scrollPane.setViewportView(mainPanel);

新しいコンポーネントが正しく追加され、スクロールペインが自動的に最後までスクロールします。

スクロールペインが最後までスクロールする(=以前の場所にとどまる)ことを回避するにはどうすればよいですか。私が試したこと:上記のアクションを次で囲みます:

int currentPos = scrollPane.getVerticalScrollBar().getValue();
//.. to the setViewPortView stuff
scrollPane.getVerticalScrollBar().setValue(value);

これは何もしません (スクロールペインは最後までスクロールし、それ以上何も起こりません)。次のネストされたinvokeLaterで再スクロールすることしかできませんでしたが、これは正しい方法ではなく、下にスクロールしてから上に戻ることを妨げません(=目を痛めます)

final int value = scrollPane.getVerticalScrollBar().getValue();
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
       public void run() { 
            scrollPane.setViewportView(mainPanel);
            Thread t = new Thread() {
                public void run() {
                    try {
                        Thread.sleep(1);
                    }
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    javax.swing.SwingUtilities.invokeLater(new Runnable() {
                           public void run() { 
                                scrollPane.getVerticalScrollBar().setValue(value);
                           }
                        });
                }
            };
            t.start();
       }
    });

2012 年 1 月 14 日追加:

public class DebugImportCommandEditPanel extends JPanel {
private static final long serialVersionUID = 1L;

private JScrollPane commandScrollPane;

public DebugImportCommandEditPanel() {
    this.setLayout(new BorderLayout());
    this.commandScrollPane = new JScrollPane(this.getMainPanel());
    this.add(this.commandScrollPane, BorderLayout.CENTER);
}

private JPanel getMainPanel() {
    Vector<InnerPanel> innerPanels = new Vector<InnerPanel>();
    for(int i=0;i<12;i++) innerPanels.add(new InnerPanel((i+1)+ "."));

    JPanel mainPanel = new JPanel(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.gridx=0;c.gridy=0;c.weightx=1;c.weighty=1;c.fill = GridBagConstraints.BOTH;
    for(InnerPanel panel: innerPanels) {
        mainPanel.add(panel,c);
        c.gridy++;
    }
    return mainPanel;
}

class InnerPanel extends JPanel {
    private static final long serialVersionUID = 1L;

    protected InnerPanel(String number) {
        this.setLayout(new BorderLayout());
        this.setBorder(BorderFactory.createTitledBorder("Inner Panel No. "+number));
        JTextPane textPane = new JTextPane();
        textPane.setText("Lorem ipsum dolor sit amet consectetuer tellus sociis sapien porttitor "+
                        "Suspendisse. Mattis morbi eu In non ante convallis\n  "+
                        "tempus risus venenatis urna. Sed ipsum et parturient volutpat\n "+ 
                        "adipiscing dolor quis adipiscing Donec odio.\n "+
                        "Neque adipiscing pretium lacus Phasellus neque a vel sed wisi alique\n"+
                        "t. Condimentum Sed pretium libero vitae facilisi pretium sit consequat a "+ 
                        "tincidunt. Pharetra ac Aliquam.");
        this.add(textPane,BorderLayout.CENTER);
    }
}

}

4

1 に答える 1

2

編集内容を見ると、ネストされたJTextPaneである可能性があります-予期せず(少なくとも:-)、ビューポートの直接の子でなくても、全体的なスクロール動作に影響を与えるようです。

解決策は、テキストの設定時に更新されないようにキャレットポリシーを構成することです。

JTextPane tp = new JTextPane();
DefaultCaret caret = (DefaultCaret) tp.getCaret();
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
textPane.setText("Lorem ipsum dolor sit amet consectetuer tellus sociis sapien porttitor "+
    ....

テキストを設定するにポリシーを設定する必要があることに注意してください。

于 2013-01-14T12:11:32.140 に答える