Codename One - Hide Animation for single Element removes everything - java

I was following a basic tutorial on how to start animating things in a mobile app created with Codename One.
https://www.codenameone.com/manual/animations.html
While I get the concept of using layout animation and unlayout animation on containers to move things into place and out of place, this does not seem to work properly for the unlayout animation.
The thought of below code is to have a list of elements that are either shown or hidden based on some search results (the example has just plain labels).
Animating things in place works well when used alone, as shown in the tutorial.
But why does everything vanish completely when calling "animateUnlayoutAndWait()"?
Form hi = new Form("Layout Animations", new BoxLayout(BoxLayout.Y_AXIS));
Button button = new Button("Hide");
hi.add(button);
for (int iter = 0; iter < 10; iter++) {
Label b = new Label("Label " + iter);
b.setWidth(button.getWidth());
b.setHeight(button.getHeight());
b.setY(-button.getHeight());
hi.add(b);
}
button.addActionListener((e) -> {
// hide every second label on click
if (button.getText().equals("Hide")) {
button.setText("Show");
for (int iter = 1; iter < hi.getContentPane().getComponentCount(); iter += 2) {
Component c = hi.getContentPane().getComponentAt(iter);
c.setHidden(false);
}
hi.getContentPane().animateUnlayoutAndWait(500, 0);
}
// show stuff again
else {
button.setText("Hide");
for (int iter = 1; iter < hi.getContentPane().getComponentCount(); iter += 2) {
Component c = hi.getContentPane().getComponentAt(iter);
c.setHidden(true);
}
hi.getContentPane().animateLayoutAndWait(500);
}
});
hi.show();
Thanks and best regards

I noticed that you mistakenly swapped setHidden() values, the if part should true while the else part should be false. Also, remove the AndWait from your animation.
Form hi = new Form("Layout Animations", new BoxLayout(BoxLayout.Y_AXIS));
Button button = new Button("Hide");
hi.add(button);
for (int iter = 0; iter < 10; iter++) {
Label b = new Label("Label " + iter);
b.setWidth(button.getWidth());
b.setHeight(button.getHeight());
b.setY(-button.getHeight());
hi.add(b);
}
button.addActionListener((e) -> {
// hide every second label on click
if (button.getText().equals("Hide")) {
button.setText("Show");
for (int iter = 1; iter < hi.getContentPane().getComponentCount(); iter += 2) {
Component c = hi.getContentPane().getComponentAt(iter);
c.setHidden(true); //should be true here
}
hi.getContentPane().animateUnlayout(500, 255, null); //remove AndWait
} // show stuff again
else {
button.setText("Hide");
for (int iter = 1; iter < hi.getContentPane().getComponentCount(); iter += 2) {
Component c = hi.getContentPane().getComponentAt(iter);
c.setHidden(false); //should be false here
}
hi.getContentPane().animateLayout(500); //remove AndWait
}
});
hi.show();

Couple of notes:
- true and false is correct. haven't paid attention to it, as the result was that everything vanished in both cases anyways.
- whether I wait for it to finish or not does not matter in this case, as I call it only case and not repeatedly on several elements.
- one more thing you changed is setting the target opacity of the unlayout animation from 0 to 255. This way, all elements remain visible.
This brings me to two questions:
1. why is unlayout animation applied to all elements in my form, not only to those whose properties were changed (position values)? When using
animateUnlayoutAndWait(500, 0);
everything will vanish, even the button.
with the current solution from diamond, when calling unlayout animation, the individual elements that should disappear vanish instantly, the only thing element being animation is label 8, and it is animation INTO place, rather than out of place.

Related

Rapidclipse - multiple windows in one screen using a filter to select

