TableRowSorter shows different result everytime I clicked searchButton - java

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();
}

Related

Java: Listen For Second KeyPress

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.

How can I limit the number of maximum selections for 1 selecting option of 20 JCombobox? javafor ex

I have 9 (+ default) selectable options (all the same for the 20) for my JComboBoxes.
The 20 are part of 2 JComboBox array. (10-10 for each).
I want to limit them like this:
If there is 4 selected from (for example) option 4 and the user selects a 5th one of it, one of them jumps back to default to keep the limit of 4.
How Can I do it ?
for ex:
for (int i = 0; i < roles1.length; i++) {
roles1[i] = new JComboBox();
roles1[i].setModel(new DefaultComboBoxModel(new String[] { "Not Selected", "PartnerInCrime", "Driver",
"Gunman", "Coordinator", "Hacker", "Distraction", "GadgetGuy", "Bruglar", "ConMan" }));
roles1[i].setBounds(boxPlace, 200, 100, 20);
boxPlace += 105;
getFrame().getContentPane().add(roles1[i]);
}
Here is a suggestion which is supposed to lead you in the right direction.
First of all, you have to add an ActionListener to each ComboBox, that calls a method which compares all selections with your current one.
roles1[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// get the current selection
JComboBox currentBox = (JComboBox)e.getSource();
String currentSelection = (String)currentBox.getSelectedItem();
// call the method and hand in your current selection
checkForSelectionExceeding(currentSelection);
}
});
In your scanning method you should memorize the amount of matches while scanning. If your limit is exceeded, reset the current box to default and stop scanning. Something like this:
private void checkForSelectionExceeding(String currentSelection){
int matches = 0;
for(int i=0; i<roles1.length; i++) {
if(roles1[i].getSelectedItem().equals(currentSelection)) {
matches++;
}
if(matches > 4) {
roles1[i].setSelectedItem("Not Selected");
break;
}
}
}
You only have to refactor this solution a little in order to scan both arrays sequentially.
Hope this helps.
If I understand your question properly, I have an idea that you may start from:
// create global HashMap that can records the occurrence of the selection of each item
Map<String, Integer> reference = new HashMap<String, Integer>();
// populate it
reference.put("PartnerInCrime", 0);
reference.put("Driver", 0);
reference.put("Gunman", 0);
reference.put("Coordinator", 0);
reference.put("Hacker", 0);
reference.put("Distraction", 0);
reference.put("GadgetGuy", 0);
reference.put("Bruglar", 0);
reference.put("ConMan", 0);
// then for every JComboBox in your array -> add action item listener to observe and control the selection like this
for(JComboBox<String> jcb : roles1){
jcb.addItemListener(new ItemListener(){
public void itemStateChanged(ItemEvent ie){
if(ie.getStateChange() == ItemEvent.DESELECTED){ // decrement record
if(!ie.getItem().toString().equals("Not Selected")){
reference.put(ie.getItem().toString(), reference.get(ie.getItem().toString()) -1);
}
}
else if(ie.getStateChange() == ItemEvent.SELECTED){
if(!ie.getItem().toString().equals("Not Selected")){
if(reference.get(ie.getItem().toString())>=4){ // if already selected 4 of them
jcb.setSelectedIndex(0); // return to the default
}
else{ // else record the selection
reference.put(ie.getItem().toString(), reference.get(ie.getItem().toString()) +1);
}
}
}
}
});
}

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;
}
}

Java Swing Dice Rolling Animation

