Wait cursor and disable java application - java

I want to have the user press a button to kick off a background thread.
While the thread is processing, I want two things to happen:
1) A WAIT_CURSOR should be displayed.
2) The application should not respond to mouse events.
As per the setCursor documentation "This cursor image is displayed when the contains method for this component returns true for the current cursor location, and this Component is visible, displayable, and enabled. ".
I want my application to be disabled while this background thread is processing.
Any ideas how to get the functionality I want?
import java.awt.Component;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class WaitCursor extends JFrame
{
private static final long serialVersionUID = 1L;
public WaitCursor()
{
setResizable(false);
setName(getClass().getSimpleName());
setTitle("My Frame");
setSize(300, 300);
getContentPane().add(new MyButtonPanel());
}
private class MyButtonPanel extends JPanel
{
private static final long serialVersionUID = 1L;
public MyButtonPanel()
{
JButton btnStart = new JButton("Start");
btnStart.addActionListener(new BtnStartActionListener());
add(btnStart);
}
private class BtnStartActionListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
// Change to WAIT_CURSOR
Component root = SwingUtilities.getRoot((JButton) e.getSource());
JOptionPane.showMessageDialog(root, "Wait 10 seconds");
root.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
// TODO: Disabling the root component prevents the WAIT_CURSOR from being displayed
root.setEnabled(false);
new Thread(new TimeKiller(root)).start();
}
}
}
private class TimeKiller implements Runnable
{
Component _root;
public TimeKiller(Component root)
{
_root = root;
}
public void run()
{
try
{
Thread.sleep(10 * 1000);
}
catch (InterruptedException e)
{
// Ignore it
}
// Change back to DEFAULT CURSOR
JOptionPane.showMessageDialog(_root, "Done waiting");
_root.setCursor(Cursor.getDefaultCursor());
_root.setEnabled(true);
}
}
private static void createAndShowGUI()
{
// Create and set up the window.
WaitCursor frame = new WaitCursor();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
try
{
createAndShowGUI();
}
catch (Exception e)
{
e.printStackTrace();
System.exit(0);
}
}
});
}
}

One way to disable it is to use the glass pane to block mouse input.
For example:
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import javax.swing.*;
#SuppressWarnings("serial")
public class WaitCursor2 extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private JComponent glassPane;
private JButton runBackgroundProcBtn;
private JTextArea textarea = new JTextArea(15, 30);
public WaitCursor2(JComponent glassPane) {
this.glassPane = glassPane;
glassPane.setFocusable(true);
glassPane.addMouseListener(new MouseAdapter() {
}); // so it will trap mouse events.
add(new JTextField(10));
add(runBackgroundProcBtn = new JButton(new AbstractAction(
"Run Background Process") {
#Override
public void actionPerformed(ActionEvent arg0) {
runBackgroundProcessAction();
}
}));
add(new JScrollPane(textarea));
}
private void runBackgroundProcessAction() {
disableSystem(true);
glassPane.setVisible(true);
new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
long sleepTime = 5000;
Thread.sleep(sleepTime);
return null;
}
#Override
protected void done() {
disableSystem(false);
}
}.execute();
}
public void disableSystem(boolean disable) {
glassPane.setVisible(disable);
runBackgroundProcBtn.setEnabled(!disable);
if (disable) {
System.out.println("started");
glassPane.requestFocusInWindow(); // so can't add text to text components
glassPane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
} else {
System.out.println("done");
glassPane.setCursor(Cursor.getDefaultCursor());
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("WaitCursor2");
WaitCursor2 mainPanel = new WaitCursor2((JComponent) frame.getGlassPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
The glass pane will trap mouse events if it set visible and given a MouseListener. It will lose t his ability if it is set invisible. Likewise it will pull the caret from text components if you make it focusable and give it focus.

added a field current_active and at method actionPerformed, do a simple check. Albeit it is not perfect but for simple app, i think this do the trick. A crude way of solving your two requirement. :-) Hope it works for you too.
import java.awt.Component;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class WaitCursor extends JFrame
{
private static boolean current_active = false;
public WaitCursor()
{
setResizable(false);
setName(getClass().getSimpleName());
setTitle("My Frame");
setSize(300, 300);
getContentPane().add(new MyButtonPanel());
}
private class MyButtonPanel extends JPanel
{
public MyButtonPanel()
{
JButton btnStart = new JButton("Start");
btnStart.addActionListener(new BtnStartActionListener());
add(btnStart);
}
private class BtnStartActionListener implements ActionListener
{
// change to wait_cursor
public void actionPerformed(ActionEvent e)
{
if (!current_active)
{
Component root = SwingUtilities.getRoot((JButton) e.getSource());
JOptionPane.showMessageDialog(root, "Wait 10 seconds");
root.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
// TODO: Disabling the root component prevents the WAIT_CURSOR from being displayed
//root.setEnabled(false);
current_active = true;
new Thread(new TimeKiller(root)).start();
}
}
}
}
private class TimeKiller implements Runnable
{
Component m_root;
public TimeKiller(Component p_root)
{
m_root = p_root;
}
#Override
public void run()
{
try
{
Thread.sleep(10 * 1000);
}
catch (InterruptedException e)
{
//Ignore it
}
// Change back to DEFAULT CURSOR
JOptionPane.showMessageDialog(m_root, "Done waiting");
m_root.setCursor(Cursor.getDefaultCursor());
current_active = false;
}
}
// create and setup the window.
public static void createAndShowGUI()
{
WaitCursor frame = new WaitCursor();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
try
{
createAndShowGUI();
}
catch (Exception e)
{
e.printStackTrace();
System.exit(0);
}
}
});
}
}

