LWUIT Painter : How to make an image the background? - java

I am trying to use Painter to make a certain jpg become my background.
mapScreen = new Form("Map");
try
{
Image image = Image.createImage("/res/try.jpg");
map = new Map(image);
mapScreen.addComponent(map);
} catch (Exception e)
{
System.out.print("Error\n\n"+e.getMessage());
mapScreen.addComponent(new Label(e.getMessage()));
}
And for the map class,
public Map(Image image)
{
this.mapImage = image;
painter = new Painter()
{
public void paint(Graphics g, Rectangle clippingRect)
{
g.clipRect(0, 0, getWidth(), getHeight());
g.drawImage(mapImage, getX(), getY());
}
};
}
public void initComponent()
{
setX(0);
setY(0);
getSelectedStyle().setBgTransparency(0);
getSelectedStyle().setBgPainter(painter);
getUnselectedStyle().setBgTransparency(0);
getUnselectedStyle().setBgPainter(painter);
}
The problem with this is that the image doesn't show up at all and when I try to debug, It doesn't even enter the paint(Graphics g, Rectangle clippingRect)...
The code
try
{
Image image = Image.createImage("/res/try.jpg");
map = new Map(image);
mapScreen.addComponent(map);
}
is successful.
Can anyone tell me how to do it properly?
And also, if anyone know how to do panning on an image larger than the size of the screen, Can you help me with that also? Thanks.

Use setBgTransparency to 255 and don't call the clipRect method.
You can look at the bg painter code within Component.java which is pretty flexible.

Related

PaintComponent not rendering image?

I'm trying to display a small 16x16 pixel image to a JPanel. I've written a simple function that creates and returns a BufferedImage object that I'm then trying to pass to paintComponent, however, nothing is rendering when I launch the program (with no errors being printed to the console). Help?
Thanks!
public BufferedImage loadImage(String filePath) {
BufferedImage img = null;
try {
img = ImageIO.read(new File(filePath));
} catch (IOException e) {
}
return img;
}
public void paintComponent(Graphics g) {
g.drawImage(loadImage("/resources/tile.png"), 0, 0, this);
}
}
we can also use the below source code inside paintComponent to draw an image swing.
public void paintComponent(Graphics g) {
Toolkit t=Toolkit.getDefaultToolkit();
Image image=t.getImage(<path of image>);
g.drawImage(image, 0,0,this);
}
where,
img - the specified image to be drawn. This method does nothing if img is null.
x - the x coordinate.
y - the y coordinate.
observer - object to be notified as more of the image is converted.
in case to load an bufferImage, you can also check the below link contains good amount of details.
https://www.baeldung.com/java-images
Thanks

How to rotate a bitmap with AffineTransform

