如何从另一个类更改JPanel?

时间:2017-10-01 09:24:55

标签: java eclipse jframe jpanel actionlistener

您好,我是Java新手,我遇到以下问题:

我创建了一个JFrame,我希望在单击JButton时更改JPanel。这几乎可以工作。唯一的问题是程序创建一个新窗口,然后有两个窗口。一个是第一个JPanel,一个是第二个JPanel。 这是我目前的代码:

第一堂课:

public class Program {

    public static void main (String [] args) {

        new window(new panel1());

    }
}

第二课:

import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Window extends JFrame {

    private static final long serialVersionUID = 1L;

    Window(JPanel panel) {

        setLocation((int) Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2 - 200,
                    (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2 - 100);
        setSize(400, 200);
        setTitle("test");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        setContentPane(panel);
        setVisible(true);

    }
}

第三课:

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

public class Panel1 extends JPanel {

    private final long serialVersionUID = 1L;

    Panel1() {

        JButton nextPanelButton = new JButton("click here");

        add(nextPanelButton);

        ActionListener changePanel = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                new window(new panel2());
            }
        };
        nextPanelButton.addActionListener(changePanel);

    }
}

第四课:

public class Panel2 extends JPanel {

    private static final long serialVersionUID = 1L;

    Panel2() {

        JLabel text = new JLabel("You pressed the Button!");

        add(text);

    }
}

但我只是想在不打开新窗口的情况下更改JPanel。有没有办法做到这一点?

提前致谢!

3 个答案:

答案 0 :(得分:0)

首先,请查看Java naming conventions,特别是您的班级名称应以大写字母开头。

如果要在每次单击按钮时避免打开新窗口,可以将框架对象传递给Panel1构造函数,并在单击按钮时将新的Panel2实例设置为框架内容窗格。也没有必要将Panel1传递给Window构造函数(请注意Window类已在java.awt包中定义,最好避免可能的名称冲突重命名您的类ApplicationWindow,MyWindow或其他东西)

您可以像这样更改您的代码(仅限相关部分):

public class Program
{
    public static void main (String [] args) {
        SwingUtilities.invokeLater (new Runnable () {
            @Override public void run () {
                new Window ().setVisible (true);
            }
        };
    }
}
class Window extends JFrame
{
    // ...

    Window () {
        // ...
        setContentPane(new Panel1 (this));
    }
}
class Panel1 extends JPanel
{
    // ...

    Panel1 (JFrame parent) {
        // ...
        ActionListener changePanel = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                parent.setContentPane (new Panel2 ());
            }
        };
        // ...
}

另请注意SwingUtilities的invokeLater调用,这是在EDT上下文中初始化GUI的最佳方式(有关this question的更多信息,请参阅)。

最后,您可以避免每次单击按钮时创建一个新的Panel2实例,只需使用CardLayout即可。 看看official tutorial

答案 1 :(得分:0)

这是一个演示

import javax.swing.*;

public class Main {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            new MainFrame("Title").setVisible(true);
        });
    }
}

<强> MainFrame.java

import javax.swing.*;
import java.awt.*;

public class MainFrame extends JFrame {
    private JPanel viewPanel;

    public MainFrame(String title) {
        super(title);
        createGUI();
    }

    private void createGUI() {
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setLayout(new BorderLayout());
        setMinimumSize(new Dimension(600, 480));

        viewPanel = new JPanel(new BorderLayout());
        add(viewPanel, BorderLayout.CENTER);

        showView(new View1(this));
        pack();
   }

   public void showView(JPanel panel) {
        viewPanel.removeAll();
        viewPanel.add(panel, BorderLayout.CENTER);
        viewPanel.revalidate();
        viewPanel.repaint();
   }
}

View1.java

import javax.swing.*;
import java.awt.*;

public class View1 extends JPanel {
    final private MainFrame owner;

    public View1(MainFrame owner) {
        super();

        this.owner = owner;
        createGUI();
    }

    private void createGUI() {
        setLayout(new FlowLayout());
        add(new JLabel("View 1"));

        JButton button = new JButton("Show View 2");
        button.addActionListener(event -> {
            SwingUtilities.invokeLater(() -> owner.showView(new View2(owner)));
        });

        add(button);
    }
}

<强> View2.java

import javax.swing.*;
import java.awt.*;

public class View2 extends JPanel {
    final private MainFrame owner;

    public View2(MainFrame owner) {
        super();

        this.owner = owner;
        createGUI();
    }

    private void createGUI() {
        setLayout(new FlowLayout());
        add(new JLabel("View 2"));

        JButton button = new JButton("Show View 1");
        button.addActionListener(event -> {
            SwingUtilities.invokeLater(() -> owner.showView(new View1(owner)));

        });

        add(button);
    }
}

答案 2 :(得分:0)

这是一个旧帖子,但以简化的方式回答它可能会有所帮助。感谢 mcwolf 先生的第一个回答。

如果我们想让 1 个子 jframe 与主 jframe 交互以修改其内容,让我们考虑以下情况。 parent.javachild.java。 所以,在 parent.java 中,我们有这样的东西:

Parent.java

public class Parent extends JFrame implements ActionListener{
    //attributes
    //here is the class we want to modify
    private some_class_to_modify = new some_class_to_modify();
    //here is a container which contains the class to modify
    private JPanel container = new JPanel();
    private some_class = new some_class();
    private int select;
    //....etc..etc
    //constructor
    public Parent(){
        this.setTitle("My title");
        //etc etc
        
        //etc....etc
        container.add(some_class_to_modify,borderLayout.CENTER);
    }
    //I use for instance actionlisteners on buttons to trigger the new JFrame
    public void actionPerformed(ActionEvent arg0){  
        if((arg0.getSource() == source_button_here)){
            //Here we call the child class and send the parent's attributes with "this"
            Child child = new Child(this);
        }
        //... all other cases
    }//Here is the class where we want to be able to modify our JFrame. Here ist a JPanel (Setcolor)
    public void child_action_on_parent(int selection){
        this.select = selection;
        System.out.println("Selection is: "+cir_select);
        if(select == 0) {
            //Do $omething with our class to modify
            some_class_to_modify.setcolor(Color.yellow);
        }
        
    }

child.java 中,我们会有这样的东西:

public class Child extends JFrame implements ActionListener {
    //Again some attributes here
    private blabla;
    //Import Parent JFrame class
    private Parent owner;
    private int select_obj=0;
    //Constructor here and via Parent Object Import
    public Child(Parent owner){
      /*By calling the super() method in the constructor method, we call the parent's 
      constructor method and gets access to the parent's properties and methods:*/
        super();
        this.owner = owner;
        this.setTitle("Select Method");
        this.setSize(400, 400);
        this.setContentPane(container);
        this.setVisible(true);
      }
    
    class OK_Button  implements ActionListener {
        public void actionPerformed(ActionEvent e) {     
                
                Object Selection = select;
                if(Selection == something) {
                    select_obj=0;
                    valid = JOptionPane.showConfirmDialog(null,"You have chosen option 1. Do you want to continue?","Minimum diameter",2);
                }
                System.out.println("Option is:"+valid);
                if(valid == 0) {
                    setVisible(false);
                    //Here we can use our herited object to call the child_action_on_parent public class of the Parent JFrame. So it can modify directly the Panel
                    owner.child_action_on_parent(select_obj);
                }
            }
    }