Related

How to make jButton.setVisible() work instantaneously?

I've written a test program with making the jButton invisible and visible:
import java.awt.Dimension;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.event.*;
public class Blink
{
private JButton btn;
private static JFrame f;
public static void delay(int ms)
{
try
{
Thread.sleep(ms);
}
catch(InterruptedException ex)
{
Thread.currentThread().interrupt();
}
}
public Blink()
{
f = new JFrame("Blink");
f.setPreferredSize(new Dimension(500, 500));
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
btn = new JButton("Click me and I'll blink!");
f.add(btn);
btn.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
buttonClicked();
}
});
f.pack();
f.setVisible(true);
}
private void buttonClicked()
{
for (int i = 0; i < 5; i++)
{
delay(300);
btn.setVisible(false);
delay(300);
btn.setVisible(true);
}
}
public static void main(String[] args)
{
new Blink();
}
}
Unfortunately, the jButton does not blink. And when the buttonClicked() function is changed, so that the jButton is set invisible 5 times and is not set visible back, the jButton disappears only when the for-loop finishes. How to make the jButton disappear an reappear instantaneously?
You cannot use Thread.sleep method in Swing Thread (all listeners are called in Event Dispatcher Thread - EDT). To achieve blinking you must use javax.swing.Timer class. For more information look here and here
Here is your reworked example:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Blink {
private JButton btn;
private JFrame f;
public void delay(int ms, boolean show) {
Timer timer = new Timer(ms, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
btn.setVisible(show);
btn.getParent().revalidate();
btn.getParent().repaint();
}
});
timer.setRepeats(false);
timer.start();
}
public Blink() {
f = new JFrame("Blink");
f.setPreferredSize(new Dimension(500, 500));
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
btn = new JButton("Click me and I'll blink!");
f.add(btn);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
buttonClicked();
}
});
f.pack();
f.setVisible(true);
}
private void buttonClicked() {
for (int i = 1; i <= 10; i += 2) {
delay(300 * i, false);
delay(300 * (i + 1), true);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Blink();
}
});
}
}
For some complicated layouts, call setVisible(false) may have side-effects. In this case the CardLayout with your component and an empty panel should be used.
Here is the variant with CardLayout
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Blink {
private static final String BUTTON_CARD = "button";
private static final String EMPTY_CARD = "empty";
private JButton btn;
private JFrame f;
private final CardLayout cardLayout = new CardLayout();
public void delay(int ms, boolean show) {
Timer timer = new Timer(ms, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
cardLayout.show(btn.getParent(), show ? BUTTON_CARD : EMPTY_CARD);
btn.getParent().revalidate();
btn.getParent().repaint();
}
});
timer.setRepeats(false);
timer.start();
}
public Blink() {
f = new JFrame("Blink");
f.setPreferredSize(new Dimension(500, 500));
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(cardLayout);
btn = new JButton("Click me and I'll blink!");
f.add(btn, BUTTON_CARD);
f.add(new JPanel(), EMPTY_CARD);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
buttonClicked();
}
});
f.pack();
f.setVisible(true);
}
private void buttonClicked() {
for (int i = 1; i <= 10; i += 2) {
delay(300 * i, false);
delay(300 * (i + 1), true);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Blink();
}
});
}
}
As #Sergiy points out - make sure you're running from the EDT, and don't sleep on the EDT, use a swing timer instead.
To make your jButton appear "invisbile", you can do something like this:
public void setInvisible(jButton jb) {
jb.setOpaque(false);
jb.setContentAreaFilled(false);
jb.setBorderPainted(false);
jb.setText("");
}
// Assuming you have the original text saved in a variable
public void setRevisible(jButton jb) {
jb.setOpaque(true);
jb.setContentAreaFilled(true);
jb.setBorderPainted(true);
jb.setText(originalString);
}
Depending on if you want the button to be clickable when it's invisible, you can also add btn.setEnabled(bool);

