Question

I've looked around a while and also played around trying to add multiple panels to a JTabbedPane.

My question is: Is it possible to add the same Jpanel to multiple TabbedPanes. Everything way that I tried, it doesn't seem to work correctly. This is how it it works.

public MainGUI() {

  JMenuBar menuBar = new JMenuBar();
  setJMenuBar(menuBar);

  JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
  getContentPane().add(tabbedPane, BorderLayout.CENTER);

  JEditorPane instructionalEditorPane = new JEditorPane();
  tabbedPane.addTab("Instructional", instructionalEditorPane);

  JPanel codePanel = new JPanel();
  JPanel drawPanel = new JPanel();

  JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, codePanel, drawPanel);
  splitPane.setResizeWeight(0.75);

  tabbedPane.addTab("Code Panel", splitPane);

  JEditorPane unifiedInstPane = new JEditorPane();
  JPanel unifiedCodePanel = new JPanel();
  JPanel unifiedDrawPanel = new JPanel();
  JSplitPane unifiedSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, unifiedCodePanel, unifiedDrawPanel);
  unifiedSplitPane.setResizeWeight(0.75);

  JSplitPane unifiedPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT,unifiedInstPane, unifiedSplitPane);
  unifiedPanel.setResizeWeight(0.40);
  tabbedPane.addTab("Unified Tab", unifiedPanel);
}

What I would like to do is just add the instructionalEditorPane and the splitPane to multiple tabbedPanes but when I do I loose the original Individual tabbedPanes. If I have to I can do it this way but I would then have to write to both the unifiedInstPane & the instructionalEditorPane to keep them updated. I would also have to do this for the 2 splitPanes which have the codePanel and drawPanels embedded. This will make it harder to keep all the panels in sync.

Any suggestions?

Was it helpful?

Solution

"Is it possible to add the same Jpanel to multiple TabbedPanes." -- no. You can only add a component to one container at a time. Your JPanels should share models but use unique components. The model will likely be a non-GUI class of your creation.

For example, here's a very simplistic rendering of my recommendations:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;

import javax.swing.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

public class MainGui2 extends JPanel {
   private static final int TAB_COUNT = 3;
   private JTabbedPane tabbedPane = new JTabbedPane();
   private PlainDocument doc = new PlainDocument();
   private Action btnAction = new ButtonAction("Button");

   public MainGui2() {
      for (int i = 0; i < TAB_COUNT; i++) {
         tabbedPane.add("Tab " + (i + 1), createPanel(doc, btnAction));
      }
      setLayout(new BorderLayout());
      add(tabbedPane);
   }

   private JPanel createPanel(PlainDocument doc, Action action) {
      JTextArea textArea = new JTextArea(doc);
      textArea.setColumns(40);
      textArea.setRows(20);          

      JPanel panel = new JPanel();
      panel.add(new JScrollPane(textArea));
      panel.add(new JButton(action));
      return panel;
   }

   private class ButtonAction extends AbstractAction {
      public ButtonAction(String title) {
         super(title);
      }

      @Override
      public void actionPerformed(ActionEvent evt) {
         try {
            String text = "Button Pressed!\n";
            doc.insertString(doc.getLength(), text, null);
         } catch (BadLocationException e) {
            e.printStackTrace();
         }
      }
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("MainGui2");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new MainGui2());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

Better would be to create a formal model class that gets injected into each view, each tabbed pane's individual panes.


Edit
You state in comment:

Yes I can fix that by making calls to the instances but then I'm back to my original problem of having to make calls to each instance to affect a change in all the panel. Say for example I have a drawing panel and I need to call repaint(), I would have to make a call to 2 different instances to get both tabbedPanes to update. Is there any way around this?

Yes, the solution is to use an MVC, or model-view-control, structure. Your model holds your overall program logic, the views are what the user sees, and the control interacts between the two.

Consider having your model notify either the control or the views that its been changed, and then this stimulates a repaint an all observer views.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top