Using Jinput and Java in Netbeans, I'm working on a very small project that simply Pops up a JFrame alarm window when lets say a user presses down on the 'K' on the keyboard and terminates the JFrame alarm window when the user lets go of 'k'. In my code, I seemed to get stuck in the while loop as the JFrame opened on the first press down and couldn't seem to close. I researched and I found that using javax.swing.Timer was the better way to do it. However, since I'm a newbie at this, all the different ways to use timer just made me even more confused. Could someone please see my code and point me in the right direction?
Here is my code;
public void startPolling() {
while(true) {
ControllerEnvironment.getDefaultEnvironment().getControllers();
ca[index].poll();
EventQueue queue = ca[index].getEventQueue();
Event event = new Event();
while(queue.getNextEvent(event)) {
StringBuffer buffer = new StringBuffer(ca[index].getName());
buffer.append(" at ");
buffer.append(event.getNanos()).append(", ");
Component comp = event.getComponent();
buffer.append(comp.getName()).append(" changed to ");
float value = event.getValue();
if(comp.isAnalog()) {
buffer.append(value);
} else {
if(value==1.0f) {
buffer.append("On");
if ("K".equals(comp.getName())){
alarmBox();
}
} else {
buffer.append("Off");
if ("K".equals(comp.getName())){
alarmBox.setVisible(false);
}
}
}
System.out.println(buffer.toString());
}
}
}
alarmBox() is my JFrame.
I was working on it and here is my updated code:
public void startPolling() {
Timer timer = new Timer(50, new ActionListener() {
public void actionPerformed(ActionEvent e) {
ca[index].poll();
EventQueue queue = ca[index].getEventQueue();
Event event = new Event();
while(queue.getNextEvent(event)) {
StringBuffer buffer = new StringBuffer(ca[index].getName());
buffer.append(" at ");
buffer.append(event.getNanos()).append(", ");
Component comp = event.getComponent();
buffer.append(comp.getName()).append(" changed to ");
float value = event.getValue();
if(comp.isAnalog()) {
buffer.append(value);
} else {
if(value==1.0f) {
buffer.append("On");
if ("K".equals(comp.getName())){
alarmBox();
}
} else {
buffer.append("Off");
if ("K".equals(comp.getName())){
alarmBox.dispose();
}
}
}
System.out.println(buffer.toString());
}
try {
Thread.sleep(20);
} catch (InterruptedException f) {
f.printStackTrace();
}
}
}); timer.start();
if you just want to open and close window,y to use timer?
you have a very complicated code,for a simple task.
you can add a ComponentListener to your JFrame to hide,somthing like this:
frame.addComponentListener(new ComponentAdapter(){
public void componentMoved(ComponentEvent e) {
if (popup.isVisible()){
popup.setVisible(false);
}
}
});
Related
my homework is about implementing an application that through threads allows me to search for a file in different folders the threads will create a ring topology, where each thread has interaction with the successor and predecessor thread.. but first I would like to print the id of the current node, the next one, and the previous one on my jframe.
The user specific how many threads he want to use, and that's the number of independent windows will be create.
But my question is, how do I know that? I think if I do that inside the for cycle using 'i' and increment it, like i+1, to print the following isn't the correct way.
this is my constructor where I am giving the index of the for cycle
then I have my Run method to print it to a jframe
public tareaHilo(int id) {
initComponents();
this.idHilo = id;
}
public void run() {
this.setVisible(true);
numeroHilo.setText(Integer.toString(idHilo));
nodoPrecedente.setText("previous one");
nodoSubsecuente.setText("next one");
}
// This is other class
private void botonCrearActionPerformed(java.awt.event.ActionEvent evt) {
try {
tareaHilo tarea;
numHilos = Integer.parseInt(inputHilos.getText());
ExecutorService ex = Executors.newFixedThreadPool(numHilos);
for (i = 1; i <= numHilos; i++) {
tarea = new tareaHilo(i);
ex.execute(tarea);
}
this.setVisible(false);
} catch (Exception e) {
e.printStackTrace();
}
}
Swing is single-threaded. Don't do this with an ExecutorService. Use the Swing Timer instead. Something like:
public tareaHilo(int id) {
initComponents();
this.idHilo = id;
}
int i;
public void actionPerformed(ActionEvent ae) {
this.setVisible(true);
numeroHilo.setText("" + i);
i++;
nodoPrecedente.setText("Hilo Anterior #");
nodoSubsecuente.setText("Hilo Siguiente #");
}
private void botonCrearActionPerformed(java.awt.event.ActionEvent evt) {
try {
tareaHilo tarea;
numHilos = Integer.parseInt(inputHilos.getText());
javax.swing.Timer t = new javax.swing.Timer();
t.scheduleAtFixedRate(...)
this.setVisible(false);
} catch (Exception e) {
e.printStackTrace();
}
}
I've let it for you to fill in the scheduledAtFixedRate parameters, as well as work out when/how to stop the timer action
I'm trying to learn Threads in Swing.
I have a Frame with a JProgressBar (progress), five JButtons (Start, Suspend, Resume, Cancel, Close), and a JLabel (label1).
The frame opens. Only Start is enabled. Start calls my class Progressor:
Updated Again Once and For All
Progressor progressor; //declared as class variable, initialized new in constructor and again in overridden done method
Here's the ButtonListener class:
public class ButtonListener implements ActionListener{
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == jbStart) {
progressor.execute();
label1.setText("Progressing ...");
jbCancel.setEnabled(true);
jbResume.setEnabled(true);
jbSuspend.setEnabled(true);
jbClose.setEnabled(true);
}
if(e.getSource() == jbCancel) {
progressor.cancel(true);
label1.setText("Progress Canceled");
}
if (e.getSource() == jbSuspend) {
label1.setText(progressor.suspendProgress());
}
if (e.getSource() == jbResume) {
label1.setText(progressor.resumeProgress());
}
if (e.getSource() == jbClose) {
dispose();
}
}
}//buttonlistener
Here's the SwingWorker class:
public class Progressor extends SwingWorker<Void, Integer> {
private volatile boolean suspend = false;
private Object lock = new Object();
#Override
protected Void doInBackground() {
for (int i = 0; i <= 10; i++) {
checkForSuspend();
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
}
publish(i);
}
return null;
}
#Override
protected void process(List<Integer> list) {
int value = list.get(list.size() - 1);
progress.setValue(value);
}
public void checkForSuspend() {
synchronized (lock) {
while (suspend) {
try {
lock.wait();
} catch (InterruptedException ie){
}
}
}
}//checkForSuspend
#Override
protected void done() {
label1.setText("All Done. Press close to exit");
progressor = new Progressor();
}
public synchronized String suspendProgress() {
suspend = true;
return "Progress suspended ...";
}
public synchronized String resumeProgress() {
synchronized (lock) {
suspend = false;
lock.notify();
return "Progress resumed ...";
}
}
}//Progressor class
Everything works except the cancel doesn't doesn't actually cancel the thread (the progress bar continues).
Should I suspend it before canceling?
This How to Pause and Resume a Thread in Java from another Thread question looks very similar to yours and has some nice examples in the answers.
As for your own code and why it does not work:
You create a new progressor on every click. You should be using and controlling one, instead of creating new ones every time.
When suspending your progressor finishes work instead of suspending. As the above question states - you should be looking at the flag at some points of your computation and acting on it. Example:
while (!cancel) {
if (!suspended) {
for (int i = 1; i <= 10; i++) {
Thread.sleep(1000);
publish(i);
}
}
}
The above code will suspend when it next reaches 10 (unless you resumed it before that), and finish when you press cancel (Cancel needs to be added as an extra flag in the obvious manner).
Your thread should run inside a while loop that looks for a boolean to change value from another object, then simply change the state with setPause(true/false) when you click the button:
while(true){
if(object_everyone_can_reference.getPause()){
Thread.sleep(1000);
}
}
Is there a way to easily convert thread.sleep to javax.swing.timer?
The reason why I would need to do this, is to stop the user-interface from freezing when you press a button, so that you can implement a pause button.
Code Example:
btnStartTiming.addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent arg0) {
try{
inputA = Double.parseDouble(txtEnterHowLong.getText()); //Changes double to string and receives input from user
}catch(NumberFormatException ex){
}
while (counter <= inputA){
txtCounter.setText(counter + "");
try {
Thread.sleep(1000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
System.out.println(counter);
counter++;
}
}
});
Some tips:
Take a look to How to use Swing
Timers
trail and come back with concrete problems. Describe what are you trying to accomplish and your work so far, show your attempts to solve the problem and make an answerable question.
Don't use MouseListener
to listen when a button is pressed. Use ActionListener
instead. Take a look to How to Use Buttons, Check Boxes, and Radio
Buttons trail.
Put the java.swing.Timer in your constructor. You can use the button to .start() the timer.
Also instead of the while, you can add an if statement in the timer code check when to .stop()
Something like this
int delay = 1000;
Timer timer = new Timer(delay, null);
public Constructor(){
timer = new Timer(delay, new ActionListener(){
public void actionPerformed(ActionEvent e) {
if (counter >= inputA) {
timer.stop();
} else {
// do something
}
}
});
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
}
I make my game run without mouse so using pointer is not a choice. High Score menu will show when player lose.
this is my code
highScore=new MyTextField("Your Name");
highScore.addKeyListener(this);
highScore.setFont(font);
highScore.requestFocusInWindow();
I have tried
highScore.setFocusable(true);
highScore.requestFocusInWindow();
highScore.requestFocus(true);
highScore.requestFocus();
but still not gained focus on my JTextField.
How to focus it?
If you want your JTextField to be focused when your GUI shows up, you can use this:
in = new JTextField(40);
f.addWindowListener( new WindowAdapter() {
public void windowOpened( WindowEvent e ){
in.requestFocus();
}
});
Where f would be your JFrame and in is your JTextField.
if is there only one Top-Level Container then last lines in GUI constructor would be for example
.
.
.
myFrame.setVisible(true);
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
myComponent.grabFocus();
myComponent.requestFocus();//or inWindow
}
});
public void actionPerformed(ActionEvent arg0)
{
if (arg0.getSource()==clearButton)
{
enterText.setText(null);
enterText.grabFocus(); //Places flashing cursor on text box
}
}
Try this one,
myFrame.setVisible(true);
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
myComponent.grabFocus();
myComponent.requestFocus();//or inWindow
}
});
If the page contains multiple item and like to set the tab sequence and focus I will suggest to use FocusTraversalPolicy.
grabFocus() will not work if you are using FocusTraversalPolicy.
Sample code
int focusNumber = 0;
Component[] focusList;
focusList = new Component[] { game, move, amount, saveButton,
printButton, editButton, deleteButton, newButton,
settingsButton };
frame.setFocusTraversalPolicy(new FocusTraversalPolicy() {
#Override
public Component getLastComponent(Container aContainer) {
return focusList[focusList.length - 1];
}
#Override
public Component getFirstComponent(Container aContainer) {
return focusList[0];
}
#Override
public Component getDefaultComponent(Container aContainer) {
return focusList[1];
}
#Override
public Component getComponentAfter(Container focusCycleRoot,
Component aComponent) {
focusNumber = (focusNumber + 1) % focusList.length;
if (focusList[focusNumber].isEnabled() == false) {
getComponentAfter(focusCycleRoot, focusList[focusNumber]);
}
return focusList[focusNumber];
}
#Override
public Component getComponentBefore(Container focusCycleRoot,
Component aComponent) {
focusNumber = (focusList.length + focusNumber - 1)
% focusList.length;
if (focusList[focusNumber].isEnabled() == false) {
getComponentBefore(focusCycleRoot, focusList[focusNumber]);
}
return focusList[focusNumber];
}
});
In my case nothing above worked untill I called requestFocus() AFTER my constructor has returned.
MyPanel panel = new MyPanel(...);
frame.add(panel);
panel.initFocus();
MyPanel.initFocus() would have:
myTextField.requestFocus();
And it works.
This code mouse cursor “jtextfield” “Jcombobox” location focused
try {
Robot robot = new Robot();
int x = Jtextfield.getLocationOnScreen().x;
int y= Jtextfield.getLocationOnScreen().y;
JOptionPane.showMessageDialog(null, x+"x< - y>"+y);// for I location see
robot.mouseMove(x, y);
} catch (AWTException ex) {
ex.printStackTrace();
}
It was not working for me when tried to use:
JOptionPane.showConfirmDialog(...)
But -
I found a solution !
Very primitive, but works.
Just jump to the field by java.awt.Robot using key "Tab".
For example:
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_TAB);
robot.delay(100);
robot.keyRelease(KeyEvent.VK_TAB);
If you should press multiple times on "Tab" to get your Component you can use below method:
GUIUtils.pressTab(3);
Definition:
public static void pressTab(int amountOfClickes)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
try
{
Robot robot = new Robot();
int i = amountOfClickes;
while (i-- > 0)
{
robot.keyPress(KeyEvent.VK_TAB);
robot.delay(100);
robot.keyRelease(KeyEvent.VK_TAB);
}
}
catch (AWTException e)
{
System.out.println("Failed to use Robot, got exception: " + e.getMessage());
}
}
});
}
If your Component location is dynamic, you can run over the while loop without limitation, but add some focus listener on the component, to stop the loop once arrived to it.
While yourTextField.requestFocus() is A solution, it is not the best since in the official Java documentation this is discourage as the method requestFocus() is platform dependent.
The documentation says:
Note that the use of this method is discouraged because its behavior is platform dependent. Instead we recommend the use of requestFocusInWindow().
Use yourJTextField.requestFocusInWindow() instead.
How about put jTextField.requestFocusInWindow(); into jTextField FocusLost event?
Works for me
have 5 controls on JPanel
Soon as click on MessageBox, focus lost on jTextField.
Used all the suggested codes but no luck
Only above method works my case.
Good day!
I wanted use a standart Swing Timer with Full Screen Exclusive Mode. To this effect I applied a SwingWorker to control the event when graphic mode should be set. All following steps are executed in run method. run() is called from main.
1)First of all, I create my SwingWorker object and override two its methods(doInBackground and done). Init is important method because it should set all needfull graphic setting to current JFrame object and bind my key listener objet(called screen_list) with it:
...
worker = new SwingWorker<Window, Void>()
{
public Window doInBackground()
{
init();
return gdev.getFullScreenWindow();
}
public void done()
{
try {
disp = get();
}
catch (InterruptedException ignore) {}
catch (java.util.concurrent.ExecutionException e) {
String why = null;
Throwable cause = e.getCause();
if (cause != null) {
why = cause.getMessage();
} else {
why = e.getMessage();
}
System.err.println("Error retrieving file: " + why);
}
}
};
...
2)then I create my screenlistener that implements an ActionListener and a Key Listener, it is bound with disp as KeyListener in init() method:
private void init()
{
...
try
{
disp = gdev.getFullScreenWindow();
if(disp != null)
{
gdev.setDisplayMode(use_dm);
disp.createBufferStrategy(2);
disp.setFocusTraversalKeysEnabled(false);
disp.addKeyListener((KeyListener)screen_list);
}
}
catch(IllegalArgumentException ex)
{
}
...
}
3)I create and initialize my Swing Timer and start it;
4)And finally i call execute method:
public void run(int pause, int delay)
{
...
try
{
screen_list = new ScreenListener();
tm = new Timer(delay, screen_list);
tm.setInitialDelay(pause);
tm.setRepeats(true);
tm.start();
worker.execute();
}
catch(Exception e)
{}
...
}
Class ScreenListener as i have written implements a KeyListener and an ActionListener. In ActionPerfomed method i check out did worker do its job(init method), if yes, i get ref to current display mode and draw something:
class ScreenListener implements ActionListener, KeyListener
{
public void actionPerformed(ActionEvent e)
{
if(!worker.isDone())
{
return;
}
else
{
//gdev - GraphicsDevice type
disp = gdev.getFullScreenWindow();
if (disp != null)
{
...
draw(gr);
...
}
}
}
...
}
Why aren't events from keyboard processed?
I don't make all of those Swing calls from init. Init should set all needfull graphic setting to current JFrame object and bind key listener with it.
OK, I see you've changed your code some:
private void init()
{
...
try
{
disp = gdev.getFullScreenWindow();
if(disp != null)
{
gdev.setDisplayMode(use_dm);
disp.createBufferStrategy(2);
disp.setFocusTraversalKeysEnabled(false);
disp.addKeyListener((KeyListener)screen_list);
}
}
catch(IllegalArgumentException ex)
{
}
...
}
but you're still making Swing calls in init when you get the JFrame, set its display mode and buffer strategy, it's focus traversal business, and add a key listener. Why are these calls being made in a background thread as they wouldn't be expected to interfere with Swing processing (so no need to be done on the background), and are actually "Swing calls" since you're changing the state of Swing objects with them. doInBackground is for running long-running or cpu-intensive processes that if run on the EDT would freeze the GUI and make it unresponsive. The code you've shown does not do this. The danger of doing Swing calls in a background thread is that while it will work 95% of the time, it will fail at unexpected times causing your app to crash and burn, usually at the most inopportune time.
Also, why the empty catch block? I'd at least put in an ex.printStackTrace() in there so as not to fly blind.
2)then I create my screenlistener that implements an ActionListener and a Key Listener, it is bound with disp as KeyListener in init() method:
So am I right in stating that you're adding a KeyListener to a JFrame? I doubt that this will work since KeyListeners only respond if the bound component has the focus, something a JFrame would rarely do or want to do. Perhaps you wish to use the more versatile key bindings as this will allow greater flexibility with regards to focus and responsiveness.
3)then I create and initialize my Swing Timer and start it;
OK
4)And finally i call execute method. –
public void run(int pause, int delay)
{
...
try
{
screen_list = new ScreenListener();
tm = new Timer(delay, screen_list);
tm.setInitialDelay(pause);
tm.setRepeats(true);
tm.start();
worker.execute();
}
catch(Exception e)
{}
...
}
Again you've got an empty catch block.
And can you tell us more about your specific problems? We see bits and pieces of unrelated code with a vague description of sort of what it does, but don't really have a full idea of anything yet. Can you give us a more detailed description of your program and its problems? Are you trying to create the SSCCE as recommended by Andrew? If you could create and post this, we'd be much better able to test and modify your program and help you to a solution. Best of luck
I used a SwingWorker capabilities because full screen mode as yet had not set by the time timer already started.
Ок. I passed up using a SwingWorker. Instead of this I added a simple condition:
class ScreenListener implements ActionListener, KeyListener
{
public void actionPerformed(ActionEvent e)
{
System.out.println("ScreenListener: actionPerformed");
disp = gdev.getFullScreenWindow();
if(disp == null)
{
return;
}
else
{
//draw something
...
}
}
}
So now my run method looks like this
public void run(int pause, int delay)
{
screen_list = new ScreenListener();
init();
try
{
tm = new Timer(delay, (ActionListener)screen_list);
tm.setInitialDelay(pause);
tm.setRepeats(true);
tm.start();
}
catch(Exception ex)
{
ex.printStackTrace();
}
finally
{
if(!tm.isRunning())
{
...
}
}
}
And I make a focusable my disp:
private void init()
{
JFrame frame = new JFrame();
...
disp = new Window(frame);
DisplayMode[] dms = gdev.getDisplayModes();
DisplayMode use_dm = null;
if(gdev.isFullScreenSupported())
{
disp.setBackground(Color.CYAN);
disp.setForeground(Color.WHITE);
gdev.setFullScreenWindow(disp);
}
use_dm = getMatchMode(dms, def_dm);
try
{
disp = gdev.getFullScreenWindow();
if(disp != null)
{
...
disp.setFocusable(true);
disp.addKeyListener((KeyListener)screen_list);
...
}
}
catch(IllegalArgumentException ex)
{
ex.printStackTrace();
}
}
but I can't still catch my keyboard events. KeyTyped, KeyPressed, KeyReleased aren't still called so it is my problem in that programm.
My first aim was make a simple animation with full screen mode. At first i used a simple thread method - sleep - as for main thread. Then I added a swing timer for the same purpose but as you look I got a problem: I can't make to work my KeyListener.
I decided my problem:
1)Now FullScreen class extends from JFrame:
public class SimpleFullScreen extends JFrame
{
...
private synchronized void init()
{
Window disp = null;
//customize my display
setFocusable(true);
setResizable(false);
setIgnoreRepaint(true);
setUndecorated(true);
setBackground(Color.CYAN);
setForeground(Color.WHITE);
addKeyListener((KeyListener)screen_list);
DisplayMode[] dms = gdev.getDisplayModes();
DisplayMode use_dm = null;
if(gdev.isFullScreenSupported())
gdev.setFullScreenWindow(this);
use_dm = getMatchMode(dms, def_dm);
try
{
disp = gdev.getFullScreenWindow();
if(disp != null)
{
gdev.setDisplayMode(use_dm);
createBufferStrategy(2);
}
}
catch(IllegalArgumentException ex)
{
ex.printStackTrace();
}
}
...
}
2)Add loop in the run method, it checks out is timer running:
public void run(int pause, int delay)
{
Window disp = null;
screen_list = new ScreenListener();
init();
try
{
//Initialize and start timer
...
while(tm.isRunning())
{
System.out.println("Run: timer running");
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
finally
{
try
{
if(!tm.isRunning())
{
disp = gdev.getFullScreenWindow();
disp.setVisible(false);
disp.dispose();
gdev.setFullScreenWindow(null);
System.exit(0);
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
3) init, actionPerfomed and KeyPressed became the synchronized methods.
So ActionListener and KeyListener works good.
Thanks for responses!