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.
Related
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");
}
});
I have a method that returns a certain int variable, but this variable should be modified by the user using a JFrame that pops out when this method is called before it's returned.
So I thought of using a timer that would delay the return statement by certain a more-than-needed number of seconds and when the button for example is pressed, the timer would stop and the variable would change
Here is the method:
public static int c(){
x.setVisible(true);// x is the name of the frame
timer.schedule(new TimerTask() {
public void run() {
System.out.println("Text");
}
}, 5000);
return q;
}
And here is the ActionListener set on the button in the constructor:
d.addActionListener(new ActionListener(){ //d is the name of the button
#Override
public void actionPerformed(ActionEvent arg0) {
q=5;
timer.cancel();
x.setVisible(false);
}
});
But all it does is delaying the printing statement inside the run method, and of course i cannot return inside the delayed task since its type is void
Thanks
but this variable should be modified by the user using a JFrame that pops out when this method is called before it's returned
An application should only have a single main JFrame (see: The Use of Multiple JFrames: Good or Bad Practice?). Child windows should be a model JDialog. Then when show the dialog, the code after the setVisible() statement will not execute until the dialog is close.
You can create you own custom JDialog or it may be easier to use a JOptionPane. See the section from the Swing tutorial on How to Make Dialogs for more information and examples.
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);
}
});
I have the following code...
runNow.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
final Search s = (Search) node.getUserObject();
// Swing worker
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
#Override
public Void doInBackground() {
s.run();
return null;
}
#Override
public void done() {
window.updateResultsPanel(s.getResults(), s.getName());
}
};
worker.run();
}
});
This is a popup menu action which should create a new SwingWorker, free up the GUI, do some work, then update the results of the window. However, right now when I click the menu item the GUI becomes locked up until the work completes which is baffling, the whole point of using a SwingWorker is so that won't happen.
Any ideas as to what I'm doing wrong would be greatly appreciated.
-Cody
You should be calling SwingWorker#execute to start the worker, not run
Run is exposed by the Runnable interface, but execute actually schedules the worker to run at some time in the future.
Have to change method SwingWorker.run() to SwingWorker.execute() and it worked like a charm.
How can I update the JProgressBar.setValue(int) from another thread?
My secondary goal is do it in the least amount of classes possible.
Here is the code I have right now:
// Part of the main class....
pp.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent event){
new Thread(new Task(sd.getValue())).start();
}
});
public class Task implements Runnable {
int val;
public Task(int value){
this.val = value;
}
#Override
public void run() {
for (int i = 0; i <= value; i++){ // Progressively increment variable i
pbar.setValue(i); // Set value
pbar.repaint(); // Refresh graphics
try{Thread.sleep(50);} // Sleep 50 milliseconds
catch (InterruptedException err){}
}
}
}
pp is a JButton and starts the new thread when the JButton is clicked.
pbar is the JProgressBar object from the Main class.
How can I update its value?(progress)
The code above in run() cannot see the pbar.
Always obey swing's rule
Once a Swing component has been realized, all code that might affect or depend on the state of that component should be executed in the event-dispatching thread.
What you can do is to create an observer that will update your progress bar -such as
- in this instance you want to show progress of data being loaded on click of a button.
DemoHelper class implements Observable and sends updates to all observers on when certain percent of data is loaded.
Progress bar is updated via public void update(Observable o, Object arg) {
class PopulateAction implements ActionListener, Observer {
JTable tableToRefresh;
JProgressBar progressBar;
JButton sourceButton;
DemoHelper helper;
public PopulateAction(JTable tableToRefresh, JProgressBar progressBarToUpdate) {
this.tableToRefresh = tableToRefresh;
this.progressBar = progressBarToUpdate;
}
public void actionPerformed(ActionEvent e) {
helper = DemoHelper.getDemoHelper();
helper.addObserver(this);
sourceButton = ((JButton) e.getSource());
sourceButton.setEnabled(false);
helper.insertData();
}
public void update(Observable o, Object arg) {
progressBar.setValue(helper.getPercentage());
}
}
Shameless plug: this is from source from my demo project
Feel free to browse for more details.
You shouldn't do any Swing stuff outside of the event dispatch thread. To access this, you need to create a Runnable with your code in run, and then pass that off to SwingUtilities.invokeNow() or SwingUtilities.invokeLater(). The problem is that we need a delay in your JProgressBar checking to avoid jamming up the Swing thread. To do this, we'll need a Timer which will call invokeNow or later in its own Runnable. Have a look at http://www.javapractices.com/topic/TopicAction.do?Id=160 for more details.
There is need not to call pbra.repaint explicitly.
Update JProgressBar shall be done through GUI dispatch thread.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// Remember to make pbar final variable.
pbar.setValue(i);
}
});