I'm trying to create a simple program that displays a bitmap zombie picture and then rotates it around using AffineTransform and Thread. I followed the example I had to accomplish this, but whenever I run the program the zombie bitmap just rotates once and stops. Also, for some reason when I painted the zombie bitmap, the image is partially off the screen along the y-axis.
So my questions are: why is the bitmap not rotating and why is the bitmap off the screen.
Code is as follows:
import java.awt.*;// Graphics class
import java.awt.geom.*;
import java.net.*;//URL navigation
import javax.swing.*;//JFrame
import java.util.*;//Toolkit
public class BitMapZombies2 extends JFrame implements Runnable
{
private Image zombieOneRight;
Thread zombieRun;
public static void main (String[] args)
{
new BitMapZombies2();
}
public BitMapZombies2()
{
super("Bit Map Zombies..RUN FOR YOUR LIFE!!!");
setSize(800,600);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Toolkit Zkit = Toolkit.getDefaultToolkit();
zombieOneLeft = Zkit.getImage(getURL("_images/_production_images/zombie_1_left_75h.png"));
zombieOneRight = Zkit.getImage(getURL("_images/_production_images/zombie_1_right_75h.png"));
zombieRun = new Thread(this);
zombieRun.start();
}
AffineTransform zombieIdentity = new AffineTransform();
private URL getURL(String filename)
{
URL url = null;
try
{
url = this.getClass().getResource(filename);
}
catch (Exception e) {}
return url;
}
public void paint(Graphics z)
{
Graphics2D z2d = (Graphics2D) z;
AffineTransform ZombiePowered = new AffineTransform();
z2d.setColor(Color.BLACK);
z2d.fillRect(0,0, 800, 600);
ZombiePowered.setTransform(zombieIdentity);
ZombiePowered.rotate(2,37.5,37.5);
z2d.drawImage(zombieOneRight,ZombiePowered,this);
}
public void run()
{
Thread zT = Thread.currentThread();
while (zT == zombieRun)
{
try
{
Thread.sleep(500);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
repaint();
}
}
}
Appreciate any help I can get on this.
Commenting your code:
AffineTransform ZombiePowered = new AffineTransform();//Create an Id. transform
ZombiePowered.setTransform(zombieIdentity);//Set it as a copy of an Id. transform
ZombiePowered.rotate(2, 37.5, 37.5);//Concatenate the rotation with the Id. transform
z2d.drawImage(zombieOneRight, ZombiePowered, this);//Apply the rotation
So your always rotating 2rads your image. If you do this assignment at the end of the paint method:
zombieIdentity = ZombiePowered;
the next time you paint the image it will be rotate 2rads more.
About the issues with the position, take a look at rotate javadoc:
Concatenates this transform with a transform that rotates coordinates
around an anchor point. This operation is equivalent to translating
the coordinates so that the anchor point is at the origin (S1), then
rotating them about the new origin (S2), and finally translating so
that the intermediate origin is restored to the coordinates of the
original anchor point (S3).
This operation is equivalent to the following sequence of calls:
translate(anchorx, anchory); // S3: final translation
rotate(theta); // S2: rotate around anchor
translate(-anchorx, -anchory); // S1: translate anchor to origin
Hope it helps.
Once you've created your transformation, you need to apply it to the graphics context...
public void paint(Graphics z)
{
//...
z2d.setTransform(ZombiePowered);
//...
}
Once you apply a transformation, it will effect everything painted to the Graphics context after it so you need to reset it or referse it. There's lots of ways to do this, but the simplest would be to create a copy of the Graphics context and simply dispose of it when you no longer need it...
public void paint(Graphics z)
{
Graphics2D z2d = (Graphics2D) z.create();
//...
z2d.dispose();
}
Also, this is just me, but I'd be creating a new instance of the AffineTransform, these things are to easy to completely screw up...

Java Draw a GIF

I'm trying to draw a GIF using the Java Graphics API, but I'm not able to successfully draw a GIF using my below code. Only the first image or thumbnail of the GIF is drawn but it doesn't play.
public void paintComponent(Graphics g){
super.paintComponent(g);
BufferedImage img = null;
try {
URL url = new URL("GIF URL");
img = ImageIO.read(url);
} catch (Exception e) {
}
g.drawImage(img, 5, 5, this);
}
Essentially I am creating graphics for a login screen and I want to draw a GIF that loops.
EDIT: Updated my code and changed the question a bit.
You can load a gif into a BufferedImage object.
Then we paint the buffered image onto your swing component
Also one must better override the paintComponent method
It's perfectly possible to do this, you just need to have a proper way to load the frames for the image. The code I use to do this, is as so:
private static Image load(final String url) {
try {
final Toolkit tk = Toolkit.getDefaultToolkit();
final URL path = new URL(url); // Any URL would work here
final Image img = tk.createImage(path);
tk.prepareImage(img, -1, -1, null);
return img;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
This uses the Toolkit to load a gif image, since ImageIO can't properly load gifs at this time, if I recall correctly.
From there, it's so simple as doing the following in a (for example) JPanel:
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g); // clear up render
//...
g.drawImage(IMAGE, x, y, this); // ImageObserver necessary here to update
//...
}
Example:
import javax.swing.*;
import java.awt.*;
import java.net.URL;
public class GifAnimation {
public GifAnimation(){
JFrame frame = new JFrame("Gif Animation");
GifPanel panel = new GifPanel(load("http://www.thisiscolossal.com/wp-content/uploads/2013/01/3.gif"));
frame.add(panel);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
private static Image load(final String url) {
try {
final Toolkit tk = Toolkit.getDefaultToolkit();
final Image img = tk.createImage(new URL(url));
tk.prepareImage(img, -1, -1, null);
return img;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args){
EventQueue.invokeLater(new Runnable() {
public void run() {
new GifAnimation();
}
}
}
public class GifPanel extends JPanel {
private final Image image;
public GifPanel(Image image){
this.image = image;
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(image, 10, 10, this);
}
#Override
public Dimension getPreferredSize(){
return new Dimension(660, 660);
}
}
}
GIF animation is not directly possible by using paint method of JPanel.
I would suggest inserting a JEditorPane in the panel whenever you want to display it and show GIF in it using HTML.
Refer showing images on jeditorpane (java swing)
Although some might criticize it as a crude way, the animation works perfectly.
Hope this helps.

How to tell when Graphics.drawImage() has actually completed

This is my first time asking a question on here, and I'm hoping I get an answer or an idea that will help me.
I am drawing a large image and scaling it down with drawImage(). I then immediately draw another image with drawImage() that I expect to be drawn on top of the previous one (second). The problem is that drawImage returns immediately, even if it takes ~50 ms to scale and render the first image. Most of the time the second image ends up underneath the first one because it's painted first while the big first one is being processed. Basically is there anyway to force drawImage() to block until it's done, or to somehow check when it has completed?
I'm aware of the ImageObserver parameter, which works fine when downloading an image from the Internet or something, but when using an already-loaded BufferedImage, it never fires ImageUpdate() just after scaling and drawing. Basically since the first image is already "loaded" it never contacts the ImageObserver, it just takes like ~50 ms in it's own thread to process, never notifying when it completes.
Does anyone know how to either force it to block or wait until it's completely done scaling and blitting an image? And obviously using Thread.sleep(xx) is a complete hack and not viable due to differences between computer speeds. All this rendering is happened on the Event thread inside the paint(Graphics g) method.
Thanks!
EDIT: The following is code I currently have to give you an idea of the issue:
public void paint(Graphics window)
{
window.setColor(Color.WHITE);
window.fillRect(0, 0, Settings.width * Settings.aaFactor, Settings.height * Settings.aaFactor);
Graphics2D window2D = (Graphics2D) window;
window2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
window2D.drawImage(this.image, 0, 0, Settings.width, Settings.height, null);
try
{
Thread.sleep(50);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
window2D.drawImage(this.image2, 0, 0, null);
repaint();
}
EDIT 2: To better explain the problem I'm talking about, I made some sample code that does better what I'm trying to explain. Run it and you will see it flickering where sometimes the first image is on bottom (like it's supposed to be), but most of the time it will be one top (second), which is wrong. Just change the File paths to a small image and a large image.
public class Main extends Applet implements ImageObserver
{
private BufferedImage imageA;
private BufferedImage imageB;
#Override
public void init()
{
try
{
this.imageA = ImageIO.read(new File("C:\\LargeImage.jpg"));
this.imageB = ImageIO.read(new File("C:\\SmallImage.jpg"));
}
catch (IOException e)
{
e.printStackTrace();
}
}
#Override
public void update(Graphics g)
{
paint(g);
}
#Override
public void paint(Graphics g)
{
Graphics2D w = (Graphics2D) g;
w.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
w.drawImage(this.imageA, 0, 0, 50, 50, this);// This takes a while to do (scaling down and drawing)...
w.drawImage(this.imageB, 10, 10, null);// While this is drawn quickly, before A is done.
repaint();
}
#Override
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height)
{
System.out.println("ImageObserver fired, done drawing image. NEVER CALLED!");
return false;
}
}
The last argument to drawImage (where you pass null) is an ImageObserver. If you provide your own implementation of that interface (see JavaDoc), you will be informed when the image has been actually drawn.
It is impossible to know when Swing will actually render the contents of a Graphics object to the screen. What is know is it won't happen until AFTER the paint methods return (as the Graphics object hasn't been finalised for rendering until it does).
What you should do is let the Component you are painting to make the decision as to when something needs to updated, this is the way it was designed...(Component implements ImageObserver)
The below example continuously re-scales the master background image as the frame is resized
public class TestPaint03 {
public static void main(String[] args) {
new TestPaint03();
}
public TestPaint03() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new PaintPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PaintPane extends JPanel {
private BufferedImage background;
private BufferedImage foreground;
private Image scaled;
public PaintPane() {
try {
background = ImageIO.read(new File("/path/to/background/image));
foreground = ImageIO.read(new File("path/to/foreground/image"));
} catch (Exception e) {
}
}
#Override
public void invalidate() {
scaled = null;
super.invalidate();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
if (scaled == null) {
int size = Math.min(getWidth(), getHeight());
scaled = background.getScaledInstance(-1, size, Image.SCALE_SMOOTH);
}
int x = (getWidth() - scaled.getWidth(this)) / 2;
int y = (getHeight() - scaled.getHeight(this)) / 2;
g.drawImage(scaled, x, y, this);
x = (getWidth() - foreground.getWidth()) / 2;
y = (getHeight() - foreground.getHeight()) / 2;
g.drawImage(foreground, x, y, this);
}
}
}
}
While I'm sure you have your reasons, personally I would avoid Applet in favor of JApplet and in fact, I would personally avoid applets or together. I started my career coding applets, they are simply a pain, especially when all you're trying to do is test an idea.

How to set a background image to JSlider?

I have an applet. I set its image background. It works fine.
Now I want to set a background image to a JSlider.
How can I do that?
You will need to create a custom JSlider class and override the paintComponent method. Be sure to call setOpaque(false) on your slider object.
public class CustomSlider extends JSlider
{
private Image img = null;
public CustomSlider()
{
try
{
img = ImageIO.read(new File("background.jpg"));
}
catch (IOException e)
{
e.printStackTrace();
}
}
#Override
public void paintComponent(Graphics g)
{
// Draw the previously loaded image to Component
g.drawImage(img, 0, 0, null);
super.paintComponent(g);
}
}

Categories