JFrame,JPanel,JButton和Inheritance

时间:2014-03-24 10:09:13

标签: java swing jframe jbutton jlabel

所以,我创建了一个JFrame类和一个JPanel类(由于此面板中有一些按钮,因此非常复杂)。在这个JFrame类中,我必须创建一个JPanel类的数组,所以它就像这样

public class frame extends JFrame
{
    //SOME VARIABLES AND METHODS HERE
    int lines;

    public frame()
    {
        //SOME CODE HERE
        panelWithButton[] pwb = new panelWithButton[5];
        //SOME CODE HERE
    }
}

问题是,此JPanel中的按钮对于每个按钮都有不同的ActionListeners,它应该更改JFrame类中的变量

public class panelWithButton extends JPanel
{
    //SOME VARIABLES AND METHOD
    Jbutton aButton = new JButton();
    Jbutton bButton = new JButton();
    Jbutton cButton = new JButton();

    public button()
    {
        //SOME CODE HERE
        add(aButton);
        aButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {   
                frame.lines = 4;
            }
        });

        add(bButton);
        aButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {   
                frame.lines = 5;
            }
        });

        add(cButton);
        aButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {   
                frame.lines = 6;
            }
        });
        //SOME CODE HERE
     }
}

所以,那就是它。每个按钮将以不同方式更改框架的变量。但它不起作用。我认为问题在于此代码,但我不知道应该将其更改为:

frame.lines

以下是错误:non-static variable lines cannot be referenced from a static context.

请帮我。抱歉我的英语不好,如果我的问题不够明确,请问。提前致谢。 :)

1 个答案:

答案 0 :(得分:2)

  

“这是错误:non-static variable lines cannot be referenced from a static context。”

您收到此错误是因为您尝试以静态方式访问lines,当lines不是static变量时,它是一个实例变量。那么你想要做的是获得对该实例变量的引用。

一种方法是通过构造函数注入将frame引用传递给panelWithButton,然后您可以访问实例字段lines。像

这样的东西
public class frame extends JFrame {
    private int lines;    // private for encapsulation. getter/setter below
    ...
    panelWithButton panel = new panelWithButton(frame.this);
    ...
    public void setLines(int lines) {
        this.lines = lines;
    }
}

public class panelWithButton extends JPanel {
    private frame f;

    public panelWithButton(final frame f) {
        this.f = f;
    }

    public void button() {
        ...
        public void actionPerformed(ActionEvent e) {
            f.setLines(5);
        }
    }
}

通过将frame的同一实例传递给panelWithButton,它可以访问实例成员,例如方法setLines。我使用setter的私有字段来打破封装规则。

但这种常见情况有更好的解决方案。这个只是一个简单的修复(带孔)。此方法不必要地公开frame类。在这种特殊情况下我会做的是使用某种MVC architecture。一个更简单的解决方案是使用interface作为中间人并让frame实现它(例如here,但由于您只想操作数据,因此MVC设计是最佳方法。


附注

  • 使用Java命名约定。班级名称以大写字母开头。

<强>更新

这是一个简单的MVC(模型,视图,控制器)设计的示例,使用您的一些程序想法。我会引导你完成它。

模型 LinesModel课程。唯一的属性是int lines。它有一个setLines方法。关于此方法的特殊之处在于它会触发属性更改事件,因此无论何时调用该方法,都可以更改视图

public void setLines(int value) {
    int oldValue = lines;
    lines = value;
    propertySupport.firePropertyChange(LINES_PROPERTY, oldValue, lines);
}

控制器 PanelWithButtons课程。然后按下按钮,调用setLines的{​​{1}}方法,激活属性更改并通知感兴趣的听众。

LinesModel

查看 fiveLines.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { lineModel.setLines(4); } }); 课程。它基本上取PaintPanel的行数并绘制该行数。

LinesModel

这是完整的运行程序。您可以浏览它并尝试了解正在发生的事情。

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    int y = 50;
    for (int i = 0; i < lineModel.getLines(); i++) {
        g.drawLine(50, y, 200, y);
        y += 20;
    }
}