所以,我创建了一个 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
这是错误:无法从静态上下文引用非静态变量行。
请帮我。抱歉我的英语很蹩脚,如果我的问题不够清楚,尽管问。提前致谢。 :)
最佳答案
"Here is the error:
non-static variable lines cannot be referenced from a static context
."
您收到此错误是因为您尝试以静态方式访问 lines
,而 lines
不是 static
> 变量,它是一个实例变量。因此,您要做的就是获取对该实例变量的引用。
一种方法是通过构造函数注入(inject)将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
。我将私有(private)字段与 setter
一起使用,以免违反封装规则。
对于这种常见情况,有更好的解决方案。这只是一个简单的修复(但有漏洞)。此方法不必要地公开了frame
类。在这种特殊情况下我会做的是使用某种 MVC architecture 。一个更简单的解决方案是使用 interface
作为中间人,并让 frame
实现它(例如 here ,但由于您想要做的只是操作数据,因此MVC 设计是最好的方法。
旁注
- 使用 Java 命名约定。类名以大写字母开头。
更新
这是一个简单的 MVC(模型、 View 、 Controller )设计示例,使用了您的一些程序想法。我将引导您完成它。
模型 LinesModel
类。唯一的属性是一个intlines
。它有一个 setLines
方法。此方法的特殊之处在于它会触发属性更改事件,因此每当调用该方法时, View 都可以更改
public void setLines(int value) {
int oldValue = lines;
lines = value;
propertySupport.firePropertyChange(LINES_PROPERTY, oldValue, lines);
}
Controller PanelWithButtons
类。然后,按钮在按下时会调用 LinesModel
的 setLines
方法,该方法会触发属性更改并通知感兴趣的监听器。
fiveLines.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
lineModel.setLines(4);
}
});
View 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;
}
}
<小时/>
这是完整的运行程序。您可以运行它并尝试了解发生了什么。
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);
}
}
关于java - JFrame、JPanel、JButton 和继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22606293/