I am stuck on probably an easy problem, but I really can't find why it isn't working. I am trying to increase mijnScore with 1 each time the method gets called. But somehow mijnScore goes back to 0 after the method is done.
int mijnScore = 0;
...
public void updateUI() {
System.out.println("updateUI");
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ikWin = true;
while(ikWin) {
mijnScore++;
System.out.println("mijnScore" + mijnScore);
Scoresp1.setText(mijnScore + "");
ikWin = false;
positie = 0;
}
}
});
}
Solved
Making the variable static solved my problem.
static int mijnScore = 0;
Please see the javadoc of the method SwingUtilities.invokeLater(..)
http://download.oracle.com/javase/1.4.2/docs/api/javax/swing/SwingUtilities.html#invokeLater(java.lang.Runnable)
It can be that the thread doing the mijnScore increments is invoked only later and this is why in the parent thread you see still the value 0 for it.
I dont know wheather you are calling with different objects or same.Just as a guess Make the variable mijnScore static then it may be ok.
why did you set ikWin = false; then loop ends in first step
If it works after you made it static, you might actually have a different problem!
Do you call updateUI() on a newly constructed class? If so, only call it on a previously constructed instance as mijnScore is local to that instance!
EDIT:
Do your classes look like this? (Maybe you should have posted more code in the question)
// Score.java
public class Score {
int mijnScore = 0;
JLabel scoreSp1 = new JLabel();
public Score(JDialog dialog) {
dialog.add(scoreSp1);
}
...
public void updateUI() {
// Code from question
}
}
// Window.java
public class Game {
...
public void scoredPoint() {
JDialog dialog = new JDialog("You scored!");
new Score(dialog).updateUI();
dialog.setVisible(true);
}
}
In this silly example, the problem is actually in the second class - you shouldn't create a new Score instance every time. For the example, the code should be written like this:
// Window.java
public class Game {
JDialog dialog = new JDialog("You scored!");
Score score = new Score(dialog);
...
public void scoredPoint() {
score.updateUI();
dialog.setVisible(true);
}
}
Related
So, I am trying to access my variable from timer task, however I can't seem to make it work. I read about global variables but wasn't quite sure on how to use it. I am new to Java so any suggestion would be extremely helpful, thank you!
public boolean verifyAnswer(String userAnswer) {
String correctAnswer = this.questions.get(currentQuestionIndex).correctAnswerText;
if(userAnswer.equals(correctAnswer)) {
timer.pauseTimer();
Timer t = new Timer();
TimerTask tt = new TimerTask() {
//This is the variable I want to use
int score = 0;
#Override
public void run() {
System.out.println(++score);
if (score == 30) {
t.cancel();
}
};
};
t.scheduleAtFixedRate(tt, 0, 1000);
TimerPanel timer2 = new TimerPanel();
long total = 0;
//Here is where I try to use it
long equation = TimerTask.score / 30000;
The simplest workaround would be to use a single-element array or holder object to store the score as anonymous inner classes cannot modify the value of outer variables.
int[] score = {0};
TimerTask tt = new TimerTask() {
#Override
public void run() {
System.out.println(++score[0]);
if (score[0] == 30) {
t.cancel();
}
};
};
//...
long equation = score[0] / 30000;
a global variable might indeed help. It is just a variable declared outside the methods but inside the class. Then it is visible in the entire class - and also from outside if you make it public.
of you are in a multithreading environment, please access it in a synchronized way, like so
public class Test {
public volatile int global_variable = 42;
public synchronized int getGlobal_variable() {
return global_variable;
}
public synchronized void setGlobal_variable(int global_variable) {
this.global_variable = global_variable;
}
public void update() {
setGlobal_variable(getGlobal_variable() + 150);
}
public Test() {
try {
while (true) {
System.out.println(getGlobal_variable());
update();
Thread.sleep(1000);
}
} catch (Exception e) {
// TODO: handle exception
}
}
public static void main(String[] args) {
new Test();
}
}
note that I have added the volatile just to be on the safe side.
it depends upon your application whether you really need that.
if you are not concerned with multithreading, just move the declaration of score outside your method and you will be fine :-)
i´m working on a Snake implementation and am mostly done. My only problem is, that,when my JMenuItem for starting a new game is clicked the game freezes. Here´s the relevant code:
this.newGame.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e){
neuesSpiel();
}
});
public void neuesSpiel()
{ //The old snake game is finished and the playing field is reseted
if(snake!=null)
{
snake.beendeSpiel();
for(int i=0; i<20;i++)
{
for(int j=0;j<10;j++)
{
spielfeld[i][j] = false;
}
}
}//the new snake game is created below
snake = new Snake(null,null, 10,5, this);
Snake snake2 = new Snake(snake,null,11,5,this);
snake.hintermann = snake2;
snake2.hintermann = new Snake(snake2,null,12,5,this);
snake.run();
}
In the class Snake:
public void run()
{
Game.zf.requestFocus();
while(spiellauf){
try
{
Thread.sleep( 120 );
}
catch ( InterruptedException e ) { }
if(spiellauf)
bewege(); //the Snake Block is moved
}
I´m pretty sure, that the run() method is the problem, because if i don´t call the method, the game doesnt freeze. Furthermore the method neuesSpiel() should be ok too, because when I call it in the constructor it works as intended.
I don´t know how else i can make my function wait for 120ms besides using threads. Is there an alternative?
Thanks in advance!
I don´t know how else i can make my function wait for 120ms besides using threads.
You are not using threads. You are executing your run method in the current thread.
If you wish to run it in a new thread, you need something like :
new Thread(snake).start();
I understand ticks, 20 ticks to a second etc. but i don't get the syntax. Can someone explain to me the steps of making something with ticks? I have a fireball move here as an example of something i need ticks for; after each time it does the effect, i need it to wait like, 2 ticks. I've looked at other examples but i really don't understand the syntax
#EventHandler
public void onPlayerInteractBlockFireBall(PlayerInteractEvent event) {
Player player = event.getPlayer();
if (player.getItemInHand().getType() == Material.MAGMA_CREAM){
List<Block> targets = player.getLineOfSight((Set)null, 30);
for (Block targetblock : targets){
Location target = targetblock.getLocation();
player.getWorld().playEffect(target, Effect.MOBSPAWNER_FLAMES,5);
}
}
}
I need to know how to add a delay to a loop, timing is really important in this plugin i'm trying to make and i just need to know the syntax.
Anyone help?
To make a timer, you can use
Bukkit.getServer().getScheduler().runTaskLater(plugin, new Runnable(){
public void run(){
//code
}
},ticksToWait);//run code in run() after ticksToWait ticks
So, if you wanted to wait 2 ticks before running the function shootFireball(), for example, you could use
Bukkit.getServer().getScheduler().runTaskLater(plugin, new Runnable(){
public void run(){
shootFireball();
}
},2L);//run code in run() after 2 ticks
plugin will be the instance of your Main class (the one that extends JavaPlugin). So, for example, your onEnable and onDisable functions in your Main class could look like this:
public static Main that; //in your case "plugin" would be "Main.that"
#Override
public void onEnable(){
that = this; //Main.that is now equal to this class
}
#Override
public void onDisable(){
that = null; //Set to null to prevent memory leaks
}
So, your code could look something like this:
#EventHandler
public void onPlayerInteractBlockFireBall(PlayerInteractEvent event) {
Player player = event.getPlayer();
if (player.getItemInHand().getType() == Material.MAGMA_CREAM){
List<Block> targets = player.getLineOfSight((Set)null, 30);
for (int i = 0; i < targets.size(); i++){
//call the spawnFlames with "i * 2" ticks, because
//every time "i" is incremented, there is a new target block
//which means we should wait 2 more ticks than the previous
//iteration before running the task
spawnFlames(player, targets.get(i), i * 2);
}
}
}
public void spawnFlames(final Player player, final Block target, final long ticks){
Bukkit.getServer().getScheduler().runTaskLater(Main.that, new Runnable(){
public void run(){
Location target = targetblock.getLocation();
player.getWorld().playEffect(target, Effect.MOBSPAWNER_FLAMES,5);
}
},ticks);
//run code in run() after "ticks" ticks
//"ticks" will be equal to "i * 2" from
//the onPlayerInteractBlockFireBall() method
}
You will start using Scheduler Programming.
Look carefully at this part of the tutorial.
You need a repeating task for this purpose:
First, create a class that extends BukkitRunnable.
Then override the Runnable.run() method: it will be called once per iteration.
Now start the task with BukkitRunnable.runTaskTimer(Plugin, long, long).
You can stop it at any time using BukkitRunnable.cancel().
You could implement the feature like this:
List<Block> blocks; // The target blocks
BukkitRunnable task = new MagmaEffect(blocks);
Plugin main; // The unique instance of the main class
task.runTaskTimer(main, 0L, 2L);
public class MagmaEffect extends BukkitRunnable {
private List<Block> blocks;
public MagmaEffect(List<Block> blocks) {
this.blocks = blocks;
}
private int index;
#Override
public void run() {
Block block = blocks.get(index);
block.getWorld().playEffect(block.getLocation(), Effect.MOBSPAWNER_FLAMES, 5);
index++;
if (index == blocks.size()) {
cancel();
}
}
}
Tons of JProgressBar questions on here I know, but through all the answers and I can't seem to diagnose my issue. I am processing a file with some address verification software. I click the Process button and I need my JProgressBar to update with each file processed.
Here is the button:
private JButton getJButton0() {
...
jButton0.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
jButton0ActionActionPerformed(event);
t.start();
}
...
Per everybody's recommendation, I used the setValue() method within a thread
Thread t = new Thread(){
public void run() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
jProgressBar0.setValue(BulkProcessor.getPercentComplete());
}
});
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
...
BulkProcessor.getPercentComplete() is a method I'm calling from another class which represents the percentage complete. I have tested this method and it updates correctly. The issue is that the progress bar will not update until the files are finished processing, and then it will jump to 100%. I apologize if this is a repeat question, but I have done some serious digging on this site with no luck. Any help much appreciated.
Edit:
Per recommended duplicate, I tried this:
public void update(){
new SwingWorker<Void,Void>() {
protected Void doInBackground() throws Exception {
jProgressBar0.setValue(BulkProcessor.getPercentComplete());
return null;
};
}.execute();
}
And then tried calling this update() method under the actionPerformed() (switched t.start() with update()). I am still having the same issue.
Edit
Based on user1676075's recommendation, however same issue:
public static void update(){
new SwingWorker<Void,Integer>() {
protected Void doInBackground() throws Exception {
do
{
percentComplete = BulkProcessor.getPercentComplete();
publish(percentComplete);
Thread.sleep(100);
} while(percentComplete < 100);
return null;
}
#Override
protected
void process(List<Integer> progress)
{
jProgressBar0.setValue(progress.get(0));
}
}.execute();
}
Edit
Here is the code from my BulkProcessor class
private String getOutputLine( String searchString, String inputLine )
throws QasException
{
..(code for processing lines)..
countRecord++;
percentComplete = (int) Math.round((countRecord/totalRecord)*100);
totalRecord is updated in the main class of my BulkProcessor class
public static void main( String input, String output ){
count.clear();
try{
String inputFile = input;
String outputFile = output;
LineNumberReader lnr = new LineNumberReader(new FileReader(new File(input)));
lnr.skip(Long.MAX_VALUE);
totalRecord = lnr.getLineNumber() + 1; //line count in file
BulkProcessor bulk = new BulkProcessor(inputFile, outputFile, ConfigManager.DFLT_NAME);
bulk.process();
}catch(Exception e ){
e.printStackTrace();
}
}
Looks like you're mixing usages. See the SwingWorker documentation, example at the top: http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html.
Ideally you'd update your BulkProcessor in the doInBackground method of the SwingWorker, and that would call setProgress, and the jProgressBar would be listening for those progress updates as in the example.
If that won't work for you, which it seems like it won't just based on the above, start a SwingWorker from the button press event. Implement the SwingWorker methods kinda like this (pseudocode):
new SwingWorker<Void,Integer>()
{
doInBackground()
{
do
{
percentComplete = BulkProcessor.getPercentComplete();
publish(percentCompete);
Thread.sleep(100);
} while (percentComplete < 100);
}
#Override
process(List<Integer> progress)
{
jProgressBar0.setValue(progress.get(0));
}
}.execute();
You'll need to add error-handling and checks for complete and failure cases, but that should get you started and to where you want to be. doInBackground runs in a background thread so won't block anything, and process() runs on the swing worker thread so will post the updates.
The mistake you probably went on is calling the t.start(); after thejButton0ActionPerformed(event); which makes that after the action is performed the thread will start. Therefore the value of the progress bar is not updated as intended.
You need to start the thread in jButton0ActionPerformed(event); and then update the value in it.
Just a hunch, but...
percentComplete = (int) Math.round((countRecord/totalRecord)*100);
Are you sure this is not integer arithmetic? I don't know the type of totalRecord, so I can't say for sure.
I'd guess everything works fine, and just the progress is 0 all the time, until complete where it magically is 100. This is because an int divided by an int will not have fraction values (ie. 99/100 == 0, 100/100 == 1). This fits perfectly with the symptoms you are experiencing.
Try replacing the line above with:
percentComplete = (int) Math.round((countRecord/(double) totalRecord)*100);
to see it I'm right. :-)
Have you tried to use the PropertyChangeListener-interface?
The calculations will be done by the Swingworker-thread and the main-gui will implement this interface. Some example-code
#Override
public void actionPerformed(ActionEvent e) {
this.myButton.setEnabled(false);
MyWorkerThread thread = new MyWorkerThread(); //Data-processing
thread.addPropertyChangeListener(this.mainguiframe); //Separation of concern
thread.execute();
}
Using the "setProgress"-method of the swing-worker-thread the main-gui-thread will be notified if something has happend.
#Override
public void propertyChange(PropertyChangeEvent property) {
Integer currentValue = new Integer(0);
currentValue = (Integer) property.getNewValue();
this.progressBar.setValue(currentValue.intValue());
}
Swing is not thread-safe. This is not the best solution but perhaps it can help you. Please comment if there is somethin horrible wrong.
I've read many different articles about JProgressBar...including the dodgy code found over at Java; here.
Most indicate you need a SwingWorker to get things happening properly, which makes perfect sense, I understand that much. I am finding that when I call setProgress(value) to update the progressbar, it's not triggering the propertyChange event most of the time. I've checked the value I'm passing to setProgess and it definitely changes every time, so I'm not sure if it's just firing the event too quickly? Please see relevant code below, any help/explanation would be greatly appreciated.
class ProgBar extends SwingWorker
{
public ProgBar()
{
addPropertyChangeListener(new PropertyChangeListener()
{
#Override
public void propertyChange(PropertyChangeEvent evt)
{
if ("progress".equals(evt.getPropertyName()))
{
int value = (Integer)evt.getNewValue();
System.out.println("propertyChange called with: " + value);
loginProg.setValue(value);
}
}
});
loginProg.setStringPainted(true);
loginProg.setValue(0);
setProgress(0);
}
#Override
public Void doInBackground() throws InterruptedException
{
...
int count = 0;
for (Folder f : folders)
{
... // process 'f'
setProgress((int)Math.min(((double)count/folders.length)*100.0, 100.0));
}
...
return null;
}
#Override
public void done()
{
System.out.println("Done called.");
setProgress(100);
loginProg.setValue(100);
}
}
JProgressBar called with this;
private void jButtonActionPerformed(java.awt.event.ActionEvent evt)
{
// Create new thread to run progess bar.
// Otherwise won't be able to update progress bar.
ProgBar pb = new ProgBar();
pb.execute();
}
}
EDIT:
Yeah, so I should have read the Javadocs better;
Because PropertyChangeListeners are notified asynchronously on the Event Dispatch Thread multiple invocations to the setProgress method might occur before any PropertyChangeListeners are invoked. For performance purposes all these invocations are coalesced into one invocation with the last invocation argument only.
For example, the following invokations:
setProgress(1);
setProgress(2);
setProgress(3);
might result in a single PropertyChangeListener notification with the value 3.
I.E. my assumption that setProgress was firing too quickly was correct. A ProgressMonitor might be a better solution.
This isn't an answer but a demonstration sscce, to show you just what I meant:
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Random;
import javax.swing.*;
public class TestProgBar {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ProgBar progBar = new ProgBar();
// **** this is key and where your code may be deficient ***
JProgressBar prog = progBar.getProg();
progBar.execute();
JOptionPane.showMessageDialog(null, prog);
}
});
}
}
class ProgBar extends SwingWorker<Void, Void> {
private JProgressBar loginProg = new JProgressBar();
public ProgBar() {
addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
int value = (Integer) evt.getNewValue();
System.out.println("propertyChange called with: " + value);
loginProg.setValue(value);
}
}
});
loginProg.setStringPainted(true);
loginProg.setValue(0);
setProgress(0);
}
public JProgressBar getProg() {
return loginProg;
}
#Override
public Void doInBackground() throws InterruptedException {
int count = 0;
int max = 5;
Random random = new Random();
// simulate uploading files
while (count < 100) {
count += random.nextInt(max);
if (count > 100) {
count = 100;
}
setProgress(count);
Thread.sleep(400);
}
// for (Folder f : folders) {
// setProgress((int) Math.min(((double) count / folders.length) * 100.0,
// 100.0));
// }
return null;
}
#Override
public void done() {
System.out.println("Done called.");
setProgress(100);
loginProg.setValue(100);
}
}
Again, this code works fine, suggesting that the code you've loaded does not show the error. You need to do further work isolating the error and getting it into code so we can test it.
Yeah, so I should have read the Javadocs better;
Because PropertyChangeListeners are notified asynchronously on the Event Dispatch Thread multiple invocations to the setProgress method might occur before any PropertyChangeListeners are invoked. For performance purposes all these invocations are coalesced into one invocation with the last invocation argument only.
For example, the following invokations:
setProgress(1);
setProgress(2);
setProgress(3);
might result in a single PropertyChangeListener notification with the value 3.
I.E. my assumption that setProgress was firing too quickly was correct. A ProgressMonitor might be a better solution. I've confirmed this with the SSCCE and my program, both are simply firing setProgress too quickly and as a result, only the last value passed to setProgress is being passed through to the PropertyChange event.
If you want listeners to be called immediately, you can try the following (which worked for me):
setProgress(1);
firePropertyChange("progress", 0, 1);