Why use ImageIcon rather than Image? - java

In what instance would I want to use ImageIcon to represent a picture file rather than an Image object? I've been searching and I've seen people say that you would use an ImageIcon object when dealing with images that will be part of the GUI, but I still don't understand the implications of this. In other words, what is the actual difference between the two object types and what situations are they each suited for?

Image is an object that represents a bitmap: an array of pixels of different colors.
Icon is an object that can draw a rectangular piece of graphics. Since it is an interface (and a simple one too), you can imagine many different types of icons: drawing predefined vector graphics, generating images on the fly etc. Therefore it is a useful abstraction and is used by Swing components (buttons, labels).
ImageIcon is an object that IS an Icon, but HAS-A Image. That is - it draws graphics based on a specific image.
When you say "why should I be using an ImageIcon instead of Image" you miss the point: in fact you are using an Image either way.

An Image is an object representing the data model of a picture. An ImageIcon is a Swing component that draws an Image on the screen, and you have to provide it with the appropriate Image to draw (either by passing in an existing Image or by giving it enough information to find and load the image).
The relationship is similar to that between a String and a JTextField; one is the representation of the data, and the other is the graphical component that draws it on the screen.

The implementation is to not hold up the Swing thread.
Images that are created from a URL, filename or byte array are preloaded using MediaTracker to monitor the loaded state of the image.
Basically, then you can set an ImageIcon for a button without actually forcing it to be loaded beforehand.
This can be seen by having a very large icon and setting the Frame's icon to this image. Once set visible, it may take a few seconds to actually appear.

Related

Is there a function to find color of point in AWT/SWING

So, I've created this little maze building algorithm (trying to understand how Java AWT & Swing works).
Now, I've used the Graphics (paint method) to create the maze itself, meaning I didn't store it anywhere.
Now I wanted to know if there is a way to know if at given a specific point on the JFrame, is there a way to tell which color it is?
If so, how can I do it?
Let's say for example in my maze I want to see what color is on the PURPLE dot (seeing if it's a wall there basically).
Is there a way to do it, or do I have to do a work-around that?
Thanks.
There is no direct way to a Component's image buffer. But there are two indirect ways.
(Better) Create an Image (Either BufferedImage or Component.createImage) with the same height and width as your Component. You can then run myComponent.paint(myBuffer.getGraphics());. This will draw the component on the image, and from there you can get the pixel Color you are interested in
(Alternative) You can use java.awt.Robot to capture the screen in an Image. Use this image similar as described above

Serializing Canvas objects in Java

I am trying to serialize a Canvas instance (using the Serializable interface) on which I have painted some pixels like the following code suggests:
Canvas board = new Canvas();
Graphics g = board.getGraphics();
g.setColor(Color.BLACK);
g.drawString("txt", 10, 20);
g.dispose();
Then when I serialize board it doesn't save the pixels I've painted. I'm guessing this is because by using getGraphics() I am not saving those pixels to any instance, so I thought that perhaps I should instead paint from within the Canvas's paint() method. Would serializing the Canvas then save the modified pixels too? If not, what are my options to save/serialize a Canvas with the pixels I've modified? I am guessing I would have to serialize the Graphics object instead of the Canvas? I am new to Java graphics, any help will be greatly appreciated.
To be more clear, what I'm trying to do is have the pixels I've put on a Canvas instance saved to a file using serialization. Then later I need to reload this Canvas instance from the serialized file I saved earlier, so that when I use it on the screen I see the exact same pixels I modified just before I serialized the Canvas. I know how to serialize objects and all that. I am just unclear where all the pixels are stored.
Update1:
The way the user draws something on the screen is by left-clicking on the Canvas area. Then MouseListener calls the following method, passing along the Point object specifying the mouse xy:
private void drawAt(Point p)
{
Graphics g = board.getGraphics();
g.setColor(brushColor);
g.setFont(brushFont);
g.drawString(brushText, p.x, p.y);
g.dispose();
}
Don't serialize Canvas or any other GUI components as you'd be serializing the "View" portion of your program, a risky thing to do (high risk for serialization exceptions due to attempting to serialize and unserialize unserializable sub components) and an inefficient thing to do -- serializing large amounts of data which are built automatically by the JVM and thus don't need serialization.
Instead you will want to serialize the "Model" portion of your data, that portion which holds the logical data of your program. So if your GUI is drawn using data held by an ArrayList, or a collection of ArrayLists, or whatever data it takes, then serialize that data. Then be sure to create your GUI so that can be built using the serialized data.
Or if you need to store an image, then store an image, probably best as a loss-less png file.
Also, I suggest that you draw into a BufferedImage, that you then display that BufferedImage within the paintComponent method override of a JPanel, and that you then save and restore the image. For more on how to draw and save, please have a look at these links. The first two contain my code, the third is that of MadProgrammer's:
Save image from JPanel after draw,
Convert a Graphics2D to an Image or BufferedImage and
Paint BufferedImage on JFrame and write to File.

Image on Canvas vs Label

What are the differences between using a Canvas control or a Label control for drawing an image?
Both controls seem to have similar capabilities in terms of drawing images onto their displayable area, and can both use PaintListeners to further customize the act. I have always assumed that Canvases are more suited for the purpose than labels simply due to their name, but I cannot determine the actual practical differences. In what scenarios would you use one over the other for loading an image file and painting the image onto the control?
The Label inherits its drawing capabilities from Control, as well as many of the features in Canvas. But Canvas was built with extra controls for images, like dynamic drawing, buffering and partial update.
Summing up, it is ok to use labels for static small images, but when it comes to heavy-duty use, a canvas is more appropriate.

How can I draw individual pixels in Java without using graphics classes?

I don't want to use the graphics/drawing libraries. The only solution I can think of is creating thousands of 1x1 jButtons (which would obviously be impractical). Is there a better solution?
The only way to draw "without using graphics functions" is populate a raw Raster with the byte values appropriate to the color map for the actual image. Then you can use a graphics primitive to render the resulting image in to a window.
Take a look BufferedImage, and work your way back from there.
You could do this by creating a own component by extending for example JPanel and overriding the paintComponent method.
Why don't you want to use the graphics functions provided by Java?
How do you expect displaying the picture onto the screen without using a graphics library? Are you going to write a native method to display pixels onto the computer screen?

Combine multiple images into a single image for later painting, with alpha blending

I have a graphics system for Java which allows objects to be "wallpapered" by specifying multiple images, which can have (relatively) complex alignment and resizing options applied.
In order to perform adequately (esp. on very low powered devices), I do the image painting to an internal image when the wallpaper is first painted, and then copy that composite image to the target graphics context to get it onto the screen. The composite is then recreated only if the object is resized so the only work for subsequent repaints is to copy the clipped region from the composite to the target graphics context.
The solution works really well, except that when I have PNG images with alpha-channel transparency the alpha channel is lost when painting the composite - that is the composite has all pixels completely opaque. So the subsequent copy to the on-screen graphics context fails to allow what's behind the wallpapered object show through.
I did manage to use an RGBImageFilter to filter out completely transparent pixels, but I can't see a solution with that to making blended transparency work.
Does anyone know of a way I can paint the images with the alpha-channel intact, and combined if two pixels with alpha values overlap?
What type of Image do you use for the composite image?
You should use a BufferedImage and set it's type to TYPE_INT_ARGB which allows translucency.

Categories