Swing application to compute the area and perimeter of shapes
up vote
4
down vote
favorite
I am a beginner programmer. How would you refactor this code to abide by good coding practices? As it stands the program has 4 classes and its aim is to compute the area and perimeter of a specific shape by inputting its length from a JSlider. The MyFrame
, MyShape
, MyTriangle
, MyCircle
and MySquare
. The initComponents()
method is autogenerated by NetBeans autobuilder so I didn't include it below. Also the program is fully functionable as of now, just want to know how to better refactor the code, splitting it in different classes etc..
package mainpackage;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import javax.swing.JFrame;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class MyFrame extends JFrame
{
MyShape myShape;
int value;
public MyFrame()
{
// Create frame, panels and items within
initComponents();
shapeSlider.setEnabled(false);
// Create instances of shapes when chosen in Menu
initShapes();
// Adds Changelistener to slider and updates dimensionOutputField
linkEventHandler();
exitButton2.addActionListener(new CloseListener());
}
private void initShapes()
{
ShapeHandler shapeHandler = new ShapeHandler();
squareMenuItem.addActionListener(shapeHandler);
circleMenuItem.addActionListener(shapeHandler);
triangleMenuItem.addActionListener(shapeHandler);
}
public class ShapeHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == squareMenuItem)
{
myShape = new MySquare();
} else if (e.getSource() == circleMenuItem)
{
myShape = new MyCircle();
} else if (e.getSource() == triangleMenuItem)
{
myShape = new MyTriangle();
}
shapeSlider.setEnabled(true);
}
}
public class MyChangeAction implements ChangeListener
{
public void stateChanged(ChangeEvent e)
{
int currentValue = shapeSlider.getValue() ;
dimensionOutputField.setText(String.valueOf(currentValue));
DecimalFormat numberFormat = new DecimalFormat("#.00");
double bLength = myShape.calculatePerimeter(currentValue);
String bLengthString = numberFormat.format(bLength);
bLengthOutputField.setText(bLengthString);
double bArea = myShape.calculateArea(currentValue);
String areaString = numberFormat.format(bArea);
areaOutputField1.setText(areaString);
}
}
private void linkEventHandler()
{
MyChangeAction sliderAction = new MyChangeAction() ;
shapeSlider.addChangeListener(sliderAction);
}
private class CloseListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
}
private void exitButtonActionPerformed(java.awt.event.ActionEvent evt) {
}
public static void main(String args)
{
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try
{
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels())
{
if ("Nimbus".equals(info.getName()))
{
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex)
{
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex)
{
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex)
{
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex)
{
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable()
{
public void run() {
new MyFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JPanel MyControlPanel;
private javax.swing.JLabel areaLabel1;
private javax.swing.JTextField areaOutputField1;
private javax.swing.JLabel bLengthLabel;
private javax.swing.JTextField bLengthOutputField;
private javax.swing.JMenuItem circleMenuItem;
private javax.swing.JLabel dimensionLabel;
private javax.swing.JTextField dimensionOutputField;
private javax.swing.JButton exitButton2;
private javax.swing.JPanel mainPanel2;
private javax.swing.JLabel mainTitle;
private javax.swing.JMenu shapeMenu;
private javax.swing.JMenuBar shapeMenuBar;
private javax.swing.JSlider shapeSlider;
private javax.swing.JMenuItem squareMenuItem;
private javax.swing.JMenuItem triangleMenuItem;
private org.jdesktop.beansbinding.BindingGroup bindingGroup;
// End of variables declaration
}
java beginner object-oriented calculator swing
add a comment |
up vote
4
down vote
favorite
I am a beginner programmer. How would you refactor this code to abide by good coding practices? As it stands the program has 4 classes and its aim is to compute the area and perimeter of a specific shape by inputting its length from a JSlider. The MyFrame
, MyShape
, MyTriangle
, MyCircle
and MySquare
. The initComponents()
method is autogenerated by NetBeans autobuilder so I didn't include it below. Also the program is fully functionable as of now, just want to know how to better refactor the code, splitting it in different classes etc..
package mainpackage;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import javax.swing.JFrame;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class MyFrame extends JFrame
{
MyShape myShape;
int value;
public MyFrame()
{
// Create frame, panels and items within
initComponents();
shapeSlider.setEnabled(false);
// Create instances of shapes when chosen in Menu
initShapes();
// Adds Changelistener to slider and updates dimensionOutputField
linkEventHandler();
exitButton2.addActionListener(new CloseListener());
}
private void initShapes()
{
ShapeHandler shapeHandler = new ShapeHandler();
squareMenuItem.addActionListener(shapeHandler);
circleMenuItem.addActionListener(shapeHandler);
triangleMenuItem.addActionListener(shapeHandler);
}
public class ShapeHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == squareMenuItem)
{
myShape = new MySquare();
} else if (e.getSource() == circleMenuItem)
{
myShape = new MyCircle();
} else if (e.getSource() == triangleMenuItem)
{
myShape = new MyTriangle();
}
shapeSlider.setEnabled(true);
}
}
public class MyChangeAction implements ChangeListener
{
public void stateChanged(ChangeEvent e)
{
int currentValue = shapeSlider.getValue() ;
dimensionOutputField.setText(String.valueOf(currentValue));
DecimalFormat numberFormat = new DecimalFormat("#.00");
double bLength = myShape.calculatePerimeter(currentValue);
String bLengthString = numberFormat.format(bLength);
bLengthOutputField.setText(bLengthString);
double bArea = myShape.calculateArea(currentValue);
String areaString = numberFormat.format(bArea);
areaOutputField1.setText(areaString);
}
}
private void linkEventHandler()
{
MyChangeAction sliderAction = new MyChangeAction() ;
shapeSlider.addChangeListener(sliderAction);
}
private class CloseListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
}
private void exitButtonActionPerformed(java.awt.event.ActionEvent evt) {
}
public static void main(String args)
{
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try
{
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels())
{
if ("Nimbus".equals(info.getName()))
{
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex)
{
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex)
{
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex)
{
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex)
{
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable()
{
public void run() {
new MyFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JPanel MyControlPanel;
private javax.swing.JLabel areaLabel1;
private javax.swing.JTextField areaOutputField1;
private javax.swing.JLabel bLengthLabel;
private javax.swing.JTextField bLengthOutputField;
private javax.swing.JMenuItem circleMenuItem;
private javax.swing.JLabel dimensionLabel;
private javax.swing.JTextField dimensionOutputField;
private javax.swing.JButton exitButton2;
private javax.swing.JPanel mainPanel2;
private javax.swing.JLabel mainTitle;
private javax.swing.JMenu shapeMenu;
private javax.swing.JMenuBar shapeMenuBar;
private javax.swing.JSlider shapeSlider;
private javax.swing.JMenuItem squareMenuItem;
private javax.swing.JMenuItem triangleMenuItem;
private org.jdesktop.beansbinding.BindingGroup bindingGroup;
// End of variables declaration
}
java beginner object-oriented calculator swing
add a comment |
up vote
4
down vote
favorite
up vote
4
down vote
favorite
I am a beginner programmer. How would you refactor this code to abide by good coding practices? As it stands the program has 4 classes and its aim is to compute the area and perimeter of a specific shape by inputting its length from a JSlider. The MyFrame
, MyShape
, MyTriangle
, MyCircle
and MySquare
. The initComponents()
method is autogenerated by NetBeans autobuilder so I didn't include it below. Also the program is fully functionable as of now, just want to know how to better refactor the code, splitting it in different classes etc..
package mainpackage;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import javax.swing.JFrame;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class MyFrame extends JFrame
{
MyShape myShape;
int value;
public MyFrame()
{
// Create frame, panels and items within
initComponents();
shapeSlider.setEnabled(false);
// Create instances of shapes when chosen in Menu
initShapes();
// Adds Changelistener to slider and updates dimensionOutputField
linkEventHandler();
exitButton2.addActionListener(new CloseListener());
}
private void initShapes()
{
ShapeHandler shapeHandler = new ShapeHandler();
squareMenuItem.addActionListener(shapeHandler);
circleMenuItem.addActionListener(shapeHandler);
triangleMenuItem.addActionListener(shapeHandler);
}
public class ShapeHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == squareMenuItem)
{
myShape = new MySquare();
} else if (e.getSource() == circleMenuItem)
{
myShape = new MyCircle();
} else if (e.getSource() == triangleMenuItem)
{
myShape = new MyTriangle();
}
shapeSlider.setEnabled(true);
}
}
public class MyChangeAction implements ChangeListener
{
public void stateChanged(ChangeEvent e)
{
int currentValue = shapeSlider.getValue() ;
dimensionOutputField.setText(String.valueOf(currentValue));
DecimalFormat numberFormat = new DecimalFormat("#.00");
double bLength = myShape.calculatePerimeter(currentValue);
String bLengthString = numberFormat.format(bLength);
bLengthOutputField.setText(bLengthString);
double bArea = myShape.calculateArea(currentValue);
String areaString = numberFormat.format(bArea);
areaOutputField1.setText(areaString);
}
}
private void linkEventHandler()
{
MyChangeAction sliderAction = new MyChangeAction() ;
shapeSlider.addChangeListener(sliderAction);
}
private class CloseListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
}
private void exitButtonActionPerformed(java.awt.event.ActionEvent evt) {
}
public static void main(String args)
{
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try
{
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels())
{
if ("Nimbus".equals(info.getName()))
{
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex)
{
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex)
{
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex)
{
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex)
{
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable()
{
public void run() {
new MyFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JPanel MyControlPanel;
private javax.swing.JLabel areaLabel1;
private javax.swing.JTextField areaOutputField1;
private javax.swing.JLabel bLengthLabel;
private javax.swing.JTextField bLengthOutputField;
private javax.swing.JMenuItem circleMenuItem;
private javax.swing.JLabel dimensionLabel;
private javax.swing.JTextField dimensionOutputField;
private javax.swing.JButton exitButton2;
private javax.swing.JPanel mainPanel2;
private javax.swing.JLabel mainTitle;
private javax.swing.JMenu shapeMenu;
private javax.swing.JMenuBar shapeMenuBar;
private javax.swing.JSlider shapeSlider;
private javax.swing.JMenuItem squareMenuItem;
private javax.swing.JMenuItem triangleMenuItem;
private org.jdesktop.beansbinding.BindingGroup bindingGroup;
// End of variables declaration
}
java beginner object-oriented calculator swing
I am a beginner programmer. How would you refactor this code to abide by good coding practices? As it stands the program has 4 classes and its aim is to compute the area and perimeter of a specific shape by inputting its length from a JSlider. The MyFrame
, MyShape
, MyTriangle
, MyCircle
and MySquare
. The initComponents()
method is autogenerated by NetBeans autobuilder so I didn't include it below. Also the program is fully functionable as of now, just want to know how to better refactor the code, splitting it in different classes etc..
package mainpackage;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import javax.swing.JFrame;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class MyFrame extends JFrame
{
MyShape myShape;
int value;
public MyFrame()
{
// Create frame, panels and items within
initComponents();
shapeSlider.setEnabled(false);
// Create instances of shapes when chosen in Menu
initShapes();
// Adds Changelistener to slider and updates dimensionOutputField
linkEventHandler();
exitButton2.addActionListener(new CloseListener());
}
private void initShapes()
{
ShapeHandler shapeHandler = new ShapeHandler();
squareMenuItem.addActionListener(shapeHandler);
circleMenuItem.addActionListener(shapeHandler);
triangleMenuItem.addActionListener(shapeHandler);
}
public class ShapeHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == squareMenuItem)
{
myShape = new MySquare();
} else if (e.getSource() == circleMenuItem)
{
myShape = new MyCircle();
} else if (e.getSource() == triangleMenuItem)
{
myShape = new MyTriangle();
}
shapeSlider.setEnabled(true);
}
}
public class MyChangeAction implements ChangeListener
{
public void stateChanged(ChangeEvent e)
{
int currentValue = shapeSlider.getValue() ;
dimensionOutputField.setText(String.valueOf(currentValue));
DecimalFormat numberFormat = new DecimalFormat("#.00");
double bLength = myShape.calculatePerimeter(currentValue);
String bLengthString = numberFormat.format(bLength);
bLengthOutputField.setText(bLengthString);
double bArea = myShape.calculateArea(currentValue);
String areaString = numberFormat.format(bArea);
areaOutputField1.setText(areaString);
}
}
private void linkEventHandler()
{
MyChangeAction sliderAction = new MyChangeAction() ;
shapeSlider.addChangeListener(sliderAction);
}
private class CloseListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
}
private void exitButtonActionPerformed(java.awt.event.ActionEvent evt) {
}
public static void main(String args)
{
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try
{
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels())
{
if ("Nimbus".equals(info.getName()))
{
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex)
{
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex)
{
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex)
{
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex)
{
java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable()
{
public void run() {
new MyFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JPanel MyControlPanel;
private javax.swing.JLabel areaLabel1;
private javax.swing.JTextField areaOutputField1;
private javax.swing.JLabel bLengthLabel;
private javax.swing.JTextField bLengthOutputField;
private javax.swing.JMenuItem circleMenuItem;
private javax.swing.JLabel dimensionLabel;
private javax.swing.JTextField dimensionOutputField;
private javax.swing.JButton exitButton2;
private javax.swing.JPanel mainPanel2;
private javax.swing.JLabel mainTitle;
private javax.swing.JMenu shapeMenu;
private javax.swing.JMenuBar shapeMenuBar;
private javax.swing.JSlider shapeSlider;
private javax.swing.JMenuItem squareMenuItem;
private javax.swing.JMenuItem triangleMenuItem;
private org.jdesktop.beansbinding.BindingGroup bindingGroup;
// End of variables declaration
}
java beginner object-oriented calculator swing
java beginner object-oriented calculator swing
edited Nov 8 '17 at 6:38
200_success
127k15149412
127k15149412
asked Nov 7 '17 at 11:35
Danielmt
212
212
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
up vote
2
down vote
For Java the Code style conventions are quite rigorous. I would adhere to the code style that is followed by 99% of the community. The firms you will be working for will determine the coding style.
When Java was launched, C++/C generally had an indentation of 3. And the
code had often a large number of nested { }.
It was decided to opt for more Methods (academic style) and indent to 4 in order to support "good style." The alternative explanation is that 4 is the half of 8, the normal tab size.
The NetBeans IDE's GUI builder let's set properties and code Fragments. You can use that to disable the slider, add Action listeners and such.
Since Java 8 one can use lambas, representations of anonymous functions, that under the hood will become an interface implementation. This abbreviates the Code, introducing parameter names:
component.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
myShape = new MyCircle();
}
});
can be shortened to
component.addActionListener(evt -> myShape = new MyCircle());
If not, always use @Override on overriden Methods. Should the method have a typo, that would be reported with a compile error.
The fields may be private.
private MyShape myShape;
private int value;
public MyFrame() {
// Create frame, panels and items within
initComponents();
shapeSlider.setEnabled(false);
// Create instances of shapes when chosen in Menu
initShapes();
// Adds Changelistener to slider and updates dimensionOutputField
shapeSlider.addChangeListener(new MyChangeAction());
exitButton2.addActionListener(actionEvent -> MyFrame.this.dispose());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
The ShapeHandler could not use if-else-if chains but be object-oriented:
public class ShapeHandler implements ActionListener {
private final Supplier<MyShape> shapeCreator;
public ShapeHandler(Supplier<MyShape> shapeCreator) {
this.shapeCreator = shapeCreator;
}
public void actionPerformed(ActionEvent e) {
myShape = shapeCreator.get();
shapeSlider.setEnabled(true);
}
}
private void initShapes() {
squareMenuItem.addActionListener(new ShapeHandler(MySquare::new));
circleMenuItem.addActionListener(new ShapeHandler(MyCircle::new));
triangleMenuItem.addActionListener(new ShapeHandler(MyTriangle::new));
// Or:
squareMenuItem.addActionListener(evt -> myShape = new MySquare());
circleMenuItem.addActionListener(evt -> myShape = new MyCircle());
triangleMenuItem.addActionListener(evt -> myShape = new MyTriangle());
}
But as you see, the class is not really needed. Though nice to not "repeat one self".
I would use @Override
and possible an other Name, as Action
is a known interface in swing.
public class MyChangeAction implements ChangeListener {
@Override
public void stateChanged(ChangeEvent e) {
The generated main
method is conservative: compilable for very old versions of Java < 7. Shorter would be:
public static void main(String args) {
try {
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException
| IllegalAccessException | UnsupportedLookAndFeelException ex) {
Logger.getLogger(MyFrame.class.getName()).log(Level.SEVERE,
"Error setting theme", ex);
}
EventQueue.invokeLater(() -> new MyFrame().setVisible(true));
}
1
This covers nearly everything that I could say, so just a comment and not an answer: Pulling the work of what e.g. aChangeListener
does into an own (private) method often leads to a cleaner structure, and allows using aaddListener(this::somethingChanged)
method reference as well. IMHO, listener methods should usually be as short as possible.
– Marco13
yesterday
@Marco13 indeed the nicest solution. I wanted to express the OO-way of not having an if-else-if/switch, and to Show that one can immediately use lambdas. eliminating an internal class. Thus the nicest: a method, passing a method handle did not reach the answer. Thanks
– Joop Eggen
21 hours ago
add a comment |
up vote
1
down vote
Create CalculateCallback
which is responsible for managing the action after the calculation is done. So perform any calculations there necessary once calculation is done.
@FunctionalInterface
public interface CalculateCallback {
public void perform(double value);
}
AreaCalculator
is responsible for doing calculations and performing the calculate call back. Once the slider changes the calculation should go through AreaCalculator
.
public class AreaCalculator {
private CalculateCallback perimeterCalculatorCallback;
private CalculateCallback areaCalculatorCallback;
private MyShape myShape;
public AreaCalculator(CalculateCallback perimeterCalculatorCallback, CalculateCallback areaCalculatorCallback) {
this.perimeterCalculatorCallback = perimeterCalculatorCallback;
this.areaCalculatorCallback = areaCalculatorCallback;
}
public void doCalculate(int currentValue) {
if (null != myShape) {
double bLength = myShape.calculatePerimeter(currentValue);
perimeterCalculatorCallback.perform(bLength);
double bArea = myShape.calculateArea(currentValue);
areaCalculatorCallback.perform(bArea);
}
}
public void setMyShape(MyShape myShape) {
this.myShape = myShape;
}
}
ShapeFactory
is responsible to provide MyShape
according to parameter. I didn't implement that. Please makes sure to implement this.
public class ShapeFactory {
public static MyShape getMyShape(String item) {
//Here you have to return MyShape according to parameter.
}
}
ShapeHandler
is responsible for handling change. It will perform calculation through AreaCalculator
by providing MyShape
according to action.
public class ShapeHandler implements ActionListener {
private AreaCalculator areaCalculator;
private ActionDoneCallback actionDoneCallback;
public ShapeHandler(AreaCalculator areaCalculator, ActionDoneCallback doneCallback) {
this.areaCalculator = areaCalculator;
this.actionDoneCallback = doneCallback;
}
@Override
public void actionPerformed(ActionEvent e) {
MyShape shape = ShapeFactory.getMyShape(e.getActionCommand());
areaCalculator.setMyShape(shape);
actionDoneCallback.perform();
}
}
Your MyFrame
constructor should like below.
Its responsible to create callback since its the owner of component and this need to modify according to requirement.
public MyFrame() {
// Create frame, panels and items within
DecimalFormat numberFormat = new DecimalFormat("#.00");
AreaCalculator areaCalculator = new AreaCalculator(
(value) -> bLengthOutputField.setText(numberFormat.format(value)),
(value -> areaOutputField1.setText(numberFormat.format(value))));
ShapeHandler shapeHandler = new ShapeHandler(areaCalculator, () -> shapeSlider.setEnabled(true));
squareMenuItem.addActionListener(shapeHandler);
triangleMenuItem.addActionListener(shapeHandler);
circleMenuItem.addActionListener(shapeHandler);
shapeSlider.setEnabled(false);
shapeSlider.addChangeListener(e -> areaCalculator.doCalculate(shapeSlider.getValue()));
exitButton2.addActionListener(new CloseListener());
}
Once a shape is selected ShapeHandler
will set MyShape
in AreaCalculator
.
Once the Jslider is changed it will do the calculation base on the value.
I design this under SOLID principles and base on TDD.
so you can write unit test easy for this design.
Let me to know if you need some clarification.
Thank you so much for your time. What are the ActionDoneCallBack class and the CalculateCallBack class please? I have never used these classes before.
– Danielmt
Nov 9 '17 at 10:08
Update the text field is responsible by MyFrame after the calculation. Calculation responsible by AreaCalculator. What I have done is separate responsible. (Please read about SOLID principle) The process after calculation, provided by outside. so if we want to use this calculator in another frame you can just provide callback implementation.
– Chamly Idunil
Nov 10 '17 at 4:19
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
For Java the Code style conventions are quite rigorous. I would adhere to the code style that is followed by 99% of the community. The firms you will be working for will determine the coding style.
When Java was launched, C++/C generally had an indentation of 3. And the
code had often a large number of nested { }.
It was decided to opt for more Methods (academic style) and indent to 4 in order to support "good style." The alternative explanation is that 4 is the half of 8, the normal tab size.
The NetBeans IDE's GUI builder let's set properties and code Fragments. You can use that to disable the slider, add Action listeners and such.
Since Java 8 one can use lambas, representations of anonymous functions, that under the hood will become an interface implementation. This abbreviates the Code, introducing parameter names:
component.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
myShape = new MyCircle();
}
});
can be shortened to
component.addActionListener(evt -> myShape = new MyCircle());
If not, always use @Override on overriden Methods. Should the method have a typo, that would be reported with a compile error.
The fields may be private.
private MyShape myShape;
private int value;
public MyFrame() {
// Create frame, panels and items within
initComponents();
shapeSlider.setEnabled(false);
// Create instances of shapes when chosen in Menu
initShapes();
// Adds Changelistener to slider and updates dimensionOutputField
shapeSlider.addChangeListener(new MyChangeAction());
exitButton2.addActionListener(actionEvent -> MyFrame.this.dispose());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
The ShapeHandler could not use if-else-if chains but be object-oriented:
public class ShapeHandler implements ActionListener {
private final Supplier<MyShape> shapeCreator;
public ShapeHandler(Supplier<MyShape> shapeCreator) {
this.shapeCreator = shapeCreator;
}
public void actionPerformed(ActionEvent e) {
myShape = shapeCreator.get();
shapeSlider.setEnabled(true);
}
}
private void initShapes() {
squareMenuItem.addActionListener(new ShapeHandler(MySquare::new));
circleMenuItem.addActionListener(new ShapeHandler(MyCircle::new));
triangleMenuItem.addActionListener(new ShapeHandler(MyTriangle::new));
// Or:
squareMenuItem.addActionListener(evt -> myShape = new MySquare());
circleMenuItem.addActionListener(evt -> myShape = new MyCircle());
triangleMenuItem.addActionListener(evt -> myShape = new MyTriangle());
}
But as you see, the class is not really needed. Though nice to not "repeat one self".
I would use @Override
and possible an other Name, as Action
is a known interface in swing.
public class MyChangeAction implements ChangeListener {
@Override
public void stateChanged(ChangeEvent e) {
The generated main
method is conservative: compilable for very old versions of Java < 7. Shorter would be:
public static void main(String args) {
try {
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException
| IllegalAccessException | UnsupportedLookAndFeelException ex) {
Logger.getLogger(MyFrame.class.getName()).log(Level.SEVERE,
"Error setting theme", ex);
}
EventQueue.invokeLater(() -> new MyFrame().setVisible(true));
}
1
This covers nearly everything that I could say, so just a comment and not an answer: Pulling the work of what e.g. aChangeListener
does into an own (private) method often leads to a cleaner structure, and allows using aaddListener(this::somethingChanged)
method reference as well. IMHO, listener methods should usually be as short as possible.
– Marco13
yesterday
@Marco13 indeed the nicest solution. I wanted to express the OO-way of not having an if-else-if/switch, and to Show that one can immediately use lambdas. eliminating an internal class. Thus the nicest: a method, passing a method handle did not reach the answer. Thanks
– Joop Eggen
21 hours ago
add a comment |
up vote
2
down vote
For Java the Code style conventions are quite rigorous. I would adhere to the code style that is followed by 99% of the community. The firms you will be working for will determine the coding style.
When Java was launched, C++/C generally had an indentation of 3. And the
code had often a large number of nested { }.
It was decided to opt for more Methods (academic style) and indent to 4 in order to support "good style." The alternative explanation is that 4 is the half of 8, the normal tab size.
The NetBeans IDE's GUI builder let's set properties and code Fragments. You can use that to disable the slider, add Action listeners and such.
Since Java 8 one can use lambas, representations of anonymous functions, that under the hood will become an interface implementation. This abbreviates the Code, introducing parameter names:
component.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
myShape = new MyCircle();
}
});
can be shortened to
component.addActionListener(evt -> myShape = new MyCircle());
If not, always use @Override on overriden Methods. Should the method have a typo, that would be reported with a compile error.
The fields may be private.
private MyShape myShape;
private int value;
public MyFrame() {
// Create frame, panels and items within
initComponents();
shapeSlider.setEnabled(false);
// Create instances of shapes when chosen in Menu
initShapes();
// Adds Changelistener to slider and updates dimensionOutputField
shapeSlider.addChangeListener(new MyChangeAction());
exitButton2.addActionListener(actionEvent -> MyFrame.this.dispose());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
The ShapeHandler could not use if-else-if chains but be object-oriented:
public class ShapeHandler implements ActionListener {
private final Supplier<MyShape> shapeCreator;
public ShapeHandler(Supplier<MyShape> shapeCreator) {
this.shapeCreator = shapeCreator;
}
public void actionPerformed(ActionEvent e) {
myShape = shapeCreator.get();
shapeSlider.setEnabled(true);
}
}
private void initShapes() {
squareMenuItem.addActionListener(new ShapeHandler(MySquare::new));
circleMenuItem.addActionListener(new ShapeHandler(MyCircle::new));
triangleMenuItem.addActionListener(new ShapeHandler(MyTriangle::new));
// Or:
squareMenuItem.addActionListener(evt -> myShape = new MySquare());
circleMenuItem.addActionListener(evt -> myShape = new MyCircle());
triangleMenuItem.addActionListener(evt -> myShape = new MyTriangle());
}
But as you see, the class is not really needed. Though nice to not "repeat one self".
I would use @Override
and possible an other Name, as Action
is a known interface in swing.
public class MyChangeAction implements ChangeListener {
@Override
public void stateChanged(ChangeEvent e) {
The generated main
method is conservative: compilable for very old versions of Java < 7. Shorter would be:
public static void main(String args) {
try {
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException
| IllegalAccessException | UnsupportedLookAndFeelException ex) {
Logger.getLogger(MyFrame.class.getName()).log(Level.SEVERE,
"Error setting theme", ex);
}
EventQueue.invokeLater(() -> new MyFrame().setVisible(true));
}
1
This covers nearly everything that I could say, so just a comment and not an answer: Pulling the work of what e.g. aChangeListener
does into an own (private) method often leads to a cleaner structure, and allows using aaddListener(this::somethingChanged)
method reference as well. IMHO, listener methods should usually be as short as possible.
– Marco13
yesterday
@Marco13 indeed the nicest solution. I wanted to express the OO-way of not having an if-else-if/switch, and to Show that one can immediately use lambdas. eliminating an internal class. Thus the nicest: a method, passing a method handle did not reach the answer. Thanks
– Joop Eggen
21 hours ago
add a comment |
up vote
2
down vote
up vote
2
down vote
For Java the Code style conventions are quite rigorous. I would adhere to the code style that is followed by 99% of the community. The firms you will be working for will determine the coding style.
When Java was launched, C++/C generally had an indentation of 3. And the
code had often a large number of nested { }.
It was decided to opt for more Methods (academic style) and indent to 4 in order to support "good style." The alternative explanation is that 4 is the half of 8, the normal tab size.
The NetBeans IDE's GUI builder let's set properties and code Fragments. You can use that to disable the slider, add Action listeners and such.
Since Java 8 one can use lambas, representations of anonymous functions, that under the hood will become an interface implementation. This abbreviates the Code, introducing parameter names:
component.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
myShape = new MyCircle();
}
});
can be shortened to
component.addActionListener(evt -> myShape = new MyCircle());
If not, always use @Override on overriden Methods. Should the method have a typo, that would be reported with a compile error.
The fields may be private.
private MyShape myShape;
private int value;
public MyFrame() {
// Create frame, panels and items within
initComponents();
shapeSlider.setEnabled(false);
// Create instances of shapes when chosen in Menu
initShapes();
// Adds Changelistener to slider and updates dimensionOutputField
shapeSlider.addChangeListener(new MyChangeAction());
exitButton2.addActionListener(actionEvent -> MyFrame.this.dispose());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
The ShapeHandler could not use if-else-if chains but be object-oriented:
public class ShapeHandler implements ActionListener {
private final Supplier<MyShape> shapeCreator;
public ShapeHandler(Supplier<MyShape> shapeCreator) {
this.shapeCreator = shapeCreator;
}
public void actionPerformed(ActionEvent e) {
myShape = shapeCreator.get();
shapeSlider.setEnabled(true);
}
}
private void initShapes() {
squareMenuItem.addActionListener(new ShapeHandler(MySquare::new));
circleMenuItem.addActionListener(new ShapeHandler(MyCircle::new));
triangleMenuItem.addActionListener(new ShapeHandler(MyTriangle::new));
// Or:
squareMenuItem.addActionListener(evt -> myShape = new MySquare());
circleMenuItem.addActionListener(evt -> myShape = new MyCircle());
triangleMenuItem.addActionListener(evt -> myShape = new MyTriangle());
}
But as you see, the class is not really needed. Though nice to not "repeat one self".
I would use @Override
and possible an other Name, as Action
is a known interface in swing.
public class MyChangeAction implements ChangeListener {
@Override
public void stateChanged(ChangeEvent e) {
The generated main
method is conservative: compilable for very old versions of Java < 7. Shorter would be:
public static void main(String args) {
try {
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException
| IllegalAccessException | UnsupportedLookAndFeelException ex) {
Logger.getLogger(MyFrame.class.getName()).log(Level.SEVERE,
"Error setting theme", ex);
}
EventQueue.invokeLater(() -> new MyFrame().setVisible(true));
}
For Java the Code style conventions are quite rigorous. I would adhere to the code style that is followed by 99% of the community. The firms you will be working for will determine the coding style.
When Java was launched, C++/C generally had an indentation of 3. And the
code had often a large number of nested { }.
It was decided to opt for more Methods (academic style) and indent to 4 in order to support "good style." The alternative explanation is that 4 is the half of 8, the normal tab size.
The NetBeans IDE's GUI builder let's set properties and code Fragments. You can use that to disable the slider, add Action listeners and such.
Since Java 8 one can use lambas, representations of anonymous functions, that under the hood will become an interface implementation. This abbreviates the Code, introducing parameter names:
component.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
myShape = new MyCircle();
}
});
can be shortened to
component.addActionListener(evt -> myShape = new MyCircle());
If not, always use @Override on overriden Methods. Should the method have a typo, that would be reported with a compile error.
The fields may be private.
private MyShape myShape;
private int value;
public MyFrame() {
// Create frame, panels and items within
initComponents();
shapeSlider.setEnabled(false);
// Create instances of shapes when chosen in Menu
initShapes();
// Adds Changelistener to slider and updates dimensionOutputField
shapeSlider.addChangeListener(new MyChangeAction());
exitButton2.addActionListener(actionEvent -> MyFrame.this.dispose());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
The ShapeHandler could not use if-else-if chains but be object-oriented:
public class ShapeHandler implements ActionListener {
private final Supplier<MyShape> shapeCreator;
public ShapeHandler(Supplier<MyShape> shapeCreator) {
this.shapeCreator = shapeCreator;
}
public void actionPerformed(ActionEvent e) {
myShape = shapeCreator.get();
shapeSlider.setEnabled(true);
}
}
private void initShapes() {
squareMenuItem.addActionListener(new ShapeHandler(MySquare::new));
circleMenuItem.addActionListener(new ShapeHandler(MyCircle::new));
triangleMenuItem.addActionListener(new ShapeHandler(MyTriangle::new));
// Or:
squareMenuItem.addActionListener(evt -> myShape = new MySquare());
circleMenuItem.addActionListener(evt -> myShape = new MyCircle());
triangleMenuItem.addActionListener(evt -> myShape = new MyTriangle());
}
But as you see, the class is not really needed. Though nice to not "repeat one self".
I would use @Override
and possible an other Name, as Action
is a known interface in swing.
public class MyChangeAction implements ChangeListener {
@Override
public void stateChanged(ChangeEvent e) {
The generated main
method is conservative: compilable for very old versions of Java < 7. Shorter would be:
public static void main(String args) {
try {
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException
| IllegalAccessException | UnsupportedLookAndFeelException ex) {
Logger.getLogger(MyFrame.class.getName()).log(Level.SEVERE,
"Error setting theme", ex);
}
EventQueue.invokeLater(() -> new MyFrame().setVisible(true));
}
edited yesterday
answered yesterday
Joop Eggen
1,137713
1,137713
1
This covers nearly everything that I could say, so just a comment and not an answer: Pulling the work of what e.g. aChangeListener
does into an own (private) method often leads to a cleaner structure, and allows using aaddListener(this::somethingChanged)
method reference as well. IMHO, listener methods should usually be as short as possible.
– Marco13
yesterday
@Marco13 indeed the nicest solution. I wanted to express the OO-way of not having an if-else-if/switch, and to Show that one can immediately use lambdas. eliminating an internal class. Thus the nicest: a method, passing a method handle did not reach the answer. Thanks
– Joop Eggen
21 hours ago
add a comment |
1
This covers nearly everything that I could say, so just a comment and not an answer: Pulling the work of what e.g. aChangeListener
does into an own (private) method often leads to a cleaner structure, and allows using aaddListener(this::somethingChanged)
method reference as well. IMHO, listener methods should usually be as short as possible.
– Marco13
yesterday
@Marco13 indeed the nicest solution. I wanted to express the OO-way of not having an if-else-if/switch, and to Show that one can immediately use lambdas. eliminating an internal class. Thus the nicest: a method, passing a method handle did not reach the answer. Thanks
– Joop Eggen
21 hours ago
1
1
This covers nearly everything that I could say, so just a comment and not an answer: Pulling the work of what e.g. a
ChangeListener
does into an own (private) method often leads to a cleaner structure, and allows using a addListener(this::somethingChanged)
method reference as well. IMHO, listener methods should usually be as short as possible.– Marco13
yesterday
This covers nearly everything that I could say, so just a comment and not an answer: Pulling the work of what e.g. a
ChangeListener
does into an own (private) method often leads to a cleaner structure, and allows using a addListener(this::somethingChanged)
method reference as well. IMHO, listener methods should usually be as short as possible.– Marco13
yesterday
@Marco13 indeed the nicest solution. I wanted to express the OO-way of not having an if-else-if/switch, and to Show that one can immediately use lambdas. eliminating an internal class. Thus the nicest: a method, passing a method handle did not reach the answer. Thanks
– Joop Eggen
21 hours ago
@Marco13 indeed the nicest solution. I wanted to express the OO-way of not having an if-else-if/switch, and to Show that one can immediately use lambdas. eliminating an internal class. Thus the nicest: a method, passing a method handle did not reach the answer. Thanks
– Joop Eggen
21 hours ago
add a comment |
up vote
1
down vote
Create CalculateCallback
which is responsible for managing the action after the calculation is done. So perform any calculations there necessary once calculation is done.
@FunctionalInterface
public interface CalculateCallback {
public void perform(double value);
}
AreaCalculator
is responsible for doing calculations and performing the calculate call back. Once the slider changes the calculation should go through AreaCalculator
.
public class AreaCalculator {
private CalculateCallback perimeterCalculatorCallback;
private CalculateCallback areaCalculatorCallback;
private MyShape myShape;
public AreaCalculator(CalculateCallback perimeterCalculatorCallback, CalculateCallback areaCalculatorCallback) {
this.perimeterCalculatorCallback = perimeterCalculatorCallback;
this.areaCalculatorCallback = areaCalculatorCallback;
}
public void doCalculate(int currentValue) {
if (null != myShape) {
double bLength = myShape.calculatePerimeter(currentValue);
perimeterCalculatorCallback.perform(bLength);
double bArea = myShape.calculateArea(currentValue);
areaCalculatorCallback.perform(bArea);
}
}
public void setMyShape(MyShape myShape) {
this.myShape = myShape;
}
}
ShapeFactory
is responsible to provide MyShape
according to parameter. I didn't implement that. Please makes sure to implement this.
public class ShapeFactory {
public static MyShape getMyShape(String item) {
//Here you have to return MyShape according to parameter.
}
}
ShapeHandler
is responsible for handling change. It will perform calculation through AreaCalculator
by providing MyShape
according to action.
public class ShapeHandler implements ActionListener {
private AreaCalculator areaCalculator;
private ActionDoneCallback actionDoneCallback;
public ShapeHandler(AreaCalculator areaCalculator, ActionDoneCallback doneCallback) {
this.areaCalculator = areaCalculator;
this.actionDoneCallback = doneCallback;
}
@Override
public void actionPerformed(ActionEvent e) {
MyShape shape = ShapeFactory.getMyShape(e.getActionCommand());
areaCalculator.setMyShape(shape);
actionDoneCallback.perform();
}
}
Your MyFrame
constructor should like below.
Its responsible to create callback since its the owner of component and this need to modify according to requirement.
public MyFrame() {
// Create frame, panels and items within
DecimalFormat numberFormat = new DecimalFormat("#.00");
AreaCalculator areaCalculator = new AreaCalculator(
(value) -> bLengthOutputField.setText(numberFormat.format(value)),
(value -> areaOutputField1.setText(numberFormat.format(value))));
ShapeHandler shapeHandler = new ShapeHandler(areaCalculator, () -> shapeSlider.setEnabled(true));
squareMenuItem.addActionListener(shapeHandler);
triangleMenuItem.addActionListener(shapeHandler);
circleMenuItem.addActionListener(shapeHandler);
shapeSlider.setEnabled(false);
shapeSlider.addChangeListener(e -> areaCalculator.doCalculate(shapeSlider.getValue()));
exitButton2.addActionListener(new CloseListener());
}
Once a shape is selected ShapeHandler
will set MyShape
in AreaCalculator
.
Once the Jslider is changed it will do the calculation base on the value.
I design this under SOLID principles and base on TDD.
so you can write unit test easy for this design.
Let me to know if you need some clarification.
Thank you so much for your time. What are the ActionDoneCallBack class and the CalculateCallBack class please? I have never used these classes before.
– Danielmt
Nov 9 '17 at 10:08
Update the text field is responsible by MyFrame after the calculation. Calculation responsible by AreaCalculator. What I have done is separate responsible. (Please read about SOLID principle) The process after calculation, provided by outside. so if we want to use this calculator in another frame you can just provide callback implementation.
– Chamly Idunil
Nov 10 '17 at 4:19
add a comment |
up vote
1
down vote
Create CalculateCallback
which is responsible for managing the action after the calculation is done. So perform any calculations there necessary once calculation is done.
@FunctionalInterface
public interface CalculateCallback {
public void perform(double value);
}
AreaCalculator
is responsible for doing calculations and performing the calculate call back. Once the slider changes the calculation should go through AreaCalculator
.
public class AreaCalculator {
private CalculateCallback perimeterCalculatorCallback;
private CalculateCallback areaCalculatorCallback;
private MyShape myShape;
public AreaCalculator(CalculateCallback perimeterCalculatorCallback, CalculateCallback areaCalculatorCallback) {
this.perimeterCalculatorCallback = perimeterCalculatorCallback;
this.areaCalculatorCallback = areaCalculatorCallback;
}
public void doCalculate(int currentValue) {
if (null != myShape) {
double bLength = myShape.calculatePerimeter(currentValue);
perimeterCalculatorCallback.perform(bLength);
double bArea = myShape.calculateArea(currentValue);
areaCalculatorCallback.perform(bArea);
}
}
public void setMyShape(MyShape myShape) {
this.myShape = myShape;
}
}
ShapeFactory
is responsible to provide MyShape
according to parameter. I didn't implement that. Please makes sure to implement this.
public class ShapeFactory {
public static MyShape getMyShape(String item) {
//Here you have to return MyShape according to parameter.
}
}
ShapeHandler
is responsible for handling change. It will perform calculation through AreaCalculator
by providing MyShape
according to action.
public class ShapeHandler implements ActionListener {
private AreaCalculator areaCalculator;
private ActionDoneCallback actionDoneCallback;
public ShapeHandler(AreaCalculator areaCalculator, ActionDoneCallback doneCallback) {
this.areaCalculator = areaCalculator;
this.actionDoneCallback = doneCallback;
}
@Override
public void actionPerformed(ActionEvent e) {
MyShape shape = ShapeFactory.getMyShape(e.getActionCommand());
areaCalculator.setMyShape(shape);
actionDoneCallback.perform();
}
}
Your MyFrame
constructor should like below.
Its responsible to create callback since its the owner of component and this need to modify according to requirement.
public MyFrame() {
// Create frame, panels and items within
DecimalFormat numberFormat = new DecimalFormat("#.00");
AreaCalculator areaCalculator = new AreaCalculator(
(value) -> bLengthOutputField.setText(numberFormat.format(value)),
(value -> areaOutputField1.setText(numberFormat.format(value))));
ShapeHandler shapeHandler = new ShapeHandler(areaCalculator, () -> shapeSlider.setEnabled(true));
squareMenuItem.addActionListener(shapeHandler);
triangleMenuItem.addActionListener(shapeHandler);
circleMenuItem.addActionListener(shapeHandler);
shapeSlider.setEnabled(false);
shapeSlider.addChangeListener(e -> areaCalculator.doCalculate(shapeSlider.getValue()));
exitButton2.addActionListener(new CloseListener());
}
Once a shape is selected ShapeHandler
will set MyShape
in AreaCalculator
.
Once the Jslider is changed it will do the calculation base on the value.
I design this under SOLID principles and base on TDD.
so you can write unit test easy for this design.
Let me to know if you need some clarification.
Thank you so much for your time. What are the ActionDoneCallBack class and the CalculateCallBack class please? I have never used these classes before.
– Danielmt
Nov 9 '17 at 10:08
Update the text field is responsible by MyFrame after the calculation. Calculation responsible by AreaCalculator. What I have done is separate responsible. (Please read about SOLID principle) The process after calculation, provided by outside. so if we want to use this calculator in another frame you can just provide callback implementation.
– Chamly Idunil
Nov 10 '17 at 4:19
add a comment |
up vote
1
down vote
up vote
1
down vote
Create CalculateCallback
which is responsible for managing the action after the calculation is done. So perform any calculations there necessary once calculation is done.
@FunctionalInterface
public interface CalculateCallback {
public void perform(double value);
}
AreaCalculator
is responsible for doing calculations and performing the calculate call back. Once the slider changes the calculation should go through AreaCalculator
.
public class AreaCalculator {
private CalculateCallback perimeterCalculatorCallback;
private CalculateCallback areaCalculatorCallback;
private MyShape myShape;
public AreaCalculator(CalculateCallback perimeterCalculatorCallback, CalculateCallback areaCalculatorCallback) {
this.perimeterCalculatorCallback = perimeterCalculatorCallback;
this.areaCalculatorCallback = areaCalculatorCallback;
}
public void doCalculate(int currentValue) {
if (null != myShape) {
double bLength = myShape.calculatePerimeter(currentValue);
perimeterCalculatorCallback.perform(bLength);
double bArea = myShape.calculateArea(currentValue);
areaCalculatorCallback.perform(bArea);
}
}
public void setMyShape(MyShape myShape) {
this.myShape = myShape;
}
}
ShapeFactory
is responsible to provide MyShape
according to parameter. I didn't implement that. Please makes sure to implement this.
public class ShapeFactory {
public static MyShape getMyShape(String item) {
//Here you have to return MyShape according to parameter.
}
}
ShapeHandler
is responsible for handling change. It will perform calculation through AreaCalculator
by providing MyShape
according to action.
public class ShapeHandler implements ActionListener {
private AreaCalculator areaCalculator;
private ActionDoneCallback actionDoneCallback;
public ShapeHandler(AreaCalculator areaCalculator, ActionDoneCallback doneCallback) {
this.areaCalculator = areaCalculator;
this.actionDoneCallback = doneCallback;
}
@Override
public void actionPerformed(ActionEvent e) {
MyShape shape = ShapeFactory.getMyShape(e.getActionCommand());
areaCalculator.setMyShape(shape);
actionDoneCallback.perform();
}
}
Your MyFrame
constructor should like below.
Its responsible to create callback since its the owner of component and this need to modify according to requirement.
public MyFrame() {
// Create frame, panels and items within
DecimalFormat numberFormat = new DecimalFormat("#.00");
AreaCalculator areaCalculator = new AreaCalculator(
(value) -> bLengthOutputField.setText(numberFormat.format(value)),
(value -> areaOutputField1.setText(numberFormat.format(value))));
ShapeHandler shapeHandler = new ShapeHandler(areaCalculator, () -> shapeSlider.setEnabled(true));
squareMenuItem.addActionListener(shapeHandler);
triangleMenuItem.addActionListener(shapeHandler);
circleMenuItem.addActionListener(shapeHandler);
shapeSlider.setEnabled(false);
shapeSlider.addChangeListener(e -> areaCalculator.doCalculate(shapeSlider.getValue()));
exitButton2.addActionListener(new CloseListener());
}
Once a shape is selected ShapeHandler
will set MyShape
in AreaCalculator
.
Once the Jslider is changed it will do the calculation base on the value.
I design this under SOLID principles and base on TDD.
so you can write unit test easy for this design.
Let me to know if you need some clarification.
Create CalculateCallback
which is responsible for managing the action after the calculation is done. So perform any calculations there necessary once calculation is done.
@FunctionalInterface
public interface CalculateCallback {
public void perform(double value);
}
AreaCalculator
is responsible for doing calculations and performing the calculate call back. Once the slider changes the calculation should go through AreaCalculator
.
public class AreaCalculator {
private CalculateCallback perimeterCalculatorCallback;
private CalculateCallback areaCalculatorCallback;
private MyShape myShape;
public AreaCalculator(CalculateCallback perimeterCalculatorCallback, CalculateCallback areaCalculatorCallback) {
this.perimeterCalculatorCallback = perimeterCalculatorCallback;
this.areaCalculatorCallback = areaCalculatorCallback;
}
public void doCalculate(int currentValue) {
if (null != myShape) {
double bLength = myShape.calculatePerimeter(currentValue);
perimeterCalculatorCallback.perform(bLength);
double bArea = myShape.calculateArea(currentValue);
areaCalculatorCallback.perform(bArea);
}
}
public void setMyShape(MyShape myShape) {
this.myShape = myShape;
}
}
ShapeFactory
is responsible to provide MyShape
according to parameter. I didn't implement that. Please makes sure to implement this.
public class ShapeFactory {
public static MyShape getMyShape(String item) {
//Here you have to return MyShape according to parameter.
}
}
ShapeHandler
is responsible for handling change. It will perform calculation through AreaCalculator
by providing MyShape
according to action.
public class ShapeHandler implements ActionListener {
private AreaCalculator areaCalculator;
private ActionDoneCallback actionDoneCallback;
public ShapeHandler(AreaCalculator areaCalculator, ActionDoneCallback doneCallback) {
this.areaCalculator = areaCalculator;
this.actionDoneCallback = doneCallback;
}
@Override
public void actionPerformed(ActionEvent e) {
MyShape shape = ShapeFactory.getMyShape(e.getActionCommand());
areaCalculator.setMyShape(shape);
actionDoneCallback.perform();
}
}
Your MyFrame
constructor should like below.
Its responsible to create callback since its the owner of component and this need to modify according to requirement.
public MyFrame() {
// Create frame, panels and items within
DecimalFormat numberFormat = new DecimalFormat("#.00");
AreaCalculator areaCalculator = new AreaCalculator(
(value) -> bLengthOutputField.setText(numberFormat.format(value)),
(value -> areaOutputField1.setText(numberFormat.format(value))));
ShapeHandler shapeHandler = new ShapeHandler(areaCalculator, () -> shapeSlider.setEnabled(true));
squareMenuItem.addActionListener(shapeHandler);
triangleMenuItem.addActionListener(shapeHandler);
circleMenuItem.addActionListener(shapeHandler);
shapeSlider.setEnabled(false);
shapeSlider.addChangeListener(e -> areaCalculator.doCalculate(shapeSlider.getValue()));
exitButton2.addActionListener(new CloseListener());
}
Once a shape is selected ShapeHandler
will set MyShape
in AreaCalculator
.
Once the Jslider is changed it will do the calculation base on the value.
I design this under SOLID principles and base on TDD.
so you can write unit test easy for this design.
Let me to know if you need some clarification.
edited Nov 8 '17 at 5:25
answered Nov 8 '17 at 4:48
Chamly Idunil
1114
1114
Thank you so much for your time. What are the ActionDoneCallBack class and the CalculateCallBack class please? I have never used these classes before.
– Danielmt
Nov 9 '17 at 10:08
Update the text field is responsible by MyFrame after the calculation. Calculation responsible by AreaCalculator. What I have done is separate responsible. (Please read about SOLID principle) The process after calculation, provided by outside. so if we want to use this calculator in another frame you can just provide callback implementation.
– Chamly Idunil
Nov 10 '17 at 4:19
add a comment |
Thank you so much for your time. What are the ActionDoneCallBack class and the CalculateCallBack class please? I have never used these classes before.
– Danielmt
Nov 9 '17 at 10:08
Update the text field is responsible by MyFrame after the calculation. Calculation responsible by AreaCalculator. What I have done is separate responsible. (Please read about SOLID principle) The process after calculation, provided by outside. so if we want to use this calculator in another frame you can just provide callback implementation.
– Chamly Idunil
Nov 10 '17 at 4:19
Thank you so much for your time. What are the ActionDoneCallBack class and the CalculateCallBack class please? I have never used these classes before.
– Danielmt
Nov 9 '17 at 10:08
Thank you so much for your time. What are the ActionDoneCallBack class and the CalculateCallBack class please? I have never used these classes before.
– Danielmt
Nov 9 '17 at 10:08
Update the text field is responsible by MyFrame after the calculation. Calculation responsible by AreaCalculator. What I have done is separate responsible. (Please read about SOLID principle) The process after calculation, provided by outside. so if we want to use this calculator in another frame you can just provide callback implementation.
– Chamly Idunil
Nov 10 '17 at 4:19
Update the text field is responsible by MyFrame after the calculation. Calculation responsible by AreaCalculator. What I have done is separate responsible. (Please read about SOLID principle) The process after calculation, provided by outside. so if we want to use this calculator in another frame you can just provide callback implementation.
– Chamly Idunil
Nov 10 '17 at 4:19
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f179810%2fswing-application-to-compute-the-area-and-perimeter-of-shapes%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown