I have severall question and excuse my denglish!
Problems:
- My actionPerformed in my controller dont react
- and I dont know how to use the update(model,object) method in the View.
- The next problem is my GridBag. It looks chaotic although the code is orientated on the oracle example.
- No the Last one. in the view line 41 i get a NPE as a result of a class initialised in the Model. dont no why. I allready testes if the Class is constructed and yes it is.
The Programm should greate a JuliaSet.
Classes without theire imports
Controller:
public class JuliaController extends WindowAdapter implements ActionListener {
private JuliaView view;
private JuliaModel model;
private String linkBuffer;
public JuliaController(){
model = new JuliaModel();
System.out.println("true!");
view = new JuliaView("JuliaMenge");
view.makeView();
}
@Override
public void actionPerformed(ActionEvent arg0) {
String action = arg0.getActionCommand();
if(action.equals(view.ACTION_CLEAR))
{
//Clear Graphics
view.setBtClear();
}
if(action.equals(view.ACTION_COMPLEX))
{
String input = view.getComplex();
view.setTfComplex(); //Zurücksetzen des Felds!
model.juliaBerechnung(input);
view.getBtPaint(); //Setzt den Button auf anklickbar
//Paint Button anklickbar machen
}
if(action.equals(view.ACTION_ENDE))
{
view.release();
System.exit(0);
}
if(action.equals(view.ACTION_LINK))
{
String inLink = view.getTfLink();
view.setTfLink();
try {
model.juliaBerechnung(dataInList(inLink));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
view.getBtPaint();
}
if(action.equals(view.ACTION_PAINT))
{
//Erzeuge Graphics!
view.getBtPaint(); //Button nicht mehr anklickbarkeit
}
}
public String dataInList(String link)throws IOException
{
String temp="";
BufferedReader inBuffer = null;
try {
inBuffer = new BufferedReader(new FileReader(new File(link)));
while((temp=inBuffer.readLine())!=null)
{
//System.out.println("Buffer : "+temp);
linkBuffer += temp;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
int dateiLength = linkBuffer.length();
inBuffer.close();
char c;
int index=0;
for(int i = index;index<dateiLength;index++){
c = linkBuffer.charAt(index);
if((c=='+')||(c=='-'))break;
}
temp = "";
for(int i=index;i<index+8;i++)
{
temp+=linkBuffer.charAt(i);
}
return temp; //Keine Anhang in der Datei
}
public void release() {
// TODO Auto-generated method stub
model = null;
view = null;
}
public void windowClosing( WindowEvent we)
{
view.release();
}
}
View:
public class JuliaView extends JFrame implements Observer{
//:::: ACTIONS
public final String ACTION_ENDE = "Ende";
public final String ACTION_PAINT = "Paint";
public final String ACTION_COMPLEX = "+a.x+b.x";
public final String ACTION_LINK = "Link";
public final String ACTION_CLEAR = "Clear";
//:::: Components
private JButton btEnde;
private JButton btPaint;
private JButton btClear;
public JuliaPanel drawArea; //Bereich für Paint
//private JButton btAutoPaint;
private JTextField tfComplex;
private JTextField tfLink;
//:::: Observer
private JuliaModel model;
private JuliaController controller;
private JuliaBild map;
public JuliaView(String titel){
super(titel);
this.model = model;
//this.map = model.getMap(); //??????//Iterationsarray einbinden
//this.model.addObserver(this);
//controller = makeController();
initForm();
//makeView();
}
void makeView() {
resetView();
// Fenster
addWindowListener( controller);
pack();
setVisible( true);
}
/*private JuliaController makeController() { ?????????????????
return new JuliaController();
}*/
/**
* Anordnen der Komponenten im GridBag
*/
private void initForm(){
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new GridBagLayout());
this.setBounds(200, 200, 800, 600);
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(15,15,15,15);
//this.add(btAutoPaint,c);
// TextField für Kompleze Zahl
tfComplex = new JTextField(ACTION_COMPLEX,8);
tfComplex.addActionListener(controller);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 2;
this.getContentPane().add(tfComplex,c);
// Link
tfLink = new JTextField(ACTION_LINK);
tfLink.addActionListener(controller);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 2;
this.getContentPane().add(tfLink,c);
// Paint Button
btPaint = new JButton(ACTION_PAINT);
btPaint.setEnabled(false);
btPaint.addActionListener(controller);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 2;
c.gridwidth = 2;
c.ipady = 40;
this.getContentPane().add(btPaint,c);
//CLS Button
btClear = new JButton(ACTION_CLEAR);
btClear.addActionListener(controller);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 4;
c.gridwidth = 2;
this.getContentPane().add(btClear,c);
//Exit Button
btEnde = new JButton(ACTION_ENDE);
btEnde.addActionListener(controller);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 1;
c.gridy = 5;
c.gridwidth = 1;
this.getContentPane().add(btEnde,c);
//draw area
drawArea = new JuliaPanel(); //Place for the JuliaSet
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 2;
c.gridy = 0;
c.gridwidth = 6;
this.getContentPane().add(drawArea,c);
setVisible( true);
pack();
}
public void resetView(){
this.tfComplex.setText("+a.x+b.x");
this.tfLink.setText("c:/...");
//drawArea.paint(g);
}
@Override
public void update(Observable m, Object o) {
// TODO Auto-generated method stub
if(model == m) setBtPaint(); //???
}
public void setBtPaint()
{
btPaint.setText(ACTION_PAINT);
btPaint.requestFocus();
btPaint.setEnabled(true);
drawArea.setKoordinaten(map);
//Zeichnen
//drawArea.repaint();
drawArea.print(getGraphics());
//drawArea.paint(getGraphics());
}
public void getBtPaint()
{
btPaint.setText(ACTION_PAINT);
drawArea.createImage();
btPaint.requestFocus();
btPaint.setEnabled(false); //anklickbarkeit
}
public void setBtClear()
{
btClear.setText(ACTION_CLEAR);
resetView();
drawArea.clearImage();
btClear.requestFocus();
}
public void setTfComplex()
{
tfComplex.setText(ACTION_COMPLEX);
tfComplex.setCaretPosition(tfComplex.getText().length());
tfComplex.requestFocus();
}
public void setTfLink()
{
tfLink.setText(ACTION_LINK);
tfLink.setCaretPosition(tfLink.getText().length());
tfLink.requestFocus();
}
public void getBtEnde()
{
btEnde.setText(ACTION_ENDE);
btEnde.requestFocus();
}
public String getComplex()
{
String temp = "";
temp = tfComplex.getText();
return temp;
}
public String getTfLink()
{
String temp = tfLink.getText();
return temp;
}
public void release(){
dispose();
// Controller
controller.release();
controller = null;
// Model
model.deleteObserver( this);
model = null;
}
}
Model:
public class JuliaModel extends Observable{
//private Complex startWert;
private Complex konst;
private String pfad;
private JuliaBild map;
public JuliaModel()
{
//startWert = new Complex(re, im);
konst = new Complex(1.0,1.0);
pfad = "";
makeBild();
}
private void makeBild()
{
map = new JuliaBild(600,600);
System.out.println("bild true");
}
public JuliaModel(double reK, double imK)
{
map = new JuliaBild(600,600);
//startWert = new Complex(re, im);
konst = new Complex(reK,imK);
pfad = "";
}
private int grundAlgoIt(double x,double y)
{
Complex temp = new Complex(x,y);
double xTemp=0;
for(int n=0;n<256;n++)
{
if(temp.abs()<4){return n;}
xTemp = Math.pow(temp.getRe(), 2)-Math.pow(temp.getIm(), 2) + konst.getRe();
temp.setIm((2*temp.getIm()*temp.getRe())+konst.getIm());//y=
temp.setRe(xTemp);
}
return 0;
}
void juliaBerechnung(String input)
{
double xmin = -2.0;//fx
double ymin = -2.0;//fy
double width = 4.0;//fw //Weg im Koordinatensystem
double height = 4.0;//fh
double schrittWeite = 4.0/600;
stringToKonst(input);
//Complex temp = new Complex(xmin-schrittWeite,1);
double xTemp,yTemp;
xTemp = xmin-schrittWeite;
//durch die Pixel gehen
for(int j=0;j<600;j++)
{
xTemp = xTemp+schrittWeite;
yTemp = ymin;
for(int i=0;i<600;i++)
{
yTemp = yTemp + schrittWeite;
map.setBild(j,i,grundAlgoIt(xTemp,yTemp));
}
}
}
private void stringToKonst(String in)
{
char cBuffer;
String sBuffer="";
double im = 0;
double re = 0;
for(int a=0;a<=4;a+=4)
for(int i=0;i<4;i++)
{
cBuffer = in.charAt(i+a);
sBuffer+=cBuffer;
if(a==0&&i==4)
{
re = Double.parseDouble(sBuffer);
}
if(a==4&&i==4)
{
im = Double.parseDouble(sBuffer);
}
}
konst.setNumber(re, im);
}
public JuliaBild getMap()
{
return map;
}}
Thanks for your help!
My actionPerformed in my controller dont react
This is because you never register you controller with anything that is capable of producing a ActionEvent
and I dont know how to use the update(model,object) method in the View.
The update
method is called on behalf of your model when it's state is changed. You should update the view based on the new state of the model.
If your model supports multiple properties, a PropertyChangeListener
might be better suited. If the model has different states, you might be better defining your own listener, which defines the states that the model might trigger.
But, again, it will never be called, as you never add an Observer
to it
The next problem is my GridBag. It looks chaotic although the code is orientated on the oracle example.
Yep, that's GridBagLayout
for you
No the Last one. in the view line 41 i get a NPE as a result of a class initialised in the Model. dont no why. I allready testes if the Class is constructed and yes it is
Which one's line 41? What's the stack trace look like?
General Advice
- MVC is not an easy thing to implement within Swing, as Swing uses a form of VC-M of it's own, so you kind of end up doubling up the effort. It's not that it can't be done, but you need to think about it differently
- In some forms of MVC, the controller knows about the model and view, but the model and view don't know about each other and all communication between the model and view is done via the controller. This is kinda of where the Swing implementation deviates, but you should be aware that this is how it's more commonly implemented
Start by defining the contract between the view and the controller. Define the actions that the controller can perform on the view as well as the event listeners the view is willing to accept.
Generally, I avoid attaching listeners directly to view controls from the controller and instead define events that the view can generate, in this way, you decouple the contract between the two and allow for different implementations of the view and controller to work together.
For example, if you have a button which is suppose to signify the user is read to process the input, instead of allowing the controller to directly add a ActionListener
to the button, you would define a userAcceptedInput
event in one of the listeners that the view supports. This way, another implementation could use some other mechanism to trigger the event, by the controller doesn't care.
For more discussions on the subject have a look at:
- Java and GUI - Where do ActionListeners belong according to MVC pattern?
- Dealing with MVC model, jbuttons and ActionListener's getSource() method
- What is the correct way of Message Passing between Classes in MVC?
Okay I added the Observer and change the constructors sothat the classes know each other.
But i still dont know where/or how i should add the actionlistener to the controller because i thought i already did it when i implements it.
But now when i initialize the classes i geht this NPE:
Exception in thread "main" java.lang.NullPointerException
at JuliaView.resetView(JuliaView.java:126)
at JuliaView.makeView(JuliaView.java:57)
at JuliaController.<init>(JuliaController.java:23)
at JuliaView.<init>(JuliaView.java:44)
at Huston.main(Huston.java:10)
Here are the changed classes:
Model:
public class Huston {
//static private JuliaController missionControl;
public static void main(String[] args) {
// TODO Auto-generated method stub
JuliaModel model = new JuliaModel();
JuliaView view = new JuliaView(model, "JuliaSet");
JuliaController missionControl = new JuliaController(model, view);
}
}
Model:
public class JuliaModel extends Observable{
//private Complex startWert;
private Complex konst;
private String pfad;
private JuliaBild map;
public JuliaModel()
{
//startWert = new Complex(re, im);
konst = new Complex(1.0,1.0);
pfad = "";
makeBild();
}
private void makeBild()
{
map = new JuliaBild(600,600);
System.out.println("bild true");
}
public JuliaModel(double reK, double imK)
{
map = new JuliaBild(600,600);
//startWert = new Complex(re, im);
konst = new Complex(reK,imK);
pfad = "";
}
private int grundAlgoIt(double x,double y)
{
Complex temp = new Complex(x,y);
double xTemp=0;
for(int n=0;n<256;n++)
{
if(temp.abs()<4){return n;}
xTemp = Math.pow(temp.getRe(), 2)-Math.pow(temp.getIm(), 2) + konst.getRe();
temp.setIm((2*temp.getIm()*temp.getRe())+konst.getIm());//y=
temp.setRe(xTemp);
}
return 0;
}
void juliaBerechnung(String input)
{
double xmin = -2.0;//fx
double ymin = -2.0;//fy
double width = 4.0;//fw //Weg im Koordinatensystem
double height = 4.0;//fh
double schrittWeite = 4.0/600;
stringToKonst(input);
//Complex temp = new Complex(xmin-schrittWeite,1);
double xTemp,yTemp;
xTemp = xmin-schrittWeite;
//durch die Pixel gehen
for(int j=0;j<600;j++)
{
xTemp = xTemp+schrittWeite;
yTemp = ymin;
for(int i=0;i<600;i++)
{
yTemp = yTemp + schrittWeite;
map.setBild(j,i,grundAlgoIt(xTemp,yTemp));
}
}
}
private void stringToKonst(String in)
{
char cBuffer;
String sBuffer="";
double im = 0;
double re = 0;
for(int a=0;a<=4;a+=4)
for(int i=0;i<4;i++)
{
cBuffer = in.charAt(i+a);
sBuffer+=cBuffer;
if(a==0&&i==4)
{
re = Double.parseDouble(sBuffer);
}
if(a==4&&i==4)
{
im = Double.parseDouble(sBuffer);
}
}
konst.setNumber(re, im);
}
public JuliaBild getMap()
{
return map;
}}
View:
public class JuliaView extends JFrame implements Observer{
//:::: ACTIONS
public final String ACTION_ENDE = "Ende";
public final String ACTION_PAINT = "Paint";
public final String ACTION_COMPLEX = "+a.x+b.x";
public final String ACTION_LINK = "Link";
public final String ACTION_CLEAR = "Clear";
//:::: Components
private JButton btEnde;
private JButton btPaint;
private JButton btClear;
public JuliaPanel drawArea; //Bereich für Paint
//private JButton btAutoPaint;
private JTextField tfComplex;
private JTextField tfLink;
//:::: Observer
private JuliaModel model;
private JuliaController controller;
private JuliaBild map;
public JuliaView(JuliaModel model,String titel){
super(titel);
this.model = model;
//this.map = model.getMap(); //??????//Iterationsarray einbinden
this.model.addObserver(this);
controller = new JuliaController(model,this);
initForm();
//makeView();
}
void makeView() {
// Fenster
addWindowListener( controller);
setVisible( true);
pack();
resetView();
}
/**
* Anordnen der Komponenten im GridBag
*/
private void initForm(){
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new GridBagLayout());
this.setBounds(200, 200, 800, 600);
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(15,15,15,15);
//this.add(btAutoPaint,c);
// TextField für Kompleze Zahl
tfComplex = new JTextField(ACTION_COMPLEX,8);
tfComplex.addActionListener(controller);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 2;
this.getContentPane().add(tfComplex,c);
// Link
tfLink = new JTextField(ACTION_LINK);
tfLink.addActionListener(controller);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 2;
this.getContentPane().add(tfLink,c);
// Paint Button
btPaint = new JButton(ACTION_PAINT);
btPaint.setEnabled(false);
btPaint.addActionListener(controller);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 2;
c.gridwidth = 2;
c.ipady = 40;
this.getContentPane().add(btPaint,c);
//CLS Button
btClear = new JButton(ACTION_CLEAR);
btClear.addActionListener(controller);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 4;
c.gridwidth = 2;
this.getContentPane().add(btClear,c);
//Exit Button
btEnde = new JButton(ACTION_ENDE);
btEnde.addActionListener(controller);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 1;
c.gridy = 5;
c.gridwidth = 1;
this.getContentPane().add(btEnde,c);
//draw area
drawArea = new JuliaPanel();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 2;
c.gridy = 0;
c.gridwidth = 6;
this.getContentPane().add(drawArea,c);
setVisible( true);
pack();
}
public void resetView(){
this.tfComplex.setText("+a.x+b.x");
this.tfLink.setText("c:/...");
//drawArea.paint(g);
}
@Override
public void update(Observable m, Object o) {
// TODO Auto-generated method stub
if(model == m) setBtPaint(); //???
}
public void setBtPaint()
{
btPaint.setText(ACTION_PAINT);
btPaint.requestFocus();
btPaint.setEnabled(true);
drawArea.setKoordinaten(map);
//Zeichnen
//drawArea.repaint();
drawArea.print(getGraphics());
//drawArea.paint(getGraphics());
}
public void getBtPaint()
{
btPaint.setText(ACTION_PAINT);
drawArea.createImage();
btPaint.requestFocus();
btPaint.setEnabled(false); //anklickbarkeit
}
public void setBtClear()
{
btClear.setText(ACTION_CLEAR);
resetView();
drawArea.clearImage();
btClear.requestFocus();
}
public void setTfComplex()
{
tfComplex.setText(ACTION_COMPLEX);
tfComplex.setCaretPosition(tfComplex.getText().length());
tfComplex.requestFocus();
}
public void setTfLink()
{
tfLink.setText(ACTION_LINK);
tfLink.setCaretPosition(tfLink.getText().length());
tfLink.requestFocus();
}
public void getBtEnde()
{
btEnde.setText(ACTION_ENDE);
btEnde.requestFocus();
}
public String getComplex()
{
String temp = "";
temp = tfComplex.getText();
return temp;
}
public String getTfLink()
{
String temp = tfLink.getText();
return temp;
}
public void release(){
dispose();
// Controller
controller.release();
controller = null;
// Model
model.deleteObserver( this);
model = null;
}}
Controller:
public class JuliaController extends WindowAdapter implements ActionListener {
private JuliaView view;
private JuliaModel model;
private String linkBuffer;
public JuliaController(JuliaModel model, JuliaView view){
this.model = model;
this.view = view;
view.makeView();
}
@Override
public void actionPerformed(ActionEvent arg0) {
String action = arg0.getActionCommand();
if(action.equals(view.ACTION_CLEAR))
{
//Clear Graphics
view.setBtClear();
}
if(action.equals(view.ACTION_COMPLEX))
{
String input = view.getComplex();
view.setTfComplex(); //Zurücksetzen des Felds!
model.juliaBerechnung(input);
view.getBtPaint(); //Setzt den Button auf anklickbar
//Paint Button anklickbar machen
}
if(action.equals(view.ACTION_ENDE))
{
view.release();
System.exit(0);
}
if(action.equals(view.ACTION_LINK))
{
String inLink = view.getTfLink();
view.setTfLink();
try {
model.juliaBerechnung(dataInList(inLink));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
view.getBtPaint();
}
if(action.equals(view.ACTION_PAINT))
{
//Erzeuge Graphics!
view.getBtPaint(); //Button nicht mehr anklickbarkeit
}
}
public String dataInList(String link)throws IOException
{
String temp="";
BufferedReader inBuffer = null;
try {
inBuffer = new BufferedReader(new FileReader(new File(link)));
while((temp=inBuffer.readLine())!=null)
{
linkBuffer += temp;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
int dateiLength = linkBuffer.length();
inBuffer.close();
char c;
int index=0;
for(int i = index;index<dateiLength;index++){
c = linkBuffer.charAt(index);
if((c=='+')||(c=='-'))break;
}
temp = "";
for(int i=index;i<index+8;i++)
{
temp+=linkBuffer.charAt(i);
}
return temp; //Keine Anhang in der Datei
}
public void release() {
// TODO Auto-generated method stub
model = null;
view = null;
}
public void windowClosing( WindowEvent we)
{
view.release();
}}