how to make image resizeable - java

i try to make imageviewer, the code is below
import javax.swing.*;
import java.awt.event.*;
import java.IO.*;
public class javaImageViewer extends JFrame{
public javaImageViewer(){
setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(200,100);
JButton openButton = new JButton("Open Images");
getContentPane().add(openButton);
openButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
JFileChooser chooser = new JFileChooser(".");
int status = chooser.showOpenDialog(javaImageViewer.this);
if(status == JFileChooser.APPROVE_OPTION){
try{
JFrame frame = new JFrame();
JLabel label = new JLabel(new ImageIcon(chooser.getSelectedFile().toURL()));
frame.add(label);
frame.setSize(500,500);
frame.setVisible(true);
}
catch(Exception e2){
System.out.println("Error"+e2);
}
}
}
});
}
public static void main(String [] args){
javaImageViewer tim = new javaImageViewer();
tim.setVisible(true);
}
}
but when i open image from camera, it always showing over the frame size
i dont know how to make the image follow my frame size ?

in order to place your image with the Full Size, you can try to make your own JPanel, override the paintComponent method, and inside this method use g.DrawImage ,
other solution and maybe easier is set the JPanel dimesion with the same dimesion of you Image and Add this JPanel to a JScrollPane , in this way is going to show a scrollbars to navigate

depends of reall size in pixels
1) put Image / BufferedImage as Icon/ImageIcon to the JLabel, then image will be resiziable up to real size in pixels
2) resize Image by usage of Image#getScaledInstance(int width, int height, int hints)

Related

How to show/hide an image attached to a Jlabel after a Jbutton is clicked?

I'm new to programming world, and I need some help. I will try to be as clear as possible.
This is my current situation:
I'm programming a simple game.
On a Jframe, I've added a Jlabel on which I attached an image. I've also added a Jbutton on the Jframe.
I would like that when I click on the Jbutton, the image appears and on the next click the image hides.
How could I do it?
Thanks in advance and excuse me for the possible english mistakes.
EDIT
Following some instructions given by people, I've reached this point:
button.addActionListener(new Actionbox());
final class Actionbox implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
if (label.getIcon() == null)
label.setIcon(new ImageIcon(myimage));
else
label.setIcon(null);
}
}
Eclipse is giving me an error message on the left side of the code editor, near the number lines. It says "Actionbox cannot be resolved to a type".
How could I solve it?
I would like that when I click on the Jbutton, the image appears and on the next click the image hides
add/remove an Icon from the label:
public void actionPerformed(ActionEvent e)
{
if (label.getIcon() == null)
label.setIcon(...);
else
label.setIcon( null );
}
Or instead of setting the Icon null, you may want to have a blank Icon so that the size of the label doesn't keep changing every time you show an image.
Don't fiddle with your button's visibility, and don't make it a final local variable. For something like this, the label should be a field. Place it in your GUI and leave it visible, since if it doesn't hold an icon or have text, nothing will show on it. Instead in your button's ActionListener, simply change the JLabel's ImageIcon via its setIcon(...) method. Pass in an Icon if you want to show an image and pass in null if you want to show nothing. Make your JLabel a field of the class, not a final local variable.
Regarding your code, one way to create your JButton's ActionListener is to use an anonymous inner class rather than a static private class. I'd also recommend reading in the image just once perhaps in your class's constructor and not each time the button is pressed. For example,
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial") // have GUI extend JPanel
public class ButtonSwapImageGui extends JPanel {
private static final String IMAGE_PATH = "https://duke.kenai.com/iconSized/duke.gif";
private Icon imageIcon; // hold our image
private Icon nullImageIcon; // hold a blank image as a placeholder
private JLabel label = new JLabel("", SwingConstants.CENTER);
// throw an exception if image can't be read
public ButtonSwapImageGui() throws IOException {
// read in an image from the internet
URL imageUrl = new URL(IMAGE_PATH);
BufferedImage image = ImageIO.read(imageUrl);
// create a blank placeholder image the same size as
// the image read in from internet
int width = image.getWidth();
int height = image.getHeight();
BufferedImage nullImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
// create ImageIcon objects with images read in above
imageIcon = new ImageIcon(image);
nullImageIcon = new ImageIcon(nullImage);
// set JLabel with the placeholder nullImageIcon
label.setIcon(nullImageIcon);
// create our button
JButton button = new JButton("Swap Image");
// add an anonymous inner class ActionListener to button
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// get the JLabel's Icon
Icon currentIcon = label.getIcon();
// if the Icon matches the null icon
if (currentIcon == nullImageIcon) {
// set label with image
label.setIcon(imageIcon);
} else {
// otherwise the label is displaying the image
// so now set label with the null (blank) icon
label.setIcon(nullImageIcon);
}
}
});
// JPanel to hold our button
JPanel buttonPanel = new JPanel();
buttonPanel.add(button);
// set our GUI's layout to BorderLayout
setLayout(new BorderLayout());
// add the JLabel to the BorderLayout.CENTER position
add(label, BorderLayout.CENTER);
// add button JPanel to the bottom
add(buttonPanel, BorderLayout.PAGE_END);
}
private static void createAndShowGui() {
// declare our GUI JPanel
ButtonSwapImageGui mainPanel = null;
try {
mainPanel = new ButtonSwapImageGui();
} catch (IOException e) {
// if we're here, the image could not be read in
e.printStackTrace();
System.exit(-1); // can't get image -- exit program
}
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel); // add GUI to JFrame
frame.pack(); // tell layout managers to layout components
frame.setLocationRelativeTo(null); // center GUI
frame.setVisible(true); // display GUI
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
You can do something like this:
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
jLabel.setVisible(!jLabel.isVisible()); //Note! jLabel has to be a final variable.
}
}
You should note that any variables used inside coming from outside the ActionListener have to be final ones. This largely restricts you into working with objects
I usually use set bounds (0,0,0,0); whenever I want to hide swing components
button.addActionListener(new Actionbox());
final class Actionbox implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
if (label.getIcon() == null) {
label.setIcon(new ImageIcon(myimage));
else{
label.setIcon(null);
}
}

