I am programming a game where as one image changes place with another and I want the second image to be removed after 200ms, something I really could use some help with.
I'm still a beginner and all help is appreciated! Answer as if you were talking to a five year old!
public void setVisible(Boolean visible) {
ImageIcon ii = new ImageIcon(this.getClass().getResource(explode));
image = ii.getImage();
//this.visible = visible;
/*WITH THIS LINE OF CODE THE EXPLODE DOES NOT SHOW AT ALL,
I WANT TO MAKE SURE IT SHOWS BUT ONLY FOR 200MS*/
}
Thanks in advance!
You can use a scheduled thread for it. You can use the ScheduledExcecutorService for it
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
public void displayImageFor200Ms(){
ImageIcon ii = new ImageIcon(this.getClass().getResource(explode));
image = ii.getImage();
scheduler.schedule(new Runnable() {
public void run() {
// remove image now!
}
}, 200 , TimeUnit.MILLISECONDS);
}
don't forget to shut down the scheduler when you don't need it anymore (you could use a global, pooled Scheduler for all your delayed actions and shut it down when your game is over)
Since you shouldn't do these time blocking methods like Thread.sleep(200) in the EDT, here is another solution with the Timer and TimerTask classes:
public void setVisible(boolean visible) {
ImageIcon ii = new ImageIcon(this.getClass().getResource(explode));
// show / hide image
ii.setVisible(visible);
if (visible) { // only hide image, if it's previously set to visible
new Timer().schedule(new TimerTask() {
public void run() {
ii.setVisible(false);
}
}, 200); // hide it after 200 ms
}
}
Thanks #AndrewThompson for the advice!
Related
I am trying to make a image slider in android that scrolls automatically after every 2000s. I have written the code ,but i don't know to loop the code automatically after every 2000s. Now I have 2 static images to test the slider scroll ,it just scrolls to the second image and stops.but it is not looping continuosly to 1st one when it reaches the last image.
Here is my code(i want to loop this code continuously)
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mRecyclerViewTwo.smoothScrollToPosition(1);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (2 <= mPostad.size()) {
mRecyclerViewTwo.smoothScrollToPosition(2);
} else {
mRecyclerViewTwo.smoothScrollToPosition(1);
}
}
}, 2000);
}
}, 2000);
Please help.
Any help is appreciatable.
You can use a ScheduledExecutorService:
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(this::codeToExecute, 0, 2, TimeUnit.SECONDS);
private void codeToExecute() {
if (2 <= mPostad.size()) {
mRecyclerViewTwo.smoothScrollToPosition(2);
} else {
mRecyclerViewTwo.smoothScrollToPosition(1);
}
}
Edit: That said, from reading your question you may well find a pre-existing widget that does this job for you. Maybe a ViewFlipper?
What I am trying to do is an Appled which throws 2 threads, each running a counter which increases itself via an infinite loop
I then use a while(true) in the Applet's paint() method, which continuously paints the counters, the problem is that I have also 2 buttons, each intended to stop each thread, but the infinite loop in the paint() method doesn't let me neither click none of them nor close the Applet's window nor anything
Here a screenshot followed by the code
btw I'm certain the problem is the paint() loop as if I disable the loop I can interact with the buttons, but the counters are obviously not updated, and weird thing is that I put the mouse cursor over the buttons to show it took the form like when you want to resize a windows but the imprpant didn't capture it :/
http://i.imgur.com/PJnDI4u.png
public class MainApplet extends Applet implements ActionListener {
private static final long serialVersionUID = -2500043816999861110L;
private Font fuente;
private Button bUno, bDos;
private HiloContador hUno, hDos;
public void init() {
setBackground(Color.LIGHT_GRAY);
fuente = new Font("Verdana",Font.BOLD,26);
bUno = new Button("Parar");
bUno.addActionListener(this);
bDos = new Button("Parar");
bDos.addActionListener(this);
bUno.setSize(40,20);
add(bUno);
bDos.setSize(40,20);
add(bDos);
hUno = new HiloContador(20);
hUno.start();
hDos = new HiloContador(40);
hDos.start();
}
#SuppressWarnings({ "deprecation", "static-access" })
public void actionPerformed(ActionEvent e) {
if(e.getSource().equals(bUno)){
hUno.parar();
bUno.setLabel("1 parado");
}else if (e.getSource().equals(bDos)){
hDos.parar();
bDos.setLabel("2 parado");
}
}
public void paint(Graphics g) {
while (true){
g.clearRect(1,1,getSize().width,getSize().height); //dibuja la ventana
g.setFont(fuente);
g.drawString(hUno.getContador()+"",40,60);
g.drawString(hDos.getContador()+"",100,60);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
in case it helps anyone, solved deleting the infinite loop and adding this method
Timer timer = new Timer();
timer.schedule( new TimerTask() {
public void run() {
repaint();}
}, 0, 1000);
Alright, so I have a null layout JPanel with a single JLabel in it. The JLabel is positioned at (0,0). What I'm trying to do is use a while loop in a new Thread to sleep the new Thread and then shift the JLabel 10px down by using SwingUtilities.invokeLater . The problem is that the UI gets updated in a laggy sort of way. It doesn't update every time it should, but skips lots of updates and shifts in big chunks. I know I can easily do it with Timer, but the point is understanding Threads better. Thanks in advance!
Code:
private void start(){
Updater up = new Updater();
up.start();
}
public void updatePosition(){
int y = label1.getLocation.y;
label.setBounds(0,y+10, 10,10);
}
private class Updater extends Thread{
public void run(){
while(!shouldQuit){
try{
Updater.sleep(100);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
updatePosition();
}
});
}catch(Exception e){
System.out.println(e);
}
}
}
}
EDIT:
I got it to work by replacing the while loop with a call to a new Thread instance in the updatePosition() method, to settle things down a bit. And also, it wasn't only the Thread that was causing the problem, so I had to force the panel to re-layout it's subviews by calling revalidate() on it.
Here's how it looks (the fully working one):
private void start(){
new Updater().start();
}
public void updatePosition(){
int y = label1.getLocation.y;
label.setBounds(0,y+10, 10,10);
panel.revalidate();
if(!shouldQuit) new Updater().start();
}
private class Updater extends Thread{
public void run(){
try{
Updater.sleep(100);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
updatePosition();
}
});
}catch(Exception e){
System.out.println(e);
}
}
}
You should try to use visibility and GridLayout to maximize movement. You can use a int var to count threads and reciprocate that to the label. As well, you should be using your ability o create Updaters, more and smoother. Just do the start() mwthod while trolling for threads :-)
You could have something besides an infinity call to start. I think you've lost the inheritance from the class, itself. The object label1 must ave been lost in tbe fray. If that's not it, then I'm pretty sure I'm not really able to answer this one.
I have a Frame that is all one color, but has some text in the corner. I set the color, actually read the color from the monitor, and then do some computations based on those measurements.
The problem is, calling repaint() causes the Frame to be painted after I do the measurements. I'm assuming this is due to repaint() delegating to the EDT, but I'm getting incorrect results due to the measurements occurring before/during the actual painting work.
My initial thought was to put a listener on paint completion, but I repaint to update the text much more frequently than I do for the color and I don't want to listen to those events. How can I wait for the actual painting task to finish before taking my measurement?
Amazing what you can find...
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
PaintEvent pe = (PaintEvent) event;
String type = "";
if (pe.getID() == PaintEvent.PAINT) {
type = "PAINT";
} else if (pe.getID() == PaintEvent.PAINT_FIRST) {
type = "PAINT_FIRST";
} else if (pe.getID() == PaintEvent.PAINT_LAST) {
type = "PAINT_LAST";
} else if (pe.getID() == PaintEvent.UPDATE) {
type = "UPDATE";
}
System.out.println(type + "; pe.UpdateRec = " + pe.getUpdateRect() + "; pe.component = " + pe.getComponent());
}
}, AWTEvent.PAINT_EVENT_MASK);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
Now, because repaint requests can come think and fast, I'd be tempted to place a small "delay" in that would fired shortly after the last request has completed...
private Timer updateTimer;
// ...
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
updateTimer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Update compulations here...
}
});
updateTimer.setRepeats(false);
updateTimer.setCoalesce(true);
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
updateTimer.restart();
}
}, AWTEvent.PAINT_EVENT_MASK);
}
}
The idea is to allow at least 250 milliseconds between the last repaint request and the start of your compilations. You might like to play around with these values a bit and see what suits you...
UPDATE
You could also try JComponent.paintImmediately
Paints the specified region in this component and all of its
descendants that overlap the region, immediately.
It's rarely necessary to call this method. In most cases it's more
efficient to call repaint, which defers the actual painting and can
collapse redundant requests into a single paint call. This method is
useful if one needs to update the display while the current event is
being dispatched.
I know this is an old thread, but in case someone is searching for an answer to this, SwingUtilities has a method called invokeAndWait(Runnable) that runs the task on AWT dispatching thread synchronously with your current thread. Note that this cannot be done if you need it to be done inside the Event dispatching thread.
I am struggling with a problem on coloring an array of JButtons.
I made two arrays of JButtons:
public JButton Speler1[] = new JButton[140]; //Player1
public JButton Speler2[] = new JButton[140]; //Player2
These two arrays of buttons make lane 1 and lane 2 of a racing game. I want the position of player 1 and 2 to be colored on both screens. So player 1 can see where player 2 is and vice versa.
I already made a method which sends the position of both players to eachother.
if (message.contains("Positie")) {
String posit = message.replaceFirst("Positie", "");
int positi = Integer.valueOf(posit);
positie2 = positi;
kleurHokje kleur = new kleurHokje();
kleur.hokVerkleur(positi); // positi is the position of each player
}
So when I call the method hokVerkleur(positi), I want to change a button on lane 2.
class kleurHokje{
public void hokVerkleur(int loc){
Speler2[loc].setBackground(Color.yellow);
Speler2[positie2].setBackground(Color.gray);
}
}
It just wont work. While i'm doing almost the same for Speler1[positie] except Speler1 doesn't use the network, which works as I want.
Any help is appreciated,
Thanks Jef
Edit:
If I place my code in one of the MouseListeners it works fine, but rather have it to be colored automatically instead of having to click each time.
class Klaar extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
Speler2[positie2].setBackground(Color.gray);
}
}
Ps. my first language isn't english, I hope you understand my problem.
If I place my code in one of the MouseListeners it works fine:
agreed, if you change Color for JButton from BackGroung Task, then there any changes, you have some issues with Concurency in Swing, your updated to the GUI is out of EDT,
1) then you have to wrap coloring JButtons into invokeLater();
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Speler2[loc].setBackground(Color.yellow);
Speler2[positie2].setBackground(Color.gray);
}
});
2) but you have to solve by using regular Swing methods
2a) wrap your GUI rellated code to the javax.swing.Action
2b) initialize your BackGroung Tasks from
SwingWorker
Runnble#Tread
Made a runnable thread, works as a charm. Thanks for help everybody.
public void actionThread() {
Thread t = new Thread() {
public void run() {
while (!stop) {
tegenspelerPositie();
Score();
eigenOgen();
try {
sleep(100);
} catch (InterruptedException ex) {
}
}
}
};
t.start();
}