I'm using Java Swing to make a GUI.
I need to present to the user some information printed on images (which are generated at run time as BufferedImage objects).
What I am doing: I put a JPanel on my JFrame, and when the system calls the paint(Graphics g) method I draw the image on g -> (g.drawImage(buffImg,0,0,null)).
The thing I do not like is: When I resize the frame, the image remains the same, I only expand the field of view. I'd like instead to make the image "stretch" with the frame when I resize it.
Is there an efficient way of doing it? (I thought I could create a new resized image, the size of the frame, each time I refresh the graphics, but I'm updating the image several times per second, so it would be a really heavy task..)
Change:
g.drawImage(BuffImg,0,0,null):
To:
g.drawImage(BuffImg,0,0,getWidth(),getHeight(),this):
Related
As part of an application I'm writing, I resize and move a picture of a pallet in a JLabel. Because the JLabel is in a JLayeredPane, I'm not using a layout manager, and as a result, ever time I resize the palletLabel's icon I use setBounds() to control its dimensions and location on the page. A picture of what it looks like is below:
The code that controls what happens when the pallet is image is resized is called each time the dimensions (specified by the JSpinners that can be seen to the left) are changed. The palletLabel is resized is below:
private void resizePalletImage(int[] size)
{
Dimension dim = calculatePalletImageSize(size[1], size[0]);
palletImage = ResizeImage.scaleImageByAbsoluteValues(originalPalletImage, dim);
ImageIcon icon = new ImageIcon(palletImage);
palletLabel.setIcon(icon);
layerPanelHeight = layerCenterPanel.getHeight();
//Have to set this twice, as the length hasn't "updated" by the time the first setBounds is called. Weird.
palletLabel.setBounds(0, layerPanelHeight - palletLabel.getHeight(), icon.getIconWidth(), icon.getIconHeight());
palletLabel.setBounds(0, layerPanelHeight - palletLabel.getHeight(), icon.getIconWidth(), icon.getIconHeight());
}
originalPalletImage is a high resolution copy of the original image, this is used to prevent blurring after lots of image resizing.
ResizeImage.scaleImageByAbsoluteValues is a static method that is used to resize the image. It just calls Image.getScaledInstance after a couple of calculations.
layerCenterPanel is the JLayeredPane upon which panelLabel sits.
As seen, I call setBounds() twice at the end. Initially it was only called once, and it resized the palletLabel, but it didn't use the values that had just been set earlier in the method, but rather the previous values, and the pallet image floated about where it shouldnt (as the previous value for palletLabel.getHeight() was being used). In other words, the method worked as intended but was always one iteration behind. I have solved this by just calling setBounds() twice and it now works exactly as intended. I am simply wondering why this is necessary, I tried putting setBounds() within an invokeLater but it had no effect.
Any input is welcome,
Thanks.
Some animations (such as some gif files) only store in each frame the pixels that change from the previous frame. To draw these animations correctly, you have to paint the first frame, then paint the succeeding frames on top of them without erasing the previous frames. JPanels, however, always redraw the background when you call repaint(), erasing the previous frames. Is there a way to prevent a JPanel from redrawing the background? I've been told that calling super.paintComponent(g) in the JPanels paintComponent(Graphics g) method is what redraws the background, but I tried commenting that out and it lead to some strange behaviour, so I'm assuming it does more than just repaint the background.
I'd recommend to build your code upon the already existent code provided by the API instead of messing with it. Just store the image as BufferedImage. This allows you to display it using an ImageIcon, so it's an additional simplification. This allows you to update single pixels without any hassles with the API. If you absolutely insist on excluding the JPanel from the repaint-routine, this question might help.
In general:
Follow the conventional use of the API. If you want to permanently store data of an image, us a BufferedImage. JComponents are supposed to be entirely overridden every time the frame is updated.
Depending on your exact requirement there are two common approaches:
Draw on a BufferedImage and then display the BufferedImage
Keep an ArrayList of Objects you want to paint and paint all the Objects in the list every time paintComponent() is invoked.
Check out Custom Painting Approaches for more information and working examples of each approach.
I want to be able to select part of an image in an ImageIcon on JLabel and fill it with color.
Is this possible I have become a little confused as I have read that an ImageIcon is not selectable but I am not sure if that means I have to find another way of displaying the image?
Possible, yes, difficult, yes.
You need to start with a BufferedImage, which you can then wrap in a ImageIcon and apply to a JLabel.
You would then need to register a MouseMotionListener and MouseListener to the label to detect the area which was selected, you would then modify the BufferedImage accordingly and repaint everything.
Having said that, I wouldn't use a JLabel, as you can't accurately calculate the location that the label renders the icon, instead, I'd make myself a custom component, extending from JPanel and encapsulate the functionality within it and use custom painting to paint the image (and the selection area)
Start by having a look at How to Write a Mouse Listener, Performing Custom Painting, 2D Graphics and possibly Reading/Loading an Image, Writing/Saving an Image
So my program creates a MigLayout GUI and has a bunch of JLabels that are given images on creation. Here you can see what the final result is right now:
The images are too big and go over the size of the JPanel they're contained in. It is simply creating it to be the size that the original image was and then display that, however, it's obviously an issue. Is there a way I can fix the size so it will try to fit every component in the GUI?
For starters, I want to ensure that the blue portion does not get shifted like that, I want it to keep to the size it was set as (half the height). I also want the images to take up the maximum size they can with keeping the aspect ratio of the original image.
I've tried setting the JLabel's size and preferred size, I've tried some attempts with MigLayout giving it paramaters when I tell it to add the JLabel, neither have worked for me. I'm entertaining the idea of extending JLabel and writing something to fix it, but not entirely sure how to go about that. I know I could overwrite paint but not sure what I'd have to actually do.
My JPanel is set as follows:
JPanel jpCards = new JPanel(new MigLayout("insets 0, gapx 0, gapy 0, wrap 7", "grow"));
My cards are being added without additional parameters and created just by giving it pictures of the size they were displayed.
Just to clarify, I need the actual JLabel's size to be changed, not just what's contained inside, because they will have mouse listeners later on. If only the image changed, I'll have problems with the mouse listener detecting itself inside a JLabel's that it doesn't look as if it should
I solved this by instead changing the size of the icon before making the JLabel.
I've found that in Java, when you create a JLabel given some sort of image, it will fit the size of the JLabel to be that of the image you give it. So instead of creating the JLabel given the original image, I scale it first using the dimensions of the screen, then create a JLabel out of it.
There's still some work to be done since I want the user to be able to resize the screen and have the image resize. I'll have to spend some time figuring out how I can get it to resize, but it's not a major concern.
I have a program that acts somewhat like a light MS Paint. Currently it reads in an XML SVG description (a very limited subset of SVG) and paints the image onto a JPanel, and then the user can update the image.
I was wondering if it was possible to save this image as a PNG (saving it back to SVG is easy). I have researched this, and seen that the examples create a BufferedImage and use Graphics to paint onto the BufferedImage. I was wondering if it was possible to take everything that has already been painted/edited and immediately transfer it to a BufferedImage.
Have you tried this?
Export JPanel Graphics to .png or .gif or .jpg
I think that there is something that you don't understand about how JPanel and graphics work in Java. Asking the JPanel to draw itself in a buffer is the same as what you want to do. A JPanel isn't drawn only once. The JPanel is repainted many many times even when you only drag a window over it.