Swing Intellij GUIDesigner image disappears if placed in JScrollPane

I'm using IntelliJ GUIDesigner.
I have JScrollPanel which contains JPanel.
The idea is that I want to add image to JPanel and to have it load at full size so I can use scrollers to move around and see whole image.
And My problem is that it paints itself alright if I won't change the size of JPanel. But the moment I'm chaning JPanel size it just repaints itself to orginal state (I suppose, IntelliJ hides a lot of code from me).
The code is:
private JPanel panel1;
private JButton button1;
private JPanel drawingPanel;
public MainPanel(){
button1.addActionListener(e -> {
JFileChooser openFile = new JFileChooser();
File chosenFile;
if(openFile.showSaveDialog(panel1) == JFileChooser.APPROVE_OPTION){
chosenFile = openFile.getSelectedFile();
drawImage(chosenFile);
}
});
}
private void drawImage(File file){
try {
BufferedImage image = ImageIO.read(file);
//Works OK if line belowed is removed, but doesn't adjust size so I can't scroll.
drawingPanel.setSize(image.getWidth(), image.getHeight());
Graphics g = drawingPanel.getGraphics();
g.drawImage(image, 0, 0, null);
drawingPanel.paintComponents(g);
}
catch (IOException e) {
e.printStackTrace();
}
}
As I wrote in comment, if the line below the comment is removed then I can load the image and it shows OK but it's too big and I can't see whole image.
If I add the line then it just clears everything and I can't see nothing.
This is important - I need to get the image to show in full size.
How do I do it?
I have JScrollPanel which contains JPanel.
Don't do custom painting.
Just create a JLabel and add the label to the viewport of the scroll pane. Then when you want to change the image you use the setIcon(...) method of the JLabel and the label will automatically repaint itself and scrollbars will appear if necessary.
Maybe you can share your IntelliJ GUI forms? Otherwise it's difficult to reproduce the scrolling problem that you're facing. Without the custom painting and using a label as camickr suggested, you can get scrolling working like this:
public class MainPanel {
private static JFrame frame;
private JPanel panel1;
private JButton button1;
private JPanel drawingPanel;
private JLabel drawingLabel;
public static void main(String[] args) {
MainPanel.test();
}
private static void test() {
frame = new JFrame("");
frame.setBounds(100, 100, 640, 480);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
new MainPanel();
frame.setVisible(true);
}
public MainPanel() {
initializeGui();
button1.addActionListener(e -> {
JFileChooser openFile = new JFileChooser("[...]");
File chosenFile;
if (openFile.showSaveDialog(panel1) == JFileChooser.APPROVE_OPTION) {
chosenFile = openFile.getSelectedFile();
System.out.println("chosenFile: " + chosenFile);
drawImage(chosenFile);
}
});
}
private void initializeGui() {
panel1 = new JPanel(new BorderLayout());
frame.getContentPane().add(panel1);
button1 = new JButton("Open image");
panel1.add(button1, BorderLayout.NORTH);
drawingPanel = new JPanel(new BorderLayout());
panel1.add(drawingPanel, BorderLayout.CENTER);
drawingLabel = new JLabel();
drawingPanel.add(new JScrollPane(drawingLabel), BorderLayout.CENTER);
}
private void drawImage(File file){
try {
BufferedImage image = ImageIO.read(file);
//Works OK if line below is removed, but doesn't adjust size so I can't scroll.
// drawingPanel.setSize(image.getWidth(), image.getHeight());
// Graphics g = drawingPanel.getGraphics();
// g.drawImage(image, 0, 0, null);
// drawingPanel.paintComponents(g);
drawingLabel.setIcon(new ImageIcon(image));
drawingPanel.validate();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
Not sure how easy it is to do something similar with the IntelliJ GUI designer; I do prefer IntelliJ (over Eclipse and NetBeans) but I also prefer to create my Java GUIs in code... ;-)

Platform independent Image in java

I am trying to paint an image onto a panel, that is contained by a frame.
Let us say I have a 320 x 480 image.
When i try to create a frame with size 320x480 and add the panel into it, I encounter a problem.
In different operating systems, the JFrame of 320x480 is of different sizes due to title bar.
Thus my correct fit image in windows XP will not be properly painted in Windows8 or Ubuntu.
A grey patch is visible because the image was not properly placed.
I tried overriding paint method and using ImageIcon.
Please do offer a solution.
TIA
Code Snippet
CLASS PA CONTENTS
setPreferredSize(new Dimension(500,500));
.
.
JLabel image= new JLabel();
ImageIcon background = new ImageIcon(getClass().getClassLoader().getResource("Flower.jpg"));
image.setBounds(0, 0, 500, 500);
image.setIcon(background);
this.add(image); //where "this" is extending from JPanel
CLASS PB CONTENTS
frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
inserting(frame.getContentPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setResizable(false);
private void inserting(Container pane)
{
cardPanel=new JPanel();
CardLayout cards=new CardLayout();
cardPanel.setLayout(cards);
PA home= new PA();
cardPanel.add(home,"homeScreen");
pane.add(cardPanel);
}
Don't call setSize at all, call pack (as VGR stated in his comment). pack will size your JFrame based on size's of component's within it, and gaps between those component's.
Now.. issue you will encounter is that your JFrame will be small at startup. So override getPreferredSize method for your JPanel to return dimensions of your image:
public void getPreferredSize() {
return new Dimension(image.getWidth(), image.getHeight());
}
Now your image will fit perfectly and your application will be fully OS independent.
And also, do not override paint method. Instead, override paintComponent.
Here is a small demo I made in cases like yours:
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class Drawing {
JFrame frame = new JFrame();
public Drawing() {
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(new Panel());
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Drawing();
}
});
}
class Panel extends JPanel {
BufferedImage image = null;
Panel() {
try {
image = ImageIO.read(new File("path-to-your-image"));
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
#Override
public Dimension getPreferredSize() {
// Panel will be sizes based on dimensions of image
return new Dimension(image.getWidth(), image.getHeight());
}
}
}
It seems to be the layout problem. The most obvious solution is to wrap you image panel into another container with proper layout, so your panel will always have the same size.

JPanel on top of JLabel

Good day!
Is it possible to add a JPanel on top of a JLabel?
I would like my JFrame to have a background image and in order to this, i used this code (based from past stackoverflow answers):
setLocation(150,50);
setSize(700,650);
setVisible(true);
JLabel contentPane = new JLabel();
contentPane.setIcon(new ImageIcon("pics/b1.jpg"));
contentPane.setLayout( new BorderLayout());
setContentPane( contentPane );
Now my problem is, I cannot put a panel on my JFrame because of the JLabel background.
Please help.
Thanks.
To create a background image for a JFrame, I recommend that you draw the image in the paintComponent method of a JPanel, and then add this JPanel to the contentPane BorderLayout.CENTER which has it fill the contentPane. You may even want to set the JPanel's preferredSize to be that of the Image. Then you can add any components you'd like to the image panel, and don't have to worry about trying to add comopnents to a JLabel which seems bass ackwards to me.
For example here's a program that does this but slightly different. It creates an ImagePanel object, a JPanel that draws an image and sizes itself to the image and then places it in a JScrollPane which is then added to the contentPane, but you can just get rid of the JScrollPane and put your image JPanel directly in the contentPane instead:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class BigDukeImage {
public static final String IMAGE_PATH = "http://" + "duke.kenai.com/nyanya/NyaNya.jpg";
private static final Dimension SCROLLPANE_SIZE = new Dimension(900, 700);
private static void createAndShowUI() {
Image image = null;
try {
URL url = new URL(IMAGE_PATH);
image = ImageIO.read(url);
// JLabel label = new JLabel(new ImageIcon(image));
ImagePanelA imagePanel = new ImagePanelA(image);
JScrollPane scrollpane = new JScrollPane();
// scrollpane.getViewport().add(label);
scrollpane.getViewport().add(imagePanel);
scrollpane.setPreferredSize(SCROLLPANE_SIZE);
JFrame frame = new JFrame("Big Duke Image");
frame.getContentPane().add(scrollpane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
JScrollBar vertSBar = scrollpane.getVerticalScrollBar();
JScrollBar horzSBar = scrollpane.getHorizontalScrollBar();
vertSBar.setValue((vertSBar.getMaximum() - vertSBar.getVisibleAmount()) / 2);
horzSBar.setValue((horzSBar.getMaximum() - horzSBar.getVisibleAmount()) / 2);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
#SuppressWarnings("serial")
class ImagePanelA extends JPanel {
private Image image;
public ImagePanelA(Image image) {
this.image = image;
setPreferredSize(new Dimension(image.getWidth(null), image.getHeight(null)));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) {
g.drawImage(image, 0, 0, null);
}
}
}
You could use a JLayeredPane. This lets you add components to different layers and have them ontop of one another.
I cannot put a panel on my JFrame because of the JLabel background
Thats because a panel is opague so it paints over top of the label. You need to use:
panel.setOpaque( false );
sure..you can....Use NetBEans IDE to simplify tedious tasks like this by drag and drop and write the actual programming..

How to display an image as a background on a JPanel

I have problem with displaying the image on JPanel when I rescaled the image according to the size of the JPanel. The image did not appear.
public class createGUII extends JFrame{
String [] background = {"c1.jpg","c2.jpg","c3.jpg","c4.jpg"};
ArrayList<String> bgPicturesFiles = new ArrayList<String>(Arrays.asList(background));
JPanel panel;
ImagePanel imgBg;
public createGUII(){
GridBagLayout m = new GridBagLayout();
Container c = getContentPane();
c.setLayout (m);
GridBagConstraints con = new GridBagConstraints();
//Panel for background
panel = new JPanel();
panel.setSize(600, 600);
con = new GridBagConstraints();
con.anchor=GridBagConstraints.CENTER;
con.gridy = 1; con.gridx = 0;
con.gridwidth = 1; con.gridheight = 1;
m.setConstraints(panel, con);
c.add(panel);
//randomized the image files
Random r = new Random();
int random = r.nextInt(bgPicturesFiles.size());
//rescale the image according to the size of the JPanel
imgBg = new ImagePanel(new ImageIcon(bgPicturesFiles.get(random)).getImage().getScaledInstance(panel.getHeight(), panel.getWidth(),Image.SCALE_SMOOTH));
panel.add(imgBg);
setResizable(false);
setVisible(true);
setExtendedState(getExtendedState()|JFrame.MAXIMIZED_BOTH);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new createGUII();
}
});
}
}
class ImagePanel extends JPanel {
private Image img;
public ImagePanel(String img) {
this(new ImageIcon(img).getImage());
}
public ImagePanel(Image img) {
this.img = img;
Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));
setPreferredSize(size);
setMinimumSize(size);
setMaximumSize(size);
setSize(size);
setLayout(null);
}
public void paintComponent(Graphics g) {
g.drawImage(img, 0, 0, null);
}
}
Have a look at this: JPanel background image, JPanel with background image, with other panels overlayed
The second link mentions that you have to do some custom painting for scaling. This is a problem. I wouldn't scale the image every single time in the paintComponent method, but do it once if the width and height have been changed since the last call, and in that case, recreate a BufferedImage containing the image which you blit every single time before calling the superclass paintComponent, scaled up to the right size (use something like Image scaling does not work when original image height & width is smaller the scaling height & width). I can see an issue where it might try to fill the panel with a colour when you call the superclass paintComponent method, but you'll have to experiment.
The problem is that in Java images get loaded asynchronously. There are several issues with the above code because of that:
The image doesn't get loaded, so it's dimensions are (-1, -1). Thus, ImagePanel's size is invalid
Even if the dimensions get set manually (i.e. changing it to new Dimension(600, 600)), the image itself may not be loaded.
JFrame resizing is disabled. If you allow it, you would be able to get the image drawn with the above code by artificially making Swing load the image when the JFrame is resized
To ensure loading, add the following:
new ImageIcon(img).getImage();
after this.img = img; in ImagePanel's constructor.
Note that this is partially a hack - I'm not a GUI expert, but I get the idea the above could be written much better. Maybe somebody else might be able to shed more light.
Here are some links that might be helpful:
http://www.exampledepot.com/egs/java.awt.image/Image2Buf.html
http://webcache.googleusercontent.com/search?q=cache:Ho0L4KoL44AJ:java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html+java+getscaledinstance&cd=1&hl=en&ct=clnk&gl=us&client=ubuntu (yes, it's from Google cache, the original link doesn't work...)
Hope this helps.
I don't see where you're actually reading the image, as suggested in this example.
Addendum: I've added an example of scaling. See also Don't Use getScaledInstance() and The Perils of Image.getScaledInstance().
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/** #see http://stackoverflow.com/questions/4170463 */
public class LoadImage extends JPanel {
private Image image;
public LoadImage() {
super(new GridLayout());
try {
image = ImageIO.read(new File("image.jpg"));
} catch (IOException ex) {
ex.printStackTrace(System.err);
}
int w = image.getWidth(null) / 2;
int h = image.getHeight(null) / 2;
this.add(new JLabel(new ImageIcon(
image.getScaledInstance(w, h, Image.SCALE_SMOOTH))));
}
private void display() {
JFrame f = new JFrame("LoadImage");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new LoadImage().display();
}
});
}
}
Here is a link that should help. However I found a way that better suited the problem I had this was what I found, and the following is what I took from that.
I hope this helps.
Container con = getContentPane();
final String backgroundPath = "C:\\background.jpg";
ImageIcon imh = new ImageIcon(backgroundPath);
setSize(imh.getIconWidth(), imh.getIconHeight());
JPanel pnlBackground = new JPanel()
{
public void paintComponent(Graphics g)
{
Image img = new ImageIcon(backgroundPath).getImage();
g.drawImage(img, 0, 0, null);
}
};
con.add(pnlBackground);
pnlBackground.setBounds(0, 0, imh.getIconWidth(), imh.getIconHeight());

Categories

Resources