I am trying to change the icon (background) of a JLabel, but I am having an issue with the icon not updating. Whenever I tried lblStatusImg.setIcon(new ImageIcon(Brix_Updater_Module.class.getResource("/resources/fail.png"))); to change the JLabel in the main method, the compiler was first complaining that the variable lblStatusImg did not exist, so I moved it from the JFrame initialization method to a class level variable. After this, Eclipse complained that I was trying to reference a nonstatic method from static context, so I made lblStatusImg static. This made it possible for the program to compile, but the icon did not change whenever it was supposed to.
Since it's kind of hard to understand my problem here is a download link for an Eclipse workspace that demonstrates my problem. When you first open it, you will notice that there are some problems with it. They were left there on purpose to make it easier for you to see where I am having a hard time. If Eclipse asks you to make the items in question static, just do it and then run the program. You'll notice that it does not change the label icons as it should.
Since not all of you have Eclipse, here's the entire code from the workspace.
import java.awt.Component;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.Font;
import javax.swing.SwingConstants;
import java.awt.Window.Type;
import java.io.BufferedOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Timer;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class StackOverflow_Image_Resource_Demo {
private JFrame frmUpdate;
JLabel lblStatusImg = new JLabel("");
JButton btnUpdateComplete = new JButton("OK");
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
StackOverflow_Image_Resource_Demo window = new StackOverflow_Image_Resource_Demo();
window.frmUpdate.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
try {
lblStatusImg.setIcon(new ImageIcon(StackOverflow_Image_Resource_Demo.class.getResource("success.png")));
btnUpdateComplete.setVisible(true);
}
catch(Exception e)
{
Component frame = null;
lblStatusImg.setIcon(new ImageIcon(StackOverflow_Image_Resource_Demo.class.getResource("/resources/fail.png")));
JOptionPane.showMessageDialog(frame, "Update Failed", "Update Failed", JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
}
/**
* Create the application.
*/
public StackOverflow_Image_Resource_Demo() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frmUpdate = new JFrame();
frmUpdate.setType(Type.UTILITY);
frmUpdate.setTitle("StackOverflow Image Resource Issue Demo");
frmUpdate.setBounds(100, 100, 450, 300);
frmUpdate.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmUpdate.getContentPane().setLayout(null);
//JLabel lblStatusImg = new JLabel(""); - Commented out when I made lblStatusImg class level.
lblStatusImg.setIcon(new ImageIcon(StackOverflow_Image_Resource_Demo.class.getResource("/resources/updating.gif")));
lblStatusImg.setBounds(10, 22, 414, 97);
frmUpdate.getContentPane().add(lblStatusImg);
//JButton btnUpdateComplete = new JButton("OK"); - Commented out when I made btnUpdateComplete class level.
btnUpdateComplete.setVisible(false);
btnUpdateComplete.addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent arg0) {
System.exit(1);
}
});
btnUpdateComplete.setBounds(170, 179, 89, 23);
frmUpdate.getContentPane().add(btnUpdateComplete);
}
}
Here is a newer version of my code that updates the image, but doesn't fully load the UI until everything else is done.
import java.awt.Component;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.Font;
import javax.swing.SwingConstants;
import java.awt.Window.Type;
import java.io.BufferedOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Timer;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class StackOverflow_Image_Resource_Demo {
private JFrame frmUpdate;
JLabel lblStatusImg = new JLabel("");
JButton btnUpdateComplete = new JButton("OK");
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
StackOverflow_Image_Resource_Demo window = new StackOverflow_Image_Resource_Demo();
try {
lblStatusImg.setIcon(new ImageIcon(StackOverflow_Image_Resource_Demo.class.getResource("success.png")));
btnUpdateComplete.setVisible(true);
}
catch(Exception e)
{
Component frame = null;
lblStatusImg.setIcon(new ImageIcon(StackOverflow_Image_Resource_Demo.class.getResource("/resources/fail.png")));
JOptionPane.showMessageDialog(frame, "Update Failed", "Update Failed", JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
window.frmUpdate.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public StackOverflow_Image_Resource_Demo() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frmUpdate = new JFrame();
frmUpdate.setType(Type.UTILITY);
frmUpdate.setTitle("StackOverflow Image Resource Issue Demo");
frmUpdate.setBounds(100, 100, 450, 300);
frmUpdate.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmUpdate.getContentPane().setLayout(null);
//JLabel lblStatusImg = new JLabel(""); - Commented out when I made lblStatusImg class level.
lblStatusImg.setIcon(new ImageIcon(StackOverflow_Image_Resource_Demo.class.getResource("/resources/updating.gif")));
lblStatusImg.setBounds(10, 22, 414, 97);
frmUpdate.getContentPane().add(lblStatusImg);
//JButton btnUpdateComplete = new JButton("OK"); - Commented out when I made btnUpdateComplete class level.
btnUpdateComplete.setVisible(false);
btnUpdateComplete.addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent arg0) {
System.exit(1);
}
});
btnUpdateComplete.setBounds(170, 179, 89, 23);
frmUpdate.getContentPane().add(btnUpdateComplete);
}
}
Two things come to find. The first is, as you say, you're trying to reference a non-static variable from a static context.
The second is, you don't seem to understand how threading works...
Basically, main is typically executed within the "main" thread (when executed by the JVM).
You then use EventQueue.invokeLater. Which as, the name suggests, will execute the Runnable "later"...at some time in the future...
EventQueue.invokeLater(new Runnable() {
public void run() {
You then try and change the the icon (let's pass over the non-static reference for a momement)...but lblStatusImg won't have been initialized nor is it likely to have been displayed, as the Runnable has not yet been executed, meaning, even if you didn't run into a NullPointerException, you won't see the change...
You can test by adding a System.out in your Runnable and before the first lblStatusImg.setIcon call in the main method.
What you should do is...
Move the "status" change change to within the Runnable context.
Provide a setStatus method that is capable of changing the label and UI content as required based on the provide status
For example...
public static final int SUCCESS = 0;
public static final int FAIL = 0;
//...
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
StackOverflow_Image_Resource_Demo window = new StackOverflow_Image_Resource_Demo();
// This e
window.frmUpdate.setVisible(true);
window.setStatus(StackOverflow_Image_Resource_Demo.SUCCESS);
} catch (Exception e) {
e.printStackTrace();
Component frame = null;
window.setStatus(StackOverflow_Image_Resource_Demo.FAIL);
JOptionPane.showMessageDialog(frame, "Update Failed", "Update Failed", JOptionPane.ERROR_MESSAGE);
window.dispose();
}
}
});
}
You should avoid exposing instance fields as public and instead, provide methods that either change their state indirectly (such as setStatus) or directly (setStatusIcon). In this case, I prefer the first method as this allows the class to determine what a change in status actually means.
Related
I'm having a problem with JButton. I need to change the text on the goPauseButton when it has been clicked, but I get this error: goPauseButton cannot be resolved. I'm quite new to Java, so I started trying to solve the issue using techniques from other languages such as Free Pascal. There you need to refer to the class where the button is in, and then the button. In my code it would look like this:
PrisonersDilemma.goPauseButton.setText("Pause");
But then I get this error: Cannot make a static reference to the non-static field PrisonersDilemma.goPauseButton
This is my code (so far), I've erased unimportant things:
Main class
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.JButton;
import javax.swing.JLabel;
import java.util.Hashtable;
//...
public class PrisonersDilemma /* possible extends... */ {
// declaring
JFrame frame;
PlayingField field;
JPanel componentPanel;
public JButton goPauseButton;
public JPanel createComponentPanel() {
componentPanel = new JPanel();
componentPanel.setLayout(new GridLayout(2,6));
// set goPauseButton
goPauseButton = new JButton("GO!");
goPauseButton.addActionListener(field);
goPauseButton.setBounds(110,350, 80,20); // first coordinates, then size
frame.add(goPauseButton);
return componentPanel;
}
void buildGUI() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
field = new PlayingField();
// set frame
frame = new JFrame("Prisoners Dilemma");
frame.add(field);
createComponentPanel();
frame.add(field, BorderLayout.CENTER);
frame.setLocation(200, 200);
frame.pack();
frame.setVisible(true);
frame.setSize(400, 450);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
} );
}
Class with ActionEventHandler
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.JButton;
public class PlayingField extends JPanel
implements ActionListener,
ChangeListener {
private boolean started;
#Override
public void actionPerformed(ActionEvent e) {
// TODO
if ("GO!".equals(e.getActionCommand())){
System.out.println("GO!");
started = true;
goPauseButton.setText("Pause"); // here is the error
} else if ("Pause".equals(e.getActionCommand())){
System.out.println("Pause");
started = false;
} else if ("Reset".equals(e.getActionCommand())){
System.out.println("Reset");
}
}
}
I think you need to change the way you're approaching the problem. The PlayingField has no responsibility for modifying the state of the goPauseButton in PrisonersDilemma. Instead, PrisonersDilemma should update the goPauseButton and call an appropriate method of PlayingField
For example...
goPauseButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
goPauseButton.setText("Pause");
field.start();
}
});
And...
public class PlayingField extends JPanel {
public void start() {
System.out.println("GO!");
started = true;
}
public void pause() {
started = false;
System.out.println("Pause");
}
public void reset() {
System.out.println("Reset");
}
}
As part of learning SwingWorker on Java swing I created a simple program where a different thread(Other than EDT) is doing some background task and once thats done that thread is updating GUI component (JTextArea).
As I understand if we try to update GUI components from an outside thread ,other than EDT , then UI might get freezed. But this is not happening. I really would like to create that situation(Freeze UI) so as to understand it better. Below is my code that I tried. Can some one help me saying what I need to do on my code so that UI is getting freezed.
App.java
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class App {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new MainFrame();
}
});
}
}
MainFrame.java
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class MainFrame extends JFrame implements ActionListener {
private JButton btn,btn2;
private JTextArea txtArea;
public MainFrame() {
super("Hello World");
setLayout(new BorderLayout());
btn = new JButton("Click Me!");
btn2 = new JButton("Click Me New!");
txtArea = new JTextArea();
btn.addActionListener(this);
add(txtArea,BorderLayout.CENTER);
add(btn,BorderLayout.SOUTH);
add(btn2,BorderLayout.NORTH);
setSize(600,800);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
MyTestThread extThr = new MyTestThread();
extThr.setBtnRef(txtArea);
extThr.start();
}
}
MyTestThread.java
import javax.swing.JTextArea;
public class MyTestThread extends Thread {
private int i = 0;
private JTextArea txtAreaRef;
public void setBtnRef(JTextArea ta) {
this.txtAreaRef = ta;
}
public void run() {
while (i < 500000) {
try {
txtAreaRef.append("test"+i+"\n");
i=i+1;
sleep(2000);
} catch (InterruptedException e) {System.out.println(e.getMessage());
e.printStackTrace();
}
}
}
}
I have no idea where you got that information from, but calling GUI updates outside of the EDT do not cause UI freezing.
If you want to produce a freeze, try making an infinite loop inside the EDT, like this.
This will cause the UI to permanently freeze.
public void actionPerformed(ActionEvent e) {
//MyTestThread extThr = new MyTestThread();
//extThr.setBtnRef(txtArea);
//extThr.start();
while(true) {}
}
I am using a scripting API for making a script for a bot for a game I play, however whenever I override a bot manager, a JOptionPane appears that blocks execution until I close it, however I would like to run this script without human intervention, so I would like to bypass this pane.
I have tried to overwrite the JOptionPane class at runtime to no avail, and I have tried contacting the developer of the bot's API to add an override however he doesn't want to add an override.
I am open to any methods of resolving this (reflection, etc.), I was thinking of detecting the pane's title and force-closing it however that it way beyond my skill level.
Pane title: Override Warning!
I would add the pane text however it reveals personal information.
Here is the possibility to suppress all JOptionPane dialogs. If you want to do it with some of them you probably need to provide additional check for dialog title.
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class CloseDialog implements Runnable {
private final AWTEventListener hideOptionPaneListener = new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
if (event instanceof WindowEvent) {
processWindowEvent((WindowEvent) event);
}
}
};
private void processWindowEvent(WindowEvent we) {
if (we.getID() == WindowEvent.WINDOW_OPENED && we.getWindow() instanceof JDialog) {
final JDialog dlg = (JDialog) we.getWindow();
Component[] comps = dlg.getContentPane().getComponents();
if (comps.length > 0 && comps[0] instanceof JOptionPane) { // probably also check dialog title
dlg.setVisible(false);
}
}
}
#Override
public void run() {
final JFrame frm = new JFrame("Test frame");
JButton button = new JButton("Show option pane");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(frm, "Simple message");
}
});
final JCheckBox checkBox = new JCheckBox("Suppress option pane");
checkBox.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (checkBox.isSelected()) {
Toolkit.getDefaultToolkit().addAWTEventListener(hideOptionPaneListener, AWTEvent.WINDOW_EVENT_MASK);
} else {
Toolkit.getDefaultToolkit().removeAWTEventListener(hideOptionPaneListener);
}
}
});
JPanel top = new JPanel(new FlowLayout());
top.add(button);
frm.add(top, BorderLayout.NORTH);
frm.add(checkBox, BorderLayout.SOUTH);
frm.setSize(400, 200);
frm.setLocationRelativeTo(null);
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new CloseDialog());
}
}
I've been trying to make it so my button will close out of the frame on click but it never does anything. I've looked through several stackoverflow threads but none of them seems to work on my this.. here is what I have so far
JButton start = new JButton("Start");
start.setBounds(251, 216, 119, 23);
start.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent evt) {
try {
int hpToEat = Integer.parseInt(GUI.textField.getText());
Frost.hp = hpToEat;
} catch(NumberFormatException nfe) {
GUI.textField.setText("");
}
setVisible(false);
}
});
contentPane.add(start);
I have tried making a closeFrame method which uses super.dispose(); and I've also tried system.exit(0);
Does anyone have any idea as to why My button won't do What i want it to do?
Someone requested the rest of my code so here it is:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JCheckBox;
import javax.swing.JTextField;
import javax.swing.JButton;
public class GUI extends JFrame{
private JPanel contentPane;
public static JTextField textField;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GUI frame = new GUI();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public GUI() {
//LABELS ===================================================================================================
The problem is that GUI.textfield is not what you think it is. You're shadowing the field here:
JTextField textField = new JTextField();
That creates a local variable by the name textField, it does not set the static field you're using in the action listener. A quick fix would be writing just:
textField = new JTextField();
However, I recommend getting out of the habit of using static fields. That approach does not scale. Furthermore, don't use absolute positioning. It leads to no end of trouble (just browse a few questions in the swing tag for examples). Learn to use layout managers right from the start.
I am experiencing a problem with Swing that only occurs when the computer monitor is powered off, but my Swing application continues to run in the background. It seems that whenever the monitor is off, Swing/AWT cancels all painting operations, leading to a number of display issues in the GUI that are visible as soon as the monitor turns back on.
For example, when I turn off the monitor using a custom JNI function and subsequently open a simple message dialog, the message dialog is blank when the monitor turns back on:
But it paints correctly after the next repaint:
Is this the expected behavior of Swing? Is there a way to instruct Swing to continue drawing to the screen even if the monitor is powered off?
EDIT: Here is an SSCCE:
package test;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
public class App {
public static void main(String[] args) throws Throwable {
System.out.println("***** Please turn off the monitor in the next 70 seconds *****");
Thread.sleep(1000L * 70);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JOptionPane.showMessageDialog(null, "Test");
}
});
}
}
I am using 64-bit Windows 7 Home Premium SP1 and 64-bit Java 1.6.0_24.
EDIT 2: Here is another program with which I experience the effect of "canceled painting operations":
package test;
import static com.mycompany.Util.turnOffMonitors;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class DialogTest extends JDialog {
private final JLabel label;
public DialogTest() {
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
label = new JLabel("Test", JLabel.CENTER);
label.setOpaque(true);
Container contentPane = getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(BorderLayout.CENTER, label);
this.setPreferredSize(new Dimension(200, 110));
pack();
setLocationRelativeTo(null);
setVisible(true);
Thread t = new Thread() {
#Override
public void run() {
turnOffMonitors();
try {
Thread.sleep(3000L);
} catch (InterruptedException ex) { }
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
label.setBackground(Color.YELLOW);
}
});
}
};
t.start();
}
public static void main(String[] args) throws Throwable {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new DialogTest();
}
});
}
}
Before the monitor shuts off, I see:
With the monitor off, the label background color is changed to yellow in the background. I then move the mouse to turn the monitor back on. The dialog is visually unchanged. It is only after I force a repaint (by ALT-TABbing, for example) do I see the yellow:
EDIT 3: Reported to Oracle as Bug ID 7049597.
I then started the program and stopped
moving the mouse/typing. After one
minute, the screen turned off. I
waited another 20 seconds to move the
mouse. The monitor turned back on and
I saw a blank message dialog.
Using your example, I don't see this on my (non-Windows) platform. You might try the example below, which should alternate between WINDOW_ACTIVATED on wake and WINDOW_DEACTIVATED on sleep. If so, you could extend JDialog and repaint() in windowActivated().
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
/** #see http://stackoverflow.com/questions/6163606 */
public class DialogEventTest extends JDialog {
public DialogEventTest() {
this.setLayout(new GridLayout(0, 1));
this.add(new JLabel("Dialog event test.", JLabel.CENTER));
this.add(new JButton(new AbstractAction("Close") {
#Override
public void actionPerformed(ActionEvent e) {
DialogEventTest.this.setVisible(false);
DialogEventTest.this.dispatchEvent(new WindowEvent(
DialogEventTest.this, WindowEvent.WINDOW_CLOSING));
}
}));
}
private static class WindowHandler extends WindowAdapter {
#Override
public void windowActivated(WindowEvent e) {
System.out.println(e);
}
#Override
public void windowDeactivated(WindowEvent e) {
System.out.println(e);
}
}
private void display() {
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
this.addWindowListener(new WindowHandler());
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new DialogEventTest().display();
}
});
}
}
The problem probably has more to do with how it repaints when the screen comes on rather than what happens while it's off. You could check by running a screen recorder.