简体   繁体   English

如何从另一个类更改 JPanel?

[英]How can I change the JPanel from another Class?

Hi, I'm new to Java and I have the following problem:嗨,我是 Java 新手,遇到以下问题:

I created a JFrame and I want the JPanel to change when clicking a JButton.我创建了一个 JFrame 并且我希望在单击 JButton 时 JPanel 发生变化。 That does almost work.The only problem is that the program creates a new window and then there are two windows.这几乎可以工作。唯一的问题是程序创建了一个新窗口,然后有两个窗口。 One with the first JPanel and one with the second JPanel.一个带有第一个 JPanel,一个带有第二个 JPanel。 Here is my current code:这是我当前的代码:

first class:第一类:

public class Program {

    public static void main (String [] args) {

        new window(new panel1());

    }
}

second class:第二类:

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

    }
}

third class:第三类:

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

    }
}

fourth class:第四课:

public class Panel2 extends JPanel {

    private static final long serialVersionUID = 1L;

    Panel2() {

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

        add(text);

    }
}

But I just want to change the JPanel without opening a new window.但我只想在不打开新窗口的情况下更改 JPanel。 Is there a way to do that?有没有办法做到这一点?

Thanks in advance!提前致谢!

This is a demo这是一个演示

import javax.swing.*;

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

MainFrame.java主框架.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查看1.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视图2.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);
    }
}

First of all, take a look at Java naming conventions , in particular your class names should start with a capitalized letter.首先,看看Java命名约定,特别是你的类名应该以大写字母开头。

If you want to avoid to open a new window every time you click the button, you could pass your frame object to Panel1 constructor, and setting a new Panel2 instance as the frame content pane when you click the button.如果要避免每次单击按钮时都打开一个新窗口,可以将框架对象传递给 Panel1 构造函数,并在单击按钮时将新的 Panel2 实例设置为框架内容窗格。 There is also no need to pass Panel1 to Window constructor (please note that Window class is already defined in java.awt package, it would be better to avoid a possible name clash renaming your class ApplicationWindow, MyWindow or something else).也不需要将 Panel1 传递给 Window 构造函数(请注意Window类已经在 java.awt 包中定义,最好避免重命名类 ApplicationWindow、MyWindow 或其他内容时可能发生的名称冲突)。

You could change your code like this (only relevant parts):您可以像这样更改代码(仅相关部分):

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

Also note the SwingUtilities's invokeLater call, which is the best way to initialise your GUI in the EDT context (for more info look at this question ).还要注意 SwingUtilities 的 invokeLater 调用,这是在 EDT 上下文中初始化 GUI 的最佳方式(有关更多信息,请查看此问题)。

Finally, you could avoid to create a new Panel2 instance every time you click the button, simply by using a CardLayout.最后,您可以避免每次单击按钮时都创建一个新的 Panel2 实例,只需使用 CardLayout。 Take a look at the official tutorial .看看官方教程

This is an old post, but it may be useful to answer it in a simplified way.这是一篇旧帖子,但以简化的方式回答它可能会有所帮助。 Thanks to mr mcwolf for the first answer.感谢 mcwolf 先生的第一个回答。

If we want to make 1 child jframe interact with a main jframe in order to modify its content, let's consider the following case.如果我们想让 1 个子 jframe 与主 jframe 交互以修改其内容,让我们考虑以下情况。 parent.java and child.java . parent.javachild.java So, in parent.java, we have something like this:所以,在 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);
        }
        
    }

In child.java we would have something like this: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);
                }
            }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM