java set delay to change imageicon - java

i'm trying to set a delay when a button is pressed to set an imageicon to a certain image then set another delay so that another image would be set, all of this by single click.
in other word :
click a button->set image->delay->set another image.
what i get in my code is the last state only "set another image".
also i don't want to use use timers, i want to use delays.
and here the part in my code i'm concerned about.
btnNewButton.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
lblNewLabel.setIcon(and);
sleeep(500);
lblNewLabel.setIcon(app);
}
});
and here is the delay function
void sleeep(int n)
{
try {
Thread.sleep(n);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}

don't add MouseListener to JButton, nor for mouseClicked(), add ActionListener instead, btw all Mouse and Key events are implemented in JButton API and correctly
don't to use Thread.sleep(n); you have an issue with Concurency in Swing, use Swing Timer instead,

You should try executing the code that sets the image in the event dispatch thread using InvokeLater.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
lblNewLabel.setIcon(and);
}
});
sleeep();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
lblNewLabel.setIcon(and);
}
});

Related

I am a beginner and I am trying to make a card flip game in netbeans

On clicking an image I want another image to be displayed pause for one second and the original image to be restored and displayed againdisplayed again When I try to do it it action handler such as code given below it sets the image after sleep .I want the image to be displayed pause and the original to be displayed again how can I achieve that
private void jButton16ActionPerformed(java.awt.event.ActionEvent evt) {
jButton16.setIcon(new javax.swing.ImageIcon("C:\\Users\\x\\Documents\\O.png"));
try { //sleep 1 seconds
Thread.sleep(1000);
}
catch (InterruptedException e)
{
}
jButton16.setIcon(new javax.swing.ImageIcon("C:\\Users\\x\\Documents\\118px-AMIGO.jpg")); }
Swing is single threaded, you should never perform long running or blocking operations within the context of the Event Dispatching Thread
Swing is NOT thread safe, this means you should never update the UI (and anything the UI needs) outside of the context of the EDT
The simplest solution to your problem is to use a Swing Timer
private void jButton16ActionPerformed(java.awt.event.ActionEvent evt) {
jButton16.setIcon(new javax.swing.ImageIcon("C:\\Users\\x\\Documents\\O.png"));
Timer timer = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
jButton16.setIcon(new javax.swing.ImageIcon("C:\\Users\\x\\Documents\\118px-AMIGO.jpg"));
}
});
timer.setRepeats(false);
timer.start();
}
See Concurrency in Swing and How to use Swing Timers for more details
You should never invoke Thread.sleep() inside Event Dispatch Thread
because Thread.sleep() will block Event Dispatch Thread and your UI will be Freeze , instead you could use a Timer to achieve your goal
Refer below code,
jButton16.setIcon(new javax.swing.ImageIcon("C:\\Users\\x\\Documents\\O.png"));
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
jButton16.setIcon(new javax.swing.ImageIcon("C:\\Users\\x\\Documents\\118px-AMIGO.jpg"));
}
});
timer.setRepeats(false);
timer.start();

Invalid Thread Access error when changing Java SWT Label

I want to run my program where the value of a label changes after the Timer goes off. But whenever the Timer runs I will keep getting the Invalid Thread access error and my label does not get updated.
protected void createContents() {
<--GUI codes -->
//Timer set to go every 10 seconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.out.println("Timer");
lblState.setText("On");
}
};
new Timer(delay, taskPerformer).start();
}
This link from the SWT FAQ explains the error and how to solve it: any code that modifies GUI components (in your case, setting the text of the label) needs to run on the display thread, otherwise this error will occur.
To run on the display thread, wrap the code inside a Runnable and call Display.getDefault().syncExec( with the provided Runnable:
Display.getDefault().syncExec(new Runnable() {
public void run() {
// code that affects the GUI
}
});
All access to UI objects must be done in the user interface thread. You can do this using Display.asyncExec (or Display.syncExec).
Change your line:
lblState.setText("On");
to
Display.getDefault().asyncExec(() -> lblState.setText("On"));
for Java 8. For Java 7 or earlier use:
Display.getDefault().asyncExec(new Runnable() {
#Override
public void run()
{
lblState.setText("On");
}
});

How to keep focus on JTextField. SwingWorker

I need to keep focus on JTextField. Application uses Swing library. I need set focus on that field from time to time in order to avoid user mistakes that would change focus to other comonents. I suppose I need to use SwingWorker. Set focus is an operation on Swing
component so it should be invoked in EDT. My question is how to write SwingWorker to do that?
I know that method done() pass tasks to be invoked in EDT but I need this task to be invoked every let's sey 2 seconds. Method done() is called one time.
So maybe sth like this will be ok?
public class myWorker extends SwingWorker<Void, Void> {
#Override
protected Void doInBackground() throws Exception {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
//here set focus on JTextField
return null;
}
});
}}
Edit:
I noticed that method process() that is a part of SwingWorker may be appropriate beacuse it is invoked in EDT. I'm not sure but this method is probably invoked always when I call publish() metod. So could you tell me if this code is valid to do this task?
private class KeepFocusWorker extends SwingWorker<Void, Void>
{
#Override
protected Void doInBackground() throws Exception
{
while(true)
{
publish();
}
}
#Override
protected void process(List<Void> chunks)
{
codeBar.requestFocusInWindow();
}
}
Use javax.swing.Timer instead of SwingWorker. In this case actionPerformed will be executed in EDT. Also to set focus in a component, you need to call requestFocus. As the name suggests, it is a request only and not guaranteed. So you may change you approach.
Timer timer = new Timer(2000, new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
codeBar.requestFocus();
}
});
timer.setRepeats(true);
timer.start();
Surely it's better to limit the user's ability to take focus away from the textfield in the first place? Personally I don't see why it's an issue but I suppose it's better to keep focus in the one component rather than letting the user shift focus only for it to be shifted back every few seconds.
Therefore you could add a FocusListener to the component, override the focusLost method and basically requestFocus() again.
codeBar.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
codeBar.requestFocus();
}
});
NB I've not actually tried this myself but can't see why it wouldn't work.
Alternatively you can use an InputVerifier which always returns false to prevent focus being taken away.

