Is it okay to use thread.sleep() when coding a bot? - java

I'm trying to code a primitive spammer. Is it okay to use thread.sleep() when coding a bot?
I'm a novice programmer. If there is any place in my code to fix it, I would appreciate it if you let me know. I may have used JComponents improperly. If it catches your eye, you can specify. Thank you.
Note: "It looks like your post is mostly code; please add some more details." I'm writing this note because I can't find any more details to add. Sorry
public class Spammer extends JFrame implements Runnable{
private boolean running = false;
private JButton jButton1;
private JLabel jLabel1, jLabel2;
private JScrollPane jScrollPane1;
private JSpinner jSpinner1;
private JTextArea jTextArea1;
public Spammer() {
setLayout(null);
jLabel1 = new JLabel("Text: ");
jTextArea1 = new JTextArea(10,28);
jLabel2 = new JLabel("Interval: ");
jSpinner1 = new JSpinner();
jScrollPane1 = new JScrollPane();
jButton1 = new JButton("Spam");
jButton1.setSize(350, 60);
jButton1.setLocation(100, 220);
jLabel1.setSize(50, 150);
jLabel1.setLocation(15, 10);
jLabel1.setFont(new Font("Verdana" , Font.BOLD , 14));
jTextArea1.setSize(350, 150);
jTextArea1.setLocation(100, 10);
jLabel2.setSize(80, 25);
jLabel2.setLocation(15, 180);
jLabel2.setFont(new Font("Verdana" , Font.BOLD , 12));
jSpinner1.setSize(350, 25);
jSpinner1.setLocation(100, 180);
getContentPane().add(jLabel1);
getContentPane().add(jTextArea1);
getContentPane().add(jLabel2);
getContentPane().add(jSpinner1);
getContentPane().add(jScrollPane1);
getContentPane().add(jButton1);
setTitle("Spammer by Me");
setLocationRelativeTo(null);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setPreferredSize(new Dimension(500, 340));
pack();
jButton1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jButton1ActionPerformed();
}
} );
}
private void jButton1ActionPerformed() {
if(!running) {
jTextArea1.setEnabled(false);
jSpinner1.setEnabled(false);
jButton1.setText("Spamming in 3 seconds...");
jButton1.setEnabled(false);
running = true;
new Thread(this).start();
}else {
jTextArea1.setEnabled(true);
jSpinner1.setEnabled(true);
jButton1.setText("Spam");
running = false;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Spammer().setVisible(true);
}
});
}
public void run() {
Robot robot = null;
try {
robot = new Robot();
} catch (AWTException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
int[] keys = new int[jTextArea1.getText().length()];
if((int) jSpinner1.getValue() < 0) {
jSpinner1.setValue((int) 0);
}
int interval = (int) jSpinner1.getValue();
for(int i = 0 ; i < keys.length; i++) {
keys[i] = KeyEvent.getExtendedKeyCodeForChar(jTextArea1.getText().charAt(i));
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
jButton1.setEnabled(true);
jButton1.setText("Stop");
while(running) {
for(int i = 0 ; i < keys.length; i++) {
robot.keyPress(keys[i]);
robot.keyRelease(keys[i]);
}
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

The key principle at work here is primarily the 'EDT' - the Event Dispatch Thread. This is a thread that does GUI stuff - if for example you drag the titlebar of a completely different app's window across the screen, and this moves that app's window over yours, the EDT is hard at work redrawing everything. The EDT is the thread that sees you press your mouse down on a button, and will render the button in the 'pressed in' view.
The EDT is the only thread from which you can do GUI stuff, whether it is to retrieve info, such as getText(), or whether it is to change things, such as updating the text of a label or whatnot.
The EDT is also the thread you're in when your code runs that you registered as a handler for events, such as the code that responds to a button click or whatnot.
You therefore must not sleep on the EDT (Because then your app looks non-responsive; the thread that responds to button clicks or repaints what needs repainting is not actively running), but you can only fetch GUI data / set GUI stuff from the EDT.
The rules:
Do not interact with any GUI elements unless you are in the EDT
Never sleep in the EDT
Your code is broken, not because you sleep (that's fine - that run() method is not in the EDT), but because you do GUI stuff from this non-EDT thread.
You need to do a careful dance here: You want to sleep (not allowed on the EDT), but interact with GUI elements, such as the interval box, to know how long to sleep, which can only be done on the EDT.
To do this, you can 'send' code to run in the EDT via SwingWorkers, or simply via:
SwingUtilities.invokeAndWait(() -> {
// code that will run in the EDT goes here
});
You can't set any variables from within this code, but you can use AtomicReference and friends to create objects you can change. So, instead of:
int[] keys = new int[jTextArea1.getText().length()];
if (jSpinner1.getValue() < 0) {
jSpinner1.setValue(0);
}
int interval = (int) jSpinner1.getValue();
which is doing GUI stuff, do:
AtomicInteger interval = new AtomicInteger();
SwingUtilities.invokeAndWait(() -> {
int[] keys = new int[jTextArea1.getText().length()];
if (jSpinner1.getValue() < 0) {
jSpinner1.setValue(0);
}
interval.set((int) jSpinner1.getValue());
};

Related

How do I set a JTextPane out of another Thread?

I am learning about multithreading right now.
I have a "main" class in which I build a JFrame with a Textfield and a Start and a Stop Button in it.
I also have another class/Thread from which I want to print the current time into my Textfield when I click the Start Button of my Frame. Everything works but the text doesn't change in my Textfield as I start the Thread even though Eclipse says my code is alright.
What am I doing wrong?
Class 1:
public class Uhr extends JFrame {
private JPanel contentPane;
public JTextPane tpZeit;
Thread t;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Uhr frame = new Uhr();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Uhr() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
tpZeit = new JTextPane();
tpZeit.setText("test");
tpZeit.setBounds(43, 50, 212, 43);
contentPane.add(tpZeit);
JButton btnstart = new JButton("GO");
btnstart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
tpZeit.setText("started");
if (t == null) {
t = new Thread(new Uhrsteuerung());
}
if(!t.isAlive()) {
t = new Thread(new Uhrsteuerung());
t.start();
}
}
});
btnstart.setBounds(10, 227, 89, 23);
contentPane.add(btnstart);
JButton btnstop = new JButton("Stop");
btnstop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
t.interrupt();
}
});
btnstop.setBounds(248, 227, 89, 23);
contentPane.add(btnstop);
}
}
Class with additional Thread:
public class Uhrsteuerung extends Uhr implements Runnable {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String time;
boolean x ;
#Override
public synchronized void run() {
// TODO Auto-generated method stub
x = true;
while (x) {
try {
time = sdf.format(System.currentTimeMillis());
System.out.println(time);
tpZeit.setText(time);
repaint();
Thread.sleep(1000);
} catch (InterruptedException ex) {
x = false;
}
}
}
}
All code for Java's Swing classes must be executed on the Event Dispatch Thread (EDT). Swing provides some special classes for helping you do this.
To execute code off the EDT, use a SwingWorker class. SwingWorker will execute a task in the background (not using the EDT) and then return a result properly synchronized that executes on the EDT. https://docs.oracle.com/en/java/javase/16/docs/api/java.desktop/javax/swing/SwingWorker.html
Its application is pretty simple. Define your own class that extends SwingWorker.
class PrimeNumbersTask extends SwingWorker<List<Integer>, Integer> {
// ...
If you need to update a component, it's good to pass in the component so that you can refer to it later.
class PrimeNumbersTask extends SwingWorker<List<Integer>, Integer> {
private JTextArea textArea;
public PrimeNumbersTask( JTextArea textArea ) {
this.textArea = textArea;
}
// ...
Do your work in the method doInBackground() by overriding it. Don't touch the Swing classes in this method. Use the publish() method to send smaller chunks of data to the EDT if you want to provide progressive results instead of waiting for the whole task to complete.
#Override
public List<Integer> doInBackground() {
while (!done && ! isCancelled()) {
// do stuff
publish(number);
setProgress(100 * numbers.size() / numbersToFind);
}
}
return numbers;
}
Finally override the method process() to update your Swing classes.
#Override
protected void process(List<Integer> chunks) {
for (int number : chunks) {
textArea.append(number + "\n");
}
}
From the EDT, you can call execute() to start your background task.
JTextArea textArea = new JTextArea();
// manipulate and set up GUI...
PrimeNumbersTask task = new PrimeNumbersTask(textArea);
task.execute();
There's a lot more docs on SwingWorker if you Google for it, that's the basics of how to use it.

Swing going from menu to actual gameplay

So I am making a space invaders clone. Originally I had no problem getting my game to work with a simple main class that created the frame, created the gameplay and started the thread.
But then I tried to implement a start menu and it all went to crap. The menu appears with success but the gameplay does not appear when I press start.
I am running out of ideas and I am completely stumped. I am somewhat new as well to SO, so if there is anything I left out, I appreciate any help.
Here is the original with no menu that worked fine:
public static void main(String[] args) {
JFrame frame = new JFrame("SpaceRaiders");
frame.setSize(600, 600);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Gameplay gameplay = new Gameplay();
frame.add(gameplay);
frame.setVisible(true);
Thread t1 = new Thread(gameplay);
t1.start();
}
However, the moment I tried to implement a menu to then play the game, I am running into all sorts of trouble. I created a UI class as well as an actual "game" class like so:
public class UI {
JFrame frame, f2;
JPanel titrePanel, startButtonPanel, loadButtonPanel, p2;
JLabel nomJeu;
JButton startButton, loadButton;
Font fontTitre, fontStart;
Gameplay gameplay;
public void createUI(ChoixJeu cj) {
frame = new JFrame("SpaceRaiders");
frame.setSize(600, 600);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setLayout(null);
frame.getContentPane().setBackground(Color.black);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//------------------ECRAN MENU---------------------
//Titre
titrePanel = new JPanel();
titrePanel.setBounds(100, 100, 400, 100);
titrePanel.setBackground(Color.BLUE);
Font fontTitre = new Font("Times New Roman", Font.BOLD, 50);
Font fontStart = new Font("Times New Roman", Font.PLAIN, 20);
nomJeu = new JLabel("SpaceRaiders");
nomJeu.setForeground(Color.white);
nomJeu.setFont(fontTitre);
titrePanel.add(nomJeu);
//Start button
startButtonPanel = new JPanel();
startButtonPanel.setBounds(200, 400, 200, 40);
startButtonPanel.setBackground(Color.BLACK);
startButton = new JButton("START");
startButton.setBackground(Color.BLACK);
startButton.setForeground(Color.WHITE);
startButton.setFont(fontStart);
startButton.setFocusPainted(false);
startButton.addActionListener(cj);
startButton.setActionCommand("start");
startButtonPanel.add(startButton);
//Load Button
loadButtonPanel = new JPanel();
loadButtonPanel.setBounds(200, 440, 200, 100);
loadButtonPanel.setBackground(Color.BLACK);
loadButton = new JButton("LOAD");
loadButton.setBackground(Color.BLACK);
loadButton.setForeground(Color.WHITE);
loadButton.setFont(fontStart);
loadButton.setFocusPainted(false);
titrePanel.add(nomJeu);
loadButtonPanel.add(loadButton);
frame.add(startButtonPanel);
frame.add(titrePanel);
//------------------ECRAN MENU FIN---------------------
frame.setVisible(true);
}
And the game class...
public class Jeu {
ChoixJeu cj = new ChoixJeu();
UI ui = new UI();
Ecrans e = new Ecrans(ui);
Gameplay gp;
public static void main(String[] args) {
new Jeu();
}
public Jeu() {
ui.createUI(cj);
Gameplay gameplay = new Gameplay();
this.gp = gameplay;
}
public class ChoixJeu implements ActionListener {
#Override
public void actionPerformed(ActionEvent ae) {
String yourChoice = ae.getActionCommand();
switch (yourChoice) {
case "start":
e.montrerEcranJeu();
new Thread(gp).start();
ui.frame.add(gp);
break;
default:
break;
}
}
}
}
I also tried to make a class/method that hides the menu panels
public void montrerEcranJeu() {
//Cache Menu
ui.titrePanel.setVisible(false);
ui.startButtonPanel.setVisible(false);
//Montre Jeu
// ui.frame.add(gameplay);
}
And just in case the Gameplay class. The run() method is at the bottom
public class Gameplay extends JPanel implements KeyListener, ActionListener, Runnable {
private Ship player = new Ship(new Point(200, 555));
Timer t = new Timer(5, this);
private ArrayList<Laser> lasers = new ArrayList<Laser>();
private int laserNb;
private boolean readytofire;
private boolean shot = false;
private ArrayList<Invader> invaders = new ArrayList<Invader>();
private boolean pause;
public Gameplay() {
super();
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
for (int j = 0; j < 80; j += 20) {
for (int i = 0; i < 20; i++) {
invaders.add(new Invader(5 + i * 30, j));
}
}
}
public boolean addLaser(Laser a) {
lasers.add(a);
return true;
}
public boolean addPlayer(Ship p) {
this.player = p;
return true;
}
#Override
public void keyTyped(KeyEvent ke) {
}
public void keyPressed(KeyEvent e) {
if (KeyEvent.VK_RIGHT == e.getKeyCode()) {
moveRight();
}
if (KeyEvent.VK_LEFT == e.getKeyCode()) {
moveLeft();
}
if (KeyEvent.VK_SPACE == e.getKeyCode()) {
shoot();
System.out.println("Space Action from Gameplay is working");
}
}
#Override
public void keyReleased(KeyEvent e) {
}
#Override
public void actionPerformed(ActionEvent ae) {
repaint();
}
public void moveRight() {
if (player.getCentre().getX() >= 580) {
player.setX(580);
} else {
double movement = player.getCentre().getX();
movement += 10;
player.setX(movement);
}
this.repaint();
}
public void moveLeft() {
if (player.getCentre().getX() <= 20) {
player.setX(20);
} else {
double movement = player.getCentre().getX();
movement -= 10;
player.setX(movement);
}
this.repaint();
}
public void shoot() {
shot = true;
if (readytofire) {
Point top = new Point(player.getTopX(), player.getTopY());
Laser laser = new Laser(top);
addLaser(laser);
}
}
public void moveShot() {
if (shot) {
for (Laser l : lasers) {
l.setY(l.getTopLeft().getY() - 1);
}
}
}
#Override
public void paint(Graphics g) {
setBackground(Color.black);
super.paint(g);
player.draw(g);
for (Laser l : lasers) {
l.draw(g);
}
for (Invader i : invaders) {
i.draw(g);
}
}
// public void paintComponent (Graphics g){
// Controle Thread
public void run() {
while (true) {
moveShot();
for (Invader i : invaders) {
i.moveAndUpdate();
}
// for (Invader i : invaders) {
// if (){
// System.out.println("YOU ARE DEAD!");
// }
// }
try {
Thread.sleep(10);
readytofire = true;
} catch (InterruptedException ex) {
Logger.getLogger(Gameplay.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
So, using null layouts is the beginning of your problems. I might recommend using CardLayout which is designed to help you dynamically switch between views. See How to Use CardLayout for more details. I'd also suggest taking the time to read through Laying Out Components Within a Container and finding one or more appropriate layouts to support your menu.
You're also making a lot of fundamental mistakes. Swing is not thread safe, so you should avoid updating the UI (or something the UI depends on) from outside the context of the EDT - see Concurrency in Swing for more information and How to Use Swing Timers for a possible solution.
As a general recommendation, you should avoid overriding paint and, in the case of classes which extend from JComponent, prefer paintComponent instead. You should also avoid call methods which might change the state of the component during a paint cycle, this can increase the number of repaint requests and degrade the performance of your program (ie, don't call setBackground inside paint).
Have a look at Performing Custom Painting and Painting in AWT and Swing for more details about how the paint system works and how best you can work with it.
You should also avoid KeyListener, this is likely to cause you issues when you introduce other, focusable, components into the picture. Instead, you should favour the Key bindings API instead
I've read through [insert link or tutorial], but it still doesn't help...
And forgive me if this doesn't happen all the time.
The point of providing you the tutorial links is to encourage you to learn something;
Learn where to find answers to your questions
Learn how the APIs work
Expand your knowledge and understanding of how the APIs work
Having said that, they're not always "obvious" as to the solution. What I do when I'm in this situation is start with one or more new projects, dedicated to just working on that aspect of the API I'm trying to understand. For here I can explore the concepts in isolation and when I "think" I understand them, try and implement them into the project I'm working on. This might take a number of iterations, but once it works, I have gained a much deeper understanding and appreciation of the API then I would have gained from a simple "copy-n-paste" solution

Disable JButton after click and enable when it done it's job

I have a JButton which has an ActionListener, which does its job as many times as I click it. Below is my code:
mouseListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
JButton source = (JButton) e.getSource();
source.setEnabled(false);
try {
RequestCommon.ctbCookie = jtf.getText();
System.out.println(RequestCommon.ctbCookie);
HttpURLConnection connection = HttpURLConnectionBuilder.getConnection(RequestCommon.login, RequestCommon.getCtb888Headers());
String connectionOuput = HttpURLConnectionBuilder.getConnectionOuput(connection);
System.out.println(connectionOuput);
new Player(new BufferedInputStream(new FileInputStream(new File("sounds/8.mp3")))).play();
} catch (IOException e1) {
e1.printStackTrace();
} catch (JavaLayerException e1) {
e1.printStackTrace();
}
source.setEnabled(true);
}
}
jb1.addActionListener(mouseListener);
I want it so that no matter how many times I click while the job is running it won't execute again. When the job is done, if I click again, the job will run again. I don't know how to do that, please tell me if you know, thanks!
Long running code should NOT execute on the Event Dispatch Thread (EDT). You need to start a separate Thread to do you HTTP request.
The easiest way to do this is to use a SwingWorker. You can disable the button before you start the worker and then the worker has a done() method that is invoked and you can enable the button.
Read the section from the Swing tutorial on Concurrency in Swing for more information about the EDT and a working example of a Swing worker.
Edit:
People seem confused about event handling. The listeners for an event are invoked before the next event is handled. So in the case of "double clicking" on the button. The button is disable on the first click and the long running task is started. The second click is then received on the disable button so the ActionListener is not invoked.
Here is some old code I have lying around which was written before a SwingWorker existed. The basic logic for the "Start in New Thread" button is:
disable the button so it can't be click while processing is happening
simulate a long running task by looping 10 times and sleeping
enable the button so the task can be done again
Here is the code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/*
* A couple of notes about long running tasks and GUI updates:
*
* 1) all GUI painting should be done in the event thread
* 2) GUI painting is not done until the event thread processing is done
*
* This means that long running code (database access, file processing ...)
* should not be done in the event thread. A new thread can be created for
* these tasks.
*
* Most Swing methods are not thread safe. If the long running task needs
* to update the GUI for any reason then the SwingUtilities class
* should be used to add code to the event thread.
*
* See the Swing tutorial on "Using Threads" for more information
* http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
*/
public class InvokeLaterTest extends JFrame
implements ActionListener, Runnable
{
JLabel status;
JButton eventThread;
JButton newThread;
JButton stop;
Thread thread;
int i;
boolean stopProcessing;
public InvokeLaterTest()
{
status = new JLabel( "Ready to Process:" );
status.setHorizontalAlignment( JLabel.CENTER );
getContentPane().add(status, BorderLayout.NORTH);
eventThread = new JButton( "Start in Event Thread" );
eventThread.addActionListener( this );
getContentPane().add(eventThread, BorderLayout.WEST);
newThread = new JButton( "Start in New Thread" );
newThread.addActionListener( this );
getContentPane().add(newThread, BorderLayout.EAST);
stop = new JButton( "Stop Processing" );
stop.addActionListener( this );
getContentPane().add(stop, BorderLayout.SOUTH);
}
public void actionPerformed(ActionEvent e)
{
// Code is executing in Event thread so label will not be updated
// and the Stop button will not be enabled.
if (e.getSource() == eventThread)
{
stopProcessing = false;
run();
}
// Code is executing in a new thread so label will be updated
else if (e.getSource() == newThread)
{
stopProcessing = false;
thread = new Thread( this );
thread.start();
}
else
{
stopProcessing = true;
status.setText("Processing Stopped");
setButtons( true );
}
}
public void run()
{
setButtons( false );
for (i = 1; i < 10; i++)
{
if ( stopProcessing ) return;
System.out.println("ProcessingFile: " + i);
// SwingUtilities makes sure code is executed in the event thread.
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
status.setText("Processing File: " + i);
status.paintImmediately(status.getBounds());
}
});
// simulate log running task
try { Thread.sleep(1000); }
catch (Exception e) {}
}
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
status.setText("Finished Processing");
setButtons( true );
}
});
}
private void setButtons(boolean value)
{
eventThread.setEnabled( value );
newThread.setEnabled( value );
}
public static void main(String[] args)
{
JFrame frame = new InvokeLaterTest();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.show();
}
}
A SwingWorker is similar to the above logic but:
you need to disable the button outside the SwingWorker
the worker will create the Thread for you and execute the code
when the worker is finished the done() method of the worker is invoked so you can enable the button.
You should use if and check if the button is enabled before executing your code.
JButton source = (JButton) e.getSource();
if(source.isEnabled()) {
.
.
.
execute your code
JButton source = (JButton) e.getSource();
if (source.isEnabled()) {
Executors.newSingleThreadScheduledExecutor().execute(() -> {
source.setEnabled(false);
--your code here--
source.setEnabled(true);
}
);
}
};
Added a completedTime variable to hold the timestamp as when the action is complete, and every event has the time when it is generated, compare and return if it is less than the completed time
long completedTime;
mouseListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
JButton source = (JButton) e.getSource();
long timeStamp = e.getWhen();
if (timeStamp < completedTime) {
System.out.println("returned");
return;
}
// source.setEnabled(false);
try {
RequestCommon.ctbCookie = jtf.getText();
System.out.println( RequestCommon.ctbCookie );
HttpURLConnection connection = HttpURLConnectionBuilder.getConnection(RequestCommon.login, RequestCommon.getCtb888Headers());
String connectionOuput = HttpURLConnectionBuilder.getConnectionOuput(connection);
System.out.println(connectionOuput);
new Player(new BufferedInputStream(new FileInputStream(new File("sounds/8.mp3")))).play();
} catch (IOException e1) {
e1.printStackTrace();
} catch (JavaLayerException e1) {
e1.printStackTrace();
}
// source.setEnabled(true);
completedTime = System.currentTimeMillis();
}
};

