"Here is the error: 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. 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
. 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
. I used the private field with the setter
as to not break the rules of encapsulation.
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. What I would do in this particular situation is use some sort of MVC architecture. 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.
Side Notes
- Use Java naming convention. Class names begin with capital letters.
UPDATE
Here's an example of a simple MVC (Model, View, Controller) design, using some of your program ideas. I'll walk you through it.
Model LinesModel
class. The only property is has is an int lines
. It has a setLines
method. 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. Then button , when pressed, calls the setLines
method of the LinesModel
, which fires the property change and notifies the interested listener.
fiveLines.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
lineModel.setLines(4);
}
});
View PaintPanel
class. It basically takes the number of lines from the LinesModel
and paints that number of lines.
@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);
}
}