Java: Listen For Second KeyPress - java

I have a list of colors with numbers associated with them. I'd like to make it so that, if the user types in "2", it selects "2: Green"; if they type in "21", it selects "21: Yellow"; etc. I'm trying to use KeyPressed, and I think I need some way for the program to listen for the first number pressed and then wait a second to see if another is pressed. For example, something like this:
// The integer pressed will always be zero or positive.
private void jComboBox1KeyPressed(KeyEvent evt) {
int code = -1;
for(int i = 0; i < 10; i++) {
if (evt.getKeyCode() == i) {
if (code == -1) {
code = i;
} else {
code += i;
}
break;
}
}
// PSEUDO-CODE: if (KeyEvent newEvt is pressed within 1 sec) {
jComboBox1KeyPressed(newEvt);
}
}
Then, I suppose I'd have a key-value map with an index and the color numbers, and I'd set the selected item for jComboBox1 based on code (the selected color number).
I've got it working for a single keyPressed:
private void jComboBox1KeyPressed(java.awt.event.KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_0) {
jComboBox1.setSelectedItem("2: Green");
}
else if (evt.getKeyCode() == KeyEvent.VK_1) {
jComboBox1.setSelectedItem("21: Yellow");
}
else if (evt.getKeyCode() == KeyEvent.VK_2) {
jComboBox1.setSelectedItem("13: Blue");
}
else if (evt.getKeyCode() == KeyEvent.VK_3) {
jComboBox1.setSelectedItem("2041: Red");
}
}
Here's the interface:
PLEASE NOTE: This is an example I quickly made and not the actual app I'm creating. My app involves many more number options, but as with this example, the numbers will always be positive.

Related

TableRowSorter shows different result everytime I clicked searchButton

