Forgotten terminology regarding making objects from a class - java

It's several years since I actually took a programming class. I know I can do what I'm thinking of, but I cannot remember the terms, so I cannot look it up.
I'm writing a mock application for a HMI class. It orders pizzas. Right now, I use a separate class to pass the values of the pizza between activities. (Values like toppings, pizza size, etc). The class is named pizzaApplication.class, and an example value would be pizzaApplication.chkPepperoni = true;
The way it's set up now, I can only have one pizza. I'd like to be able to have the pizzaApplication class setup to have more than one pizza. The code (from memory) would then end up looking similar to
pizzaApplication.pizzaOne(chkPepperoni = true);
So, two questions:
What is the exact terminology for this
What is the best way to increment the different objects I'd make? Ie
pizzaApplication.pizzaOne(chkPepperoni = true);
or
pizzaApplication.pizza.1(chkPepperoni = true);
Edit:
For further clarification, I'm writing an Android app. I first ask them to make their selections for their pizza, and save them to a a different java file, named PizzaApplication.java Here are the first lines of code.
public class PizzaApplication extends Application {
private Order order = new Order();
//private final String[] toppings = new String[] { "Pepperoni", "Onion",
// "Sausage", "etc." };
public PizzaApplication() {
}
//Booleans for checking whether the individual pages have been completed.
Boolean vfTop = false;
Boolean vfAdd = false;
Boolean vfBill = false;
//Booleans for whether to add toppings
Boolean cheese = false;
Boolean italian = false;
Boolean pineapple = false;
Boolean ham = false;
Boolean pepperoni = false;
Boolean chicken = false;
//Globally accessible storage strings for various things
public String creditCard = "none";
public String crustType = "";
public String addressLine1 = "";
public String addressLine2 = "";
public String phoneNumber = "";
public String Toppings = "";
public Integer pizzaCount;
public String pizzaSize = "";
Now, here is some sample code from the Toppings class.
public class Toppings_Page extends Activity {
PizzaApplication pizzaApplication;
CheckBox Cheese, Ham, Italian, Pepperoni, Chicken, Pineapple;
Integer intpizzaCount;
TextView t;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_toppings__page);
pizzaApplication = (PizzaApplication) getApplication();
Cheese = (CheckBox)findViewById(R.id.chkCheese);
Italian = (CheckBox)findViewById(R.id.chkItalian);
Ham = (CheckBox)findViewById(R.id.chkHam);
Pepperoni = (CheckBox)findViewById(R.id.chkPepperoni);
Chicken = (CheckBox)findViewById(R.id.chkChicken);
Pineapple = (CheckBox)findViewById(R.id.chkPinapple);
and a little further down that class
public void onChecked(View view){
if (Cheese.isChecked()){pizzaApplication.cheese=true;}
else {pizzaApplication.cheese = false;}
if (Italian.isChecked()){pizzaApplication.italian=true;}
else {pizzaApplication.italian = false;}
if (Ham.isChecked()){pizzaApplication.ham=true;}
else {pizzaApplication.ham = false; }
if (Pepperoni.isChecked()){pizzaApplication.pepperoni=true;}
else {pizzaApplication.pepperoni = false;}
if (Chicken.isChecked()){pizzaApplication.chicken=true;}
else {pizzaApplication.chicken = false; }

You should have a seperate class named Pizza that represents a single pie. It should have no direct connection to your UI/Android code. You might use the builder pattern as shown in this example, which would allow you to create a pizza using something like this:
Pizza pizza = new Pizza.Builder(12).cheese().pepperoni().build();
At that point, working with multiple pizzas simply means using a List<Pizza> (or some other type of Collection):
List<Pizza> order = Arrays.asList(
new Pizza.Builder(9).cheese().ham().pineapple().build(),
new Pizza.Builder(12).cheese().sausage().build()
);

Related

Hangman game: stuck on randomly selecting players

For my school examn I have to make a console-application game of Hangman in Java, in which a player should be able to play against another player or a computer (2 players). A player should however also be able to play against a computer/AI. On top of that computers should be able to play against a computer as well.
Given the above, I have defined HashMaps with the player's names as String indexes and respective objects as values, like so:
private HashMap<String, PlayerHuman> humans = new HashMap<>(2);
private HashMap<String, PlayerComputer> computers = new HashMap<>(2);
Since both 2 players and 2 computers can play against each other, both HashMaps have a capacity of 2. Now when creating the players, there should either be real names entered (e.g. "John", "Mary") or a simple "C" if a player is computer-controlled. I then run a check on wether the input given was a "C" or not, resulting in creating the respective class for that player, like so:
Scanner scanner = new Scanner(System.in);
System.out.println("First create the players for the game!");
//
System.out.println("Type the name of player 1 (type C for computer): ");
String playerName1 = scanner.nextLine();
System.out.println("Type the nam of player 2 (type C for computer): ");
String playerName2 = scanner.nextLine();
if (playerName1.equals("C")) {
PlayerComputer player1 = new PlayerComputer();
player1.setPlayerName(playerName1);
if (playerName2.equals("C")) {
playerName1 = "C1";
playerName2 = "C2";
PlayerComputer player2 = new PlayerComputer();
player1.setPlayerName(playerName1);
player2.setPlayerName(playerName2);
this.computers.put(playerName2, player2);
} else {
PlayerHuman player2 = new PlayerHuman();
player2.setPlayerName(playerName2);
this.humans.put(playerName2, player2);
}
this.computers.put(playerName1, player1);
} else {
PlayerHuman player1 = new PlayerHuman();
player1.setPlayerName(playerName1);
if (playerName2.equals("C")) {
PlayerComputer player2 = new PlayerComputer();
player2.setPlayerName(playerName2);
this.computers.put(playerName2, player2);
} else {
PlayerHuman player2 = new PlayerHuman();
player2.setPlayerName(playerName2);
this.humans.put(playerName2, player2);
}
this.humans.put(playerName1, player1);
}
String startingPlayer = raffle(playerName1, playerName2);
There is definitely an easier way to do this, I have just run completely stuck and do not see a way out anymore. I then have to randomly select either of 2 players to be the first to play. I do this in the following method "raffle".
private String raffle(String nameOne, String nameTwo) {
Random random = new Random();
String raffledName = random.nextBoolean() ? nameOne : nameTwo;
System.out.println(raffledName + " may begin!");
return raffledName;
}
After this is where I run stuck. I'm getting the expected result from the "raffle" method; one of two given player's names, however I'm lost on how to make the code know which array to retrieve the returned player from, as a computer could either be named "C", or "C1" and "C2" when both players are computer-controlled, to know which computer represents which player. How do I make my code take this into consideration when retrieving the player's respective instance?
Any suggestions on creating the players are welcome too, since I feel the above written code is dirty and too procedural.
Thanks in advance!
I would like to suggest that you define a super class "Player" that your two player types derive from.
abstract class Player {
private String name;
public void setPlayerName(String name) {
this.name = name;
}
public String getPlayerName() { return name; }
abstract public boolean isCPU();
...
}
class PlayerHuman extends Player {
public boolean isCPU() { return false; }
...
}
class PlayerComputer extends Player {
public boolean isCPU() { return true; }
...
}
HashMap<String, Player> players = ...
Or, you can just use an array for players:
Player[] players = new Player[2];
You don't have to refer to player by name, then, and you can shuffle the array to decide who goes first.

Linking java functions/subroutines

I am developing a slots machine game as part of an assignment.
I have two functions that I need to link together, shown below:
public static void DisplayOnScreen(){
int LeftVal = GenerateNumber();
int MidVal = GenerateNumber();
int RightVal = GenerateNumber();
FruitVal1 = showFruit[LeftVal];
FruitVal2 = showFruit[MidVal];
FruitVal3 = showFruit[RightVal];
System.out.println(" |",FruitVal1, "|", FruitVal2, "|", FruitVal3, "| ");
--
public String showFruit(int inVal) {
String[] strFruitArr = new String[6];
strFruitArr[0] = "Orange";
strFruitArr[1] = "Pear";
strFruitArr[2] = "Banana";
strFruitArr[3] = "Cherry";
strFruitArr[4] = "Lemon";
strFruitArr[5] = "Apple";
strFruitArr[6] = "Bar";
while(inVal > 0){
if(inVal == 0){
return strFruitArr[0];
}
else if (inVal == 7){
return strFruitArr[6];
}
else{
return strFruitArr[inVal];
}
}
}
As you can see, each "FruitVal" is assigned by taking for example "LeftVal" which is a randomly generated number, and applying that to one of the fruits from the "showFruit" function. I'm aware this is done completely wrong however i do not understand the different java functions to do so.
Could someone explain the basic java functions e.g. 'public static void' and try and help implement them in to this code correctly.
If anyone wants to see the full program code then please do ask, I wasn't sure if the full code was necessary, however it is only short.
Learn Java coding standards. Your code will be more readable.
You link them by having one method return the data that the other needs to have passed to it.
public void displayFruitOnScreen(String [] fruit) {
// display here
}
public String [] getFruit() {
// populate the fruit array here
}
Neither of these is static; they are associated with some instance of a Java class.

Retrive and compare int value from an ArrayList

good night. I'm trying to retrieve and compare an int variable value from an ArrayList (if that is possible) but no matter what I do it never works. I already tried methods like contains(), get() and others. My logic is really bad I guess, could someone help me ? Please?
public class Obras extends Books implements ILibrary {
protected ArrayList<Obras> ListObra = new ArrayList<Obras>();
protected String typeObra;
protected String statusBorrow;
protected int ISBNuser;
Scanner userInput = new Scanner(System.in);
Scanner tipoInput = new Scanner(System.in);
public void createnewObra()
{
System.out.println("Insert the type of the new item: [Book, article...");
typeObra = tipoInput.nextLine();
super.createnewObra();
}
....
public void addObra() {
Obras newObra = new Obras();
newObra.createnewObra();
ListObra.add(newObra);
System.out.println("> Uma nova obra foi adicionada com sucesso!\n");
....
public void BorrowObra() {
System.out.println("> Choose a book from the list: ");
showListObras();
System.out.println("\n\n> Please choose one of the items from the above list by typing it's ISBN value: ");
ISBNuser = opcaoInput.nextInt();.
if(ListObra.get(ISBN).equals(ISBNuser))
{
System.out.println("> You successfully borrowed this book");
statusBorrow = false;
}
To get an int from an ArrayList, your ArrayList would have to be defined along the lines of this:
ArrayList<Integer> arrayListOfIntegers = new ArrayList<Integer>();
or
List<Integer> listOfIntegers = new ArrayList<Integer>();
Your list appears to contain objects of class Obras.
Also, when you call ListObra.get(ISBN), this method is designed to return the object at the specified index within the list - I suspect ISBN is not an index in the list, rather an ISBN of a book?
On a separate note, try to stick to Java naming standards - variables start with lower case letters and methods use camel case (e.g. createNewObra()). It makes things easier for other developers to understand.
ListObra.get(ISBN).equals(ISBNuser)
to:
Obras o = ListObra.get(ISBN);
if (o != null && o.getISBNuser() == ISBNuser) {
System.out.println("> You successfully borrowed this book");
statusBorrow = false;
}
because you only get a object Obras and you doesn't Override equal function in Obras, so you need to get Integer ISBUser and equal to the user input.
Another Way:
Override equal:
public class Obras extends Books implements ILibrary {
#Override
public boolean equals(Object e) {
Integer i = (Integer)e;
if (this.ISBUser == i) return true;
return false;
}
}
so now can use equals function to compare:
ListObra.get(ISBN).equals(ISBNuser)

Creating a "favorite" feature on a list of questions that get randomized

I'm having a hard time correctly implementing a 'favorites' feature for my app. Moving through a list of objects, the user should be able to check/uncheck something as a favorite. Once the activity moves into the onPause(); state, it should save the list of favorites (rather, the complete list of boolean markers that signal whether something is a favorite or not... true for favorite, false for not a favorite.) Obviously, upon moving into the onResume(); state, the list should be loaded so they can view the favorites that they've previously marked.
My issue, I think, truly comes from the fact that the list is randomized upon initialization. I'm sure my algorithm is off, but I've tried various ways to the point where I can hardly bare to look at it anymore.
Main Activity Java
public class MainActivity extends ActionBarActivity {
Global global_main;
#Override
protected void onCreate(Bundle savedInstanceState) {
global_main = Global.getInstance("all");
}
#Override
protected void onResume(){
super.onResume();
SharedPreferences settings = getSharedPreferences(FILE_FAVORITES, 0);
for(int index = 0; index < TOTAL_QUESTIONS; index++){
boolean favFromFile = settings.getBoolean(("savedFavorite_" + String.valueOf(index)), false);
global_main.setFav(index, favFromFile);
}
}
#Override
protected void onPause(){
super.onPause();
SharedPreferences settings = getSharedPreferences(FILE_FAVORITES, 0);
SharedPreferences.Editor editor = settings.edit();
for(int index = 0; index < TOTAL_QUESTIONS; index++){
editor.putBoolean(("savedFavorite_" + String.valueOf(index)), global_main.getFav(index));
// Commit the edits!
editor.commit();
}
}
Practice Java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
selectedSection = intent.getStringExtra(chooseSection.chosenSection);
global = Global.getInstance(selectedSection);
}
Global Class
public class Global {
private static Global global = null;
//Current total of questions which the user has chosen
//EX: if Multiplication was chosen and has 10 questions in the array
//Then this equals 10
int CURRENT_TOTAL;
//This is the position that the first question of the user's choice starts with
//EX: If user chooses Multiplication, and the multiplication questions start at questions[19];
//Then this equals 19
int CURRENT_START;
//This is the position that the last question of the user's choice ends with
//EX: If user chooses Multiplication, and the multiplication questions end at questions[24];
//Then this equals 24
int CURRENT_END;
//Basic question structure
class questionStruct
{
String q;
String a;
int position; //original position in the array;
boolean favorite;
}
//Array of question structures
questionStruct[] questions = new questionStruct[TOTAL_QUESTIONS];
//userChoice is the choice of question type that the user has selected.
//EX: Multiplication, Division, Addition, Subtraction, or All/Default
public static Global getInstance(String userChoice) {
if(global == null)
{
global = new Global();
global.initialize();
}
global.getChoice(userChoice);
global.setQuestionsDefault();
global.randomize();
return global;
}
public void initialize() {
for (int i = 0; i < TOTAL_QUESTIONS; i++) {
questions[i] = new questionStruct();
}
questions[0].q = "Question 1 Text";
questions[0].a = "Answer";
questions[0].position = 0;
questions[1].q = "Question 2 Text";
questions[1].a = "Answer";
questions[1].position = 1;
questions[2].q = "Question 3 Text";
questions[2].a = "Answer";
questions[2].position = 2;
....ETC.
....ETC.
....ETC.
}
public void setQuestionsDefault(){
questionStruct temp = new questionStruct();
for(int index = 0; index < TOTAL_QUESTIONS; index++){
int count = questions[index].position;
temp = questions[count];
questions[count] = questions[index];
questions[index] = temp;
temp = null;
}
}
//Randomize the questions only within the range of the category
//which the user has chosen
public void randomize(){
for(int index = CURRENT_END; index >= CURRENT_START; index --)
{
//Generate random number to switch with random block
Random rand = new Random();
int currentQ = rand.nextInt((CURRENT_END - CURRENT_START) + 1) + CURRENT_START;
//Switch two Question blocks
questionStruct temp = questions[currentQ];
questions[currentQ] = questions[index];
questions[index] = temp;
}
}
public void setFav(int q, boolean b){
questions[q].favorite = b;
}
public boolean getFav(int q){
return questions[q].favorite;
}
That MIGHT be everything pertinent to my issues. I apologize if I left anything out or if something doesn't make sense. Feel free to ask questions. I'm still currently in the middle of altering everything to get it to work, so I might have copied over something that doesn't quite add up.
EDIT: I'll also add the code for the "favorite" button click to turn a favorite into a non-favorite and vise versa. Even though it's critical to having this work, it's not something I was worried about functioning properly because it's so simple. But, if someone feels they'd like to see it, and in turn help me out, then here it is.
This is also in the Practice Questions Java file:
public void setFavoriteButton(){
if(global.getFav(tempQQ)){
FAVORITE.setBackgroundColor(Color.YELLOW);
}
else{
FAVORITE.setBackgroundColor(getResources().getColor(R.color.primary));
}
}
#Override
public void onClick(View v){
switch(v.getId()){
case R.id.favorite:
updateFavorite();
break;
}
}
public void updateFavorite(){
if(global.getFav(tempQQ)){
global.setFav(tempQQ, false);
}
else{
global.setFav(tempQQ, true);
}
setFavoriteButton();
}
EDIT: I might should add that I believe the issue is algorithmic. If I didn't have the "randomize" feature in conjunction with the favorites, I'd be fine I think. But I think both are important for my app to be very useful. So that's where my focus is at, trying to implement a favorites feature at the same time while keeping the randomization each time the Global is called.
I really suggest you to use a more Object-oriented approach to handle your model.
You can create the model class Quiz, that will probably looks like this:
class Quiz{
private boolean favorite;
private String question;
private String answer;
public Quiz(String question, String answer){
this.question = question;
this.answer = answer;
}
public boolean isFavorite() {
return favorite;
}
public void setFavorite(boolean favorite) {
this.favorite = favorite;
}
//...
}
In this way, you can create a list of Quiz and do shuffle, ordering, check for favorite and so on:
//Create the list of questions
ArrayList<Quiz> myQuiz = new ArrayList<Quiz>();
myQuiz.add(new Quiz("Question?", "Ansewer!"));
//...
//Shuffle all!
Collections.shuffle(myQuiz);
//Iterate and check for favorites
for(Quiz q : myQuiz){
if(q.isFavorite()){
//this is favorite!
}
}
Regarding the persistence of the data, you can consider an SQLite approach, or simply serialize your list and save it in your SharedPreference.
As I believe you are storing your favorites state in your questionStruct class, you don't need to restore your favorites state in your onResume(), you can keep it in onCreate().
As #bonnyz has answered, you can use Collections.shuffle(myQuiz); to shuffle your items in onResume() and refresh your Adapter with notifyDataSetChanged().

Problems of checkName() and storing user input to ArrayList and boolean[]

Here I have a GUI window and it basically ask the user to select a JRadioButton and type something in a JTextField, then choose confirm/cancel.
It is a project which we have to make a UML-to-Java text file. User would enter class information and choose a UML relationship, and this programme have to print out the Java clsas text on a JTextField. Just like when you create a new class in eclipse.
what I want to do is make a boolean[] to store an array of booleans, when user selects JRadioButton_A it'll store true and when user select JRadioButton_B it'll store false.And also I want the things typed in JTextField to be checked by a checkName(), if the method returns false, the string will be stored in an ArrayList.
Below is my code - there's some problems in getName() method and the boolean[] for storing true and false. When user needs to input name again, it would save the discarded sting/boolean into the array. (Sorry for my bad english!) Is there any better way to make this programme? I feel like I am complicating things and there should be a simpler way to make it.
Here's the UI stuffs asking user to enter class information. User have to select public/private and then type in class name and JTextField
private class Handler implements ActionListener{
public void actionPerformed(ActionEvent event){
String name = inputClassName.getText();
classObject.addName(name);
while (classObject.checkName(name) == true){
JOptionPane.showMessageDialog(null, "Class name invalid. " +
"\nEntered name should not contain java keywords or equal to other existing names. " +
"\nPlease try again."); // doesn't work
name = inputClassName.getText();
classObject.addName(name);
}// end if
JOptionPane.showMessageDialog(null, "Class saved."); // doesn't work
name = inputClassName.getText();
classObject.addName(name);
}// end actionPerformed()
}// end Handler class
private class Handler2 implements ActionListener{
public void actionPerformed(ActionEvent event){
boolean b = true;
b = classObject.setPP();
}
}
private class Handler3 implements ActionListener{
public void actionPerformed(ActionEvent event){
boolean b = false;
b = classObject.setPP();
}
}
Here's the methods for storing the inputs to the ArrayList and boolean[]
Scanner input = new Scanner(System.in);
JavaKeywords keyObject = new JavaKeywords();
private ArrayList<String> className = new ArrayList<String>();
private String name = new String();
private int size = className.size();
private Boolean[] bArray = new Boolean[size];
public boolean checkName(String name){
boolean check = true;
for (int i=0; i<=size; i++){
if (keyObject.containsKeyword(className.get(i)) || name.equals(className.get(i))){
boolean o = false;
check = o;
}// end if
}// end for
return check;
}// end checkName
public boolean setPP(){
boolean b = true;
return b;
}
public void addPP(Boolean[] bArray){
this.bArray = bArray;
for (int i=0; i>=size; i++){
bArray[i] = setPP();
}
}// add a Array of boolean. for className[i], its class type = item[i] in bArray.
// public = true, private = false
public String getPublicPrivate(){
String p = "";
for (int i =0; i<=size; i++){
if(bArray[i]=true)
p = "public";
else
p = "private";
}
return p;
}
Solved
Solution: store the string className and boolean isPrivate in a class and make the class into an ArrayList can save me from all the trouble. But then i faced anther problem, that is the checkName() doesn't work after I changed my code.
here is the ActionListener
private class Handler implements ActionListener{
public void actionPerformed(ActionEvent event){
VirtualClass virtualObject = new VirtualClass();
classObject.addClass(virtualObject);
String name = inputClassName.getText();
virtualObject.className = name;
if (classObject.checkName(name) == false){
JOptionPane.showMessageDialog(null, "Class name invalid. " +
"\nEntered name should not contain java keywords or equal to other existing names. " +
"\nPlease try again."); // Always return "invalid" message
} else {
JOptionPane.showMessageDialog(null, "Class saved.");
name = inputClassName.getText();
virtualObject.className = name;
}
if (event.getSource() == publicButton) {
virtualObject.isPrivate = false;
} else if (event.getSource() == privateButton) {
virtualObject.isPrivate = true;
}
}// end actionPerformed()
and here is the checkName() method
public boolean checkName(String name){
boolean check = true;
for (int i=0; i<=size; i++){
if (keyObject.containsKeyword(classes.get(i).className) || name.equals(classes.get(i).className)){
boolean o = false;
check = o;
}// end if
}// end for
return check;
}// end checkName
For containsKeyword() in checkName() I've used a JavaKeywords class from How to check if the class name is valid? by #MrLore.
Probably what I would do is create a simple class to represent your fields so you don't have to use multiple lists at all.
public class VirtualClass {
public boolean isPrivate;
public String className = "Object";
}
ArrayList<VirtualClass> classes = new ArrayList<VirtualClass>(0);
public void addClass(VirtualClass clazz) {
classes.add(clazz);
}
Otherwise you will have to create a second list of some kind to hold the public/private. You will just have to change them in parallel.
// in actionPerformed
ClassObject.VirtualClass clazz = new ClassObject.VirtualClass();
clazz.isPrivate = rbPrivate.isSelected();
clazz.className = tfClassName.getText();
classObject.addClass(clazz);
And just ignore the listening on the radio buttons since you technically do not need their states until you go to add the class to the list.
To access the fields later you just need to
for (VirtualClass clazz : classes) {
System.out.println((clazz.isPrivate ? "private" : "public") + " " + clazz.className);
}
// or something like
for (int i = 0; i < classes.size(); i++) {
System.out.println(classes.get(i).className + ":");
if (classes.get(i).isPrivate) {
System.out.println(" private");
} else {
System.out.println(" public");
}
}
I'm not entirely convinced by your over all approach. What I think "should"/"could" happen is, the user enters all the information you ask, they hit "accept", you valid the information that the user has entered and if it is correct, you create a new object representing the results of this input as you need.
I would, personally, avoid using an array of booleans, or at least, expose them differently. The main problem I have with it is keeping it all straight in my head, what does the element at 0 actually mean?
Instead, I would provide getter/setters on the ClassName class that allowed me to set/get particular properties. You could, of course, keep the values in an array internally, but anyone using the class wouldn't need to know how you store these values.
The problem with your check name Handler is the fact you are blocking the Event Dispatching Thread with your while-loop
This will stop you program from responding to user input (and painting itself)
while (classObject.checkName(name) == true){
JOptionPane.showMessageDialog(null, "Class name invalid. " +
"\nEntered name should not contain java keywords or equal to other existing names. " +
"\nPlease try again."); // doesn't work
name = inputClassName.getText();
classObject.addName(name);
}// end if
Swing is a single threaded framework, meaning that all interactions and changes to the UI are expected to be executed within the context of the EDT. Equally, anything that blocks or stops this thread from processing the Event Queue, will stop it from responding to new events, including repaint requests, making your program hang
Instead, you should simply check the name within a if-else statement. If it's valid, create the new ClassName object, if it's not, display a message and let the method exit.
Check out Concurrency in Swing for more details

Categories