I am creating a simple java program with a GUI built with the help of window builder. The GUI consists of just a button.
On button click,start a thread that will print to the random number infinitely until it is stopped by clicking the same button again.
Here is my code
LoopTest.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class LoopTest extends JFrame implements ActionListener {//******
private JButton startB, stopB;
private JTextArea oa;
Start sta;
public LoopTest(){
super("Final Exam: Question ");
Container c = getContentPane();
c.setLayout(new FlowLayout());
startB = new JButton("START"); c.add(startB);
stopB = new JButton("STOP"); c.add(stopB);
oa = new JTextArea(5,20); c.add(oa);
c.add(new JScrollPane(oa));
registerEvents();
sta = new Start("Loop", oa);
}
public void registerEvents(){
startB.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent ae){
if(startB.isEnabled() == true )
sta.setLoopFlag(true);
if(!sta.isAlive())
sta.start();
startB.setEnabled(false);
}
}
);
stopB.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent ae){
if(stopB.isEnabled()==true){
sta.setLoopFlag(false);
}
}
}
);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
public static void main(String[] args){
LoopTest app = new LoopTest();
app.setSize(300,300);
app.setLocationRelativeTo(null);
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setVisible(true);
}
}
Start.java
public class Start extends Thread {
private JTextArea ta;
private boolean loopFlag;
public Start(String name, JTextArea ta){
super(name);
this.ta = ta;
ta.setText("");
loopFlag = true;
}
public void run(){
int num=0;
while(true)
while(loopFlag){
num = 1+ (int)(Math.random()*100);
ta.append(num + "\n");
}
}
public void setLoopFlag(boolean value){
loopFlag = value;
}
}
Stop.java
public class Stop extends Thread {
public Stop( String name ){
super(name);
}
public void run(){
}
}
Thanks in advance.
Your code breaks Swing threading rules as you're making mutational changes to Swing components off of the Swing event thread.
Suggestions:
Never extend Thread. It's almost always better to implement Runnable and use the Runnable in a Thread.
Avoid making Swing calls, other than repaint() off of the Swing event thread.
Your while (true) is a "tight" loop -- it has no Thread.sleep within it, and that means that it risks typing up the CPU in its tight loop, something that can hamper your program and your computer.
Best to avoid using direct background threading altogether here as your code issue can be solved much more easily and cleanly by using a Swing Timer. Please check the Swing Timer Tutorial
You can easily start and stop this Timer by calling its start() and stop() methods.
I would also use a JList preferentially over a JTextArea since it can more easily handle large amounts of data.
I also like using AbstractActions rather than ActionListeners for my JButton, and this problem lends itself nicely to their use. You can create an Action for start and one for stop and simply swap out the button's actions.
For example:
import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class StartStop extends JPanel {
private static final int TIMER_DELAY = 300;
private StartAction startAction = new StartAction();
private StopAction stopAction = new StopAction();
private JButton button = new JButton(startAction);
private DefaultListModel<Integer> model = new DefaultListModel<>();
private JList<Integer> jList = new JList<>(model);
private Timer timer = new Timer(TIMER_DELAY, new TimerListener());
public StartStop() {
JPanel btnPanel = new JPanel();
btnPanel.add(button);
jList.setFocusable(false);
jList.setVisibleRowCount(10);
jList.setPrototypeCellValue(100000);
JScrollPane scrollPane = new JScrollPane(jList);
setLayout(new BorderLayout());
add(scrollPane, BorderLayout.CENTER);
add(btnPanel, BorderLayout.PAGE_END);
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
int num = 1 + (int) (Math.random() * 100);
model.addElement(num);
}
}
private class StartAction extends AbstractAction {
public StartAction() {
super("Start");
putValue(MNEMONIC_KEY, KeyEvent.VK_S);
}
#Override
public void actionPerformed(ActionEvent e) {
timer.start();
button.setAction(stopAction);
}
}
private class StopAction extends AbstractAction {
public StopAction() {
super("Stop");
putValue(MNEMONIC_KEY, KeyEvent.VK_S);
}
#Override
public void actionPerformed(ActionEvent e) {
timer.stop();
button.setAction(startAction);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Start Stop");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new StartStop());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
Related
I have a class whitch extends JPanel:
public class ButtonPanel extends JPanel {
private label;
public ButtonPanel() {
label=new JLabel("waiting for click");
add(label);
}
public void setButtonText() {
label.setText("just clicked");
}
}
I have several instances of that class which is added to JFrame. I want to create one instanse of MouseAdapter class and then add them as a mouse listener to all of the ButtonPanel components on my JFrame. I meen:
ButtonPanel butt1 = new ButtonPanel();
ButtonPanel butt2 = new ButtonPanel();
ButtonPanel butt3 = new ButtonPanel();
//... here goes code which add ButtonPanels to JFrame
MouseAdapterMod mam = new MouseAdapterMod();
butt1.addMouseListener(mam);
butt2.addMouseListener(mam);
butt3.addMouseListener(mam);
The MouseAdapterMod class I want to be separate from the other and locate in it's own package. It should looks like this:
public class MouseAdapterMod extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
//here goes the code of calling setButtonText method of ButtonPanel component on which the event had occurred
}
}
So the problem is that I don't know how to implement mouseClicked method to make it determine which of ButtonPanel generate the event and call the corresponding to that component setButtonText() method. Is anyone know how to do that?
I know that I can achieve this by including event handling functionality in the ButtonPanel class, but thats not appropriate way for me, cuz I want to keep the class structure as I described above and have only one instance of MouseAdapterMod class for handling all of the ButtonPanels.
The MouseEvent#getSource method will return which object has been clicked:
public class MouseAdapterMod extends MouseAdapter {
// usually better off with mousePressed rather than clicked
public void mousePressed(MouseEvent e) {
ButtonPanel btnPanel = (ButtonPanel)e.getSource();
btnPanel.setButtonText();
}
}
As the comments note, you're often better off listening for mousePressed or mouseReleased rather than mouseClicked because for mouseClicked to work, the press and release must be from the same point, and if the mouse shifts even a slight amount, the click won't register.
My test program:
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;
public class MainForButtonPanel extends JPanel {
public MainForButtonPanel() {
setLayout(new GridLayout(4, 4));
MouseAdapter myMA = new MouseAdapterMod();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
ButtonPanel btnPanel = new ButtonPanel();
btnPanel.addMouseListener(myMA);
add(btnPanel);
}
}
}
private static void createAndShowUI() {
JFrame frame = new JFrame("MainForButtonPanel");
frame.getContentPane().add(new MainForButtonPanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
class ButtonPanel extends JPanel {
private static final int TIMER_DELAY = 2000;
private static final String JUST_CLICKED = "just clicked";
private static final String WAITING_FOR_CLICK = "waiting for click";
private static final Color CLICKED_COLOR = Color.pink;
private JLabel label;
public ButtonPanel() {
label = new JLabel(WAITING_FOR_CLICK);
add(label);
}
public void setButtonText() {
label.setText(JUST_CLICKED);
setBackground(CLICKED_COLOR);
new Timer(TIMER_DELAY, new ActionListener() {
public void actionPerformed(ActionEvent ae) {
label.setText(WAITING_FOR_CLICK);
setBackground(null);
((Timer)ae.getSource()).stop();
}
}).start();
}
}
class MouseAdapterMod extends MouseAdapter {
// usually better off with mousePressed rather than clicked
public void mousePressed(MouseEvent e) {
ButtonPanel btnPanel = (ButtonPanel)e.getSource();
btnPanel.setButtonText();
}
}
I cannot get my Jframe to close when a user hits the (X) button. I tried many ways to do them but none of them work.
I tried:
JFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Nothing happens. My main class extends jframe and implements action listener. What am I doing wrong?
My code:
package com.xflare.Bot;
import static java.lang.System.out;
import java.awt.*;
import java.lang.String;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Main extends JFrame implements ActionListener{
private static Frame frame;
private static boolean debug = true;
private static boolean enabled = true;
private static JButton exitbutton; // reference to the button object
private static JButton webbutton; // reference to the button object
private static JButton aboutbutton; // reference to the button object
public static void main(String[] args) {
new Main().start();
}
private void start(){
//start up
printSystem("starting");
//create frame
printSystem("Creating a frame...");
createFrame();
//create button(s)
createQuitButton();
createWebButton();
createAboutButton();
//Spawn init.
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getFrame().setResizable(false);
getFrame().setVisible(true);
printSystem("Started up successfully!");
}
private void createFrame(){
Main.frame = new Frame("app");
frame.setSize(600, 300);
}
private void createQuitButton(){
exitbutton = new JButton("Exit!");
getFrame().setLayout(null);
exitbutton.setBounds(225,45,150,75);//setBounds(x,y,width,height)
exitbutton.setActionCommand("exit");
exitbutton.addActionListener(this);
getFrame().add(exitbutton);
}
private void createWebButton(){
webbutton = new JButton("Open hacked browser");
getFrame().setLayout(null);
webbutton.setBounds(225,130,150,75);//setBounds(x,y,width,height)
webbutton.setActionCommand("web");
webbutton.addActionListener(this);
getFrame().add(webbutton);
}
private void createAboutButton(){
aboutbutton = new JButton("About");
getFrame().setLayout(null);
aboutbutton.setBounds(225,215,150,75);//setBounds(x,y,width,height)
aboutbutton.setActionCommand("about");
aboutbutton.addActionListener(this);
getFrame().add(aboutbutton);
}
private Frame getFrame(){
return Main.frame;
}
public void actionPerformed(ActionEvent e) {
String actionCommand = ((JButton) e.getSource()).getActionCommand();
printDebug("Button " + actionCommand + " was pressed.");
if(actionCommand.equals("exit")){
exitbutton.setVisible(false);
shutdown();
}
else if(actionCommand.equals("about")){
aboutbutton.setVisible(false);
webbutton.setVisible(false);
exitbutton.setVisible(false);
showAbout();
}
else{
printCritical("Unknown button pressed!");
}
}
private void showAbout(){
}
private void shutdown(){
printSystem("Attempting to shut down...");
enabled = false;
printSystem("Shut down successful!");
System.exit(0);
}
private boolean debugEnabled(){
return debug;
}
private String getVersion(){
return "1.0.0";
}
private String getCodename(){
return "[BeastReleased]";
}
private static void printSystem(String var){
out.println("System> " + var);
}
private static void printError(String var){
out.println("Error> " + var);
}
private static void printCritical(String var){
out.println("Critical> " + var);
}
private void printDebug(String var){
if(debugEnabled()) {
out.println("Debug> " + var);
}
}
}
Link to same code: http://pastebin.com/1fDbjm74
This: setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
needs to be called on the JFrame that you're actually displaying, Main.frame. You're not doing this.
getFrame().setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getFrame().setVisible(true);
You've got too many Frame / JFrames. Your class extends JFrame but you're not displaying it. You've also got a Frame variable called frame, (NOT a JFrame variable) that you are displaying, and of course since this is not a JFrame, you can't make JFrame method calls, like the one above on it.
Simplify: create ONE JFrame not a Frame, and call this method on it and set it visible. So either get rid of the frame variable and use the class itself, the this, as your JFrame, and display it, or don't have your class extend JFrame and use your frame variable, but make it a JFrame object not a Frame object, since Frame does not have the setDefaultCloseOperation(...) method.
Also you're over-using static modifiers where they shouldn't be used. All your fields should be instance (non-static) fields.
Also, use of null layouts and setBounds will bite you in the end. For instance when I run your program, portions of the middle button's text are missing because its size has been artificially constrained in a bad way. Much better is to us layout managers to your advantage. For example:....
Please have a look at this program structure:
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class MyMain extends JPanel {
public static final String MENU_PANEL = "MENU";
public static final String ABOUT_PANEL = "About";
private CardLayout cardLayout = new CardLayout();
public MyMain() {
JPanel aboutPanel = new JPanel(new GridBagLayout());
JLabel aboutLabel = new JLabel("About");
aboutLabel.setFont(aboutLabel.getFont().deriveFont(Font.BOLD, 32));
aboutPanel.add(aboutLabel);
JPanel buttonPanel = new JPanel(new GridLayout(0, 1, 10, 10));
buttonPanel.add(createButton(new ExitAction("Exit!", KeyEvent.VK_X)));
buttonPanel.add(createButton(new OpenBrowserAction("Open Hacked Browser", KeyEvent.VK_O)));
buttonPanel.add(createButton(new AboutAction("About", KeyEvent.VK_A, this)));
JPanel menuPanel = new JPanel(new GridBagLayout());
int ebGap = 40;
menuPanel.setBorder(BorderFactory.createEmptyBorder(ebGap, ebGap, ebGap, ebGap));
menuPanel.add(buttonPanel);
setLayout(cardLayout);
add(menuPanel, MENU_PANEL);
add(aboutPanel, ABOUT_PANEL);
}
private JButton createButton(Action action) {
JButton button = new JButton(action);
Font btnFont = button.getFont().deriveFont(Font.BOLD, 20);
button.setFont(btnFont);
return button;
}
private static void createAndShowGui() {
JFrame frame = new JFrame("My Main Application");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new MyMain());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
public void showPanel(String cardLayoutKey) {
cardLayout.show(this, cardLayoutKey);
}
}
class ExitAction extends AbstractAction {
public ExitAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
Component comp = (Component) e.getSource();
if (comp != null) {
Window win = SwingUtilities.getWindowAncestor(comp);
if (win != null) {
win.dispose();
}
}
}
}
class OpenBrowserAction extends AbstractAction {
public OpenBrowserAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Open Browswer");
}
}
class AboutAction extends AbstractAction {
private MyMain myMain;
public AboutAction(String name, int mnemonic, MyMain myMain) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
this.myMain = myMain;
}
#Override
public void actionPerformed(ActionEvent e) {
if (myMain != null) {
myMain.showPanel(MyMain.ABOUT_PANEL);
}
}
}
You are calling the setDefaultCloseOperation method on the wrong place. Here's what you should do:
private void start(){
//start up
printSystem("starting");
//create frame
printSystem("Creating a frame...");
createFrame();
//Spawn init.
getFrame().setResizable(false);
getFrame().setVisible(true);
printSystem("Started up successfully!");
}
private void createFrame(){
Main.frame = new Frame("app");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 300);
}
I have a JTextComponent and I want to invoke a method when user stops editing text in that JTextComponent for a period of time. I was thinking to start a timer every time the model is modified and cancel it if another text edit arrives, but it gives me a feeling that it is not the best desition. Can you share your experience how to implement such behaviour?
Yes, that's likely the best decision. You don't even cancel the Timer, but rather just call restart() on the Timer from within your DocumentListener.
e.g., a program that turns the JTextField background red if editing has been inactive for over 2 seconds:
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
#SuppressWarnings("serial")
public class ResetCounter2 extends JPanel {
private static final int TIMER_DELAY = 2000; // 2 seconds
public static final Color LATE_BACKGROUND = Color.RED;
private JTextField textField = new JTextField(10);
private Timer timer = new Timer(TIMER_DELAY, new TimerListener());
public ResetCounter2() {
textField.getDocument().addDocumentListener(new MyDocListener());
add(textField);
// make sure timer does not repeat and then start it
timer.setRepeats(false);
timer.start();
}
private class MyDocListener implements DocumentListener {
#Override
public void changedUpdate(DocumentEvent e) {
docChanged();
}
#Override
public void insertUpdate(DocumentEvent e) {
docChanged();
}
#Override
public void removeUpdate(DocumentEvent e) {
docChanged();
}
private void docChanged() {
textField.setBackground(null);
timer.restart();
}
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
textField.setBackground(LATE_BACKGROUND);
}
}
private static void createAndShowGui() {
ResetCounter2 mainPanel = new ResetCounter2();
JFrame frame = new JFrame("ResetCounter");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
}
i have a question , i have this timer code in java that when its executed it displays a count down timer on its own JFrame label, what i want to do is to display this timer on another JFrame form label without having to move the code to other classes.
I hope you can help me with this thanks lot guys .
this is the code for the Timer class:
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class TimerExample extends JFrame {
final JLabel label;
Timer countdownTimer;
int timeRemaining = 10;
public TimerExample() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(200, 200);
label = new JLabel(String.valueOf(timeRemaining), JLabel.CENTER);
getContentPane().add(label);
countdownTimer = new Timer(1000, new CountdownTimerListener());
setVisible(true);
countdownTimer.start();
}
class CountdownTimerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (--timeRemaining > 0) {
label.setText(String.valueOf(timeRemaining));
} else {
label.setText("Time's up!");
countdownTimer.stop();
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new TimerExample();
}
});
}
}
thanks
Here it is,
Following is my TestTimer class which accepts a JLabel as input
public class TestTimer {
private JLabel label;
Timer countdownTimer;
int timeRemaining = 10;
public TestTimer(JLabel passedLabel) {
countdownTimer = new Timer(1000, new CountdownTimerListener());
this.label = passedLabel;
countdownTimer.start();
}
class CountdownTimerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (--timeRemaining > 0) {
label.setText(String.valueOf(timeRemaining));
} else {
label.setText("Time's up!");
countdownTimer.stop();
}
}
}
}
And here is another Main class which is actually extending a JFrame and showing a label in it,
public class TimerJFrame extends JFrame{
private static final long serialVersionUID = 1L;
private JLabel label;
public TimerJFrame() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(200, 200);
label = new JLabel("10", JLabel.CENTER);
getContentPane().add(label);
new TestTimer(label);
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new TimerJFrame();
}
});
}
}
Second Code passes a created JLabel to first class and first class uses it to show timer.
You need to follow following steps,
Modify TimerExample constructor to accept JLabel. And initialize JLabel of TimerExample class with passwd JLabel
Pass JLabel from other JFrame class.
Remove main method from this as it will not be required.
Bu first step here, constructor will accept predefined JLabel from other classes and use those to display timer.
I have a class whitch extends JPanel:
public class ButtonPanel extends JPanel {
private label;
public ButtonPanel() {
label=new JLabel("waiting for click");
add(label);
}
public void setButtonText() {
label.setText("just clicked");
}
}
I have several instances of that class which is added to JFrame. I want to create one instanse of MouseAdapter class and then add them as a mouse listener to all of the ButtonPanel components on my JFrame. I meen:
ButtonPanel butt1 = new ButtonPanel();
ButtonPanel butt2 = new ButtonPanel();
ButtonPanel butt3 = new ButtonPanel();
//... here goes code which add ButtonPanels to JFrame
MouseAdapterMod mam = new MouseAdapterMod();
butt1.addMouseListener(mam);
butt2.addMouseListener(mam);
butt3.addMouseListener(mam);
The MouseAdapterMod class I want to be separate from the other and locate in it's own package. It should looks like this:
public class MouseAdapterMod extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
//here goes the code of calling setButtonText method of ButtonPanel component on which the event had occurred
}
}
So the problem is that I don't know how to implement mouseClicked method to make it determine which of ButtonPanel generate the event and call the corresponding to that component setButtonText() method. Is anyone know how to do that?
I know that I can achieve this by including event handling functionality in the ButtonPanel class, but thats not appropriate way for me, cuz I want to keep the class structure as I described above and have only one instance of MouseAdapterMod class for handling all of the ButtonPanels.
The MouseEvent#getSource method will return which object has been clicked:
public class MouseAdapterMod extends MouseAdapter {
// usually better off with mousePressed rather than clicked
public void mousePressed(MouseEvent e) {
ButtonPanel btnPanel = (ButtonPanel)e.getSource();
btnPanel.setButtonText();
}
}
As the comments note, you're often better off listening for mousePressed or mouseReleased rather than mouseClicked because for mouseClicked to work, the press and release must be from the same point, and if the mouse shifts even a slight amount, the click won't register.
My test program:
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;
public class MainForButtonPanel extends JPanel {
public MainForButtonPanel() {
setLayout(new GridLayout(4, 4));
MouseAdapter myMA = new MouseAdapterMod();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
ButtonPanel btnPanel = new ButtonPanel();
btnPanel.addMouseListener(myMA);
add(btnPanel);
}
}
}
private static void createAndShowUI() {
JFrame frame = new JFrame("MainForButtonPanel");
frame.getContentPane().add(new MainForButtonPanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
class ButtonPanel extends JPanel {
private static final int TIMER_DELAY = 2000;
private static final String JUST_CLICKED = "just clicked";
private static final String WAITING_FOR_CLICK = "waiting for click";
private static final Color CLICKED_COLOR = Color.pink;
private JLabel label;
public ButtonPanel() {
label = new JLabel(WAITING_FOR_CLICK);
add(label);
}
public void setButtonText() {
label.setText(JUST_CLICKED);
setBackground(CLICKED_COLOR);
new Timer(TIMER_DELAY, new ActionListener() {
public void actionPerformed(ActionEvent ae) {
label.setText(WAITING_FOR_CLICK);
setBackground(null);
((Timer)ae.getSource()).stop();
}
}).start();
}
}
class MouseAdapterMod extends MouseAdapter {
// usually better off with mousePressed rather than clicked
public void mousePressed(MouseEvent e) {
ButtonPanel btnPanel = (ButtonPanel)e.getSource();
btnPanel.setButtonText();
}
}