How can I Listen for Keyboard input without Text Field Java

I am working on a Java application and interfacing with an RFID reader that acts as a keyboard input device.
The application will be used for employee time tracking, so the employee should not see the code that his/her RFID tag contains.
Currently, the application opens a jFrame that asks the employee to scan their tag. This is where I would like to listen for the keyboard input.
All of the RFID tags are 10 digits, so I would like to use some kind of regex to detect when a card is scanned if possible.
If someone could point me in the right direction, or contribute some code I would be grateful.
Thanks in advance.
UPDATE:
I was able to read the input of the scanner by adding the following to the constructor of my JFrame.
addKeyListener(new KeyListener(){
#Override
public void keyPressed(KeyEvent e){ System.out.print(e.getKeyChar());}
#Override
public void keyReleased(KeyEvent e) { }
#Override
public void keyTyped(KeyEvent e) { }
});
So it is now confirmed that the Reader is just standard Keyboard input.
Here is an example of what I get for a tag: 0006459027
Now, the big question is, how do I take the characters that I got, and detect that it is a 10 digit string, and from there trigger an event to open a new frame?
First, I'd see if the RFID reader is triggering an ActionEvent to be fired when the tag is scanned. This would be the simplest approach.
Failing that, you would need to attach a DocumentListener to the fields underlying document and monitor for changes.
You'll need to decide how best to interrupt the results (as you're likely to get each letter of the RFID at a time). You could monitor the length of the document or have a javax.swing.Timer which triggers after a short delay (you'd reset the timer on each update event triggered by the DocumentListener)
Check out
JTextField.addActionListener
JTextField.getDocument().addDocumentListener
I'd suggest taking a look at DocumentFilter as well, but your interested in the final result, not modifying it.
UPDATED with DocumentListener Example
// In the classes variable decleration section...
private JTextField rfidField;
// In the classes constructor or UI init method...
rfidField = new JTextField(12);
rfidField.getDocument().addDocumentListener(new DocumentListener() {
public void handleUpdate(DocumentEvent e) {
if (e.getDocument().getLength() == 10) {
System.out.println("Trigger me happy...");
SwingUtilities.invokeLater(new Runnable() {
public void run() {
rfidField.setText(null);
}
});
}
}
#Override
public void insertUpdate(DocumentEvent e) {
handleUpdate(e);
}
#Override
public void removeUpdate(DocumentEvent e) {
handleUpdate(e);
}
#Override
public void changedUpdate(DocumentEvent e) {
handleUpdate(e);
}
});
// Now don't forget to add the field to your forms container ;)
//////
One of things I would be do when you "trigger" the code event is, once you've read it from the text field, is clear the text field (JTextField.setText(null)) - IMHO
If the RFID reader acts as a keyboard input device, try with key events:
JFrame frame = new JFrame();
// frame setup
frame.addKeyListener(new KeyAdapter(){
public void KeyPressed(KeyEvent ke)
{
System.out.println(ke);
}
});
Otherwise you have to check which kind of event it fires.
I was in a similar situation but with a bar-code scanner.
I really worked hard on a custom DocumentListener that would take care of all scenarios, and none of it worked.
Out of desperation, I added an ActionListener and it then worked very well.
Here is a code snap-shot :
try {
txtStockItemRef.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
System.out.println(txtStockItemRef.getText());
DatabaseManager.peformStockItemLookupByBarcodeRef(txtStockItemRef.getText());
}
});
} catch(Exception exc) {
LiveCityRetailTools.handleExceptionWithUserMessage(exc);
}

MouseListener in Java Swing sometimes not respond

I've implemented right mouse click for open menu listener on my main Jframe, it works fine except one problem. One out of 5 (give or take) clicks it not responding, this can be very annoying for the user. Here is my code:
contentPane = new JPanel();
contentPane.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON3)
{
//Do Stuff
}
}
});
Can you please help me
You won't get clicks from sub-components of contentPane.
I think your problem is that you have added things to your panel. When the user clicks at regions occupied by a sub-component, that sub-component get's the click event.
Quick fix: I would recommend you to add the same mouse listener to all sub-components.
You are not "clicking"
A click is when the mouse is pressed and release really quickly. If you are not careful you might get events for (for instance) "pressed, moved, released" instead of "clicked".
Quick fix: use mouseReleased event instead.
Use this Code instead:
private MouseAdapter listener = new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
if (downer) {
downer = false;
if (new Rectangle(e.getComponent().getLocationOnScreen(), e.getComponent().getSize())
.contains(e.getLocationOnScreen())) {
downer = false;
// CODE
new Thread(new Runnable(){
public void run(){
//Your Listener code
}
}).start();
/// COde
}
}
}
boolean downer = false;
public void mousePressed(java.awt.event.MouseEvent e) {
downer = true;
}
};
This code only reacts if you press on the component and release on the component AND starts a new Thread for the custom task. This should work allways, because the AWT Thread isnt blocked with long calculations.

Categories