简体   繁体   English

JFrame,JPanel,JButton和继承

[英]JFrame, JPanel, JButton, and Inheritance

So, I made a JFrame class and a JPanel class (which is pretty complicated beacuse there are some buttons in this panel). 因此,我制作了一个JFrame类和一个JPanel类(这很复杂,因为此面板中有一些按钮)。 In this JFrame class, I have to make an array of the JPanel class, so it goes like this 在这个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
    }
}

And the problem is, the buttons in this JPanel have different ActionListeners for each button where it should change the variables in that JFrame class 问题是,此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
     }
}

So, that's it. 就是这样了。 Each button will change the variable of the frame differently. 每个按钮将不同地更改框架的变量。 But it's not working. 但这不起作用。 I think the problem is with this code, but I don't know what should I change it to: 我认为问题出在此代码上,但是我不知道应该将其更改为什么:

frame.lines

Here is the error: non-static variable lines cannot be referenced from a static context. 这是错误: non-static variable lines cannot be referenced from a static context.

Please help me. 请帮我。 Sorry for my broken English and if my question is not clear enough, just ask. 对不起,我的英语不好,如果我的问题不清楚,请问。 Thanks in advance. 提前致谢。 :) :)

"Here is the error: non-static variable lines cannot be referenced from a static context ." “这里是错误: non-static variable lines cannot be referenced from a static context 。”

You're getting this error because you're trying to access the lines in a static way, when lines isn't a static variable, it's an instance variable. 之所以出现此错误,是因为您试图以静态方式访问lines ,而当lines不是static变量时,它是一个实例变量。 So what to you want to do is get a reference to that instance variable. 因此,您要做的就是获取对该实例变量的引用。

One way is to pass the frame reference to the panelWithButton through constructor injection, then you can access the instance field lines . 一种方法是通过构造函数注入将frame引用传递给panelWithButton ,然后可以访问实例字段lines Something like 就像是

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

By passing the same instance of frame to panelWithButton , it's able to access the instance members, like the method setLines . 通过将相同的frame实例传递给panelWithButton ,它可以访问实例成员,如setLines方法。 I used the private field with the setter as to not break the rules of encapsulation. 我将私有字段与setter是为了不破坏封装规则。

There are better solutions to this common scenario though. 但是,对于这种常见情况有更好的解决方案。 This one is just one simple fix (bu with holes). 这只是一个简单的解决方法(带有孔)。 This method exposes the frame class unnecesarily. 此方法不必要地公开了frame类。 What I would do in this particular situation is use some sort of MVC architecture . 在这种特殊情况下,我将使用某种MVC体系结构 An easier solution would be to use an interface as a middleman and have the frame implement it (example here , but since all you want to do is manipulate data, the MVC design is the best approach. 一个简单的解决方案是使用一个interface作为中间人并让frame实现它( 这里是示例,但是由于您要做的只是操纵数据,因此MVC设计是最好的方法。


Side Notes 旁注

  • Use Java naming convention. 使用Java命名约定。 Class names begin with capital letters. 类名以大写字母开头。

UPDATE UPDATE

Here's an example of a simple MVC (Model, View, Controller) design, using some of your program ideas. 这是一个使用一些程序思想的简单MVC(模型,视图,控制器)设计的示例。 I'll walk you through it. 我会引导您完成。

Model LinesModel class. 模型 LinesModel类。 The only property is has is an int lines . 唯一的属性是具有int lines It has a setLines method. 它具有setLines方法。 The special thing about this method is that it fires a property change event so when ever the method is called, the view can be changed 此方法的特殊之处在于它会触发属性更改事件,因此,无论何时调用该方法,都可以更改视图

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

Controller PanelWithButtons class. 控制器 PanelWithButtons类。 Then button , when pressed, calls the setLines method of the LinesModel , which fires the property change and notifies the interested listener. 然后按钮,按下时,调用setLines的方法LinesModel ,它将触发属性变化,并通知感兴趣的听众。

fiveLines.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        lineModel.setLines(4);
    }
});

View PaintPanel class. 查看 PaintPanel类。 It basically takes the number of lines from the LinesModel and paints that number of lines. 它基本上从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;
    }
}

Here's the complete running program. 这是完整的运行程序。 You can run through it and try and learn what's going on. 您可以运行它并尝试了解发生了什么。

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Frame extends JFrame {

    private LinesModel lineModel;
    private PaintPanel paintPanel;
    private PanelWithButtons panelWithButtons;

    public Frame() {
        lineModel = new LinesModel();
        paintPanel = new PaintPanel();
        panelWithButtons = new PanelWithButtons(lineModel);

        lineModel.addPropertyChangeListener(new PropertyChangeListener(){

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                String prop = evt.getPropertyName();
                if (LinesModel.LINES_PROPERTY.equals(prop)) {
                    paintPanel.repaint();
                }
            }   
        });

        add(paintPanel);
        add(panelWithButtons, BorderLayout.SOUTH);

        setTitle("MVC Example");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        pack();
        setVisible(true);
    }

    public class PaintPanel extends JPanel {

        @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;
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 300);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            public void run() {
                new Frame();
            }
        });
    }
}


class PanelWithButtons extends JPanel {

    private final JButton fourLines = new JButton("FOUR");
    private final JButton fiveLines = new JButton("FIVE");
    private LinesModel lineModel;

    public PanelWithButtons(LinesModel lineModel) {
        this.lineModel = lineModel;

        fiveLines.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                PanelWithButtons.this.lineModel.setLines(4);
            }
        });

        fourLines.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                PanelWithButtons.this.lineModel.setLines(5);
            }
        });

        add(fourLines);
        add(fiveLines);
    }
}

class LinesModel implements Serializable {

    public static final String LINES_PROPERTY = "linesProperty";
    private int lines;

    private PropertyChangeSupport propertySupport;

    public LinesModel() {
        propertySupport = new PropertyChangeSupport(this);
    }

    public int getLines() {
        return lines;
    }

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

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        propertySupport.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        propertySupport.removePropertyChangeListener(listener);
    }  
}

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

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