如何使用Java中的另一个类设置布局?

时间:2017-05-10 16:03:20

标签: java gridbaglayout

我正在编写一个带有复杂TabbedPane的程序,其中包含许多元素。由于我在其中一个类中达到了字节限制,因此我决定将该类拆分为Initialisation / Button Listeners和实际的GridBagLayout。但是现在我无法让它发挥作用。我的主类看起来像这样:

public class Main{
JFrame mainFrame = new JFrame("");
JTabbedPane tabpane = new JTabbedPane();
JPanel panelTab1 = new Tab1();
JScrollPane scrollTab2 = new JScrollPane(new Tab2());
JScrollPane scrollTab3 = new JScrollPane(new Tab3());
JPanel panelTab4 = new Tab4();
JMenuBar bar = new MenuBar();


public Main(){
    tabpane.add("Tab1", panelTab1);
    tabpane.add("Tab2", scrollTab2);
    tabpane.add("Tab3", scrollTab3);
    tabpane.add("Tab4", panelTab4);
    mainFrame.getContentPane().add(tabpane);
    mainFrame.setSize(1920,1080);   
    mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
    mainFrame.setVisible(true);     
    mainFrame.validate();
    mainFrame.setJMenuBar(bar);

}



public static void main(String[] args)
{

    SwingUtilities.invokeLater(new Runnable(){
        public void run(){
            new Main();
        }
    });


}}

Tab3是罪魁祸首所以这里是我分裂的两个类。

public class Tab3 extends JPanel {
JPanel Annex = new JPanel();
//A Bunch of Labels and Buttons
.
.
.
public Tab3(){
//ActionListeners for the Buttons
this.setLayout(new BorderLayout());
this.add(Annex,BorderLayout.WEST);
this.add(Bsp,BorderLayout.EAST);
}}

所有GridBagLayout都在以下类中:

public class Tab3Layout extends Tab3{
    public Tab3Layout(){
        Annex.setLayout(new GridBagLayout());
        GridBagConstraints co1 = new GridBagConstraints();
        co1.gridx = 0;
        co1.gridy = 0;
        co1.anchor = GridBagConstraints.FIRST_LINE_START;
        co1.weighty = 1.0;
        Annex.add(Annex1, co1);
        //and so on...
        }}

现在我的问题是,如何让它工作?现在,如果我编译,Tab3只是空的。如果所有内容都在一个类中,它就可以完全按照我的要求运行,但代码太长了。在我看来,我在Tab3课程中错过了一行,但即使经过数小时的修补和搜索,我也不知道如何解决这个问题。我试过的所有东西都产生了更多的错误。

1 个答案:

答案 0 :(得分:2)

问题在于继承。 Tab3Layout有自己的Annex JPanel(继承自Tab3),它正在修改和添加组件,而Tab3类正在插入其Annex }},它是通过new JPanel()初始化的,你不用做任何其他事情。 Tab3Layout课程甚至从未触及Annex小组您初始化并添加Tab3

public class Tab3 extends JPanel {
JPanel Annex = new JPanel(); // <----- this, an empty JPanel
//A Bunch of Labels and Buttons

public Tab3(){
//ActionListeners for the Buttons
this.setLayout(new BorderLayout());
this.add(Annex,BorderLayout.WEST); // <----- is inserted here
this.add(Bsp,BorderLayout.EAST);
}}

如果删除new JPanel(),将会出现错误,这将说明这两个类正在对不同的对象进行操作,这些对象恰好被命名为相同。您需要将要在Tab3中显示的所有组件/面板传递给Tab3Layout进行修改,然后您可以稍后使用getters检索它们。另一种方法是创建AnnexPanel类,它本身将扩展JPanel类。它将设置自己的布局,组件等,并能够直接添加。如果你的班级规模增长,那么Single Responsibility Principle最好。如果它是200多行代码,你应该考虑重构它。如果你允许你的课程增长超过3000行代码,那么你将度过一段美好的时光。尝试预测在开发的早期阶段可以创建新类/方法的位置。请参阅KISS principle

嗯......我会用不同的方式分开那些。

我的Tab3Layout课程。附件面板为injected via constructor,您可以为此设置setter,但请记住在注射前不要调用createAnnex()。无论如何,编译器会让你记住。

public final class Tab3Layout {

    private JPanel Annex;
    JPanel Annex1; //just to avoid compiler error
    private GridBagLayout gridBagLayout;
    private GridBagConstraints co1;

    public Tab3Layout(JPanel Annex) {
        this.Annex = Annex;
        this.gridBagLayout = new GridBagLayout();
        this.co1 = new GridBagConstraints();
    }

    public void createAnnex() {
        this.Annex.setLayout(gridBagLayout);

        this.co1.gridx = 0;
        this.co1.gridy = 0;
        this.co1.anchor = GridBagConstraints.FIRST_LINE_START;
        this.co1.weighty = 1.0;

        this.Annex.add(Annex1, co1);
    }

    public JPanel getAnnex() {
        return this.Annex;
    }
}

然后是Tab3类:

public class Tab3 extends JPanel {

    JPanel Annex;
    Tab3Layout tab3Layout;

    public Tab3() {
        super();
        this.Annex = new JPanel();

        this.tab3Layout = new Tab3Layout(Annex);
        this.tab3Layout.createAnnex();

        this.setLayout(new BorderLayout());
        this.add(tab3Layout.getAnnex(), BorderLayout.WEST);
        this.add(new JPanel(), BorderLayout.EAST);
    }
}

查看我的GridBagManager回购,它可以让您了解如何使用其他类设置布局。

您还可以使用JPanel扩展Tab3Layout。并记得使用GridBagConstraints设置anchorfill

Java naming convention

JPanel Annex = new JPanel();
GridBagConstraints co1 = new GridBagConstraints();

JPanel annexPanel = new JPanel();
GridBagConstraints gridBagConstraints = new GridBagConstraints();

我个人使用gbc作为GridBagConstraints对象,正如您在我上面提到的回购中看到的那样。

编辑: 我认为你应该将你的实现分成几个较小的类。这将是专业的方法。重构你的代码。对于初学者,你可以让每个小组都有自己的类JPanel(就像我在AnnexPanel类中建议的那样)。

Edit2:createAnnex()可以返回JPanel类型,减少样板代码,然后调用如下:

this.add(Tab3Layout.createAnnex(), co1);

而不是

Tab3Layout.createAnnex();
this.add(Tab3Layout.getAnnex(), co1);

如果它是单例,甚至可以将createAnnex()带到构造函数(假设类扩展JPanel)。