Java design for multiple values scenario - java

I have two combo-boxes as below,
whenever i click done button, i get the values from combo-box and store it in a object like below,
public class comboValues{
private String label1ComboString;
private String label2ComboString;
public String setLabel1Combo(String val){
this.label1ComboString = val;
}
public String setLabel2Combo(String val){
this.label2ComboString = val;
}
public void getLabel1Combo(){
return this.label1ComboString;
}
public void getLabel2Combo(){
return this.label2ComboString;
}
}
in a controller class i use,
comboValues obj = new comboValues();
obj.setLabel1Combo(label1ComboBox.getSelectionModel().getSelectedItem());
obj.setLabel2Combo(label2ComboBox.getSelectionModel().getSelectedItem());
For a design with two combo box the code looks simple. My doubt is what if the number of combo-boxes increases? with the above approach code will have
lot of lines. What is the design to overcome this problem and how can i implement that to this scenario?

You can have an array or an ArrayList of ComboBoxes. This way you can reference an arbitrary number of boxes. Your class would change to something like this:
public class ComboValues {
private String[] comboStrings;
...
public void setComboLabel(String label, int comboNum) {
comboStrings[comboNum] = label;
}
public void getComboLabel(int comboNum) {
return comboStrings[comboNum];
}
public void getComboBoxCount() {
return comboStrings.length;
}
}
...
String[] labels = ...
for (int i = 0; i < obj.getComboBoxCount(); i++) {
obj.setComboLabel(labels[i], i);
}

I can see from your approach that you want to add more combo-boxs and against it you want to do less code in java to handle those all.
You have option of implementing Array List collection and store multiple combo boxes inside this. so every time you will not be needed to create new object and it will become dynamic.
Hope it will clear your doubt. If you have not cleared please comment.

Related

Is there any way to delete entries of an arraylist dynamically

As you can see from the image below I want to select something from my table ( which changes whenever I press a button from the vertical box to the left i.e "Overview", "Orders" ... ) and delete the record from an array ( i.e. where the content comes from ).
The method I approached bellow works but it is not elegant since I have to create at most 8 if statements for each button id. Is there any way to delete the content dynamically. Is there any way for the JVM to figure out which record belongs to which array list?
TableController
#FXML
private TableView<Object> defaultTableView;
public void delete(){
if( MockServer.getServer().currentButton.equals("btnIngredients"))
MockServer.getServer().removeIngredient(defaultTableView.getSelectionModel().getSelectedItem());
else if ( MockServer.------.equals("btnOrders"))
MockServer.getServer().removeOrder(defaultTableView.getSelectionModel().getSelectedItem());
}
Controller
#FXML
private TableController tableController;
#FXML
public void deleteRecord(ActionEvent event){
tableController.delete();
}
MockServer
public class MockServer implements ServerInterface {
public Restaurant restaurant;
public ArrayList<Dish> dishes = new ArrayList<Dish>();
public ArrayList<Drone> drones = new ArrayList<Drone>();
public ArrayList<Ingredient> ingredients = new ArrayList<Ingredient>();
public ArrayList<Order> orders = new ArrayList<Order>();
public ArrayList<Staff> staff = new ArrayList<Staff>();
public MockServer(){}
public ArrayList<Ingredient> getIngredients() { return this.ingredients; }
public ArrayList<Order> getOrders() { return this.orders; }
public ArrayList<Staff> getStaff() { return this.staff; }
....
static public ServerInterface getServer(){
return server;
}
#Override
public void removeIngredient(Ingredient ingredient) {
int index = this.ingredients.indexOf(ingredient);
this.ingredients.remove(index);
this.notifyUpdate();
}
}
This pseudocode will need refactoring since I don't have all the code that you are using but I wish that you will get the general idea
Ok I believe that in the button click code you have to tell your mock server which list is currently used try adding this to the mock server
List currentList = null;
public void setCurrentList(String listName) { // you can use integer but the best is to use enum type setCurrentList(enum) this way you will get tapeSafety
switch(listName){
case "ingredients" : currentList = ingredients ; break;
//other cases
default : throw new Exception(" list not referred error with key value"+listName);
}
}
public void delete(Object o){
int index = this.currentList.indexOf(o);
this.currentList.remove(index);
}
now you can update you controller delete as bellow
public void delete(){
MockServer.getServer().delete(defaultTableView.getSelectionModel().getSelectedItem());
}
Why this should work?
you have to know that there is a good practice that says code to an interface, not an implementation
As you know List in java is an interface so when I assigned the ingredients object this interface will reference the same ArrayList as the object and it will take all it behaviours (how to search for an ingredient object etc...) this way when we will use the currentList on runtime after a button click we are sure that the currentList will be the same as the clicked list and pointing to the same list in the memory
Wish this simple and really resume explanation could help you

