How to achieve effect of shrinking picture? - animation

I'd like to hide a picture which is on JavaFX application's stage. I want it disappear by shrinking.
Let's says there are some:
#FXML
private ImageView iv;
private Image img = new Image(...);
real img size is 100x100 pixels
then
iv.setImage(img);
iv.setFitWidth(50);
next I made method like that:
private Timeline shrink(ImageView iv)
{
final Timeline animation = new Timeline();
animation.getKeyFrames().addAll(
new KeyFrame(Duration.ZERO,
new KeyValue(iv.fitWidthProperty(), 50)
),
new KeyFrame(Duration.millis(400),
new KeyValue(iv.fitWidthProperty(), 0)
)
);
animation.setCycleCount(1);
animation.play();
}
so after that, the picture is shrinking, but it doesn't stay with 0 width, even worse, it appears again in its original size: 100.
what should I do to stay it shrinked ? I don't want to hide it by setVisibile cause I need that extra space later to fill it with some text.

ok, my fault...
0 is for default, so that is why picture appears in its original size. It needs to be set to 0.01 for example and then maybe set the visibility to false. But i'm sure there is better and nicer way to do it.

Related

Solving Overlapping Images when zooming in Codenameone

I have an imageviewer with a couple images, When i zoom in the first image and wanna see the right side of the image. The folowing image is overlapping the inzooming image. This is very annoying. Is there a way how i can set the zoom in image on the front.
How can i set the zoomed image always on front.
See picture https://i.stack.imgur.com/5f5JZ.jpg
My imageviewer is in a container
Image red ;
red = EncodedImage.create("/HW_Delfzijl_Waddenzee_Oost.jpg");
Image blue = Image.createImage(500, 500, 0xff0000ff);
Image red2 = Image.createImage(500, 500, 0xffff0000);
Image List1[]= new Image [3];
List1[0] = red;
List1[1] = blue;
List1[2] = red2;
iv = new ImageViewer();
iv.setWidth(500);
iv.setHeight(500);
iv.setImageList(new DefaultListModel<>(List1));
Container1 = BoxLayout.encloseY( Kaarten.AuvHW, AdvSpr,iv,
Up,progressbar);
I was able to reproduce this with the following code:
Form hi = new Form("ImageViewer", BoxLayout.y());
Image red = Image.createImage(2000, 800, 0xffff0000);
Image blue = Image.createImage(2000, 500, 0xff0000ff);
ImageViewer viewer = new ImageViewer();
viewer.setImageList(new DefaultListModel<>(red, blue));
hi.add(BoxLayout.encloseY(viewer, new Label("Dummy")));
hi.show();
The problem only happens if I stand on the blue image (the second one) scale it up and then try to move. It doesn't happen when moving from the red image to the blue.
I believe this is due to this method in the ImagaViewer code. Since background isn't painted the old image isn't cleaned up. We need to add a condition that disables that while dragging. I think changing the code in that method to this will fix the problem but it's a bit risky and might trigger flickering:
protected void paintBackground(Graphics g) {
// disable background painting for performance when zooming
if(imageDrawWidth < getWidth() || imageDrawHeight < getHeight() || panPositionX != 0) {
super.paintBackground(g);
}
}
I would suggest filing an issue so we can consider the options here as this isn't trivial. One partial workaround is to use:
viewer.setImageInitialPosition(ImageViewer.IMAGE_FILL);
Which minimizes the impact of the issue.

Is it possible to save a generated image in Codename One?

