0

StackOverflow コミュニティの皆さん、StackOverflow に問題があります。

[+] タブが選択されている場合、GUI の JTabbedPane コンテナに新しいタブを追加するのが困難です。これまでのところ、[+] タブをクリックすると、StackOverflowError が発生するまで新しいタブが追加されます。

次の条件が true の場合、新しいタブが JTabbedPane に追加されます。

if(songPanel.getSelectedIndex()==songPanel.getTabCount()-1){
...
}

JTabbedPane にタブが繰り返し追加されるのを避けるために、以前に選択したタブに戻そうとしましたが、役に立ちませんでした。ChangeEvent アクチュエーターが起動されると、無期限にオンのままになりますか? SE7 API で役に立つものは何も見つかりませんでした。

関連するコード (コンパイル不可、より大きなプログラムからの抜粋。コードの抜粋をコピーして貼り付けただけで、間違いを犯しやすいため、括弧が欠落している可能性があります)

@Override
    public void init(){
        setLayout(new GridLayout(MAIN_LAYOUT_ROWS, MAIN_LAYOUT_COLUMNS));
        add(renderPanel = new JScrollPane());
        add(controlPanel = new JPanel());
        add(colourPanel = new JPanel());
        add(songPanel = new JTabbedPane());

        //songPanel options
        songPanel = new JTabbedPane();
        songPanel.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
        songPanel.addTab("#1", new JTextArea());
        songPanel.addTab("+", null, new JLabel(), "+");

        Container cp = getContentPane();
        cp.add(BorderLayout.SOUTH, songPanel);

        //integrate songPanel changeListener 
        songPanel.addChangeListener(new ChangeListener(){

            @Override //Method called when selected tab changes
            public void stateChanged(ChangeEvent e){
                try {          
                    if(songPanel.getSelectedIndex()==songPanel.getTabCount()-1){
                        addTab("songPanel");
                    }
                } catch (StackOverflowError soe){soe.printStackTrace();}
            }
        });
//*************************************************************************
    @Override
    public void start(){

    }
//*************************************************************************
    private void addTab(String panelName){
        System.out.println("ADDING TAB");
        if(panelName.equals("songPanel")){
            String tabName = ("#" + Integer.toString(songPanel.getTabCount()-1));
            songPanel.insertTab(tabName, null, new JTextField(), tabName,           songPanel.getTabCount()-2);
        }
    }
}
//**************************************************************************
}

私はもう試した:

  • addTab() メソッドで元に戻すインデックスを設定すると、最新のタブが選択されます (それでも StackOverflowError が発生します)

次の行に注意してください。

songPanel.getSelectedIndex()==songPanel.getTabCount()-1)

「songPanel.getSelectedIndex()」と「songPanel.getTabCount()-1)」は常に等しいため、条件は常に true ( StackOverflowError の原因)

エラーメッセージ:

java.lang.StackOverflowError
at javax.swing.text.StyleContext$SmallAttributeSet.getAttributeNames(StyleContext.java:947)
at javax.swing.text.StyleContext$SmallAttributeSet.containsAttributes(StyleContext.java:973)
at javax.swing.text.StyleContext$SmallAttributeSet.equals(StyleContext.java:852)
at java.util.WeakHashMap.eq(WeakHashMap.java:282)
at java.util.WeakHashMap.get(WeakHashMap.java:379)
at java.util.Collections$SynchronizedMap.get(Collections.java:2031)
at javax.swing.text.StyleContext.getImmutableUniqueSet(StyleContext.java:520)
at javax.swing.text.StyleContext.addAttributes(StyleContext.java:340)
at javax.swing.text.AbstractDocument$AbstractElement.addAttributes(AbstractDocument.java:1985)
at javax.swing.text.AbstractDocument$AbstractElement.<init>(AbstractDocument.java:1777)
at javax.swing.text.AbstractDocument$LeafElement.<init>(AbstractDocument.java:2502)
at javax.swing.text.AbstractDocument$BidiElement.<init>(AbstractDocument.java:2674)
at javax.swing.text.AbstractDocument.<init>(AbstractDocument.java:149)
at javax.swing.text.AbstractDocument.<init>(AbstractDocument.java:109)
at javax.swing.text.PlainDocument.<init>(PlainDocument.java:90)
at javax.swing.text.PlainDocument.<init>(PlainDocument.java:80)
at javax.swing.text.DefaultEditorKit.createDefaultDocument(DefaultEditorKit.java:130)
at javax.swing.plaf.basic.BasicTextUI.installUI(BasicTextUI.java:799)
at javax.swing.JComponent.setUI(JComponent.java:655)
at javax.swing.text.JTextComponent.setUI(JTextComponent.java:338)
at javax.swing.text.JTextComponent.updateUI(JTextComponent.java:348)
at javax.swing.text.JTextComponent.<init>(JTextComponent.java:322)
at javax.swing.JTextField.<init>(JTextField.java:231)
at javax.swing.JTextField.<init>(JTextField.java:172)
at application.Analyzer.addTab(Analyzer.java:133)
at application.Analyzer.access$100(Analyzer.java:24)
at application.Analyzer$1.stateChanged(Analyzer.java:101)
at javax.swing.JTabbedPane.fireStateChanged(JTabbedPane.java:416)
at javax.swing.JTabbedPane$ModelListener.stateChanged(JTabbedPane.java:270)
at javax.swing.DefaultSingleSelectionModel.fireStateChanged(DefaultSingleSelectionModel.java:132)
at javax.swing.DefaultSingleSelectionModel.setSelectedIndex(DefaultSingleSelectionModel.java:67)
at javax.swing.JTabbedPane.setSelectedIndexImpl(JTabbedPane.java:616)
at javax.swing.JTabbedPane.insertTab(JTabbedPane.java:735)
at application.Analyzer.addTab(Analyzer.java:133)
at application.Analyzer.access$100(Analyzer.java:24)
.
.
.