I'm coding up a GUI game of craps. There is a JButton called "roll" which when clicked rolls the dice for the game. The GUI then displays what you rolled using jpeg's of die faces.
Everything works great, except I'm supposed to now add an animation to the GUI. My idea was to somehow rapidly display different face values for a short period of time (simulating a "roll") using the same method of displaying the jpeg's. However, as I'm sure you all know, that doesn't work.
I'm familiar with the idea of EDT and the Timer class, but I'm not sure exactly how to use them. Basically I want this animation to happen when I hit the "roll" button, and when the animation is finished, I want it to display what was actually rolled like it did before.
Any help would be greatly appreciated. Here's the code I have thus far:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/* This is the GUI declaration */
public class NCrapsGUI extends JFrame {
//code...
/* Action when "roll" is clicked */
private void rollActionPerformed(java.awt.event.ActionEvent evt){
game.rollDice();
//Rolls both die
sumOfDice.setText(Integer.toString(game.getSum()));
//Displays the sum of the die
numRolls.setText(Integer.toString(game.getNumRolls()));
//Displays the number of rolls in each game
// <editor-fold defaultstate="collapsed" desc="Die JPEG's">
// If statements display the die face based on the number rolled
if (game.getDie1Value() == 1) {
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face1.jpg")));
}
if (game.getDie1Value() == 2) {
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face2.jpg")));
}
if (game.getDie1Value() == 3) {
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face3.jpg")));
}
if (game.getDie1Value() == 4) {
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face4.jpg")));
}
if (game.getDie1Value() == 5) {
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face5.jpg")));
}
if (game.getDie1Value() == 6) {
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face6.jpg")));
}
if (game.getDie2Value() == 1) {
die2Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face1.jpg")));
}
if (game.getDie2Value() == 2) {
die2Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face2.jpg")));
}
if (game.getDie2Value() == 3) {
die2Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face3.jpg")));
}
if (game.getDie2Value() == 4) {
die2Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face4.jpg")));
}
if (game.getDie2Value() == 5) {
die2Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face5.jpg")));
}
if (game.getDie2Value() == 6) {
die2Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face6.jpg")));
}
//</editor-fold>
/*
* If the game is beyond the first roll, it checks to see if the sum of the
* values rolled equal 7 or the point value for a loss or win respectively.
* If it is a win, it adds a win. Likewise for a loss.
*/
if (game.getGameStatus() == 2) {
if (game.getSum() == game.getPoint()) {
game.addWin();
numWins.setText(Integer.toString(game.getWins()));
game.setGameStatus(1);
game.setPoint(0);
game.resetRolls();
return;
}
if (game.getSum() == 7) {
game.addLoss();
numLosses.setText(Integer.toString(game.getLosses()));
game.setGameStatus(1);
game.setPoint(0);
game.resetRolls();
return;
}
}
/*
* This checks to see if the game is on the first roll. If it is, it checks
* if the sum of the die is 7 or 11 for a win, or 2, 3, or 12 for a loss. If
* not, it passes it on to the next roll and sets the point value to the sum
*/
if (game.getGameStatus() == 1) {
game.setPoint(game.getSum());
dieSum.setText(Integer.toString(game.getPoint()));
if (((game.getSum() == 7) || ((game.getSum() == 11)))) {
game.addWin();
numWins.setText(Integer.toString(game.getWins()));
game.setPoint(0);
dieSum.setText(Integer.toString(game.getPoint()));
game.resetRolls();
return;
}
if (((game.getSum() == 2) || ((game.getSum()) == 3)) || (game.getSum()) == 12) {
game.addLoss();
numLosses.setText(Integer.toString(game.getLosses()));
game.setPoint(0);
dieSum.setText(Integer.toString(game.getPoint()));
game.resetRolls();
return;
} else {
game.setGameStatus(2);
}
}
}
EDIT WITH UPDATED CODE!!!
Here's where the Timer and array are declared:
public class NCrapsGUI extends JFrame
{
private Timer timer;
private int numPlayers;
private int totalIcons = 6;
private ImageIcon imageArray[];`
/* CODE */
And here is where the array is populated inside the NCrapsGUI constructor:
imageArray = new ImageIcon[totalIcons];
for (int i = 0; i < 6 ;i++)
{
int temp = i + 1;
imageArray[i] = new ImageIcon("face" + temp + ".jpg");
}
initComponents();`
This is the entire rollActionPerformed method. I'm guessing the Timer gets started right
at the beginning, but whenever I try to start it I get loads of error. However, when I
I made a new JPanel seperately, and made it implement action listener, I got no
errors. I tried adding implements ActionListner to this declaration, but NetBeans literally
would not let me type anything in.
private void rollActionPerformed(java.awt.event.ActionEvent evt) {
game.rollDice();
//Rolls both die
sumOfDice.setText(Integer.toString(game.getSum()));
//Displays the sum of the die
numRolls.setText(Integer.toString(game.getNumRolls()));
//Displays the number of rolls in each game
// <editor-fold defaultstate="collapsed" desc="Die JPEG's">
// If statements display the die face based on the number rolled
if (game.getDie1Value() == 1)
{
die1Disp.setIcon(imageArray[0]);
}
if (game.getDie1Value() == 2)
{
die1Disp.setIcon(imageArray[1]);
}
if (game.getDie1Value() == 3)
{
die1Disp.setIcon(imageArray[2]);
}
if (game.getDie1Value() == 4) {
die1Disp.setIcon(imageArray[3]);
}
if (game.getDie1Value() == 5) {
die1Disp.setIcon(imageArray[4]);
}
if (game.getDie1Value() == 6)
{
die1Disp.setIcon(imageArray[5]);
}
if (game.getDie2Value() == 1)
{
die2Disp.setIcon(imageArray[0]);
}
if (game.getDie2Value() == 2)
{
die2Disp.setIcon(imageArray[1]);
}
if (game.getDie2Value() == 3)
{
die2Disp.setIcon(imageArray[2]);
}
if (game.getDie2Value() == 4)
{
die2Disp.setIcon(imageArray[3]);
}
if (game.getDie2Value() == 5)
{
die2Disp.setIcon(imageArray[4]);
}
if (game.getDie2Value() == 6)
{
die2Disp.setIcon(imageArray[5]);
}
//</editor-fold>
/*
* If the game is beyond the first roll, it checks to see if the sum of the
* values rolled equal 7 or the point value for a loss or win respectively.
* If it is a win, it adds a win. Likewise for a loss.
*/
if (game.getGameStatus() == 2) {
if (game.getSum() == game.getPoint()) {
game.addWin();
numWins.setText(Integer.toString(game.getWins()));
game.setGameStatus(1);
game.setPoint(0);
game.resetRolls();
return;
}
if (game.getSum() == 7) {
game.addLoss();
numLosses.setText(Integer.toString(game.getLosses()));
game.setGameStatus(1);
game.setPoint(0);
game.resetRolls();
return;
}
}
`
Your basic idea behind the animation is a good one I think, but whether it works or not is all in the implementation details of course. I suggest
That you read in your images and make ImageIcons once, probably at the start of the program.
That you put the icons into an ImageIcon array with a length of 7 -- but you'll put an icon into the 1-6 slots, leaving the 0th item null.
That you use a Swing Timer to swap these icons randomly with some appropriate delay, say 200 or 300 msec.
That you use a a Random object to get a random number between 1 and 6, and then with this number as your array index, get the Icon out of the array.
That you display the ImageIcons in a JLabel (or two JLabels if you're displaying 2 die) and swap Icons by simply calling the JLabel's setIcon(...) method.
Edit
You state in your comment that you tried:
timer = new Timer(100,this);
And that's your problem -- your use of this. You shouldn't try to use the same ActionListner for everything. Instead create an ActionListener right there, where you need it. Something like,
timer = new Timer(100, new ActionListener() {
public void actionPerformed(ActionEvent actionEvt) {
// ... put your ActionListener's code here
}
});

Categories