My question is related to this previous question. What I want to achieve is to stack images (they have transparency), write a string on top, and save the photomontage / photocollage with full resolution.
#Override
protected void beforeMain(Form f) {
Image photoBase = fetchResourceFile().getImage("Voiture_4_3.jpg");
Image watermark = fetchResourceFile().getImage("Watermark.png");
f.setLayout(new LayeredLayout());
final Label drawing = new Label();
f.addComponent(drawing);
// Image mutable dans laquelle on va dessiner (fond blanc)
Image mutableImage = Image.createImage(photoBase.getWidth(), photoBase.getHeight());
drawing.getUnselectedStyle().setBgImage(mutableImage);
drawing.getUnselectedStyle().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FIT);
// Paint all the stuff
paints(mutableImage.getGraphics(), photoBase, watermark, photoBase.getWidth(), photoBase.getHeight());
// Save the collage
Image screenshot = Image.createImage(photoBase.getWidth(), photoBase.getHeight());
f.revalidate();
f.setVisible(true);
drawing.paintComponent(screenshot.getGraphics(), true);
String imageFile = FileSystemStorage.getInstance().getAppHomePath() + "screenshot.png";
try(OutputStream os = FileSystemStorage.getInstance().openOutputStream(imageFile)) {
ImageIO.getImageIO().save(screenshot, os, ImageIO.FORMAT_PNG, 1);
} catch(IOException err) {
err.printStackTrace();
}
}
public void paints(Graphics g, Image background, Image watermark, int width, int height) {
g.drawImage(background, 0, 0);
g.drawImage(watermark, 0, 0);
g.setColor(0xFF0000);
// Upper left corner
g.fillRect(0, 0, 10, 10);
// Lower right corner
g.setColor(0x00FF00);
g.fillRect(width - 10, height - 10, 10, 10);
g.setColor(0xFF0000);
Font f = Font.createTrueTypeFont("Geometos", "Geometos.ttf").derive(220, Font.STYLE_BOLD);
g.setFont(f);
// Draw a string right below the M from Mercedes on the car windscreen (measured in Gimp)
g.drawString("HelloWorld",
(int) (848 ),
(int) (610)
);
}
This is the saved screenshot I get if I use the Iphone6 skin (the payload image is smaller than the original one and is centered). If I use the Xoom skin this is what I get (the payload image is still smaller than the original image but it has moved to the left).
So to sum it all up : why is the saved screenshot with Xoom skin different from the one I get with Iphone skin ? Is there anyway to directly save the graphics on which I paint in the paints method so that the saved image would have the original dimensions ?
Thanks a lot to anyone that could help me :-)!
Cheers,
You can save an image in Codename one using the ImageIO class. Notice that you can draw a container hierarchy into a mutable image using the paintComponent(Graphics) method.
You can do both approaches with draw image on mutable or via layouts. Personally I always prefer layouts as I like the abstraction but I wouldn't say the mutable image approach is right/wrong.
Notice that if you change/repaint a lot then mutable images are slower (this will not be noticeable for regular code or on the simulator) as they are forced to use the software renderer and can't use the GPU fully.
In the previous question it seems you placed the image with a "FIT" style which naturally drew it smaller than the containing container and then drew the image on top of it manually... This is problematic.
One solution is to draw everything manually but then you will need to do the "fit" aspect of drawing yourself. If you use layouts you should position everything based on the layouts including your drawing/text.

How to place my logo on my map without white fields?