何か提案はありますか?漠然としていることはわかっていますが、何が間違っているのか本当にわかりません。

助言がありますか?ありがとう。タイラー

4

3 に答える 3

1

StackOverflow は無限再帰を識別します。したがって、最初のことは、その再帰を見つけることです。あなたの場合、これらはその再帰を識別するスタックトレースの行です:

application.Analyzer.addTab(Analyzer.java:133) で application.Analyzer.access$100(Analyzer.java:24) で application.Analyzer$1.stateChanged(Analyzer.java:101) で javax.swing.JTabbedPane.fireStateChanged( JTabbedPane.java:416) で javax.swing.JTabbedPane$ModelListener.stateChanged(JTabbedPane.java:270) で javax.swing.DefaultSingleSelectionModel.fireStateChanged(DefaultSingleSelectionModel.java:132) で javax.swing.DefaultSingleSelectionModel.setSelectedIndex(DefaultSingleSelectionModel.java) :67) javax.swing.JTabbedPane.setSelectedIndexImpl(JTabbedPane.java:616) で javax.swing.JTabbedPane.insertTab(JTabbedPane.java:735) で application.Analyzer.addTab(Analyzer.java:133) で

したがって、タブを挿入すると、選択したタブの変更が自動的にトリガーされ、タブの挿入などをトリガーする ChangeEventListener が呼び出されます...

したがって、2 つの簡単な解決策があります。

  1. 新しいタブを追加する前に設定され、完了したら元に戻すフラグ (a boolean) を使用します。タブを追加する必要があるかどうかをテストする条件では、このフラグが ではないことも確認します。truefalsetrue
  2. タブを挿入する前に JTabbedPane から変更リスナーを削除し、後で元に戻します。

どちらの場合も、try/finally ブロックを使用して、一貫した状態に確実に戻るようにします。

于 2012-06-21T06:14:31.320 に答える
0

問題は、+タブを選択したタブとしてもう一度追加した後にchangeListenerが呼び出され、新しいタブが作成されることなどです。

非常に簡単な解決策は、Guillaume Poletが述べたように、ブールフラグを追加することです。

    songPanel.addChangeListener(new ChangeListener(){

        @Override //Method called when selected tab changes
        public void stateChanged(ChangeEvent e){
            try {   
                if(songPanel.getSelectedIndex()==songPanel.getTabCount()-1 && !adding){
                    adding = true;
                    addTab("songPanel");
                    adding = false;
                }
            } catch (StackOverflowError soe){soe.printStackTrace();}
        }
    });

追加フラグはfalseに初期化されたクラスフィールドであり、タブの追加が進行中であるかどうかを示します。すべてを機能させるためのaddTabへのマイナーな変更:

private void addTab(String panelName){
    System.out.println("ADDING TAB");
    if(panelName.equals("songPanel")){
        String tabName = ("#" + Integer.toString(songPanel.getTabCount()));
        int index = songPanel.getTabCount()-1;
        songPanel.insertTab(tabName, null, new JTextField(), tabName, index);
        songPanel.setSelectedIndex(index);
    }
}

コードに少し変更を加え、アクティブなタブを新しく作成したタブにし、インデックスを少しずらしました。

お役に立てれば :)

于 2012-06-21T08:51:02.500 に答える
0

更新 された解決策 申し訳ありませんが、以前の解決策は期待どおりに機能していません。ここで私の更新されたもの:

public class TabbedPaneTest {

    private final static JButton ADD_NEW_TAB_BUTTON = new JButton();
    private JFrame mainFrame;
    private JTabbedPane tabbedPane;

    public void run() {
        mainFrame = new JFrame("Test JTabbedPane");
        mainFrame.setSize(300, 400);
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        tabbedPane = new JTabbedPane();
        tabbedPane.addTab("default new tab", new JLabel("this is a default tab"));

        addNewTabButton();
        tabbedPane.addChangeListener(new ChangeListener() {

            @Override
            public void stateChanged(ChangeEvent e) {
                if (tabbedPane.getSelectedComponent() == ADD_NEW_TAB_BUTTON) {
                    tabbedPane.addTab("new tab", new JLabel("new tab label"));
                    addNewTabButton();
                }
            }
        });


        mainFrame.getContentPane().add(tabbedPane);
        mainFrame.setVisible(true);
    }

    private void addNewTabButton() {
        tabbedPane.remove(ADD_NEW_TAB_BUTTON);
        tabbedPane.addTab("[+]", ADD_NEW_TAB_BUTTON);
    }

    public static void main(String[] params) {
        TabbedPaneTest test = new TabbedPaneTest();
        test.run();
    }

}
于 2012-06-21T02:06:46.993 に答える