How to convert type Class<?> to int

I am trying to convert this data type to call out the method later on in another class to switch around layouts being made in other methods such as recipe1Layout(); by the index number of a class that has a field of a Class<?> Array.
Here is the getItem() method
public int getItem(){
int index = 0;
for(int i = 0; i < 100; i++) {
try{
index = recipe.getClass().getField("Classes").get(i);
} catch(Exception e){
}
}
return index;
}
Here is the Recipe Class
public class Recipes {
public Class<?>[] Classes = {
ChileConLecheActivity.class,
ArrozActivity.class,
EnchiladasActivity.class,
SopaActivity.class
};
}
The type of Class needs to be here because I have other uses for the recipe class.
For example, making a new instance of all classes to later on be called out to make adjustments to all the classes with one method.
The only thing I can think of is converting the type Class to an int so I can call out the method returning the index number I can do something like recipe.
index = Integer.parseInt(Classes[I].getName().toString());
But this is where I am asking for help I have no idea how to get rid of the error in the logcat.
The error shows up as
IndexOutOfArrayException
First off, stop using reflection. Use a public static array.
public class Recipes {
public static final Class<?>[] CLASSES = {
ChileConLecheActivity.class,
ArrozActivity.class,
EnchiladasActivity.class,
SopaActivity.class
};
}
Then, assuming your recipe instance has a field of what Class<Activity> it is assigned to, then, you would want something like this
public int getItem(){
int index = -1;
for(int i = 0 ; i < Recipe.CLASSES.length; i++) {
if (recipe.getActivityClass().equals(Recipe.CLASSES[i]) {
index = i;
break;
}
}
return index;
}
However, under certain situations, coupling one Activity class to any single Recipe instance, probably isn't a good idea.
I am trying to convert this data type to call out the method later on in another class to switch around layouts being made in other methods
if I understand what you are trying to do, you want a some mapping structure to some classes which have some pre-defined layouts.
Generally, this can be done with enums and OOP patterns
Have some base classes like this
public interface Layoutable {
int getLayout();
}
public enum Recipe {
ChileConLeche(R.layout.chile_con_leche),
Arroz(R.layout.arroz),
Enchiladas(R.layout.enchiladas),
Sopa(R.layout.sopa)
int layout;
Recipe(int layout) { this.layout = layout };
}
Ideally, you would want to use Fragments, but here is an example of an Activity structure
public abstract class RecipeActvity extends AppCompatActivity implements Layoutable {
protected Recipe recipe;
protected int getLayout() { return recipe.layout; }
}
public class ChileConLecheActivity extends RecipeActvity {
public ChileConLecheActivity() {
this.recipe = Recipe.ChileConLeche;
}
#Override
public void onCreate(...) {
setContentView(getLayout());
}
}
You can also combine this with a Map<Recipe, Class<RecipeActivity>>, from which you would use map.get(Recipe.ChileConCarne) to get the respective class element, for which you can startActivity() with

Java - changing a variable through pass-by-value

So I've read about the pass-by-value nature of Java and I've tried to change my variable after passing it to a function by having the function return the variable again. I didn't succeed in that.
My code
public class Logic {
private int position;
public class Logic(){
position = 1;
}
public void appendPosition(){
position = calculatePosition(position);
}
}
This is the barebones code. I call this method from an instance of Logic which is instantiated in another class:
public class MainLogic {
ILogic L;
public MainLogic(ILogic L){
this.L = L;
}
public void start(){
L.appendPosition();
}
}
Through repeated debugging I find to my dismay that the position variable does not change at all. The position variable passed to calculatePosition changes fine, as expected. What am I missing? I've tried making the variable public and static.
calculatePosition
private int calculatePosition(int position){
position += 6;
if(snakeLocations[position]>0) {
position -= 6;
}
else if(ladderLocations[position]>0) {
position += 6;
}
return position;
}
private final int[] snakeLocations = new int[] {0,0,0,0,0,0,0,0,0,9,0,0,0,13,0,0,0,0,0,19,0,0,0,0,0};
private final int[] ladderLocations = new int[] {0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,15,0,0,0,0,20,0,0,0,0};
public class Logic {
private int position;
public Logic(){
position = 1;
}
//to get position.....................
public int getPosition(){
return this.position;
}
public void appendPosition(){
position = calculatePosition(position);
}
private int calculatePosition(int position){
position += 6;
if(snakeLocations[position]>0) {
position -= 6;
}
else if(ladderLocations[position]>0) {
position += 6;
}
return position;
}
private final int[] snakeLocations =
new int[] {0,0,0,0,0,0,0,0,0,9,0,0,0,13,0,0,0,0,0,19,0,0,0,0,0};
private final int[] ladderLocations =
new int[] {0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,15,0,0,0,0,20,0,0,0,0};
}
//next class
public class MainLogic {
Logic L;
public MainLogic(Logic L){
this.L = L;
}
public void start(){
L.appendPosition();
}
public static void main(String[] args) {
Logic L = new Logic();
MainLogic ml = new MainLogic(L);
System.out.println(ml.L.getPosition());
ml.start();
System.out.println(ml.L.getPosition());
}
}
Let's read your code.
// There is a logic class.
public class Logic {
// So Logic has a position. it starts with zero.
private int position;
// Logic also has an inner class, also called Logic.
public class Logic(){
position = 1;
// When a new Logic().Logic() is created, the instance
// variable of the parent instance gets set to one. WHAT?!?
}
// ... lots of code
}
So, It's a bit like that Yo Dawg! meme - I heard you like Logic, so we've put A logic instance into your Logic instance so you can Logic while your Logic.
You probably want a constructor.
// So this is Logic.
public class Logic {
private int position;
// When an Logic instance is created, position starts with 1.
public Logic(){
this.position = 1;
}
Ok. So we're not talking about Yo Dawg Memes.
So Let's talk pass by value.
Pass-by-value means classes are like very egotistic children: You can't play with their toys, unless they tell you so.
This is a good thingĀ® since this means only the owning instance is allowed to change their private state. Trust me, it prevents quite a bit of havoc.
One way to allow the outside world to actually change the state is by using query and mutator methods. Back in the day, we used to call them getter and setter, but that sounds too simple, so software architects will usually use the fancier term.
But... all of this doesn't really apply since calculatePosition() is defined at Logic. Oops.
Let's try this:
Renaming some instance variables
Be a bit verbose to help the debugger. baby steps.
(Also, dropping a few jokes to fish for upvotes).
public class Logic {
private int position = 1;
public void appendPosition(){
// When debugging strange stuff,
// keep each step simple.
// Is calculatePosition working as it should?
int newPosition = calculatePosition(this.position);
this.position = newPosition;
}
// Always use parameters as final. It's good karma.
// You don't NEED to declare them as final,
// but let's try to be EXTRA clear.
private int calculatePosition(final int targetPosition){
// Yes, make as much as you can immutable
// You'll save a ton of mental bandwidth.
final int localCopy = targetPosition +6;
if(snakeLocations[localCopy]>0) {
return (localCopy -6);
// Don't force the maintenance programmer to
// read all your stuff. Return often, return early.
// This isn't Cc++, where you need to
// actually free your reference/pointers,
// so there's no point enforcing a single return.
}
if(ladderLocations[localCopy]>0) {
return (localCopy+6);
}
return localCopy;
}
}
So... Did this worked as it should?
I found the answer. This is often my mistake in posting here. I try to strip down my code as much as possible to ease the work for you guys, but sometimes the problem lies outside of the scope of what I provide due to a lack of understanding, or oversight, on my part.
I was actually calling MainLogic from two levels above:
public mainFrame() {
initComponents();
logic = Factory.getMainLogic();
}
where
public static class Factory {
public MainLogic getMainLogic(){
PlayerLogic pL = new PlayerLogic();
ImageLogic iL = new ImageLogic();
DieLogic dL = new DieLogic();
MainLogic mainLogic = new MainLogic(pL,iL,dL);
return mainLogic;
}
}
I forgot I had accidentally put Factory as static. My sincerest apologies for wasting your time.

Synchronizing events / data in java swing between many different classes

My question is conceptual about synchronizing data and events in programming a gui. (This example shows batch state being the facilitator of taking classes that implement the same interface and dynamical updating cells in two different frames.This code is where I got my idea. )
I am assuming that I will create new instances of this batch state object specifically in the classes where an event is triggered(panel) and the reaction to that event(another panel) . I will do this by adding the classes that need to communicate to the a list of bsListeners. Then call the batch state function like "setSelectedCell()" to iterate over each class to synchronize them.
The Problem
This would work perfect if the object both shared the same arrayList but since they are both new instances they don't. I tried changing things to static and it is freaking out especially in the interface. Is this approach logical I am brand new to programming gui's? Sorry this is a novel.
interface BatchStateListener {
public void valueChanged(Cell cell, String newValue);
public void selectedCellChanged(Cell newSelectedCell)
}
class BatchState {
private String[][] values;
private Cell selectedCell;
private List<BatchStateListener> listeners;
public BatchState(int records, int fields) {
values = new String[records][fields];
selectedCell = null;
listeners = new ArrayList<BatchStateListener>();
}
public void addListener(BatchStateListener l) {
listeners.add(l);
}
public void setValue(Cell cell, String value) {
values[cell.record][cell.field] = value;
for (BatchStateListener l : listeners) {
l.valueChanged(cell, value);
}
}
public String getValue(Cell cell) {
return values[cell.record][cell.field];
}
public void setSelectedCell(Cell selCell) {
selectedCell = selCell;
for (BatchStateListener l : listeners) {
l.selectedCellChanged(selCell);
}
}
public Cell getSelectedCell() {
return selectedCell;
}
}
My questions was a bit confusing, but I came to my answer. I was just wondering how to implement this BatchState class in my code. I found that if I make it in main and pass it to the constructors frames/panels that need to communicate with each other they all can share reference to it.

How can I make a class implement an interface correctly?

I'm trying to make a class implement an interface correctly but seem to have hit a brick wall. I am not sure if the code I have already written is correct but it was the only way I understood how to approach the task. I have been given an interface with this information:
package mvcchords;
public interface NoteStore {
int getNextNote();
boolean hasNextNote();
void noteAdded(int midicode);
void start(int sortOrder);
}
The application displays piano keys which allow the user to click on them, and it saves the order they were clicked and the midicode of the notes for the specific sound. Then when the user clicks play, it recalls the tune in the order the notes were saved. When a user clicks on a note noteAdded is called. hasNextNote is used to check if it is the end of the saved notes or not. getNextNote is used to get the next note from the array list and start is called when the user clicks the play button. I have been told the integer sortOrder is irrelevant for this part of the task. I have been told that when the play button is clicked it should call the start method and then repeatedly call the getNextNote method until all the notes have been retrieved.
Below is the code I have written so far for a class to implement this interface;
import java.util.*;
import mvcchords.*;
public class MyNoteStore implements NoteStore {
public ArrayList<Integer> Notes;
public void noteAdded(int midicode) {
Notes.add(midicode);
}
public boolean hasNextNote(int k) {
if(Notes.get(k) != null)
return true;
else
return false;
}
public int getNextNote(int k) {
if(hasNextNote(Notes.get(k)) == true)
return Notes.get(k);
else
return 0;
}
public void start(int sortOrder) {
for(int k = 0; k < Notes.size(); k++){
hasNextNote(k);
getNextNote(k);
}
}
}
This code gives me an error saying
MyNoteStore is not abstract and does not override abstract method `hasNextNote()` in `mvcchords.NoteStore`.
I don't know where to go from here and any help would be appreciated. If further information is needed then I will do my best to clarify any points I have made.
Thank you in advance :)
While you have created methods with the correct names you need to have the correct parameters and return types as well. So in this case you need to alter:
int getNextNote(int i);
boolean hasNextNote(int k);
to remove the integer parameters.
Basically you need to keep track of the notes played back so far in the class so that you don't need to pass an integer about all the time. You could either use an Iterator or just store a integer to track the last index played. The below method uses an iterator, maybe you should try and create the one with an integer yourself.
public class MyNoteStore implements NoteStore {
ArrayList<Integer> notes = new ArrayList<Integer>();
Iterator<Integer> playbackIter;
public void noteAdded(int midicode) {
notes.add(midicode);
}
public boolean hasNextNote() {
if (playbackIter != null) {
return playbackIter.hasNext();
}
else {
return false;
}
}
public int getNextNote() {
if (playBackIter != null) {
return playBackIter.next();
}
else {
return -1;
}
}
public void start(int sortOrder) {
playBackIter = notes.iterator();
while(hasNextNote()) {
int note = getNextNote();
//play note
}
}
}
The parameters in the method are different between your implementation and the declaration in the interface.
Well,
your interface defines the methods:
int getNextNote();
boolean hasNextNote();
void noteAdded(int midicode);
void start(int sortOrder);
So,
your class has to implement them with the exact definition, which means with the same return type AND parameters. So you can either change them in the interface declaration or in the class implementation.

Categories