1

I want to ask if there is a possible way to switch the tab panels from a click of a button in another class. I have 2 class and classA is in default package and the other one is in another package. My button is placed in classB and my tabbed panes are in classA.

How can I change tabs by clicking the button in my classB?

If passing variables are not going to work between the default package and another package its okay I'll just put classB in the same package so it'll be easier to access variables from classA.

** EDIT **

Okay I made a short ver of my code and this is the result:

Test.java

  package test;

  import java.awt.*;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import javax.swing.*;
  import btn.button;

public class Test {

JFrame frame = new JFrame();
JTabbedPane tabpane = new JTabbedPane();
JPanel panel1 = new JPanel();
GridBagConstraints c = new GridBagConstraints();
final static boolean shouldFill = true;
GridBagLayout grid = new GridBagLayout();

public Test() {
    // TODO code application logic here

   // public button switch;

    frame.setVisible(true);
    frame.setSize(821,421);


    final Toolkit toolkit = Toolkit.getDefaultToolkit();
    Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();      
int x=(int)((dimension.getWidth() - frame.getWidth())/2);
int y=(int)((dimension.getHeight() - frame.getHeight())/2);

    frame.setLocation(x, y);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

     JPanel container = new JPanel();
     container.setLayout(new BorderLayout());
     container.setBackground(new Color(0,128,0));

tabpane = new JTabbedPane(); //Tab Pane
tabpane.setBackground(new Color(0,128,0));
tabpane.setSize(801,351);       


JPanel jp1 = new JPanel(); // First Tab Panel
jp1.setBackground(new Color(0,128,0));
jp1.setLayout(grid);

    JButton popout = new JButton("MORE");
    popout.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
        button button = new button();     
        }
    });
    jp1.add(popout);

JPanel jp2 = new JPanel(); // Second Tab Panel
jp2.setBackground(new Color(0,128,0));
jp2.setLayout(grid);

    JPanel jp3 = new JPanel(); // Third Tab Panel
jp3.setBackground(new Color(0,128,0));
jp3.setLayout(grid);

    tabpane.addTab("Tab 1", jp1);
    //add selectedIndex here (1);
    tabpane.addTab("Tab 2", jp2);
    //add selectedIndex here (2);
    tabpane.addTab("Tab 3", jp3);
    //add selectedIndex here (3);

    frame.add(container);
    container.add(tabpane, BorderLayout.NORTH);

}

 public static void main(String[] args){
     //Use the event dispatch thread for Swing components
 EventQueue.invokeLater(new Runnable()
 {
    @Override
     public void run()
     {
         new Test();         
     }
 });

 }
}

button.java

 package btn;

import java.awt.Color;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class button {
 JFrame frame2 = new JFrame();
 GridBagLayout grid = new GridBagLayout();      

 public button(){

         frame2.setVisible(true);
         frame2.setSize(200,200);

         JPanel jp = new JPanel(); // First Tab Panel
         jp.setBackground(new Color(0,128,0));
         jp.setLayout(grid);

         JButton btn = new JButton("SWITCH TO PANEL 2");
         btn.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
        //what should i put here???
        }
    });

         jp.add(btn);

         frame2.add(jp);
 }
}

I know I'm missing the set selected index for each tab but I don't know how to replicate that because in my project those tabs are in a separate java file. So to shorten it I made it in one java file. So yeah. As you can see I have the more button and then the switch button for tab 2. My question is how can I switch to panel 2 by clicking the button in the pop out?

