I've tried many things to get this button bb or continue to output "Hey Buddy", yet it still does not work. It is displayed yet when i press it nothing happens. The code uses both java swing a awt.
package Game;
import java.awt.*;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.TextEvent;
import java.awt.event.TextListener;
import java.util.concurrent.TimeUnit;
import javax.swing.JButton;
public class base extends java.applet.Applet implements ActionListener, TextListener {
//Graphics
//Graphics
#SuppressWarnings("deprecation")
public static JButton bb = new JButton("Continue");
public TextArea ta = new TextArea(30, 140);
TextArea tb = new TextArea(3, 130);
public int counter = 0;
//main class
public static void main(String[] args) {
Frame f = new Frame("---Quest---");
base ex = new base();
ex.init();
f.add("Center", ex);
f.pack();
f.show(true);
bb.addActionListener(ex);
}
public void actionPerformed1(ActionEvent Continue) {
bb.addActionListener(this);
counter++;
if (Continue.getSource() == bb && counter == 1) {
tb.append("Hey Buddy");
}
}
//graphics
public void init() {
bb.addActionListener(this);
Panel p;
setLayout(new BorderLayout());
p = new Panel();
ta.append("Hey");
bb.addActionListener(this);
p.add(bb);
p.add(ta);
p.add(tb);
p.setBackground(Color.blue);
ta.setBackground(Color.cyan);
ta.setEditable(false);
add("Center", p);
p.setVisible(true);
}
//time class
public static int nap(int time) {
try {
TimeUnit.SECONDS.sleep(time);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return 0;
}
//end of code
#Override
public void textValueChanged(TextEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
The whole code is buggy.Read the Comments inline.
1.Idk why you are adding actionListener to the button 4 times(Keep one)
2.You have to have to change the actionPerformed1 to actionPerfromed as you are implementing the ActionListener and assigning this to button's ActionListener
public TextArea ta = new TextArea(30, 140);
TextArea tb = new TextArea(3, 130);
public int counter = 0;
//main class
public static void main(String[] args) {
f.show(true);//show is deprecated use setVisible(true) instead;
bb.addActionListener(ex);//1
}
public void actionPerformed1(ActionEvent Continue) {//have to change the actionPerformed1 to actionPerfromed
bb.addActionListener(this);//2 What is this assigning inside actionPerformed Need to be removed
counter++;
if (Continue.getSource() == bb && counter == 1) {
tb.append("Hey Buddy");
}
}
//graphics
public void init() {
bb.addActionListener(this);//3
Panel p;
setLayout(new BorderLayout());
p = new Panel();
ta.append("Hey");
bb.addActionListener(this);//4
p.add(bb);
p.setVisible(true);//already called a show for JFrame why you want to set Visible of Panel
}
Related
I want to display a "loading message" when a process is started and I want to change the message when the process is finished. I tried to update the text from a JLabel before and after the thread with the process is started but the problem is that on the frame appears only the last update.
Here is my code:
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class MyClass extends JFrame {
private JLabel loading;
private JButton jButton;
private JPanel jPanel;
public static void main(String[] args) {
new MyClass();
}
MyClass() {
jPanel = new JPanel();
setLayout(new GridLayout(0, 1));
loading = new JLabel("");
loading.setVisible(true);
jButton = new JButton("Click me!");
addActionToJButon();
setSize(300, 300);
jPanel.add(jButton);
jPanel.add(loading);
add(jPanel);
setVisible(true);
}
private void addActionToJButon() {
jButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
loading.setText("Loading....");
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i <= 1000000; i++) {
System.out.println(i);
}
}
}).start();
loading.setText("Done!");
}
});
}
}
I was expecting to appear the label "Loading..." once what the process is started and the message "Done" when the process is finished but I can't find out why on the frame appears the label with the message "Done!".
Thanks to JB Nizet advices I used SwingWorker and the code is working now.
Here is the correct code:
package view;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutionException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
public class MyClass extends JFrame {
private JLabel loading;
private JButton jButton;
private JPanel jPanel;
public static void main(String[] args) {
new MyClass();
}
MyClass() {
jPanel = new JPanel();
setLayout(new GridLayout(0, 1));
loading = new JLabel("");
loading.setVisible(true);
jButton = new JButton("Click me!");
addActionToJButon();
setSize(300, 300);
jPanel.add(jButton);
jPanel.add(loading);
add(jPanel);
setVisible(true);
}
private void addActionToJButon() {
jButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
loading.setText("Loading....");
swingWorker();
}
});
}
private void swingWorker() {
SwingWorker worker = new SwingWorker<String, String>() {
#Override
protected String doInBackground() throws Exception {
// TODO Auto-generated method stub
for (int i = 0; i <= 1000000; i++) {
System.out.println(i);
}
return "Done";
}
protected void done() {
try {
String finished = get();
loading.setText(finished);
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
worker.execute();
}
}
Because you are doing your "loading" within a thread, and you are setting your loading text outside the thread, you immediately set loading to "Done!" when you begin loading. What you want to do is set loading within your run() function like this:
private void addActionToJButon() {
jButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
new Thread(new Runnable() {
#Override
public void run() {
loading.setText("Loading....");
// TODO Auto-generated method stub
for (int i = 0; i <= 1000000; i++) {
System.out.println(i);
}
loading.setText("Done!");
}
}).start();
}
});
}
I am having trouble getting my Image to display when I click my Jbutton, the test sysoutprint works but the Image does not. Any Ideas on what to do I am very lost! The Image is an easter egg for a school project, feel free to make comments. Should I use something besides a ImageIcon or what not?
Also if there are any other errors please let me know!
package GUI;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class mainView{
private static JFrame main; //main frame we add everything too
private static JPanel newGame; //panel for new game
private static JPanel dropDownPanel; //panel for the combobox
private static CardLayout clayout; //cardlayout for new game
private static JComboBox dropDown; //dropdown combobox
ImageIcon eastImg;
public void codeNameView(){
main = new JFrame("CodeNames");
main.setSize(600, 900);
main.setVisible(true);
//dropdown menu for quit and new game
String[] choice = {" " , "NewGame" , "Quit"};
dropDown = new JComboBox(choice);
//below is the panel where we add new game and quit options too
dropDownPanel = new JPanel();
dropDownPanel.setSize(100, 100);
dropDownPanel.add(dropDown);
main.getContentPane().add(dropDownPanel,BorderLayout.NORTH);
//easter egg
JButton easterButt = new JButton("Pass CSE 116");
JLabel eastLbl = new JLabel();
//added button to JLabel
eastLbl.add(easterButt);
try{
String path = "/Users/nabeelkhalid/git/s18semesterproject-b4-zigzag1/src/GUI/MatthewPhoto.jpg";
eastImg = new ImageIcon(path);
}catch(Exception ex){
System.out.print(ex);
}
//added label to Panel
dropDownPanel.add(eastLbl);
eastLbl.addMouseListener(new MouseListener(){
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
eastLbl.setIcon(eastImg);
System.out.print("test");
}
//Ignore
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
});
//action listener for dropdown combobox
dropDown.addActionListener(new ActionListener(){
/**
* Allows for the user to select New Game or Quit and have the game perform said action
*/
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
JComboBox cb = (JComboBox) e.getSource();
Object selectedOption = dropDown.getSelectedItem();
if (selectedOption.equals("Quit")) {
main.dispose();
}else if(selectedOption.equals("NewGame")){
codeNameView();
System.out.print("yolo");
}
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
mainView x = new mainView();
// create a instance on mainview to run instead of using static methods
}
});
}
}
The primary issue seems to be right here
try{
String path = "/Users/nabeelkhalid/git/s18semesterproject-b4-zigzag1/src/GUI/MatthewPhoto.jpg";
eastImg = new ImageIcon(path);
}catch(Exception ex){
System.out.print(ex);
}
The path is referencing a resource within the context of your src path. You should never reference src in your code, it won't exist once the program is exported (to a Jar or run on a different computer)
Instead, you should consider using Class#getResource to obtain a reference to the image and I'd personally use ImageIO.read over ImageIcon as a personal preference.
try{
String path = "/GUI/MatthewPhoto.jpg";
eastImg = new ImageIcon(ImageIO.read(this.getClass().getResource(path)));
}catch(Exception ex){
System.out.print(ex);
}
And, your next problem is, you're trying to add a JLabel to a JButton, expect, a JButton has not layout manager AND JButton already has support for display an image, so instead, you should be doing something more like...
JButton easterButt = new JButton("Pass CSE 116");
//JLabel eastLbl = new JLabel();
//added button to JLabel
//eastLbl.add(easterButt);
try {
String path = "/GUI/MatthewPhoto.jpg";
eastImg = new ImageIcon(ImageIO.read(this.getClass().getResource(path)));
} catch (Exception ex) {
System.out.print(ex);
}
//added label to Panel
dropDownPanel.add(easterButt);
easterButt.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
easterButt.setIcon(eastImg);
}
});
You really should take a closer look at How to Use Buttons, Check Boxes, and Radio Buttons
Test Code
This is the code I used to test the solutions suggested above
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class mainView {
private static JFrame main; //main frame we add everything too
private static JPanel newGame; //panel for new game
private static JPanel dropDownPanel; //panel for the combobox
private static CardLayout clayout; //cardlayout for new game
private static JComboBox dropDown; //dropdown combobox
ImageIcon eastImg;
public void codeNameView() {
main = new JFrame("CodeNames");
main.setSize(600, 900);
//dropdown menu for quit and new game
String[] choice = {" ", "NewGame", "Quit"};
dropDown = new JComboBox(choice);
//below is the panel where we add new game and quit options too
dropDownPanel = new JPanel();
dropDownPanel.setSize(100, 100);
dropDownPanel.add(dropDown);
main.getContentPane().add(dropDownPanel, BorderLayout.NORTH);
//easter egg
JButton easterButt = new JButton("Pass CSE 116");
// JLabel eastLbl = new JLabel();
// //added button to JLabel
// eastLbl.add(easterButt);
try {
String path = "/GUI/MatthewPhoto.jpg";
eastImg = new ImageIcon(ImageIO.read(this.getClass().getResource(path)));
} catch (Exception ex) {
System.out.print(ex);
}
//added label to Panel
dropDownPanel.add(easterButt);
easterButt.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
easterButt.setIcon(eastImg);
}
});
//action listener for dropdown combobox
dropDown.addActionListener(new ActionListener() {
/**
* Allows for the user to select New Game or Quit and have the game
* perform said action
*/
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
JComboBox cb = (JComboBox) e.getSource();
Object selectedOption = dropDown.getSelectedItem();
if (selectedOption.equals("Quit")) {
main.dispose();
} else if (selectedOption.equals("NewGame")) {
codeNameView();
System.out.print("yolo");
}
}
});
main.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
System.out.println("Hello");
mainView x = new mainView();
x.codeNameView();
// create a instance on mainview to run instead of using static methods
}
});
}
}
Try using something like this:
String path = "C:\\Users\\nabeelkhalid\\git\\s18semesterproject-b4-zigzag1\\src\\GUI\\MatthewPhoto.jpg";
Hi I have the following code where I have a start and stop button . when start is pressed canvas starts painting but I cannot press stop button until the start operation is done . I need to stop and resume the paint on the button press . Once the start button is pressed the other buttons cannot be pressed till the canvas is painted.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Hashtable;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.Timer;
public abstract class JUIApp extends JPanel implements ActionListener {
public static CACanvas cacanvas= null;
public ArrayList<int[]> genL;
public JFrame frame = null;
protected JPanel mainPanel = null;
private JButton btn0 = null;
private JButton btn1 = null;
private JButton btn2 = null;
#SuppressWarnings("rawtypes")
DefaultComboBoxModel rules = null;
#SuppressWarnings("rawtypes")
JComboBox rulesCombo =null;
JScrollPane ruleListScrollPane=null;
JLabel lable=null;
JTextField generation=null;
JLabel gLable=null;
public static String Rule;
public static String Generations;
public boolean isChanged =false;
public int gridCellSize=4;
private static final long serialVersionUID = 1L;
public int genCurrent=0;
public int posCurrent=0;
public int i;
public Color cellColor= null;
public Timer waitTimer;
public static boolean waitFlag;
public static boolean alert1Flag=false;
public boolean stopFlag=false;
public JLabel Alert1=new JLabel();
public int genCheck=0;
//private List<Point> fillCells;
public JUIApp() {
initGUI();
}
public void initGUI() {
//fillCells = new ArrayList<>(25);
frame = new JFrame();
frame.setTitle("Cellular Automata Demo");
frame.setSize(1050, 610);
frame.setResizable(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(getMainPanel(),BorderLayout.NORTH);
frame.setVisible(true);
Toolkit.getDefaultToolkit().setDynamicLayout(false);
cacanvas=new CACanvas();
frame.add(cacanvas);
}
#SuppressWarnings({ "unchecked", "rawtypes" })
public JPanel getMainPanel() {
mainPanel = new JPanel();
mainPanel.setLayout(new FlowLayout());
//cacanvas=new CACanvas();
btn0 = new JButton("Start");
btn0.addActionListener(this);
//waitTimer = new Timer(1000, this);
mainPanel.add(btn0);
JButton btn2 = new JButton("Stop");
btn2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent s)
{
stopFlag=true;
//cacanvas.repaint();
}
});
mainPanel.add(btn2);
btn1 = new JButton("Clear");
btn1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
CACanvas.clearFlag=true;
generation.setText("");
alert1Flag=true;
rulesCombo.setSelectedIndex(0);
Alert1.setText("Please enter the number of generations");
Alert1.setBounds(30, 20, 5, 5);
Alert1.setVisible(alert1Flag);
mainPanel.add(Alert1);
cacanvas.repaint();
frame.setSize(1060, 610);
}
});
mainPanel.add(btn1);
lable=new JLabel();
lable.setText("Select Rule :");
mainPanel.add(lable);
rules=new DefaultComboBoxModel();
for (int i=0;i<=100;i++)
{
String p=String.valueOf(i);
rules.addElement(p);
}
rules.addElement("250");
rules.addElement("254");
rulesCombo = new JComboBox(rules);
rulesCombo.setSelectedIndex(0);
ruleListScrollPane = new JScrollPane(rulesCombo);
mainPanel.add(ruleListScrollPane);
//mainPanel.revalidate();
gLable=new JLabel();
gLable.setText("Enter the number of Generations (Max 64)");
generation=new JTextField(2);
mainPanel.add(gLable);
mainPanel.add(generation);
// mainPanel.add(cacanvas);
return mainPanel;
}
public abstract void run();
#Override
public void actionPerformed(ActionEvent arg0) {
Alert1.setVisible(false);
waitFlag=false;
System.out.println("We received an ActionEvent " + arg0);
Generations=generation.getText();
System.out.println(Generations);
Rule = "";
if (rulesCombo.getSelectedIndex() != -1) {
Rule =
(String) rulesCombo.getItemAt
(rulesCombo.getSelectedIndex());
}
System.out.println(Rule);
int rule=Integer.parseInt(Rule);
Hashtable<String,Integer> rules= new Hashtable<String,Integer>();
CARule ruleClass=new CARule();
rules=ruleClass.setRule(rule);
CAGenetationSet sa =new CAGenetationSet(100, false,rules);
genL=new ArrayList<int[]>();
genL=sa.runSteps(Integer.parseInt(Generations));
System.out.println("calling pattern set");
for(int i=0;i<=genL.size()-1;i++)
{
System.out.println("Painting generation :"+i);
if(stopFlag==false)
{
cacanvas.repaint();
}
//genPaint();
//sleep();
int[] newCell=genL.get(i);
for(int r=0;r<newCell.length;r++)
{
if(newCell[r]==1)
{
System.out.println("Generaton is"+i+"CellLife is"+r);
cacanvas.fillCell(i,r);
}
}
}
/*cacanvas.patternSet(genL);
waitFlag=true;
System.out.println("run completed");
// cacanvas.clearFlag=true;
*/
}
public void genPaint()
{
cacanvas.repaint();
}
public void sleep()
{
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public static void main(String[] args) {
JUIApp app = new JUIApp() {
#Override
public void run() {
// TODO Auto-generated method stub
System.out.println("Run method");
}
};
}
}
Seems like you are using the current Thread on that task, you should create another Thread and add one listeners code to the new Thread.
So I'm trying to create a simple test program where the user can enter something into a JTextField, click the "add" JButton, and a JTextArea will add the users string to the the JTextArea (continuously appending with new line).
I added the actionListener for the button and have a stateChanged and an update method, but nothing happens when I click the add button. No errors either. Could someone please point me in the right direction?
Here's my code:
MVCTester (main)
public class MVCTester {
public static void main(String[] args) {
// TODO Auto-generated method stub
MVCController myMVC = new MVCController();
MVCViews myViews = new MVCViews();
myMVC.attach(myViews);
}
}
MVCController
import java.util.ArrayList;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class MVCController {
MVCModel model;
ArrayList<ChangeListener> listeners;
public MVCController(){
model = new MVCModel();
listeners = new ArrayList<ChangeListener>();
}
public void update(String input){
model.setInputs(input);
for (ChangeListener l : listeners)
{
l.stateChanged(new ChangeEvent(this));
}
}
public void attach(ChangeListener c)
{
listeners.add(c);
}
}
MVCModel
import java.util.ArrayList;
public class MVCModel {
private ArrayList<String> inputs;
MVCModel(){
inputs = new ArrayList<String>();
}
public ArrayList<String> getInputs(){
return inputs;
}
public void setInputs(String input){
inputs.add(input);
}
}
MVCViews
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class MVCViews implements ChangeListener {
private JTextField input;
private JTextArea echo;
private ArrayList<String> toPrint = new ArrayList<String>();
MVCController controller;
MVCViews(){
controller = new MVCController();
JPanel myPanel = new JPanel();
JButton addButton = new JButton("add");
echo = new JTextArea(10,20);
echo.append("Hello there! \n");
echo.append("Type something below!\n");
myPanel.setLayout(new BorderLayout());
myPanel.add(addButton, BorderLayout.NORTH);
input = new JTextField();
final JFrame frame = new JFrame();
frame.add(myPanel, BorderLayout.NORTH);
frame.add(echo, BorderLayout.CENTER);
frame.add(input, BorderLayout.SOUTH);
addButton.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
controller.update(input.getText());
}
});
frame.pack();
frame.setVisible(true);
}
#Override
public void stateChanged(ChangeEvent e) {
// TODO Auto-generated method stub
toPrint = controller.model.getInputs();
for(String s: toPrint){
echo.append(s + "\n");
}
}
}
This is my first time trying to follow MVC format, so there might be issues with the model itself as well. Feel free to point them out. Thank you for your help!
The controller within the GUI is not the same controller that is created in main. Note how many times you call new MVCController() in your code above -- it's twice. Each time you do this, you're creating a new and distinct controller -- not good. Use only one. You've got to pass the one controller into the view. You can figure out how to do this. (hint, a setter or constructor parameter would work).
hint 2: this could work: MVCViews myViews = new MVCViews(myMVC);
one solution:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class MVCTester {
public static void main(String[] args) {
MVCController myMVC = new MVCController();
MVCViews myViews = new MVCViews(myMVC);
myMVC.attach(myViews);
// myViews.setController(myMVC); // or this could do it
}
}
class MVCController {
MVCModel model;
ArrayList<ChangeListener> listeners;
public MVCController() {
model = new MVCModel();
listeners = new ArrayList<ChangeListener>();
}
public void update(String input) {
model.setInputs(input);
for (ChangeListener l : listeners) {
l.stateChanged(new ChangeEvent(this));
}
}
public void attach(ChangeListener c) {
listeners.add(c);
}
}
class MVCModel {
private ArrayList<String> inputs;
MVCModel() {
inputs = new ArrayList<String>();
}
public ArrayList<String> getInputs() {
return inputs;
}
public void setInputs(String input) {
inputs.add(input);
}
}
class MVCViews implements ChangeListener {
private JTextField input;
private JTextArea echo;
private ArrayList<String> toPrint = new ArrayList<String>();
MVCController controller;
MVCViews(final MVCController controller) {
// !! controller = new MVCController();
this.controller = controller;
JPanel myPanel = new JPanel();
JButton addButton = new JButton("add");
echo = new JTextArea(10, 20);
echo.append("Hello there! \n");
echo.append("Type something below!\n");
myPanel.setLayout(new BorderLayout());
myPanel.add(addButton, BorderLayout.NORTH);
input = new JTextField();
final JFrame frame = new JFrame();
frame.add(myPanel, BorderLayout.NORTH);
frame.add(echo, BorderLayout.CENTER);
frame.add(input, BorderLayout.SOUTH);
addButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (controller != null) {
controller.update(input.getText());
}
}
});
frame.pack();
frame.setVisible(true);
}
public void setController(MVCController controller) {
this.controller = controller;
}
#Override
public void stateChanged(ChangeEvent e) {
if (controller != null) {
toPrint = controller.model.getInputs();
for (String s : toPrint) {
echo.append(s + "\n");
}
}
}
}
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);
}
}
});
}
}