repaint function not work when event happen - java

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.

Related

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

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());
};

Best way to make a thread start from a jbutton?

I have 15 different threads running all with dynamic input from the user. I need these Threads to run ONLY when my JButton is pressed. I know i didnt supply the code for the button but its just a simple deceleration.
JButton JButton_Button1 = new JButton("Start");
To clarify one more time i just want the thread to start only when JButton_Button1 is clicked
new Thread() {
int counter = 10;
public void run() {
while(counter >= 0) {
JLabel_MistyvaleLoot.setText("Test" + (counter--));
try{
Thread.sleep(1000);
} catch(Exception e) {}
}
}
}.start();
If you're looking to have 15 threads running, but you want them to do nothing except when a JButton is pressed, then consider using a fixed-size thread pool. Try using:
private ExecutorService threadPool = Executors.newFixedThreadPool(15);
This constructs 15 processing threads that will idle until you submit a task. If you are looking to submit a task when the JButton is pressed, then you should add an ActionListener. That is, try this:
JButton jButton1 = new JButton("Start");
jButton1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
threadPool.submit(new Runnable(){
int counter = 10;
public void run() {
while(counter >= 0) {
JLabel_MistyvaleLoot.setText("Test" + (counter--));
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
}
}
}
});
}
});
To get one of the fifteen threads to run the task, you call threadPool.submit() and to get the button to respond to a click, you call jButton1.addActionListener().

Java - Trigger swing timer with a mouseEvent?

I'm trying to turn on the timer using mouseEntered event with MouseListener it doesn't seem to work. Am i doing somthing wrong? I'm new to Java. Thanks in advance!
int counter = 0;
Timer timer = new Timer(1000,this);
public void mouseEntered(e MouseEvent)
{
if(e.getComponent == mouseEnteredArea)
{
timer.start()
counter++;
if(counter == 10)
{
timer.stop();
}
}
}
What's happening is when the mouse enters the area, your code starts the timer, adds one to counter (so counter == 1), checks if counter is equal to 10. Since it isn't, the code then skips the if statement and exits the method.
It's difficult to tell your actual intentions from that question, so if that wasn't enough to help, please explain what you're trying to do.
I think you may not understand how the timer works. Basically the timer has an ActionListener. Every 1000 milliseconds (in your case), the actionPerformed will be called. So I believe the code you have above should be in the ActionListener, and just call timer.start() in the mouse method. Something like.
Timer timer = new Timer(1000, new ActionListener(){
private int counter = 0;
#Override
public void actionPerformed(ActionEvent e) {
if (counter == 10) {
((Timer)e.getSource()).stop();
counter = 0;
} else {
System.out.println("Count: " + (++counter));
}
}
});
....
#Override
public void mouseEntered(MouseEvent e) {
timer.start();
}
Resources
How to Use Swing Timers
How to Write a Mouse Listener

Java: Perform Action Every X Seconds

I've got a working Java program and I would like to draw an object on the display every X seconds. What is the best way to do this? I was thinking of using a for loop and some sleep statements, but I'm curious if there is an easier or more efficient way to go about this.
Thanks.
The simplest way would be to use a javax.swing.Timer
Timer timer = new Timer(X, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// Update the variables you need...
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
You might also like to have a read through
The Event Dispatching Thread
Concurrency in Swing
So you can understand why you should never use a while (true) { Thread.sleep(X) } call in Swing (inside the EDT)
ScheduledExecutorService might help here. The Javadoc shows example usage. Don't forget to call the shutdown method when you're finished.
Using Thread, this will draw a rectangle on the screen every XMilSeconds. This will stop after 5 runs. Edit the xMilSeconds for slower runs, and j > 4 for how many runs before stoping. It does freeze though, that I can't fix.
int i = 0;
private long xMilSeconds = 300;
private boolean paint;
public boolean running = true;
public void paint(Graphics g)
{
super.paint(g);
if(paint)
{
for(;i < i+1;)
{
g.drawRect(i+49,i+49,i+299,i+99);
g.setColor(Color.RED);
g.fillRect(i+49,i+49,i+299,i+99);
}
paint = false;
}
}
public void run()
{
while(running)
{
try
{
Thread.sleep(xSeconds);
paint = true;
repaint();
i++;
j++;
if(j > 4)
{
running = false;
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}

Rectangle colouring logic

I have one three rectangles in my canvas. I wanted to change the colours of three rectangles
in a slow manner one by one.
For example: When starting the application, user should be able to see three rectangles with the same colour (blue).
After 2 secons that rectangles colour should change to red.
Again after 2 secons the next rectangles colour should get changed.
The last one is also done the same way, that means after 2 seconds of the 2nd rectangle.
I wrote in my own way. But it is not working. All the rectanlges are changed together. I want one by one.
Could anyone give me the logic.
final Runnable timer = new Runnable() {
public void run() {
//list of rectangles size =3; each contain Rectangle.
for(int i = 0 ; i < rectangleList.size();i++){
if(rectangleListt.get(i).getBackgroundColor().equals(ColorConstants.blue)){
try {
rectangleList.get(i).setBackgroundColor(ColorConstants.yellow);
Thread.sleep(1500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//rectSubFigureList.get(i).setBorder(null);
}/*else{
rectSubFigureList.get(i).setBackgroundColor(ColorConstants.blue);
}*/
}
You're likely calling Thread.sleep inside of Swing's event thread or EDT (for event dispatch thread), and this will cause the thread itself to sleep. Since this thread is responsible for all of Swing's graphics and user interactions, this will in effect put your entire application to sleep, and is not what you want to have happen. Instead, read up on and use a Swing Timer for this.
References:
Swing Timer tutorial
Swing Event Dispatch Thread and Swingworker tutorial
To expand on Hidde's code, you could do:
// the timer:
Timer t = new Timer(2000, new ActionListener() {
private int changed = 0; // better to keep this private and in the class
#Override
public void actionPerformed(ActionEvent e) {
if (changed < rectangleList.size()) {
rectangleList.setBackgroundColor(someColor);
} else {
((Timer) e.getSource()).stop();
}
changed++;
}
});
t.start();
You can set a Timer:
// declaration:
static int changed = 0;
// the timer:
Timer t = new Timer(2000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Change the colour here:
if (changed == 0) {
// change the first one
} else if (changed == 1) {
// change the second one
} else if (changed == 2) {
// change the last one
} else {
((Timer) e.getSource()).stop();
}
changed ++;
}
});
t.start();

Categories