Java 如何从另一个类/包中的按钮切换选项卡?

Java 如何从另一个类/包中的按钮切换选项卡?,java,swing,oop,Java,Swing,Oop,我想问一下,是否有一种可能的方法可以通过单击另一个类中的按钮来切换选项卡面板。我有两个类,classA在默认包中,另一个在另一个包中。我的按钮位于classB中,我的选项卡式窗格位于classA中 如何通过单击我的classB中的按钮来更改选项卡 如果在默认包和另一个包之间传递变量不起作用,那么我将把classB放在同一个包中,这样就更容易从classA访问变量 **编辑** 好的,我对我的代码做了一个简短的版本,结果如下: Test.java package test; import

我想问一下,是否有一种可能的方法可以通过单击另一个类中的按钮来切换选项卡面板。我有两个类,
classA
在默认包中,另一个在另一个包中。我的按钮位于
classB
中,我的选项卡式窗格位于
classA

如何通过单击我的
classB
中的按钮来更改选项卡

如果在默认包和另一个包之间传递变量不起作用,那么我将把
classB
放在同一个包中,这样就更容易从
classA
访问变量

**编辑**

好的,我对我的代码做了一个简短的版本,结果如下:

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();         
     }
 });

 }
}
 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);
 }
}
button.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();         
     }
 });

 }
}
 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);
 }
}

我知道我丢失了每个选项卡的set selected index,但我不知道如何复制它,因为在我的项目中,这些选项卡位于单独的java文件中。为了缩短它,我在一个java文件中创建了它。所以是的。正如你所见,我有更多的按钮,然后切换按钮的标签2。我的问题是,如何通过单击弹出窗口中的按钮切换到面板2?

您需要做的是将对象的引用从原始类(此处为Test)传递到需要更改测试对象状态的类中,我所说的状态是指显示的JTabbedPane,但具体状态并不重要。同样重要的是引用传递,并提供第二个类可以调用的测试公共方法来更改状态。例如:

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);
   }
}

这里的关键是我给了第二个类一个测试字段,然后更改了第二个类构造函数,以允许将测试类对象传递给它:

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
我已经给出了可以调用的测试公共方法:

// !! 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;
}
在创建第二个类时,我将当前的Test实例
Test传递到第二个类的构造函数中

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

        new HisTestButton(Test.this); //!! passing in this
     }
现在,第二个类可以调用测试对象方法:

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

请注意,您可以以非常相同的方式使用CardLayout,再次逐个调用一个类的公共方法,只要第二个类对第一个类的当前显示实例具有可行的引用。像往常一样掌握正确的引用是关键



还要注意的是,默认包中的所有类都应该放在包中,既可以是现有包,也可以是新包,以更有意义的包为准,也可以是相似与相似的组合。唯一属于默认包的类是不需要与其他类交互的玩具类。

在当前JVM中,可以通过使用CardLayout或编程方式“是”。没关系,我只将classB放在同一个包中“ClassA不应该在默认包中,因此,将其移动到
ClassB的包中(或另一个包)。他们是否可以互相访问则取决于a)如果他们持有对其他类的引用b)其他类声明的任何方法或属性的访问修饰符。
“我认为cardlayout不会在不同类的面板上工作。”
--抱歉,但这只是一个疯狂的说法。如果你这样陈述,这意味着你在学习java基础知识之前,试图创建Swing GUI,因为任何有基础知识的好基础的人都知道这不是真的。请帮自己一个忙,读一本关于Java和OOP的好书,因为它将在编码的各个方面对您有巨大的帮助,就像它帮助了我一样。然后您就会明白CardLayout是一个合适的、可能是最好的解决方案。您最好尝试使用它,如果它不起作用,请尝试调试您的尝试。@AndrewThompson“提示:分别发表两条评论。”“是的,我这样做了。”。非常感谢。我会阅读你提供的链接。嗨@满是鳗鱼的气垫船!我很高兴你能抽出时间帮我解决问题。这也可以在不同的包中完成吗?