I have a problem with the my picturebox.
I want to place it on my map which i got in my program.
That works when i put my img in a Picturebox and then BringToFront();
i wanted to add a picture with the problem, but i just started at StackOverflow and doesnt have enough reputation yet... :(
Anyway my img got displayed but with the white fields around it. The img I use doenst have these white stuff around it.
How can i make my Picturebox transparent so that the white fields get removed.
LogoBox.Location = new Point(size.Width - 340, size.Height - 100);
LogoBox.Image = Properties.Resources.Troepoet;
LogoBox.Size = new System.Drawing.Size(250, 40);
LogoBox.SizeMode = PictureBoxSizeMode.StretchImage;
LogoBox.BackColor = Color.Transparent;
I tried to do it with only drawing a bitmap aswell but then i cant see any possibility to place it on the map. The map is a 'dominant' control.
Any help/suggestions?
Thx.
You don't need to put a picturebox on the map to draw your logo.
The easy way is to override the Map OnPainOverlays() and draw whatever you want (Logo, Text, any shape) on the map or another way if you don't want to inherit the GmapControl and work with the GMapControl by drag & drop it over a form to handle the Paint() Event:
Private Sub GMapControl1_Paint(sender As Object, e As PaintEventArgs) Handles GMapControl1.Paint
Dim logo As Image = image.FromFile("C:\transparentLogo.png")
e.Graphics.DrawImage(logo, GMapControl1.Width - logo.Width - 5, 5, logo.Width, logo.Height)
End Sub
Make sure you make image transparent and save it as PNG format.

BlueJ - GUI JTextField, how to make the corners of it round like an oval?

How do I make the corners of a TextField round?
I'm using Javax.swing.*;
Here's my code for BlueJ:
inputLine = new JTextField();
inputLine.setBounds(480, 350, 150, 30);
contentPane.add(inputLine);
inputLine.setForeground(Color.black);
inputLine.setBackground(Color.white);
inputLine.setBorder(BorderFactory.createLineBorder(Color.black));
inputLine.setFont(new Font("Tahoma", Font.BOLD, 13));
inputLine.setHorizontalAlignment(JTextField.CENTER);
inputLine.setEditable(true);
contentPane.add(inputLine);
inputLine.addActionListener(this);
inputLine.setText("ID Number");
what you can do, is first create a Jframe window.
If you want only a text Field, make the dimensions of the j Frame a bit bigger than the preferred text Field size.
Then, set the layout of the jFrame to absolute.
Create a Jlabel that covers the whole screen Jframe.
Create the text Field only after this step.
Then create the text Field at the preferred location in the j Frame.
Design a graphic / picture for the background and set the icon of the background jLabel to the graphic you have designed.
The graphic you have designed must have a rounded rectangular picture in it and the text Field must be exactly positioned on top of that.
Once that is done set the opacity of the Text Field to 0.0. This should work very well...
JFrame frame = new JFrame("FrameDemo");
jframe.setPreferredSize(new Dimension(x, y));
[please add the other methods to create a jframe window...these are only the basic commands]
pane.setLayout(null);//makes it an absolute layout so that it does not reshape itself
frame.setVisible(true);
after doing this, design your graphics.
then:
import it into the current working directory, where this program has been written.
then:
create a jLabel inside the jFrame.
JLabel label1 = new JLabel("JLabel Set Icon Example.");
set its icon to the graphic you have designed.
label1.setIcon(new ImageIcon("full path of the image _ with the proper file extension"));
then
textField = new JTextField(desired value);//please add the desired value into the brackets
//set its location and all the other thing that are required
set the location of the textField exactly over the the rounded rectangle in the graphic.
then:
textField.isOpaque("false");
jTextField1.setBorder(null);//this should work
and there you go...the user will think that the textField is a rounded rectangle but actually it is like a rectangle which has a transparent background...
let me know if there are any problems.
thanks.

Starling TouchEvent on Sprite

I have some images/sprites/buttons (i tried them all :)) scrolling/moving on the stage. The user has to tap them to remove them.
The problem is that the touchevent does not match the position of the image.
The faster the touchable sprites move, the further the distance between the touch and the actual image. i.e.:
a image is moving across the screen with 20px/frame:
Touching the image triggers nothing, touching 20 before it triggers a touch on the image.
when image is not moving, this doesn't happen. It seems that the image is already moved internally, but not yet drawn to the screen, but thats just a wild guess. The example below uses a button, but the same goes for an image. I"ll provide a short example of the code, but i guess its pretty straightforward what i'm trying to do.
private var _image:Button;
protected function init():void {
//create pickup image
_image = new Button(assets.getTexture("button"));
_image.scaleWhenDown = 1;
_image.addEventListener(Event.TRIGGERED, onClick_image);
addChild(_image);
//listen to touch event (not used, but example for touch on image instead of button
//touchable = true;
//addEventListener(TouchEvent.TOUCH, onTouch_image);
}
private function onEnter_frame(e:Event):void {
_image.x -= 20;
}

Resources