Is there a possibilty to create a certain number of windows in one screen. Each window has the same layout but different content. I would like to include a filter so that I can choose which window I would like to see. Right now I have a table with four entries. For each entry one window is generated, but that looks quite messy.
final int i = this.table.size();
for (int h = 1; h <= i; h++) {
final Window win = new Window("Window" + h, new SecondView());
this.getParent().getUI().addWindow(win);
}
Edit:
The Starting point is as described. I have a table with content from a database. In this table i can select multiple rows. For each row a pre-defined window should open. In this window i have textFields, that should contain the values of the matching attributes from the selected row. In order to get a better structure i want to choose which window should be visbile.
final int i = this.table.size();
List<Window> windowList= new LinkedList<>();
for (int h = 1; h <= i; h++) {
Window win = new Window("Window" + h, new SecondView());
windowList.add(win);
}
Then later on, you can itterate the list and do addWindow(...) or removeWindow(...)with the correct window instance
Here is what you need to do:
1) fetch the selected items from the table. Not the amount of selected items, but the actual items - instances of Person if your table is of type Person.
2) iterate over these selected items.
2.a) For each item, create a new Window and pass that item into the constructor of your SecondView, so each SecondView can show values of that item or bind inputs to this bean.
2.b) Add that window to the UI
Since I am not very accustomed to the Table class I use a newer Grid instead in my example. I'm sure the table has some API to get the selected rows - use that instead.
Button openDetailWindowsButton = new Button("Open Details", click -> {
Set<Person> selectedItems = grid.getSelectedItems();
for (Person selectedItem : selectedItems) {
Window win = new Window(selectedItem.getName(), new SecondView(selectedItem));
this.getParent().getUI().addWindow(win);
}
});
Thank you for your help, but meanwhile i found another solution.
private void button_buttonClick(final Button.ClickEvent event) {
final int i = this.table.getSelectedItems().size() - 1;
for(int h = 0; h <= i; h++) {
final int personId = this.table.getSelectedItems().get(h).getBean().getId();
final Window win = new Window("Person", new SecondView(personId));
this.getUI().addWindow(win);
}
That's the button click event.
And here is the constructor for my SecondView
public SecondView(final int personId) {
super();
this.initUI();
final Person myPerson = new PersonDAO().find(personId);
this.fieldGroup.setItemDataSource(myPerson);
}
The one last problem that i have, is that for every selected person/row each window shows seperately. My intent was to only show one window where i can select between the different selected persons/rows.

Connect JProgress Bar to an array to show progress of the tool

I've created a tool where I paste some data in a text area and this data is being split per lines by (\n) in an array.
My tool works perfect, I just need to connect this progress of the array to the progress bar so the user may know what's going on.
so if the array will have 10 lines the progress bar shall start from one and count till it reaches ten when the tool moves to the next line.
so I mean when it starts working on the array in position 0, the progress bar shall show 1, and when the array moved to position 1, progress bar shall show 2 .......
Here is an example of my code:
// Run button (start the search)
final JButton btn = new JButton("Run");
btn.addActionListener(new ActionListener() {
#SuppressWarnings("resource")
public void actionPerformed(ActionEvent e) {
try {
String getTextArea;
getTextArea = textArea.getText();
// converting the input to an array
String[] arr = getTextArea.split("\\n");
// clearing the text
textArea_1.setText("");
//line = arr.length;
// looping for the input
// doing something.....
}
// end of for loop
} catch (Exception e2) {
JOptionPane.showMessageDialog(null, "Search was not completed due to bad connection, please try pressing run again or close the tool and reopen it");
}
}
});
// Creating the progress bar
JProgressBar progressBar = new JProgressBar();
progressBar.setStringPainted(true);
progressBar.setValue(0);
for(int z = 0; z <= line; z++) {
progressBar.setValue(z);
z = z + 1;
progressBar.repaint();
}
progressBar.setBounds(364, 11, 139, 22);
contentPane.add(progressBar);
Thank you for your help in advance
I've interpreted your question as how do I get the line number to be displayed instead of the percentage?
If that is the question, then you need to use the JProgressBar's setString(String s) method as well as setValue(int n)
For example:
// Set up of the JProgressBar
final int MIN = 0;
final int MAX = 100;
JProgressBar progressBar = new JProgressBar(MIN, MAX);
progressBar.setStringPainted(true); // show the text on the progress bar
progressBar.setString("Loop no. " + MIN); // initial display
// Code to update the JProgressBar
for (int i=MIN; i<=MAX; i++) {
progressBar.setValue(i);
progressBar.setString("Loop no. " + i);
}
Personally I prefer to use an implementation of BoundedRangeModel when working with progress bars. Swing provides DefaultBoundedRangeModel which is good for most tasks.
Remember to use concurrency correctly in your implementation, otherwise your interface will be unrespsonive if the task is long. SwingWorker can assist you with this https://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html

