I'm making some simple animation using Actors (Labels, to be precize) and Actions.
My initial plan was to move one of them far to the left instantly, then make it smoothly appear through the edge of screen, replacing another. But every time a new Action is executed, Label's position resets, so I can't get the effect I planned. How do I avoid it?
Here's code, if you need it:
newAttack.addAction(Actions.moveBy(-1 * game.W, 0));
newAttack.setText(game.local.get(_attack));
newAttackType.background = game.skin.getDrawable("attack_" + getAttackType(_attack));
lastAttack.addAction(Actions.sequence(Actions.moveBy(game.W, 0, 1.5f),
Actions.run(new Runnable() {
public void run() {
System.out.println(lastAttack.getX() + " " + lastAttack.getY());
newAttack.addAction(Actions.sequence(Actions.moveBy(game.W, 0, 1.5f), Actions.run(new Runnable() {
public void run() {
lastAttack.addAction(Actions.moveBy(-1 * game.W, 0));
newAttack.addAction(Actions.moveBy(-1 * game.W, 0));
System.out.println(lastAttack.getX() + " " + lastAttack.getY() + "\n" + "--");
lastAttack.setText(game.local.get(_attack));
lastAttackType.background = game.skin.getDrawable("attack_" + getAttackType(_attack));
}
})));
}
})));
This may not work, but looking into the source code of Label.setText() reveals that the method calls Actor.invalidateHierarchy. This means that whatever is containing the lastAttack actor will reset the lastAttack's position.
So since you are adding the actions before you are calling Label.setText(), the position will be reset and then the actions won't work properly.
You should try setting the text, then setting the position of the actor to off screen, and then adding the slide in Action.
Related
I've been having some issues with making a GUI for a program. Back-end program works fine but sometimes it takes a while to complete.
In the GUI I want to show the user that work is being done and thought an indeterminate JProgressBar (progress) would suffice - it's indeterminate as I only want an indicator that something is happening and not actually follow the real progress. The bar has already been added to a frame so it's always there, and it's just unhidden when the button is clicked and the process starts.
It should then be re-hidden once the process has finished. I've also put in some text that also should show that the process is running, which is then changed to a completed bit after it's run.
However, it's not working as intended. What seems to be happening is that the code appears to be executing in the wrong order. The c.run() instruction seems to run before the setVisible(true) one does as the progress bar only appears once the run command has finished, and I can't see why. The run() command is quite a large operation so takes a while (it's only a single threaded application), but I don't know why it would be doing this as the code definitely runs in the right order when you use print debugging to see which instructions run in which order.
but.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
runCSVReader(e);
}
});
private void runCSVReader(ActionEvent evt) {
progress.setVisible(true);
label8.setForeground(Color.YELLOW);
label8.setText("Processing...");
correctInput();
String accTypes = tf5.getText() + "\\" + tf6.getText() + ".csv";
String inputFile = tf.getText() + "\\" + tf4.getText() + ".csv";
String outputFile = tf7.getText() + "\\" + tf2.getText();
System.out.println("acctypes " + accTypes+"\ninput " + inputFile + "\noutput " + outputFile);
try {
csvreader c = new csvreader();
c.setAccTypesFile(accTypes);
c.setInputFile(inputFile);
c.setOutputFile(outputFile);
c.run();
// progress.setVisible(false);
label8.setForeground(Color.GREEN);
label8.setText("Complete");
//pb.end();
}
It's just weird as it almost seems like the code runs in the order
c.run();
progress.setVisible(true);
label8.setForeground(Color.YELLOW);
label8.setText("Processing...");
// progress.setVisible(false);
label8.setForeground(Color.GREEN);
label8.setText("Complete");
as the text changes straight to the green completion message (with only the yellow message showing for a very short time) and (when uncommented) the setvisible go straight to false.
Any idea on why this might be happening? As far as I can tell there aren't any conflicting calls within the called methods that should affect this.
Is it the case that because it's a single-threaded program the progress bar won't show until the main thread is free from the run() command, and if so, why is it that the text also appears to not run when first called?
I want to draw a moving cursor (in green) in my 2D plan view (in red) . I use a joystick to command it.
To access to the red panel I have to get components of components from the controller following this scheme :
JPanel => JScrollPane => JViewPort => PlanComponent (extends JComponent)
My cursor coordinates are continuously updated by reading a socket.
When the coordinates are changed, it calls the drawCross fonction.
My cursor is perfectly moved by the joystick but the red area blinks and the cursor blinks over more.
Coloured program screenshot
public ThreadGestionObjetImu(Home home, HomeController homeController) {
_sweetHome3dHomeControllerVar = homeController;
_jComponentLayer1 = (MultipleLevelsPlanPanel) _sweetHome3dHomeControllerVar.getPlanController().getView();
_jComponentLayer2 = (JPanel) _jComponentLayer1.getComponent(1);
_jComponentLayer3 = (JScrollPane) _jComponentLayer2.getComponent(0);
_jComponentLayer4 = (JViewport) _jComponentLayer3.getComponent(0);
_planComponent = (PlanComponent) _jComponentLayer4.getComponent(0);
}
public void update(Observable o, Object arg) {
//parsing socket signal
switch(XImuPlugin.state){
case PLAN:
drawCross();
break;
}
}
public void drawCross() {
_planComponent.getGraphics().drawLine(_crossPositionX + _intImuValueX, _crossPositionY + 25 + _intImuValueY, _crossPositionX + 50 + _intImuValueX, _crossPositionY + 25 + _intImuValueY);
_planComponent.getGraphics().drawLine(_crossPositionX + 25 + _intImuValueX, _crossPositionY + _intImuValueY, _crossPositionX + 25 + _intImuValueX, _crossPositionY + 50 + _intImuValueY);
if (_intImuValueX > 1 || _intImuValueX < -1 || _intImuValueY > 1 || _intImuValueY < -1) {
_planComponent.update(_planComponent.getGraphics());
// I tried update, repaint, updateUI and all the possible functions
}
}
EDIT:
I forgot to precise that I was stuck in only using the sweetHome3D Api because I'm creating a plug-in, I can't modify the original code.
Problem solved by using _planComponent.add(MyComponent);
I created a JComponent with an override of paintComponent.
This is a know problem, if you draw in a component already in the UI the result is this blinking (the component drawing his background color and then drawing the image).
To avoid that, you can use a "double buffer", drawing the new image in a hide image and then, when it is ready replace directly in your UI.
A nice explanation can be found in oracle doc page
And an example here in stackoverflow: double buffering in java SWING
i have a button in java that calls a function when clicked and that function works just fine but the for loop won't refresh the text area. Instead at the end of the function (after 10s) it only shows i = 10 in the text area. I just simply want the text area to refresh and show i at every second and replace the i. I do not want to show them all at once, just replace them;
int i;
for (i = 0; i<4; i++)
{
try
{
input.setText("i = " + i);
Thread.sleep(1000); // delay of 1.000 seconds
}
catch(InterruptedException e)
{
}
}
Assuming you're using Swing, you could attempt using append instead, since I know that works with adding to the textarea:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
input.append("i = " + i + "\n");
}
});
As Maroun suggested, use Timer after this to pace your appending.
This question refers to andengine GL-ES1.
I am having trouble making a wallpaper activity that refreshes when your return to it, or when the user performs actions in the game.
My game has two activities. In one, you can edit and arrange the background elements in a room. In the other you play the game, and it uses the same background with the elements you arranged in the first activity.
There is also a live wallpaper in which your room is the background and characters move around in front of it.
I am making updtaes in onResume() in the wallpaper.
first I detach all the backgroudn sprites i used before.
Then I attach new sprites in the updated positions.
What happens is: some of the sprites don't show up.
Here is the method: Can you see anything I'm doing wrong?
private void loadBackgroundDecorations() {
//Add new decorations
Log.d(TAG, "loadBackgoundDecorations");
mEngine.runOnUpdateThread(new Runnable() {
#Override
public void run() {
// Remove Old Decorations
Log.d(TAG, "loadBackgoundDecorations: decorationList.size() =" + decorationList.size());
while(decorationList.size() > 0){
Sprite d = decorationList.remove(0);
scene.detachChild(d);
Log.d(TAG, "loadBackgoundDecorations: detachChild");
}
decorationList.clear();
//Add new decorations
ArrayList<Integer> decorations = app.getBackgroundManager().getDecorations();
Log.d(TAG, "loadBackgoundDecorations: decorations.size()" +decorations.size());
for (int i = 0; i < decorations.size(); i+=3) {
Log.d(TAG, "Decoration Values: texture-"+decorations.get(i)+", x-"+decorations.get(1+i)+", y-"+decorations.get(2+i));
Sprite draggable = new Sprite(decorations.get(1+i),decorations.get(2+i),mGameTextureRegionLibrary.get(decorations.get(i)));
draggable.setIgnoreUpdate(true);
scene.attachChild(draggable,0);
decorationList.add(draggable);
Log.d(TAG, "loadBackgoundDecorations: attachChild"+ i);
}
}
});
}
#Override protected void onResume() {
super.onResume();
Log.d(TAG, "onResume");
BitmapTextureAtlasTextureRegionFactory.createFromAsset(mTexture, this, app.getAquariumBackground(), 0, 0);
addBubbles();
loadBackgroundDecorations();
addCharacters()
}
============ UPDATE =================
As some people have suggested below, I tried adding all the scene setup functions into the runnable. This has no effect. What has worked for me is to set the "wrong" decorations visible property to "false". But I am worried that this will eventually cause a memory leak as more and more duplicates of the sprites are hidden on the wallpaper.
The problem only exists when I call "detachChild". For some reason that seems to prevent "attachChild" from firing correcly. Anybody have ideas for what could be causing this?
Can anyone else create an activity that adds and removes sprites in the onResume function?
I am fairly certain that the error has to do with your onResume method. The order you have your methods in is
addBubbles();
loadBackgroundDecorations();
addCharacters()
but your loadBackgroundDecorations uses a runnable so there is no guarantee that the method will run in between.
My Explanation:
From what I understand both addCharacter and addBubbles will be running on the UIthread whereas the loadBackgroundDecorations method will run on the update thread. The two threads will go through the methods at different times and that is where you are seeing some inconsistencies.
To Fix:
Put addBubbles and addCharacters in the same runnable in the order that you want and it should work as expected.
Yes, this is homework. Yes, I am completely stuck.
Here is the gist. I have created a JFrame. There are 3 panels (top, middle, bottom). In the bottom panel are 3 buttons called: Red, Green, and Blue. In the top Panel are 3 text fields that give us the number of times we have clicked the respective button. The max we are allowed is 10 for each button. In the middle Panel is an 8 x 8 grid of Jbuttons numbered from 0 to 63. So far, so good.
Every time we click a button, a thread starts. No thread ever dies When a thread starts, a number from 0 to 63 is randomly chosen. The JButton corresponding to that number is painted the color that was clicked on. So if the red button was clicked, we should see a box with a white background turn red. But then the color of that JButton starts to fade until it becomes white. The process should take about 8 seconds.
Threads that you create should not have access to any Swing components. Rather, one has to maintain a data structure and update by threads according to their cycle of execution. On the other hand, periodically invoke repaint() methods from main thread to invite Swing Event Dispatcher thread to eventually visit the content of the data structure and display the GUI components accordingly.
........ I have gotten all the objects created and displayed. You can't click more than 10 times on a button. Here is where I am:
I have two arrays: one is an array of strings with size 64. They represent the buttons. I also have an array of ints. This is so that I know the order by which the threads were created. I have created the threads as a button is clicked, and I have started them. Here is my run method for the threads:
public void run() {
Random num = new Random(new Date().getTime());
while (true) {
Thread j = Thread.currentThread();
int randInt = num.nextInt(64);
synchronized (lock) {
if ((array[randInt].compareTo("red") == 0
|| array[randInt].compareTo("blue")
== 0 || array[randInt].compareTo("green") == 0))
{
randInt = num.nextInt(64);
}
for (int k = 0; k < 10; k++) {
if (threadarray[k] == -1) {
threadarray[k] = randInt;
break;
}
}
}
}
}
Even though we haven't covered it, I have tried to use a Timer object that immediately goes off right outside of the lock section. This takes me to the actionPerformed method. I have added all the appropriate registration.
public void actionPerformed(ActionEvent arg0) {
for (int i = 0; i < threadarray.length; i++) {
int num = threadarray[i];
if (num != -1) {
System.out.println(num);
String s = array[num];
System.out.println(s + "is ");
if (s.compareTo("red") == 0) {
button[num].setOpaque(true);
button[num].setBackground(Color.red);
while (button[num].getBackground() != Color.white) {
System.out.println("not white yet");
int g = button[num].getBackground().getGreen();
int b = button[num].getBackground().getBlue();
if (255 - (g + 1) >= 0) {
Color c = new Color(255, g + 1, b + 1, 1);
button[num].setOpaque(true);
button[num].setBackground(c);
System.out.println(c + " " + " c is");
} else {
button[num].setBackground(Color.white);
}
}
}
System.out.println(i + " i is " + button[num].getBackground()); //just some debugging info
threadarray[i] = -1; //clear the thread array
array[num] = "0"; //clear the string array
}
}
}
The actionPerformed method is handled by the Event Dispatch Thread. (Note the code immediately above is for the red threads only. The idea is to fade the color by inclemently increasing the green and blue colors till it becomes white.
Problems: no button ever changes color when I click the red button on bottom (yes, appropriate registration has been done.) I also have no idea how to control the timing with a multitude of threads going. Am I even going down the right road here?
Without giving away too much, this example illustrates a way to deal with color and buttons that ignore setBackground(). Examples here and here demonstrate how to fade the color. As both rely on a javax.swing.Timer thread, neither is a solution, but the techniques may prove useful.