user3771102
  • 558
  • 2
  • 8
  • 27
  • 4
    yes is possible in current JVM, by using CardLayout or programatically – mKorbel Jun 30 '14 at 11:13
  • 3
    *"..its okay i'll just put classB in the same package"* Class A should ***not*** be in the default package, so instead move **it** into the package of `ClassB` (or another package). Whether they can access one another then becomes dependent on a) if they hold a reference to the other class b) the access modifiers of any methods or attributes the other class declares. – Andrew Thompson Jun 30 '14 at 11:21
  • mKorbel: hi. i'm not using a cardlayout and its in different classes. i dont think cardlayout will work on panels on different classes. i have tried that but failed to do so. @AndrewThompson hi andrew. thanks for helping me again. _Class A should not be in the default package_ Well the thing is all of the classes are in default package and well i could try to put it in another package but I don't know if everything will be the same after I did that. Anyway, do you know how to switch tabs when the button is in another class? – user3771102 Jun 30 '14 at 11:47
  • 3
    `"i dont think cardlayout will work on panels on different classes."` -- Sorry, but this is just crazy talk. If you make statements like this, it means that you're trying to create Swing GUI's before learning the basics of Java, since anyone with a good foundation in the basics would know that this is simply not true. Please do yourself a favor and read a good book on Java and OOP as it will help you immensely in all aspects of your coding, just as it's helped me. – Hovercraft Full Of Eels Jun 30 '14 at 11:49
  • @AndrewThompson Yes I know only one person can be tagged and I'm sorry I really didn't know Java that well. – user3771102 Jun 30 '14 at 11:56
  • I think what you might most benefit from at this point is to go through the [Classes and Objects Lesson](http://docs.oracle.com/javase/tutorial/java/javaOO/index.html) of the tutorial. – Andrew Thompson Jun 30 '14 at 12:01
  • @HovercraftFullOfEels I know the basics of java but not everything. Only what they taught at school and not the manual coding of the GUI. That's why I'm having trouble of understanding things. I get it that cardlayout can work in panels even with different classes. Well what I tried was cardlayout in default package and the cards is in other packages. That's why it wasn't working since i cannot import default packages. That's what I meant when I said that. – user3771102 Jun 30 '14 at 12:01
  • 1
    Then you understand that CardLayout is an appropriate and likely best solution. Your best bet is to try to use it, and if it doesn't work, try to debug your attempt. – Hovercraft Full Of Eels Jun 30 '14 at 12:05
  • 1
    @AndrewThompson _"Tip: Make 2 separate comments. ;) "_ yes i did that. Thank you! I'll read the link you've provided. – user3771102 Jun 30 '14 at 12:05
  • @HovercraftFullOfEels _"CardLayout is an appropriate and likely best solution" _Ah about that. I have tabbed panels and I cannot change that to CardLayout. I also know that its much more easy use but tabbed panels are the required panels that i **must** use even if I want to change that to CardLayout I can't. _"if it doesn't work, try to debug your attempt"_ I already tried having CardLayout in one part of the project but I cannot debug it cause my main class is in default package and i cannot move that cause most of my packages is in default package. I cannot import default packages. – user3771102 Jun 30 '14 at 12:13
  • 1
    As an aside. I have not (yet) voted to close this question, but cannot understand the down votes. +1 for some balance. +1 also to @mKorbel for the suggestion of an [MCVE](http://stackoverflow.com/help/mcve) (Minimal Complete and Verifiable Example) or [SSCCE](http://sscce.org/) (Short, Self Contained, Complete Example). – Andrew Thompson Jun 30 '14 at 13:59
  • If this is homework, what is the homework actually about? Using objects? Using packages? Creating a particular app.? The reason I ask is that if it is not about the first two, that entire GUI could be made by a single class (solving most, if not all, of the problems that have been outlined). See also [The Use of Multiple JFrames, Good/Bad Practice?](http://stackoverflow.com/a/9554657/418556) That second frame that is produced by the button should be a `JDialog` or a `JOptionPane`. – Andrew Thompson Jul 01 '14 at 04:18
  • @AndrewThompson not really homework. It's work. Well I used jframe for the button because there are still things that is in there and i just didn't want to put since i just want to replicate my problem and the code will be long if I also put it in there. `that entire GUI could be made by a single class (solving most, if not all, of the problems that have been outlined)` yes i know that but its more organized that way because you don't have to scroll for so long. The code is really long. It has also database part. So yeah. – user3771102 Jul 01 '14 at 04:25
  • *"yes i know that but its more organized that way because you don't have to scroll for so long."* An IDE can jump to any method in a class. It is the methods that need to be kept short *"The code is really long. It has also database part."* It is that 'database part' that needs (from a design POV) to be in another class. – Andrew Thompson Jul 01 '14 at 05:18
  • @AndrewThompson yeahhh. you're right. Well I can't really complain to the one who did all of the code. It was just given to me to finish. Thank you for the time you've given for my question. I guess there's no solution to my question. – user3771102 Jul 01 '14 at 05:31
  • 1
    @user3771102 [see one lesson for me by one of gurus here(HFOE)](http://stackoverflow.com/a/7054114/714968), this is answer to your question, quite complex code, nice 1Mio_dollars_baby for rockets start, story ended, if not then post a new question +1 .... – mKorbel Jul 01 '14 at 06:50
  • @mKorbel hi! The link you have posted is a bit of a complex code and I have understand what it does. I don't think its still applicable if one of the north or southpanel are in different packages like one is in default and the other one is not. Since you can't import default package in a class with different package. Am I wrong? – user3771102 Jul 01 '14 at 08:53

1 Answers1

1

What you need to do is pass a reference of the object from the original class (here Test) into the class that needs to change the Test object's state, and by state I mean which JTabbedPane is showing, but the specific state doesn't matter. Again what matters is reference passing, and giving Test public methods that the second class can call to change the state. For example:

import java.awt.*;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

//!! import btn.button;

public class Test {

   private JFrame frame = new JFrame();
   private JTabbedPane tabpane = new JTabbedPane();
   private JPanel panel1 = new JPanel();
   private GridBagConstraints c = new GridBagConstraints();
   private final static boolean SHOULD_FILL = true;
   private GridBagLayout grid = new GridBagLayout();

   public Test() {

      frame.setVisible(true);
      frame.setSize(821, 421);

      final Toolkit toolkit = Toolkit.getDefaultToolkit();
      Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
      int x = (int) ((dimension.getWidth() - frame.getWidth()) / 2);
      int y = (int) ((dimension.getHeight() - frame.getHeight()) / 2);

      frame.setLocation(x, y);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      JPanel container = new JPanel();
      container.setLayout(new BorderLayout());
      container.setBackground(new Color(0, 128, 0));

      tabpane = new JTabbedPane(); // Tab Pane
      tabpane.setBackground(new Color(0, 128, 0));
      tabpane.setSize(801, 351);

      JPanel jp1 = new JPanel(); // First Tab Panel
      jp1.setBackground(new Color(0, 128, 0));
      jp1.setLayout(grid);

      JButton popout = new JButton("MORE");
      popout.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            //!! HisTestButton button = new HisTestButton();

            new HisTestButton(Test.this); //!! passing in this
         }
      });
      jp1.add(popout);

      JPanel jp2 = new JPanel(); // Second Tab Panel
      jp2.setBackground(new Color(0, 128, 0));
      jp2.setLayout(grid);

      JPanel jp3 = new JPanel(); // Third Tab Panel
      jp3.setBackground(new Color(0, 128, 0));
      jp3.setLayout(grid);

      tabpane.addTab("Tab 1", jp1);
      // add selectedIndex here (1);
      tabpane.addTab("Tab 2", jp2);
      // add selectedIndex here (2);
      tabpane.addTab("Tab 3", jp3);
      // add selectedIndex here (3);

      frame.add(container);
      container.add(tabpane, BorderLayout.NORTH);

   }

   // !! public method that other classes can call to change tab
   public void openNextTab() {
      int selectedIndex = tabpane.getSelectedIndex();
      selectedIndex++;
      selectedIndex %= tabpane.getTabCount();
      tabpane.setSelectedIndex(selectedIndex);
   }

   //!! needed by JDialog
   public JFrame getFrame() {
      return frame;
   }

   public static void main(String[] args) {
      // Use the event dispatch thread for Swing components
      EventQueue.invokeLater(new Runnable() {
         @Override
         public void run() {
            new Test();
         }
      });

   }
}

class HisTestButton {
   protected static final int PREF_W = 200;
   protected static final int PREF_H = 200;
   JDialog dialog; // !! make this a JDialog
   GridBagLayout grid = new GridBagLayout();
   private Test test;  //!! add field

   //!! changed constructor parameter
   public HisTestButton(final Test test) {
      this.test = test; // !! set field

      // !! create our JDialog. Going to make it non-modal 
      dialog = new JDialog(test.getFrame(), "MyDialog", ModalityType.MODELESS);

      //!! frame2.setVisible(true);
      // !! frame2.setSize(200, 200); // never set visible til after components added

      JPanel jp = new JPanel() {
         @Override
         public Dimension getPreferredSize() {
            return new Dimension(PREF_W, PREF_H);
         }
      };
      jp.setBackground(new Color(0, 128, 0));
      jp.setLayout(grid);

      JButton btn = new JButton("SWITCH TO PANEL 2");
      btn.addActionListener(new ActionListener() {

         @Override
         public void actionPerformed(ActionEvent e) {
            //!! 
            test.openNextTab();
         }
      });

      jp.add(btn);

      dialog.add(jp);

      // !! added
      dialog.pack();
      dialog.setVisible(true);
   }
}

Key here is that I gave the second class a Test field and then changed the 2nd classes constructor to allow the Test class object to be passed into it:

class HisTestButton {
   protected static final int PREF_W = 200;
   protected static final int PREF_H = 200;
   JDialog dialog; // !! make this a JDialog
   GridBagLayout grid = new GridBagLayout();
   private Test test;  //!! add field   ****************

   //!! changed constructor parameter
   public HisTestButton(final Test test) { // *****
      this.test = test; // !! set field

I've given Test public methods that can be called:

// !! public method that other classes can call to change tab
public void openNextTab() {
  int selectedIndex = tabpane.getSelectedIndex();
  selectedIndex++;
  selectedIndex %= tabpane.getTabCount();
  tabpane.setSelectedIndex(selectedIndex);
}

//!! needed by JDialog constructor
public JFrame getFrame() {
  return frame;
}

And when creating the second class, I pass the current instance of Test, Test.this because it's in an inner class, into the second class's constructor:

     public void actionPerformed(ActionEvent e) {
        //!! HisTestButton button = new HisTestButton();

        new HisTestButton(Test.this); //!! passing in this
     }

Now the second class can call Test object methods:

     @Override
     public void actionPerformed(ActionEvent e) {
        //!! 
        test.openNextTab();
     }

Note that you can use a CardLayout in the very same way, again calling public methods of one class by another, as long as the 2nd class has a viable reference to the current displayed instance of the first class. Getting a handle on proper references as always is key.


Also note that all of your classes in the default package should be placed within packages, either existing packages or new packages, whichever makes more sense, and whichever combines like with like. The only classes that belong in the default package are toy classes that don't require interaction with other classes.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Hi @Hovercraft Full Of Eels! I'm so happy that you've taken time to help me with my problem. Can this be also done in different packages? – user3771102 Jul 02 '14 at 07:03