Why won't my JFrame respond to mouse and window changes?

Here is my code:
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class wind extends JFrame implements ComponentListener, MouseListener
{
JButton button;
JLabel label;
public wind()
{
// initialise instance variables
setTitle("My First Window!");
setSize(400, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
JPanel content = new JPanel();
content.setLayout(new FlowLayout());
content.addComponentListener(this);
content.addMouseListener(this);
label = new JLabel("My First Window");
content.add(label);
label.addComponentListener(this);
button = new JButton("Click If You Wish To Live!");
button.addMouseListener(this);
content.add(button)
setContentPane(content);
}
public void componentHidden(ComponentEvent e){
try{wait(100);}
catch(InterruptedException error){}
button.setText("Hidden!");
}
public void componentShown(ComponentEvent e){
try{wait(100);}
catch(InterruptedException error){}
button.setText("Shown!");
}
public void componentResized(ComponentEvent e){
try{wait(100);}
catch(InterruptedException error){}
button.setText("Resized!");
}
public void componentMoved(ComponentEvent e){
try{wait(100);}
catch(InterruptedException error){}
button.setText("Moved!");
}
public void mouseExited(MouseEvent e){
try{wait(100);}
catch(InterruptedException error){}
label.setText("Exited!");
}
public void mouseEntered(MouseEvent e){
try{wait(100);}
catch(InterruptedException error){}
label.setText("Entered!");
}
public void mousePressed(MouseEvent e){
try{wait(100);}
catch(InterruptedException error){}
label.setText("pressed at: "+e.getX()+" "+e.getY());
}
public void mouseReleased(MouseEvent e){
try{wait(100);}
catch(InterruptedException error){}
label.setText("Released!");
label.setLocation(e.getX(), e.getY());
}
public void mouseClicked(MouseEvent e){}
}
It won't respond to the mouse or window re-sizing, hiding, or moving. Furthermore the button is not being displayed. fixed! I am just starting to learn about Java's JFrame and other graphics so I have no idea what's wrong with my code, although I suspect it has something to do with the way I made the button and added the listeners to the objects. Could someone please explain why it does this, and how to fix it. Thank you in advance!
Your problem is that you are using the wait function not correctly. Try to use the class javax.swing.Timer also known as a Swing Timer for delays in Swing programs, for simple animations and for repetitive actions. For more information see this example on stackoverflow: Java Wait Function
One possible way to add a ActionListener to a JButton:
// You are adding an ActionListener to the button
//Using the method addActionListener and a anonymous inner class
button.addActionListener(new ActionListener() {//anonymous inner class
#Override
public void actionPerformed(ActionEvent arg0)
{
button.setText("Text modified by an event called ActionEvent!");
}
});
I decided to play with similar code and came up with this bit of code that tries to show the state of things in a status bar at the bottom:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
#SuppressWarnings({ "serial"})
// so the compiler won't complain
public class MyWindPanel extends JPanel {
private static final int PREF_W = 1200;
private static final int PREF_H = 600;
private static final String MOUSE_LOCATION = "Mouse Location [%04d, %04d]";
private static final String COMPONENT_STATE = "Component: %-15s";
private static final String TIMER_LABEL = "Elapsed Time: %02d:%02d:%02d:%03d";
private static final int TIMER_DELAY = 20;
private static final String MOUSE_STATE = "Mouse State: %-15s";
public static final String BUTTON_TEXT = "Set MyWindPanel %s";
private JLabel mouseLocation = new JLabel(
String.format(MOUSE_LOCATION, 0, 0));
private JLabel mouseState = new JLabel(String.format(MOUSE_STATE, ""));
private JLabel componentState = new JLabel(
String.format(COMPONENT_STATE, ""));
private JLabel timerLabel = new JLabel(
String.format(TIMER_LABEL, 0, 0, 0, 0));
private long startTime = System.currentTimeMillis();
private Action buttonAction = new MyButtonAction(String.format(BUTTON_TEXT, "Invisible"));
private JPanel statusPanel;
public MyWindPanel() {
setBackground(Color.pink);
Font font = new Font(Font.MONOSPACED, Font.BOLD, 14);
mouseLocation.setFont(font);
mouseState.setFont(font);
componentState.setFont(font);
timerLabel.setFont(font);
statusPanel = new JPanel();
statusPanel.setLayout(new BoxLayout(statusPanel, BoxLayout.LINE_AXIS));
statusPanel.add(mouseLocation);
statusPanel.add(Box.createHorizontalStrut(25));
statusPanel.add(mouseState);
statusPanel.add(Box.createHorizontalStrut(25));
statusPanel.add(componentState);
statusPanel.add(Box.createHorizontalStrut(25));
statusPanel.add(timerLabel);
new Timer(TIMER_DELAY, new TimerListener()).start();
MouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseMotionListener(myMouseAdapter);
addMouseListener(myMouseAdapter);
addComponentListener(new MyComponentListener());
setLayout(new BorderLayout());
// add(statusPanel, BorderLayout.PAGE_END);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
public Action getButtonAction() {
return buttonAction;
}
public JComponent getStatusPanel() {
return statusPanel;
}
private class TimerListener implements ActionListener {
private static final int SECONDS_PER_MIN = 60;
private static final int MSEC_PER_SEC = 1000;
private static final int MIN_PER_HOUR = 60;
#Override
public void actionPerformed(ActionEvent evt) {
if (!MyWindPanel.this.isDisplayable()) {
((Timer) evt.getSource()).stop(); // so timer will stop when program
// over
}
long currentTime = System.currentTimeMillis();
long diff = currentTime - startTime;
int hours = (int) (diff / (MIN_PER_HOUR * SECONDS_PER_MIN * MSEC_PER_SEC));
int minutes = (int) (diff / (SECONDS_PER_MIN * MSEC_PER_SEC))
% MIN_PER_HOUR;
int seconds = (int) ((diff / MSEC_PER_SEC) % SECONDS_PER_MIN);
int mSec = (int) diff % MSEC_PER_SEC;
timerLabel.setText(String.format(TIMER_LABEL, hours, minutes, seconds,
mSec));
}
}
private class MyComponentListener extends ComponentAdapter {
#Override
public void componentHidden(ComponentEvent e) {
componentState.setText(String.format(COMPONENT_STATE, "Hidden"));
}
#Override
public void componentMoved(ComponentEvent e) {
componentState.setText(String.format(COMPONENT_STATE, "Moved"));
}
#Override
public void componentResized(ComponentEvent e) {
componentState.setText(String.format(COMPONENT_STATE, "Resized"));
}
#Override
public void componentShown(ComponentEvent e) {
componentState.setText(String.format(COMPONENT_STATE, "Shown"));
}
}
private class MyButtonAction extends AbstractAction {
public MyButtonAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
boolean visible = MyWindPanel.this.isVisible();
String text = visible ? "Visible" : "Invisible";
((AbstractButton) e.getSource()).setText(String.format(BUTTON_TEXT, text));
MyWindPanel.this.setVisible(!MyWindPanel.this.isVisible());
Window win = SwingUtilities.getWindowAncestor(MyWindPanel.this);
win.revalidate();
win.repaint();
}
}
private class MyMouseAdapter extends MouseAdapter {
#Override
public void mouseMoved(MouseEvent e) {
mouseLocation.setText(String.format(MOUSE_LOCATION, e.getX(), e.getY()));
}
#Override
public void mouseDragged(MouseEvent e) {
mouseState.setText(String.format(MOUSE_STATE, "Dragged"));
mouseLocation.setText(String.format(MOUSE_LOCATION, e.getX(), e.getY()));
}
public void mousePressed(MouseEvent e) {
mouseState.setText(String.format(MOUSE_STATE, "Pressed"));
};
public void mouseReleased(MouseEvent e) {
mouseState.setText(String.format(MOUSE_STATE, "Released"));
};
public void mouseEntered(MouseEvent e) {
mouseState.setText(String.format(MOUSE_STATE, "Entered"));
};
public void mouseExited(MouseEvent e) {
mouseState.setText(String.format(MOUSE_STATE, "Exited"));
};
}
private static void createAndShowGui() {
MyWindPanel mainPanel = new MyWindPanel();
JPanel topPanel = new JPanel();
topPanel.add(new JButton(mainPanel.getButtonAction()));
JFrame frame = new JFrame("MyWind");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.getContentPane().add(topPanel, BorderLayout.PAGE_START);
frame.getContentPane().add(mainPanel.getStatusPanel(), BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

How to open a new window or switch using a button?

I'm trying to figure out this for ages, starting to wonder if it is possible!
I have a starting window for my app - I need it so that when I click on a button I have created, the window either closes and opens a new window or the window resizes and leaves just the canvas (ready to put new widgets, sprites etc... ).
I know I need a handler event for this but I just can't get the code to work.
Im not quite sure whats your question but i coded a example with a JFrame and 3 Buttons.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class OpenWindowAndResizeWindow
{
private JFrame frame;
private JButton btnOpenNewWindow;
private JButton btnResizeWindow;
private JButton btnRemoveAllButtons;
/**
* Launch the application.
*/
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
OpenWindowAndResizeWindow window = new OpenWindowAndResizeWindow();
window.frame.setVisible(true);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public OpenWindowAndResizeWindow()
{
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize()
{
frame = new JFrame();
frame.setBounds(100, 100, 300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(getBtnOpenNewWindow(), BorderLayout.NORTH);
frame.getContentPane().add(getBtnResizeWindow(), BorderLayout.SOUTH);
frame.getContentPane().add(getBtnRemoveAllButtons(), BorderLayout.CENTER);
frame.setVisible(true);
}
private void openNewWindow()
{
OpenWindowAndResizeWindow newWindow = new OpenWindowAndResizeWindow();
frame.dispose();
}
private void removeButtons()
{
getBtnOpenNewWindow().setVisible(false);
getBtnRemoveAllButtons().setVisible(false);
getBtnResizeWindow().setVisible(false);
}
private void resizeWindow()
{
Rectangle rectangle = frame.getBounds();
rectangle.width = (int)rectangle.getWidth() + 100;
rectangle.height = (int)rectangle.getHeight() + 100;
frame.setBounds(rectangle);
}
private JButton getBtnOpenNewWindow() {
if (btnOpenNewWindow == null) {
btnOpenNewWindow = new JButton("Open new Window");
btnOpenNewWindow.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
openNewWindow();
}
});
}
return btnOpenNewWindow;
}
private JButton getBtnResizeWindow() {
if (btnResizeWindow == null) {
btnResizeWindow = new JButton("Resize Window");
btnResizeWindow.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
resizeWindow();
}
});
}
return btnResizeWindow;
}
private JButton getBtnRemoveAllButtons() {
if (btnRemoveAllButtons == null) {
btnRemoveAllButtons = new JButton("Remove All Buttons");
btnRemoveAllButtons.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
removeButtons();
}
});
}
return btnRemoveAllButtons;
}
}
This code is ready to compile with javac or just paste it in your IDE.
Maybe this helps a bit. The Java SE API Documentation is useful too.