Android animation blink

The code is for making a text color change evenly every 200 ms. Why is the first version change uneven/flickering, and the second one evenly changes?
//first version
long lt = System.currentTimeMillis();
TextView tv = ...
for (int i = 1; i < 120; i++) {
final int cl = i % 2 == 0 ? 0xFFFF0000 : 0x00000000;
Message w = Message.obtain(handler, new Runnable() {
public void run() {
tv.setTextColor(cl);
tv.requestLayout();
}
});
handler.sendMessageDelayed(w,i * 200L - (System.currentTimeMillis()-lt));
}
//second version
Animation anim = new AlphaAnimation(0.0f, 1.0f);
anim.setDuration(200); //You can manage the time of the blink with this parameter
anim.setStartOffset(20);
anim.setRepeatMode(Animation.RESTART);
anim.setRepeatCount(Animation.INFINITE);
tv.startAnimation(anim);
I have had this problem before when creating/using animations. After you are done with your animation, simply call clearAnimation().
This will insure that it has fully stopped and should be nice and smooth, giving the user the experience you desire.
How to stop an animation (cancel() does not work)
Read more:
http://developer.android.com/reference/android/view/View.html
Regards,

Reorder items after mouse release

I am not sure what is wrong, so I will attempt to explain it, and you can test it in the following example:
The Project (3 MB): http://ryannaddy.com/downloads/dist.zip
Un-Zip and run the jar file
Open 2 image files within the application
On the right hand side is a list of all the open images, you can drag and drop the layers to eventually order z-order of the main picture.
If you drag the top layer below the bottom layer it gets moved back to the top (Should be moved below the bottom layer)
If you drag the top layer down a few pixels it will move the top layer below the bottom layer.
If you drag the bottom layer down it moves it above the top layer (Should be kept on the bottom)
In the end, I would like to drag those labels to any spot and there is where it will place the label.
Code block that gets executed after the mouse is released to organize the labels:
public void lblMouseReleased(MouseEvent evt){
if(dragging){
int componentCount = layers.getComponentCount() - 1;
LayerItem[] comps = new LayerItem[componentCount];
FocusTraversalPolicy focus = layers.getFocusTraversalPolicy();
Component comp = focus.getFirstComponent(layers);
for(int i = 0; i < componentCount; i++){
Component newComp = focus.getComponentAfter(layers, comp);
comp = newComp;
comps[i] = (LayerItem)newComp;
System.out.println(comps[i].layerID);
}
Layers.rebuild(layers, comps);
}
dragging = false;
}
Code for Layers.rebuild:
public static void rebuild(JPanel layers, Component[] list){
for(int i = 0; i < list.length; i++){
layers.remove(list[i]);
}
for(int i = 0; i < list.length; i++){
list[i].setBounds(0, i * 50 + 30, 198, 50);
layers.add(list[i]);
}
layers.revalidate();
layers.repaint();
}
This should be all the relevant code to the problem, let me know if you need more.
I got it! I it was because I wasn't getting all the items needed in the panel. The first item in my panel is a header with focus set to false, since it isn't apart of the grouping, so I was telling my code to only order items 1+ when it should have been 0+

Swing, Java and multithreading, and coloring buttons

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.

Categories