Reputation: 1
I wrote this little program for an specific utility, didn't optimize it yet but so far everything works as intended, but when I accidentaly double click on JTextField it crashes, and I have no idea why. (JTextField is on line 62 for the matter)
package smoothies;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import java.awt.*;
public class smoothies extends JFrame {
public smoothies(List<List<List<String>>> smoothies) {
//setBackground(new Color());
setDefaultCloseOperation(3);
setSize(400,400);
setLayout(new BorderLayout(50,50));
JPanel lIng= new JPanel();
lIng.setLayout(new GridLayout(8,2));
ArrayList<JCheckBox> ingredients = new ArrayList<>();
// kelp,horse,grapes,apple,pepper,nectar,milk,cactus,potato,salt,butter,pumpkin,guts,fang,mango,egg
JCheckBox kelp = new JCheckBox("kelp");
ingredients.add(kelp);
JCheckBox horse = new JCheckBox("horse");
ingredients.add(horse);
JCheckBox grapes = new JCheckBox("grapes");
ingredients.add(grapes);
JCheckBox apple = new JCheckBox("apple");
ingredients.add(apple);
JCheckBox pepper = new JCheckBox("pepper");
ingredients.add(pepper);
JCheckBox nectar = new JCheckBox("nectar");
ingredients.add(nectar);
JCheckBox milk = new JCheckBox("milk");
ingredients.add(milk);
JCheckBox cactus = new JCheckBox("cactus");
ingredients.add(cactus);
JCheckBox potato = new JCheckBox("potato");
ingredients.add(potato);
JCheckBox salt = new JCheckBox("salt");
ingredients.add(salt);
JCheckBox butter = new JCheckBox("butter");
ingredients.add(butter);
JCheckBox pumpkin = new JCheckBox("pumpkin");
ingredients.add(pumpkin);
JCheckBox guts = new JCheckBox("guts");
ingredients.add(guts);
JCheckBox fang = new JCheckBox("fang");
ingredients.add(fang);
JCheckBox mango = new JCheckBox("mango");
ingredients.add(mango);
JCheckBox egg = new JCheckBox("egg");
ingredients.add(egg);
for(JCheckBox ing: ingredients) {
lIng.add(ing);
}
Button calculate = new Button("calculate");
JTextField result = new JTextField("hai :D");
result.setEditable(false);
calculate.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("\n\n\n\n\n\n\n\n\n\n\n\nSMOOTHIES YOU CAN MAKE:");
for(List<List<String>> smoothie: smoothies) {
for(JCheckBox ing1: ingredients) {
if(smoothie.get(0).contains(ing1.getText()) && ing1.isSelected()) {
for(JCheckBox ing2: ingredients) {
if(smoothie.get(1).contains(ing2.getText()) && ing2.isSelected()) {
System.out.println(smoothie);
break;
}
}
}
}
}
}
});
Thread h = new Thread(new Runnable() {
@Override
public void run() {
while(true) {
int p = 0;
for(List<List<String>> smoothie: smoothies) {
for(JCheckBox ing1: ingredients) {
if(smoothie.get(0).contains(ing1.getText()) && ing1.isSelected()) {
for(JCheckBox ing2: ingredients) {
if(smoothie.get(1).contains(ing2.getText()) && ing2.isSelected()) {
p++;
break;
}
}
}
}
}
result.setText(String.valueOf(p));
}
}
});
h.start();
add(lIng,BorderLayout.WEST);
add(result,BorderLayout.CENTER);
add(calculate,BorderLayout.EAST);
setVisible(true);
}
public static void main(String[] args) {
List<List<List<String>>> smoothies = List.of(List.of(List.of("nectar"), List.of("nectar")),
List.of(List.of("nectar"), List.of("milk")),
List.of(List.of("grapes"), List.of("grapes")),
List.of(List.of("grapes"), List.of("horse","apple","cactus","salt","butter","mango")),
List.of(List.of("grapes"), List.of("nectar")),
List.of(List.of("grapes"), List.of("milk")),
List.of(List.of("milk"), List.of("milk")),
List.of(List.of("milk"), List.of("apple","cactus")),
List.of(List.of("milk"), List.of("salt")),
List.of(List.of("mango"), List.of("mango")),
List.of(List.of("mango"), List.of("kelp","apple","cactus","butter")),
List.of(List.of("nectar"), List.of("mango")),
List.of(List.of("milk"), List.of("mango")),
List.of(List.of("salt"), List.of("mango")),
List.of(List.of("cactus"), List.of("cactus","horse","nectar","pumpkin")),
List.of(List.of("cactus"), List.of("salt")),
List.of(List.of("pepper"), List.of("pepper")),
List.of(List.of("pepper"), List.of("cactus","pumpkin")),
List.of(List.of("pepper"), List.of("potato")),
List.of(List.of("pepper"), List.of("grapes","apple","milk","mango")),
List.of(List.of("apple"), List.of("apple")),
List.of(List.of("apple"), List.of("horse","nectar","cactus","potato")),
List.of(List.of("apple"), List.of("salt")),
List.of(List.of("kelp"), List.of("kelp")),
List.of(List.of("kelp"), List.of("grapes","apple","potato")),
List.of(List.of("kelp"), List.of("pumpkin")),
List.of(List.of("kelp"), List.of("milk")),
List.of(List.of("kelp"), List.of("salt")),
List.of(List.of("horse"), List.of("horse","kelp","pepper","nectar","potato","salt","mango")),
List.of(List.of("horse"), List.of("milk")),
List.of(List.of("potato"), List.of("potato")),
List.of(List.of("potato"), List.of("grapes","cactus","butter")),
List.of(List.of("nectar"), List.of("potato")),
List.of(List.of("milk"), List.of("potato")),
List.of(List.of("potato"), List.of("mango")),
List.of(List.of("potato"), List.of("salt")),
List.of(List.of("butter"), List.of("butter","kelp")),
List.of(List.of("apple"), List.of("butter")),
List.of(List.of("cactus"), List.of("butter")),
List.of(List.of("nectar"), List.of("butter")),
List.of(List.of("butter"), List.of("pumpkin")),
List.of(List.of("milk"), List.of("butter")),
List.of(List.of("salt"), List.of("butter")),
List.of(List.of("pumpkin"), List.of("pumpkin")),
List.of(List.of("pumpkin"), List.of("horse","grapes","apple","potato")),
List.of(List.of("nectar"), List.of("pumpkin")),
List.of(List.of("milk"), List.of("pumpkin")),
List.of(List.of("pumpkin"), List.of("mango")),
List.of(List.of("salt"), List.of("pumpkin")),
List.of(List.of("egg"), List.of("egg","grapes","nectar","milk","salt")),
List.of(List.of("egg"), List.of("mango")),
List.of(List.of("egg"), List.of("cactus")),
List.of(List.of("egg"), List.of("pepper")),
List.of(List.of("egg"), List.of("apple")),
List.of(List.of("egg"), List.of("kelp")),
List.of(List.of("egg"), List.of("horse")),
List.of(List.of("egg"), List.of("potato")),
List.of(List.of("egg"), List.of("butter")),
List.of(List.of("egg"), List.of("pumpkin")),
List.of(List.of("guts"), List.of("mango")),
List.of(List.of("guts"), List.of("cactus")),
List.of(List.of("fang"), List.of("pepper")),
List.of(List.of("guts"), List.of("pepper")),
List.of(List.of("guts"), List.of("apple")),
List.of(List.of("fang"), List.of("kelp")),
List.of(List.of("fang"), List.of("horse")),
List.of(List.of("fang"), List.of("potato")),
List.of(List.of("fang"), List.of("butter")),
List.of(List.of("fang"), List.of("pumpkin")));
System.out.println(smoothies);
new smoothies(smoothies);
}
}
You are not supposed to interact with it, and i did setEditable to false, but sometimes it just crashes out of nowhere, and other times it actualy sends the error
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: bad position: 1
that along something about caret, I don't understand what means this here
Upvotes: -1
Views: 64
Reputation: 48693
You should organize your code into reusable methods (and classes).
Use a singleton thread executor to spawn a loop to calculate the possible smoothies based on the currently selected ingredients.
Here is a refined updater method:
private void startSmoothieUpdater(List<Smoothie> smoothies) {
executor.submit(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
int smoothieCount = calculateSmoothiesCount(smoothies);
SwingUtilities.invokeLater(() -> resultField.setText(String.valueOf(smoothieCount)));
Thread.sleep(UPDATE_INTERVAL_MS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
}
Here it is in action. At the bottom, I included a YAML file that can be used as configuration. This makes the application more dynamic. A separate model
package makes data more readable and modular.
I also included lombok
and SnakeYAML
as dependencies:
implementation: 'org.yaml:snakeyaml:2.3'
compileOnly 'org.projectlombok:lombok:1.18.36'
package org.example.smoothies;
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.example.smoothies.model.Ingredients;
import org.example.smoothies.model.Smoothie;
import org.example.smoothies.model.SmoothiesWrapper;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
public class SmoothieApp {
private static final String[] INGREDIENTS_LIST = {
"apple", "butter", "cactus", "egg", "fang", "grapes",
"guts", "horse", "kelp", "mango", "milk", "nectar",
"pepper", "potato", "pumpkin", "salt"
};
private static final int WINDOW_WIDTH = 400;
private static final int WINDOW_HEIGHT = 400;
private static final int GRID_ROWS = 8;
private static final int GRID_COLUMNS = 2;
private static final int UPDATE_INTERVAL_MS = 500;
private final List<JCheckBox> ingredientCheckBoxes = new ArrayList<>();
private final JTextField resultField = new JTextField("hai :D");
private final ExecutorService executor = Executors.newSingleThreadExecutor();
public SmoothieApp(List<Smoothie> smoothies) {
JFrame frame = initializeUI(smoothies);
startSmoothieUpdater(smoothies);
frame.setVisible(true);
}
private JFrame initializeUI(List<Smoothie> smoothies) {
JFrame frame = new JFrame("Smoothie Maker");
frame.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
frame.setLayout(new BorderLayout(10, 10));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.add(createIngredientPanel(), BorderLayout.WEST);
frame.add(resultField, BorderLayout.CENTER);
frame.add(createCalculateButton(smoothies), BorderLayout.EAST);
resultField.setEditable(false);
return frame;
}
private JPanel createIngredientPanel() {
JPanel panel = new JPanel(new GridLayout(GRID_ROWS, GRID_COLUMNS));
for (String ingredient : INGREDIENTS_LIST) {
JCheckBox checkBox = new JCheckBox(ingredient);
ingredientCheckBoxes.add(checkBox);
panel.add(checkBox);
}
return panel;
}
private JButton createCalculateButton(List<Smoothie> smoothies) {
JButton calculateButton = new JButton("Calculate");
calculateButton.addActionListener(e -> displayPossibleSmoothies(smoothies));
return calculateButton;
}
private void displayPossibleSmoothies(List<Smoothie> smoothies) {
System.out.println("\n=== SMOOTHIES YOU CAN MAKE ===");
boolean smoothiesFound = false;
for (Smoothie smoothie : smoothies) {
Ingredients ingredients = smoothie.getIngredients();
if (canMakeSmoothie(ingredients)) {
smoothiesFound = true;
System.out.printf("Smoothie: %s%n", smoothie.getName());
System.out.printf(" - Required: %s%n", String.join(", ", ingredients.getRequired()));
System.out.printf(" - Optional: %s%n%n", String.join(", ", ingredients.getOptional()));
}
}
if (!smoothiesFound) {
System.out.println("No smoothies can be made with the selected ingredients.");
}
System.out.println("================================");
}
private boolean canMakeSmoothie(Ingredients ingredients) {
return ingredients.getRequired().stream().anyMatch(this::isIngredientSelected) &&
ingredients.getOptional().stream().anyMatch(this::isIngredientSelected);
}
private boolean isIngredientSelected(String ingredient) {
return ingredientCheckBoxes.stream()
.anyMatch(box -> box.getText().equals(ingredient) && box.isSelected());
}
private void startSmoothieUpdater(List<Smoothie> smoothies) {
executor.submit(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
int smoothieCount = calculateSmoothiesCount(smoothies);
SwingUtilities.invokeLater(() -> resultField.setText(String.valueOf(smoothieCount)));
Thread.sleep(UPDATE_INTERVAL_MS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
}
private int calculateSmoothiesCount(List<Smoothie> smoothies) {
int count = 0;
for (Smoothie smoothie : smoothies) {
Ingredients ingredients = smoothie.getIngredients();
if (canMakeSmoothie(ingredients)) {
count++;
}
}
return count;
}
public static void main(String[] args) {
Yaml yaml = new Yaml(new Constructor(SmoothiesWrapper.class, new LoaderOptions()));
try (InputStream inputStream = SmoothieApp.class.getClassLoader().getResourceAsStream("smoothies.yaml")) {
if (inputStream == null) {
throw new RuntimeException("smoothies.yaml not found");
}
SmoothiesWrapper wrapper = yaml.load(inputStream);
SwingUtilities.invokeLater(() -> new SmoothieApp(wrapper.getSmoothies()));
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Failed to load YAML", e);
}
}
}
package org.example.smoothies.model;
import java.util.*;
import lombok.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SmoothiesWrapper {
private List<Smoothie> smoothies;
}
package org.example.smoothies.model;
import lombok.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Smoothie {
private String name;
private Ingredients ingredients;
}
package org.example.smoothies.model;
import lombok.*;
import java.util.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Ingredients {
private List<String> required;
private List<String> optional;
}
Note: I generated a YAML file (smoothies.yaml
) based on all the smoothie possibilities from your original code:
smoothies:
- name: Nectar Smoothie
ingredients:
required: ["nectar"]
optional: ["nectar"]
- name: Nectar Milkshake
ingredients:
required: ["nectar"]
optional: ["milk"]
- name: Grape Smoothie
ingredients:
required: ["grapes"]
optional: ["grapes"]
- name: Grape Medley
ingredients:
required: ["grapes"]
optional: ["horse", "apple", "cactus", "salt", "butter", "mango"]
- name: Grape Nectar Blend
ingredients:
required: ["grapes"]
optional: ["nectar"]
- name: Grape Milkshake
ingredients:
required: ["grapes"]
optional: ["milk"]
- name: Double Milkshake
ingredients:
required: ["milk"]
optional: ["milk"]
- name: Milk Cactus Delight
ingredients:
required: ["milk"]
optional: ["apple", "cactus"]
- name: Milk with a Dash of Salt
ingredients:
required: ["milk"]
optional: ["salt"]
- name: Mango Puree
ingredients:
required: ["mango"]
optional: ["mango"]
- name: Mango Adventure
ingredients:
required: ["mango"]
optional: ["kelp", "apple", "cactus", "butter"]
- name: Nectar Mango Fusion
ingredients:
required: ["nectar"]
optional: ["mango"]
- name: Milk Mango Smoothie
ingredients:
required: ["milk"]
optional: ["mango"]
- name: Salted Mango Smoothie
ingredients:
required: ["salt"]
optional: ["mango"]
- name: Cactus Delight
ingredients:
required: ["cactus"]
optional: ["cactus", "horse", "nectar", "pumpkin"]
- name: Cactus and Salt Combo
ingredients:
required: ["cactus"]
optional: ["salt"]
- name: Pepper Explosion
ingredients:
required: ["pepper"]
optional: ["pepper"]
- name: Spicy Cactus Pumpkin Mix
ingredients:
required: ["pepper"]
optional: ["cactus", "pumpkin"]
- name: Pepper Potato Mashup
ingredients:
required: ["pepper"]
optional: ["potato"]
- name: Pepper Grape Smoothie
ingredients:
required: ["pepper"]
optional: ["grapes", "apple", "milk", "mango"]
- name: Apple Smoothie
ingredients:
required: ["apple"]
optional: ["apple"]
- name: Apple Adventure
ingredients:
required: ["apple"]
optional: ["horse", "nectar", "cactus", "potato"]
- name: Salted Apple Mix
ingredients:
required: ["apple"]
optional: ["salt"]
- name: Kelp Smoothie
ingredients:
required: ["kelp"]
optional: ["kelp"]
- name: Kelp Fruit Blend
ingredients:
required: ["kelp"]
optional: ["grapes", "apple", "potato"]
- name: Pumpkin with a Hint of Kelp
ingredients:
required: ["kelp"]
optional: ["pumpkin"]
- name: Kelp Milkshake
ingredients:
required: ["kelp"]
optional: ["milk"]
- name: Salted Kelp Smoothie
ingredients:
required: ["kelp"]
optional: ["salt"]
- name: Horsepower Smoothie
ingredients:
required: ["horse"]
optional: ["horse", "kelp", "pepper", "nectar", "potato", "salt", "mango"]
- name: Horse Milkshake
ingredients:
required: ["horse"]
optional: ["milk"]
- name: Potato Smoothie
ingredients:
required: ["potato"]
optional: ["potato"]
- name: Potato Grape Mashup
ingredients:
required: ["potato"]
optional: ["grapes", "cactus", "butter"]
- name: Potato Nectar Blend
ingredients:
required: ["nectar"]
optional: ["potato"]
- name: Milk Potato Mix
ingredients:
required: ["milk"]
optional: ["potato"]
- name: Mango Potato Fusion
ingredients:
required: ["potato"]
optional: ["mango"]
- name: Salted Potato
ingredients:
required: ["potato"]
optional: ["salt"]
- name: Butter Smoothie
ingredients:
required: ["butter"]
optional: ["butter", "kelp"]
- name: Apple Butter Delight
ingredients:
required: ["apple"]
optional: ["butter"]
- name: Cactus Butter Smoothie
ingredients:
required: ["cactus"]
optional: ["butter"]
- name: Butter Nectar Mix
ingredients:
required: ["nectar"]
optional: ["butter"]
- name: Butter Pumpkin Smoothie
ingredients:
required: ["butter"]
optional: ["pumpkin"]
- name: Milk Butter Combo
ingredients:
required: ["milk"]
optional: ["butter"]
- name: Salted Butter Mix
ingredients:
required: ["salt"]
optional: ["butter"]
- name: Pumpkin Delight
ingredients:
required: ["pumpkin"]
optional: ["pumpkin"]
- name: Pumpkin Harvest
ingredients:
required: ["pumpkin"]
optional: ["horse", "grapes", "apple", "potato"]
- name: Pumpkin Nectar Smoothie
ingredients:
required: ["nectar"]
optional: ["pumpkin"]
- name: Milk Pumpkin Fusion
ingredients:
required: ["milk"]
optional: ["pumpkin"]
- name: Pumpkin Mango Smoothie
ingredients:
required: ["pumpkin"]
optional: ["mango"]
- name: Salted Pumpkin Blend
ingredients:
required: ["salt"]
optional: ["pumpkin"]
- name: Egg Smoothie
ingredients:
required: ["egg"]
optional: ["egg", "grapes", "nectar", "milk", "salt"]
- name: Mango Egg Mix
ingredients:
required: ["egg"]
optional: ["mango"]
- name: Egg and Cactus Combo
ingredients:
required: ["egg"]
optional: ["cactus"]
- name: Spicy Egg
ingredients:
required: ["egg"]
optional: ["pepper"]
- name: Apple Egg Delight
ingredients:
required: ["egg"]
optional: ["apple"]
- name: Egg and Kelp Mix
ingredients:
required: ["egg"]
optional: ["kelp"]
- name: Horse Egg Smoothie
ingredients:
required: ["egg"]
optional: ["horse"]
- name: Potato Egg Combo
ingredients:
required: ["egg"]
optional: ["potato"]
- name: Buttered Egg Delight
ingredients:
required: ["egg"]
optional: ["butter"]
- name: Pumpkin Egg Fusion
ingredients:
required: ["egg"]
optional: ["pumpkin"]
- name: Gutsy Mango Mix
ingredients:
required: ["guts"]
optional: ["mango"]
- name: Guts and Cactus Combo
ingredients:
required: ["guts"]
optional: ["cactus"]
- name: Fang Pepper Mashup
ingredients:
required: ["fang"]
optional: ["pepper"]
- name: Gutsy Pepper Smoothie
ingredients:
required: ["guts"]
optional: ["pepper"]
- name: Apple Guts Smoothie
ingredients:
required: ["guts"]
optional: ["apple"]
- name: Fang Kelp Mix
ingredients:
required: ["fang"]
optional: ["kelp"]
- name: Horse Fang Smoothie
ingredients:
required: ["fang"]
optional: ["horse"]
- name: Potato Fang Delight
ingredients:
required: ["fang"]
optional: ["potato"]
- name: Butter Fang Fusion
ingredients:
required: ["fang"]
optional: ["butter"]
- name: Pumpkin Fang Combo
ingredients:
required: ["fang"]
optional: ["pumpkin"]
Upvotes: 0