Good way to set/refresh information with thread in java swing app

I'm not a Java programmer and I'm not sure if what I'm doing is correct or not, or if exist a better way to do this.
I'm making a swing Java app with multi-threading.
I have many swing component (textfield, texarea, label, list, ...) which are set and refresh with many threads.
For all my component I use something like the code below (it's just a tiny example) for set/refresh it.
Is Main.mainUI.setThumbLbl(image); for set/refresh my component a good way or not ? (I use something like this in other threads for all component)
And is there another better way to do this ?
Main :
public class Main {
public static MyMainUI mainUI;
public static void main(String args[]) {
mainUI = new mainUI();
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
mainUI.setVisible(true);
}
});
}
}
Jframe :
public class MyMainUI extends JFrame {
private JLabel thumbLbl;
private JButton thumbBtn;
public MyMainUI(){
// add thumbLbl, thumBtn
...
thumBtn.addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent evt) {
new MyThread().start();
}
});
}
public void setThumbLbl(final Image image) {
SwingUtilities.invokeLater(new Thread() {
#Override
public void run() {
thumbLbl.setIcon(new ImageIcon(image.getScaledInstance(thumbLblDim.width,
thumbLblDim.height, Image.SCALE_DEFAULT)));
}
});
}
}
Thread :
public class MyThread extends Thread {
#Override
public void run() {
//Get image from web server
...
Main.mainUI.setThumbLbl(image);
}
}
NB: I wrote this sample code in a text editor very quickly, maybe there are some mistakes but it's not what I'm asking for ^^.
NB2: Sorry for my bad English.
An example of what I meant is something like this:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.ExecutionException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class Main {
private static void createAndShowGui() {
JFrame frame = new JFrame("Main");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new MyMainUI());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
#SuppressWarnings("serial")
class MyMainUI extends JPanel {
public static final String IMG_URL_PATH = "http://duke.kenai.com/Oracle/OracleStrat.png";
private static final int PREF_W = 900;
private static final int PREF_H = 650;
private JLabel thumbLbl = new JLabel();
private JButton thumbBtn = new JButton("Get Image");
public MyMainUI() {
thumbBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
thumbBtn.setEnabled(false);
final ImageDownloader imgDownLoader = new ImageDownloader(IMG_URL_PATH);
imgDownLoader.execute();
imgDownLoader.addPropertyChangeListener(new ImgDownLoaderListener(imgDownLoader));
}
});
JPanel btnPanel = new JPanel();
btnPanel.add(thumbBtn);
setLayout(new BorderLayout());
add(new JScrollPane(thumbLbl), BorderLayout.CENTER);
add(btnPanel, BorderLayout.PAGE_END);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private class ImgDownLoaderListener implements PropertyChangeListener {
ImageDownloader imgDownLoader;
public ImgDownLoaderListener(ImageDownloader imgDownLoader) {
this.imgDownLoader = imgDownLoader;
}
#Override
public void propertyChange(PropertyChangeEvent evt) {
// swing worker is done
if (evt.getNewValue().equals(SwingWorker.StateValue.DONE)) {
thumbBtn.setEnabled(true);
try {
ImageIcon icon = imgDownLoader.get();
if (icon != null) {
thumbLbl.setIcon(icon);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
}
class ImageDownloader extends SwingWorker<ImageIcon, Void> {
private String imageUrlPath;
public ImageDownloader(String imageUrlPath) {
this.imageUrlPath = imageUrlPath;
}
#Override
protected ImageIcon doInBackground() throws Exception {
try {
URL imgUrl = new URL(imageUrlPath);
BufferedImage img = ImageIO.read(imgUrl);
return new ImageIcon(img); // return the ImageIcon
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null; // or return null if an error occurs
}
}
The background worker thread in this example has no knowledge about the structure of the GUI. All it does is download an image -- that's it, and then the GUI which listens for completion with a PropertyChangeListener gets the image by calling get() on the worker, and decides what it wants to do with it.

Problems with a SwingWorker

I'm trying to get a SwingWorker to work.
I've the following code at the moment:
public class ImageWorker extends SwingWorker<Void, Void> implements KeyListener
{
private JLabel imageLabel;
private ImageIcon basicImage;
private ImageIcon whiteImage;
public static void main(String[] args)
{
new ImageWorker();
}
public ImageWorker()
{
final JFrame frame = new JFrame();
imageLabel = new JLabel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.getContentPane().add(imageLabel);
frame.setVisible(true);
try
{
basicImage = new ImageIcon(ImageIO.read(new File("src\\img\\basis1.jpg")).getScaledInstance(1024, 768, Image.SCALE_SMOOTH));
whiteImage = new ImageIcon(ImageIO.read(new File("src\\img\\wit.jpg")).getScaledInstance(1024, 768, Image.SCALE_SMOOTH));
}
catch(IOException ex)
{
ex.getMessage();
}
this.execute();
}
#Override
protected Void doInBackground()
{
try
{
while (true)
{
displayImage(basicImage);
Thread.sleep(1000L);
if(isCancelled())
return null;
}
}
catch(InterruptedException e)
{
e.getMessage();
}
return null;
}
private void displayImage(final Icon image)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
imageLabel.setIcon(image);
}
});
}
I was expecting the images to appear in the JLabel, but I only see the JFrame popping up. The files are loaded correctly Ive tested that in another setup.
Any pointers?
Here is an example using a Timer rather than using the SwingWorker which really isn't appropriate to your situation. Note that it's not too different from your existing code.
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class ImageWorker implements KeyListener
{
private JLabel imageLabel;
private ImageIcon basicImage;
private ImageIcon whiteImage;
private boolean isBasic = true;
private int delay = 1000; //milliseconds
private Timer timer;
public static void main(String[] args)
{
new ImageWorker();
}
public ImageWorker()
{
final JFrame frame = new JFrame();
imageLabel = new JLabel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.getContentPane().add(imageLabel);
frame.setVisible(true);
try
{
basicImage = new ImageIcon(ImageIO.read(new File("src\\img\\basis1.jpg")).getScaledInstance(1024, 768, Image.SCALE_SMOOTH));
whiteImage = new ImageIcon(ImageIO.read(new File("src\\img\\wit.jpg")).getScaledInstance(1024, 768, Image.SCALE_SMOOTH));
}
catch (IOException ex)
{
ex.getMessage();
ex.printStackTrace();
}
frame.addKeyListener(this);
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if(isBasic) {
//display basic image
imageLabel.setIcon(basicImage);
}
else {
//display white image
imageLabel.setIcon(whiteImage);
}
//toggle the flag
isBasic = !isBasic;
}
};
//use a timer instead of SwingWorker
timer = new Timer(delay, taskPerformer);
timer.start();
}
#Override
public void keyPressed(KeyEvent e)
{
//key pressed, we want to stop toggling so stop the timer
timer.stop();
//do whatever else you were doing to set the value for isCancelled();
}
#Override
public void keyReleased(KeyEvent e)
{
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e)
{
// TODO Auto-generated method stub
}
}
A SwingWorker is not appropriate for your situation look into a Timer in the swing package. Here is a link to the API: http://download.oracle.com/javase/6/docs/api/javax/swing/Timer.html
You have the timer run and change an image every second since that is what you need.
Also, whenever you have exceptions, print out a stacktrace or the message at least. Otherwise you won't know if an exception occurs and is caught.

Categories