Model-View-Controller, or a more simple level, Passing Information to a Method or a Constructor and a observer pattern are the concepts you want to learn and understand.
Essentially, your "view" is a visual representation of your "model". The "view" "observers" the "model" for changes and updates itself accordingly.
In order to achieve this in your context, you need to share the model between both views, passing a reference to each. The "renderer" view will also "observer" the model for any possible changes
Start by defining the model...
public class MazeModel {
private List<ChangeListener> listeners = new ArrayList<>(25);
private int rows;
private int cols;
public void setSize(int cols, int rows) {
this.cols = cols;
this.rows = rows;
fireStateChanged();
}
public int getRows() {
return rows;
}
public int getCols() {
return cols;
}
public void addChangeListener(ChangeListener listener) {
listeners.add(listener);
}
public void removeChangeListener(ChangeListener listener) {
listeners.remove(listener);
}
protected void fireStateChanged() {
ChangeEvent evt = new ChangeEvent(this);
for (ChangeListener listener : listeners) {
listener.stateChanged(evt);
}
}
}
Personally, I'd prefer to start with a interface
to define the contract, but for brevity. The model should contain the data and logic required to manage the maze.
Next, update your classes so that the instance of the MazeModel
can be passed in...
public class Frame extends JFrame {
private VariableDetails vDetails;
private MazeArea mArea;
private int width;
private int height;
private MazeModel model;
public Frame(String title, MazeModel model) {
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.model = model;
this.model.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
// Update the state as required...
}
});
width = 500;
height = 500;
// Prefer pack :/
setSize(width, height);
setLayout(new BorderLayout());
// I'm guessing that model should be passed to this
// and it should modify it's state accoridingly....
mArea = new MazeArea();
vDetails = new VariableDetails(model);
Container c = getContentPane();
c.add(mArea, BorderLayout.CENTER);
c.add(vDetails, BorderLayout.EAST);
setVisible(true);
}
public class VariableDetails extends JPanel {
private MazeModel model;
public VariableDetails(MazeModel model) {
this.model = model;
JButton genBtn = new JButton("Generate");
genBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
model.setSize(cols, rows);
}
});
}
}
}
This now allows the classes an independent communication channel, via the ChangeListener
, which ensures that they remain de-coupled.
A note about resizing the window
I wouldn't. Instead, I would pass the model to the instance MazeArea
, so it could observer the changes to the model and update itself accordingly. I'd then wrap the MazeArea
in a JScrollPane
, which would allow it to change size to anything and the frame could remain at a relative static size.
See How to Use Scroll Panes for more details
As a user, it would annoy me to no end if I'd set the size of the window myself and you came along and changed it