For my code, I had a really weird bug.
Everytime I press the Search Button, the result always different.
This is my dummy database.
I have 4 columns and 3 rows in the table :
001 Viagra 1 APL
002 Diane 2 SBF
003 Santibi 3 BSP
The first time I pressed the Search Button, the data inside table didn't change at all.
This is the screenshot of my program.
This is what happened if I pressed the Search Button the second time (the result is correct)
The third time I pressed the button, it shows an incorrect result
If I pressed the button continuously, the result keep changing back and fort from correct to incorrect one.
This is my code :`
public void searchPerformed() {
if (tSearch.getText().toString() == sch) { return; }
sch = tSearch.getText().toString();
int iColumn = cbSearch.getSelectedIndex();
TableRowSorter<TableModel> sorter = new TableRowSorter<>(model);
tbl.setRowSorter(sorter);
if (tSearch.getText().length() > 0) {
sorter.setRowFilter(RowFilter.regexFilter("(?i)" + tSearch.getText(), iColumn));
} else {
sorter.setRowFilter(null);
}
if (tbl.getRowCount() != 0) { tbl.setRowSelectionInterval(0, 0); }
else { clearText(); }
}
private void tSearchKeyPressed(java.awt.event.KeyEvent evt) {
if (evt.getKeyCode() != KeyEvent.VK_ENTER) { return; }
searchPerformed();
}
private void tSearchKeyPressed(java.awt.event.KeyEvent evt) {
if (evt.getKeyCode() != KeyEvent.VK_ENTER) { return; }
searchPerformed();
}

JTextField won't disappear completely

I created a dialog box and have the user enter 5 colors in it from memory. That all completely works, there's just a slight aesthetic problem. Upon entering all 5 colors correctly, or getting one incorrect, it's suppose to wipe the contents within the dialog box and print a message "Sorry! Incorrect color" or "Congratulations". It prints the message, but the JTextField can still be seen somewhat behind the message (A left over portion/clipping).
I've tried using the hide() and remove() methods but they didn't seem to work (Or I'm using them incorrectly), I tried re-making a dialog box upon either but I couldn't seem to solve the issue still. What am I doing wrong/how can I make the JTextField disappear upon completion? Thank you in advance for any help!
Here's the portion where if the user enters a color incorrectly or gets them all correct (txtName is the JTextField):
if(count == 6)//User either finished or entered a color incorrectly
{
//Entered color incorrectly
if(incorrect == true)
{
txtName.setEnabled(false); //Doesn't work
homeScreen.remove(txtName); //Doesn't work
labelName.setText("Incorrect! Sorry - Wrong color.");
//txtName.removeActionListener(new MyButtonListener());
}
else//Correctly finished the game.
{
labelName.setText("Congratulations - your memory skills are perfect!");
//txtName.removeActionListener(new MyButtonListener());
homeScreen.remove(txtName);//Doesn't work
}
}
Here's my entire program (I can't get it format properly in the post):
package memorygame;
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.FlowLayout;
public class MemoryGame
{
private JFrame homeScreen;
private JLabel labelName;
private JTextField txtName;
private JLabel correct;
Vector<String> name = new Vector();
private int count = 1;
private MyButtonListener listen1 = new MyButtonListener();
//Constructor - Method to be called when MemoryGame object called
public void MemoryGame ()
{
homeScreen = new JFrame();
homeScreen.setSize(400,200);
homeScreen.setTitle("Memory Game");
homeScreen.setDefaultCloseOperation(homeScreen.EXIT_ON_CLOSE);
homeScreen.setLayout(new FlowLayout());
labelName = new JLabel();
txtName = new JTextField(10);
createContents();
homeScreen.setVisible(true);
}//End Constructor
//Create components and add them to the window/dialog box
private void createContents()
{
labelName.setText("Enter the color " + count + ":");
System.out.println("The current count is: " + count);
homeScreen.add(labelName);
homeScreen.add(txtName);
txtName.addActionListener(new MyButtonListener());//Allows you to press enter to invoke action
}
//Upon user hitting enter
private class MyButtonListener implements ActionListener
{
public void actionPerformed (ActionEvent e)//When event occurs
{
Scanner in = new Scanner (System.in);//For program input
String answer = "";
//Make memColor an array for randomized colors
/*
Random r = new Random();
String[] memColors = new String[5];
String[] colors = {"red", "green", "blue", "yellow", "brown", "purple"};
for(int i =0; i < memColors.length; i++)
{
memColors[i] = colors[r.nextInt(6)];
}
*/
String memColor1 = "red";
String memColor2 = "black";
String memColor3 = "yellow";
String memColor4 = "green";
String memColor5 = "blue";
boolean incorrect = false;
//If answered incorrectly set count to 5(it'll be 6)
//And have a boolean for if count== 6 for congrats and failure
if(e.getSource() == txtName)
{
answer = txtName.getText();
System.out.println(answer);
}
else
{}
//Check if user entered Correct color, 1= Red, 2= Black, etc.
if(count == 1)
{
if(answer.equalsIgnoreCase(memColor1))
{
txtName.setText("");
}
else
{//Needs to be a custom message box
count = 5;
incorrect = true;
}
}
else if(count == 2)
{
if(answer.equalsIgnoreCase(memColor2))
{
txtName.setText("");
}
else
{
count = 5;
incorrect = true;
}
}
else if(count == 3)
{
if(answer.equalsIgnoreCase(memColor3))
{
txtName.setText("");
}
else
{
count = 5;
incorrect = true;
}
}
else if(count == 4)
{
if(answer.equalsIgnoreCase(memColor4))
{
txtName.setText("");
}
else
{
count = 5;
incorrect = true;
}
}
else if(count == 5)
{
if(answer.equalsIgnoreCase(memColor5))
{
txtName.setText("");
}
else
{
count = 5;
incorrect = true;
}
}
else
{
JOptionPane.showMessageDialog(null, "Something went wrong!");
}
count += 1;
//User has completed the game or entered a color incorrectly
if(count == 6)
{
if(incorrect == true) //Incorrect color
{
txtName.setEnabled(false);
homeScreen.remove(txtName);
labelName.setText("Incorrect! Sorry - Wrong color.");
//txtName.removeActionListener(new MyButtonListener());
}
else //Completed the game correctly
{
labelName.setText("Congratulations - your memory skills are perfect!");
//txtName.removeActionListener(new MyButtonListener());
homeScreen.remove(txtName);
}
}
else
{
labelName.setText("Enter the color " + count + ":");
}
}//End Listener
}//End Button class
public static void main(String[] args) {
//Show message box
//Randomize colors
JOptionPane.showMessageDialog(null, "How good is your memory?\nTry to memorize this color sequence:\n\n red black yellow green blue");
MemoryGame mem = new MemoryGame();
mem.MemoryGame();
}//End Main
}// End Class
Use txtName.setVisible(false); instead of homeScreen.remove(txtName);
Basically, if you want to call remove, you will need to revalidate and repaint container...
You'll also want to ensure that your UI is create within the context of the Event Dispatching Thread, see Initial Threads for more details
Change the code
homeScreen.remove(txtName);
to
homeScreen.remove(txtName);
homeScreen.revalidate();
homeScreen.repaint();
The reason why remove() does not imply revalidate() + repaint() is that remove() is not atomic. The caller might want to perform multiple updates, a sequence of several add() and remove() calls. revalidate() basically "completes" your "UI update transaction", repaint() "pushes it to the screen".
As a side note, your code will be easier to understand and maintain, if you perform a small tiny improvements on variable names. What's homeScreen? And why is it called labelName - what name? And what's txtName - the name of what text? count of what, icecreams?
I suggest the following improvements:
incorrect -> isIncorrect (also change if (incorrect == true) to if (isIncorrect)
homeScreen -> mainFrame or just frame (as you only have one frame)
labelName -> infoLabel or just label (as you only have one label - and remove JLabel correct, it's unused)
txtName -> answerTextField
count -> answerCount
Remove variable listen1, it's not used.
Plus, if you look at the code that does if (count == 1) and the following four if clauses, they are all identical except for the number. A perfect situation for an array. You can convert the variables memColor* to an array String[] memColor. Or maybe that's what the Vector was for. You might instead want to use ArrayList, nobody uses Vector these days in such situations.

Java label set icon with getComponent

I have a frame, in this frame I have 10 labels.
If I click on label then it icon should be set to "zoldgomb.jpg", if I click a second time it should be set to "sargagomb.jpg".
This part is working, now my question is: How can it be written so that I don't have to write this part down ten times for each of the 10 labels (label name A1-A11)?
if (event.getSource()==A1) {
if (x==1) {
A1.setIcon(new ImageIcon("zoldgomb.jpg"));
x=2;
}else if (x==2) {
A1.setIcon(new ImageIcon("sargagomb.jpg"));
x=1;
} }
event.getSource() return reference to your JLabel, you can use something like next:
if (event.getSource() instanceof JLabel) {
if (x == 1) {
((JLabel)event.getSource()).setIcon(new ImageIcon("zoldgomb.jpg"));
x = 2;
} else if (x == 2) {
((JLabel)event.getSource()).setIcon(new ImageIcon("sargagomb.jpg"));
x = 1;
}
}

JLabel updating problems

I am creating a hangman game and I was having trouble getting the jlabel that contained each character of the word to update after the right letter button has been clicked. I have been having trouble with this as I am relatively new to working with Java Guis. Below is the action listener for the letter buttons.
private class LetterHandler implements ActionListener{
private char letterVal;
public LetterHandler(char lv){
letterVal = lv;
}
//checks if clicked button has the correct value as word char
public void actionPerformed(ActionEvent e){
for(int x = 1; x <= selectedWord.wordLength; x++){
if(selectedWord.wordValue.charAt(x - 1) == letterVal){
// JLabel letterValLabel = new JLabel(String.valueOf(letterVal));
wordSpacesArray.get(x-1).setName(String.valueOf(letterVal));
wordSpacesArray.get(x-1).revalidate();
continue;
}
else{
continue;
}
}
checkWin();
triesLeft--;
triesLeftLabel.revalidate();
}
//finds if all jlabels are complete or not
public void checkWin(){
for(int x = 1; x <= wordSpacesArray.size(); x++){
String charVal;
charVal = String.valueOf(wordSpacesArray.get(x-1));
if(charVal != "?"){
System.out.println("youWon");
System.exit(0);
}
else{
break;
}
charVal = null;
}
}
}
Any help is appreciated. Let me know if you need for of the programs code Thanks :)
There are some issues with the code. However, I'll first try to focus on your current problem:
I assume that wordSpacesArray is a list that contains the JLabels of individual letters of the word.
When this ActionListener will be notified, you try to update the labels in wordSpacesArray with the letter that corresponds to this button. However, in order to update the text that is shown on a JLabel, you have to call JLabel#setText(String) and not JLabel#setName(String). So the line should be
wordSpacesArray.get(x-1).setText(String.valueOf(letterVal));
// ^ Use setText here!
Now, concerning the other issues:
As pointed out in the comments, you should use 0-based indexing
The calls to revalidate are not necessary
The use of continue in its current for is not necessary
You should not compare strings with ==, but with equals
// if(charVal != "?") { ... } // Don't do this!
if(!charVal.equals("?")){ ... } // Use this instead
But the charVal in this case will be wrong anyhow: It will be the string representation of the label, and not its contents. So you should instead obtain the text from the label like this:
// String charVal = String.valueOf(wordSpacesArray.get(x-1)); // NO!
String charVal = wordSpacesArray.get(x-1).getText(); // Yes!
The triesLeftLabel will not be updated as long as you don't call setText on it
I think the logic of the checkWin method is flawed. You print "You won" when you find the first letter that is not a question mark. I think it should print "You won" when no letter is a question mark.
You should not call System.exit(0). That's a bad practice. Let your application end normally. (In this case, maybe by just disposing the main frame, although that would also be questionable for a game...)
So in summary, the class could probably look like this:
private class LetterHandler implements ActionListener
{
private char letterVal;
public LetterHandler(char lv)
{
letterVal = lv;
}
// checks if clicked button has the correct value as word char
#Override
public void actionPerformed(ActionEvent e)
{
for (int x = 0; x < selectedWord.wordLength; x++)
{
if (selectedWord.wordValue.charAt(x) == letterVal)
{
wordSpacesArray.get(x).setText(String.valueOf(letterVal));
}
}
checkWin();
triesLeft--;
triesLeftLabel.setText(String.valueOf(triesLeft));
}
// finds if all jlabels are complete or not
public void checkWin()
{
for (int x = 0; x < wordSpacesArray.size(); x++)
{
String charVal = wordSpacesArray.get(x).getText();
if (charVal.equals("?"))
{
// There is still an incomplete label
return;
}
}
// When it reaches this line, no incomplete label was found
System.out.println("You won");
}
}

Selecting buttons at random in java

How can I randomly select a java button, I am trying to create a tic-tac-toe game where the user plays the cpu or another player. I have it working fine for 2 players but am stuck on 1 player game, I dont know if it can be done but my idea is that I just randomly select a button for the cpu check to see if its been selected previously and then assign the appropiate x or o to the selected square .
public void buttonSelected(ActionEvent click) {
Object source = click.getSource();
// loop through to see which button has been selected
if(onePlayer){
// User Vs CPU
/*if((turn % 2 == 0)){// CPU Turn
int selected;
do {
selected = new Random().nextInt(btnEmpty.length );
if (chosen[selected -1] == false){
chosen[selected -1] = true;
}
}while (chosen[selected -1] == true);
source = Integer.valueOf(selected);
for(int i=1; i<= btnNotSelected.length; i++) {
if(source == btnNotSelected[i] && turn < 10) {
btnClicked = true; // user has selected a button
// Check which user selected button and insert appropriate x or y
btnNotSelected[i].setText("X");
btnNotSelected[i].setEnabled(false); // disable selected button
pnlPlayingField.requestFocus(); // highlight selected panel
}
}
}
else{ //User Turn
for(int i=1; i<=9; i++) {
if(source == btnNotSelected[i] && turn < 10) {
btnClicked = true; // user has selected a button
// Check which user selected button and insert O
btnNotSelected[i].setText("O");
btnNotSelected[i].setEnabled(false);
chosen[i] = true;// disable selected button
pnlPlayingField.requestFocus(); // highlight selected panel
}
}
} */
turn++;
}
else if(twoPlayer){
for(int i=1; i<=9; i++) {
if(source == btnNotSelected[i] && turn < 10) {
btnClicked = true; // user has selected a button
// Check which user selected button and insert appropriate x or y
if(turn % 2 == 0){
btnNotSelected[i].setText("X");
}
else{
btnNotSelected[i].setText("O");
}
btnNotSelected[i].setEnabled(false); // disable selected button
pnlPlayingField.requestFocus(); // highlight selected panel
turn++;
}`
A one player tic-tac-toe game can certainly be done, and your strategy of selecting at random is fine. The first specific error in your commented out one player code is an infinite do-while loop. The condition on the loop always evaluates to true since chosen[selected - 1] is always true (if it is false, you set it to true right before the condition check), and therefore loops again.
Your do-while should look like this:
do {
selected = new Random().nextInt(btnEmpty.length);
} while (chosen[selected - 1] == true);
chosen[selected - 1] = true;
That way, you are setting the chosen flag after the while loop condition.
A couple of additional issues I see with the onePlayer block:
in the CPU turn block, the comparison between source (here an Integer) and btnNotSelected[i] (assuming a java button based on the working code in the twoPlayer block) will not work as you expect it to
this method is called in response to a user input, which is clicking one of the buttons. The computer will not provide any such input, so you should have another trigger that calls running the code for the computer's turn. The easiest one is just to run it after the user's turn
Without making any drastic changes to your overall coding style and strategy, I'll attempt to translate the onePlayer portion into something more functional:
public void buttonSelected(ActionEvent click) {
Object source = click.getSource();
if (onePlayer) {
// User's turn first
source.setText("O");
source.setEnabled(false);
pnlPlayingField.requestFocus();
// Mark that button as chosen
for (int i = 0; i < btnNotSelected.length; i++) {
if (source == btnNotSelected[i]) {
chosen[i] = true;
break;
}
}
// Increment turn counter
turn++;
// Check if game is over
if (turn > 9) return;
// CPU turn
int selected;
do {
selected = new Random().nextInt(btnNotSelected.length);
} while (chosen[selected]);
chosen[selected] = true;
btnNotSelected[selected].setText("X");
btnNotSelected[selected].setEnabled(false);
pnlPlayingField.requestFocus();
turn++;
} else if (twoPlayer) {
/* your preexisting twoPlayer code */
}
}
int selected;
do {
selected = new Random().nextInt(btnEmpty.length );
if (chosen[selected -1] == false){
chosen[selected -1] = true;
}
}while (chosen[selected -1] == true);
code above is an endless loop, change it to:
int selected;
do {
selected = new Random().nextInt(btnEmpty.length);
}while (chosen[selected] == true);
chosen[selected] == true;
remove -1, because nextInt(n) will give you a number "between 0 (inclusive) and n (exclusive)"
I, personally, would start out with a List of the buttons, removing each on as it become selected, this would make easier to determine what has being selected and what hasn't, but lets work with what we've got...
List<Integer> free = new ArrayList<Integer>(chosen.length);
for (int index = 0; index < chosen.length; index++) {
if (!chosen[index]) {
free.add(index);
}
}
if (!free.isEmpty()) {
Collections.shuffle(free);
int selected = free.get(0);
// Continue with game logic
}
Basically, this places an Integer in a List which represents the "free" slots. We then use Collections.shuffle to randomise the list, then we grab the first element (for want of something to grab) and continue with the game logic...
This eliminates the possibility of a infinite loop trying to find free slots that don't exist...

Categories