repaint function not work when event happen

i am trying to change button background color for 10 time when event happen?
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
try {
for (int i = 0; i < 10; ++i) {
Random r = new Random();
jButton2.setBackground(new Color(r.nextInt(150), r.nextInt(150), r.nextInt(150)));
jButton2.repaint();
Thread.sleep(200);
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
but the button show the last color??
thanks it's work correctly
int x = 0;
Timer timer;
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Random r = new Random();
jButton2.setBackground(new Color(r.nextInt(150), r.nextInt(150), r.nextInt(150)));
jButton2.repaint();
if(x==10){
timer.stop();
x=0;
} else{
x++;
}
}
});
timer.start();
}
Don't call Thread.sleep(...) on the Swing event thread as this puts the entire Swing GUI to sleep. In other words, your GUI does no painting, accepts no user input or interaction at all and becomes completely useless while the event (also known as the Event Dispatch Thread or EDT). Use a Swing Timer instead. Please check out the Swing Timer Tutorial for more help on this.
Also have a look at some of the answers to this question, including mKorbel's.

How to simulate JDialog movement in JFC

I have a JDialog being displayed on screen and I want to simulate its movement (Drag from one location to another) based on a condition. Is there any way this can be done ?
See this piece of code below. I have just tested it and it works fine. It is just a proof of concept.
private void startDialog() {
final JDialog d = new JDialog(this, "Test", true);
d.getContentPane().add(new JLabel("Something"));
d.setBounds(100, 100, 400, 300);
Thread t = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 50; i++) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Point p = d.getLocation();
d.setLocation(p.x + 10, p.y + 10);
}
});
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// ignore
}
}
}
});
t.start();
d.setVisible(true);
}
You can improve the code yourself:
use a Timer instead of a regular Thread
tweak the sleep times and the location jumps and so on
Just call this method from any Swing application and it will work.

Categories