如何从另一个类中的外化JPanel设置框架的标题?

时间:2016-03-09 10:36:52

标签: java swing jpanel

我有2个班级:MainClass.javaBasicDataPage.java,而第一个班级是JFrameCardLayout,第二个班级是JPanel,只是一个标签。

当我点击MainClass中的按钮时,卡片显示JPanel BasicDataPage的内容(在此示例中只有1张卡片,在我的真实程序中还有几张卡片)。

但是我无法从JPanel内部更改窗口/框架的标题:

MainClass.setTitle("BasicDataPage");无法使用,因为我无法对非静态方法setTitle()进行静态引用。

我的第一个冲动是更改标题,当单击按钮时,但在我的实际应用程序中,我有另一个名为Navigation.java的类,其中包含导航按钮的监听器。所以如何更改标题也是同样的问题:

Buttonclick in MainClass -> Navigation gets active -> needs to talk to MainClass and change the title

OR

Buttonclick in MainClass -> BasicDataPage gets active -> needs to talk to MainClass and change the title

那么如何从另一个班级的JFrame更改JPanel的标题?

MainClass.java:

import java.awt.CardLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.UIManager;

public class MainClass extends JFrame{
    public CardLayout contentCardsLayout = new CardLayout();

    BasicDataPage basicDataPage = new BasicDataPage();

    JButton changePageButton = new JButton("Goto BasicDataPage");

    public MainClass(){
        super("My MainClass");
        setBounds(300, 50, 400, 400);
        setLayout(contentCardsLayout);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        changePageButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                contentCardsLayout.show(getContentPane(), "basicDataPage");
            }
        });

        basicDataPage.setName("basicDataPage");

        add(changePageButton);
        add(basicDataPage, "basicDataPage");
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");

                    MainClass window = new MainClass();
                    window.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

}

BasicDataPage.java:

import javax.swing.JLabel;
import javax.swing.JPanel;

public class BasicDataPage extends JPanel {

    public BasicDataPage() {
        add(new JLabel("MainClass - BasicDataPage"));
    // This does not work, since I can not make a static reference to the non-static method setTitle()
    // MainClass.setTitle("BasicDataPage");
    }
}

2 个答案:

答案 0 :(得分:1)

如果您的JPanel已添加到JFrame中,那就是BasicDataPage已添加到MainClass

在此关系下,您可以使用getParent()

轻松地从添加的组件中获取父容器

示例:

class BasicDataPage extends JPanel{
    //constructors and initializations not shown..

    public void setPrentComponent(){
        Object o = getParent();
        MainClass mc;
        if(o != null && o instanceof MainClass)
            mc = (MainClass)o;

        mc.setTitle(lbl.getText());            
    }   
}

如果你想获得顶级容器。例如,A JFrame添加了一个MainPanel,MainPanel添加了另一个面板......依此类推。

如果您想获得 顶级容器 (即框架)的参考,您可以使用:

SwingUtilities.windowForComponent();
  

如何调用setParentComponent()?

假设您有一个JFrame类和一个JPanel类。我通常不会将这些类作为主要的项目类。您可以使用另一个单独的类来驱动代码。

class TestRunner{
    public static void main(String[] args){
        MainClass mc = new MainClass();   //I will rename this class if I were you
        BasicDataPage bdp = new BasicDataPage();
        mc.add(bdp);                      //add panel to frame;
        bdp.setParentComponent();         //Set parent container
    }
}

这是你所拥有的,通常我不会创建自定义的JFrame,而是在EDT中运行Frame并将包含所有组件的面板添加到Frame中。

答案 1 :(得分:0)

如果两个类都不知道彼此的存在,则可以使用一个控制器类来保持对两个类的实例的引用。从那里,从面板中获取“标题”并将其传递给框架:

class Contorller(){
    public static void main(String[] args){
        MainClass mainClass = new MainClass():
        BasicDataPage bdp = new BasicDataPage();

        mainClass.setTitle(bdp.getTitle()); //Need a setter in BasicDataPage class
    }
}

class BasicDataPage{
    private JLabel lblTitle;

    //constructors and initializations not shown

    public String getTitle(){
        return lblTitle.text();
    }
}