JTabbedPane не переключает содержимое вкладки

У меня проблема с JTabbedPane, поскольку содержимое отдельных вкладок не отображается (каждый раз, когда я нажимаю новую вкладку, активная вкладка меняется, но содержимое не изменяется, поэтому я вижу одно и то же содержимое независимо от того, какая вкладка выбирается.).

Я пытаюсь написать IDE для своего собственного языка программирования, но никогда раньше не работал с JTabbedPane. Моя панель с вкладками состоит из JEditTextArea (написанный пользователем компонент), размещенного в JScrollPanes. Вот ответственный класс

package tide.editor;

import javax.swing.*;

import javax.swing.filechooser.FileNameExtensionFilter;

import java.awt.Toolkit;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;

import org.syntax.jedit.*;
import org.syntax.jedit.tokenmarker.*;

@SuppressWarnings("serial")
public class Editor extends JFrame implements ActionListener {

//Version ID
final static String VERSION = "0.01a";

//The editor pane houses the JTabbedPane that allows for code editing
//JPanel editorPane;

JTabbedPane tabbedPanel;

//The JTextPanes hold the source for currently open programs
ArrayList<JEditTextArea> textPanes;

//The toolbar that allows for quick opening, saving, compiling etc
JToolBar toolBar;

//Buttons for the toolbar
JButton newButton, openButton, saveButton, compileButton, runButton;


public Editor()
{
    super("tIDE v" + VERSION);
    setSize(Toolkit.getDefaultToolkit().getScreenSize());
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLayout(new BorderLayout());
    init();
    setVisible(true);
    textPanes.get(0).requestFocus();
}

public void init()
{
    //Initialise toolbar
    toolBar = new JToolBar();
    toolBar.setFloatable(false);

    newButton = new JButton("New");
    newButton.addActionListener(this);
    openButton = new JButton("Open");
    openButton.addActionListener(this);
    saveButton = new JButton("Save");
    saveButton.addActionListener(this);
    compileButton = new JButton("Compile");
    compileButton.addActionListener(this);
    runButton = new JButton("Run");
    runButton.addActionListener(this);

    toolBar.add(newButton);
    toolBar.add(openButton);
    toolBar.add(saveButton);
    toolBar.add(compileButton);
    toolBar.add(runButton);


    tabbedPanel = new JTabbedPane();

    textPanes = new ArrayList<JEditTextArea>();

    JEditTextArea initialProgram = createTextArea("program.t");

        tabbedPanel.addTab(initialProgram.getName(), new JScrollPane(initialProgram));


    getContentPane().add(tabbedPanel, BorderLayout.CENTER);
    add(toolBar, BorderLayout.NORTH);
}

public static void main(String[] args)
{
java.awt.EventQueue.invokeLater(new Runnable() {

    @Override
    public void run() {
        new Editor();
    }
});

}

JEditTextArea createTextArea(String name)
{
    JEditTextArea editPane = new JEditTextArea(name);
    editPane.setTokenMarker(new TTokenMarker());

    textPanes.add(editPane);

    return editPane;
}

public void actionPerformed(ActionEvent e) {

    if (e.getSource() == newButton)
    {
        String filename = "program2";
        boolean fileExists = true;

        //Ensures that no duplicate files are created
        while (fileExists)
        {
        fileExists = false;
        //Get new file name from user
        filename = JOptionPane.showInputDialog(null, "Enter a name for the file", "program.t");

        //Cancel was clicked in the new file dialog
        if (filename == null)
            return;

            for (JEditTextArea panes: textPanes)
            {
                if (panes.getName().equals(filename) || panes.getName().equals(filename.concat(".t")) || panes.getName().concat(".t").equals(filename))
                    fileExists = true;
            }
        }

        //add extension if it is missing
        if(!filename.endsWith(".t"))
            filename = filename.concat(".t");

        //Add the new "file" to the editor window in a new tab
        tabbedPanel.addTab(filename, new JScrollPane(createTextArea(filename)));
        tabbedPanel.setSelectedIndex(tabbedPanel.getSelectedIndex()+1);
    }

    if (e.getSource() == openButton)
    {
        File f = null;


        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("Choose target file location");
        fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        fileChooser.setAcceptAllFileFilterUsed(false);
        FileNameExtensionFilter filter = new FileNameExtensionFilter(
                "t source or bytecode(.t, .tbc)", "t", "tbc");

        fileChooser.setFileFilter(filter);

        if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION)
        {
            f = fileChooser.getSelectedFile();
        }

        //Cancel button was clicked on the open file dialog
        if (f == null)
            return;

        //Load the contents of the selected file into the editor
        else
        {
            JEditTextArea textArea = null;
            StringBuilder inputText = null;

            try {
                Scanner sc = new Scanner(f);

                //Add a new text area to the editor
                textArea = createTextArea(f.getName());
                tabbedPanel.add(new JScrollPane(textArea), textArea.getName());

                //The newly added tab is set as the active tab
                tabbedPanel.setSelectedIndex(tabbedPanel.getTabCount()-1);
                textArea.requestFocus();

                inputText = new StringBuilder();
                while (sc.hasNext())
                {
                    inputText.append(sc.nextLine() + "\n");
                }

            } catch (FileNotFoundException e1) {
                e1.printStackTrace();
            }

            //Set the contents of the current text area to that of the opened file
            textArea.setText(inputText.toString());
        }
    }

}

}

person Peter Pretorius    schedule 04.04.2012    source источник


Ответы (3)


1) удалить строки кода из FileIO связанного try - catch блока

textArea = createTextArea(f.getName());
tabbedPanel.add(new JScrollPane(textArea), textArea.getName());
//The newly added tab is set as the active tab
tabbedPanel.setSelectedIndex(tabbedPanel.getTabCount()-1);
textArea.requestFocus();

подготовить эти Object до или после Input / OutputStreams

2) close() все Objects из Input / OutputStreams, в finally блоке (try - catch - finally)

3) JTextComponets реализует read() и write(), принимая все разделители, тогда нет причин программно вызывать "\n"

4) используйте код SwingWorker для FileIO

person mKorbel    schedule 04.04.2012
comment
Я пробовал большую часть того, что вы здесь предложили (я не знаю, как использовать SwingWorker), но все равно не повезло. - person Peter Pretorius; 04.04.2012
comment
@Peter: Пожалуйста, прочитайте SwingWorker в учебниках. Я боюсь, что ваша проблема может быть проблемой параллелизма. - person Hovercraft Full Of Eels; 05.04.2012

Это может не быть решением основной причины, но в вашем коде может быть некоторое несоответствие, которое вызывает проблемы с отрисовкой в ​​TestAreas, поэтому я предлагаю вам зарегистрировать TabChageListener, а затем перерисовать ScrollPane для этой конкретной вкладки, это должно работать :

tabbedPanel.addChangeListener(new ChangeListener() {
    public void stateChanged(ChangeEvent e) {
     int selectedIndex =   tabbedPane.getSelectedIndex();
  // get the ScrollPane for this selectedIndex and then repaint it.

    }
});
person NiranjanBhat    schedule 04.04.2012
comment
Я пробовал это, но, к сожалению, это не сработало. Та же проблема все еще сохраняется. - person Peter Pretorius; 04.04.2012

Я боролся с этой самой проблемой в течение последних нескольких часов.

Фактически, не имеет значения, сколько JEditTextArea вы создаете, все они полагаются на один и тот же SyntaxDocument, а значит, на один и тот же текст. Именно так это закодировано в JEditTextArea.

В конструкторе public JEditTextArea(TextAreaDefaults defaults) вам нужно будет найти строку:

setDocument(defaults.document);

и замените его на:

setDocument(новый СинтаксическийДокумент());

и он будет создавать новый Document каждый раз, когда вы создаете новый JEditTextArea.

person Dotoma    schedule 21.02.2013