JScrollPane and Zooming Images - java

I'm trying to write a simple class that extends from JPanel that can zoom in and zoom out on an image and then uses a JScrollPane at the top level to allow someone to scroll back and forth across the zoomed image. I've having trouble with the JScrollPane portion.
When clicking one of the zoom buttons (whether it be in, out, or reset), the button must be clicked twice in order for the JScrollBars to appear(or in the case of the reset button, disappear). Even after they've appear if you continue to zoom in or out the bars do not update according to the new level of zoom. Resizing the window fixes this issue but I'm looking for a more concrete solution.
ImagePanel Code:
package com.zephyr.graphics;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class ImagePanel extends JPanel implements PropertyChangeListener{
private File imageFile;
private BufferedImage image;
private double zoomMultiplier;
public ImagePanel()
{
imageFile = null;
image = null;
zoomMultiplier = 1;
}
public ImagePanel(File imageFile)
{
this.imageFile = imageFile;
try {
image = ImageIO.read(imageFile);
} catch (IOException e) {
image = null;
}
zoomMultiplier = 1;
}
public void setImageFile(File imageFile)
{
this.imageFile = imageFile;
if(imageFile == null)
{
image = null;
}
else
{
try {
image = ImageIO.read(imageFile);
} catch (IOException e) {
image = null;
}
}
zoomMultiplier = 1;
this.revalidate();
this.repaint();
}
public File getImageFile()
{
return imageFile;
}
public void paintComponent(Graphics g)
{
g.clearRect(0, 0, this.getWidth(), this.getHeight());
if(image == null)
{
this.setPreferredSize(new Dimension(this.getParent().getWidth(), this.getParent().getHeight()));
g.setColor(Color.black);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
}
else
{
double preferredWidth = this.getParent().getWidth() * zoomMultiplier;
double preferredHeight = this.getParent().getHeight() * zoomMultiplier;
this.setPreferredSize(new Dimension((int)preferredWidth, (int)preferredHeight));
Image scaled = image.getScaledInstance((int)preferredWidth, (int)preferredHeight, Image.SCALE_DEFAULT);
g.drawImage(scaled, 0, 0, null);
}
}
#Override
public void propertyChange(PropertyChangeEvent evt) {
if(evt.getPropertyName().equals("Image File"))
{
setImageFile((File)evt.getNewValue());
}
else if(evt.getPropertyName().equals("Zoom In"))
{
double additive = ((Number)evt.getNewValue()).doubleValue();
zoomMultiplier += additive;
this.revalidate();
this.repaint();
}
else if(evt.getPropertyName().equals("Zoom Out"))
{
double subtractive = ((Number)evt.getNewValue()).doubleValue();
zoomMultiplier -= subtractive;
this.revalidate();
this.repaint();
}
else if(evt.getPropertyName().equals("Zoom Reset"))
{
zoomMultiplier = 1;
this.revalidate();
this.repaint();
}
}
}
Main Class
package com.zephyr.graphics;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class Main {
public static void main(String[] args)
{
PropertyChangeSupport pcs = new PropertyChangeSupport(Main.class);
JFileChooser chooser = new JFileChooser(System.getProperty("user.home"));
chooser.setDialogTitle("Select an image");
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
File file = null;
if(chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION)
{
file = chooser.getSelectedFile();
}
else
{
System.err.println("NO FILE WAS SELECTED OR THE WINDOW WAS CLOSED");
return;
}
JFrame frame = new JFrame("ImagePanel Tester");
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ImagePanel iPanel = new ImagePanel(file);
pcs.addPropertyChangeListener(iPanel);
JScrollPane iScroll = new JScrollPane(iPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
iScroll.setPreferredSize(new Dimension(1024, 768));
JPanel controlPanel = new JPanel();
controlPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
JButton zoomIn = new JButton("Zoom In");
zoomIn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
pcs.firePropertyChange("Zoom In", null, new Double(.25));
frame.revalidate();
frame.repaint();
}
});
controlPanel.add(zoomIn);
JButton zoomOut = new JButton("Zoom Out");
zoomOut.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
pcs.firePropertyChange("Zoom Out", null, new Double(.25));
frame.revalidate();
frame.repaint();
}
});
controlPanel.add(zoomOut);
JButton zoomReset = new JButton("Zoom Reset");
zoomReset.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
pcs.firePropertyChange("Zoom Reset", null, null);
frame.revalidate();
frame.repaint();
}
});
controlPanel.add(zoomReset);
JButton changeImage = new JButton("Change Image");
changeImage.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(chooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION)
{
File tempFile = chooser.getSelectedFile();
pcs.firePropertyChange("Image File", null, tempFile);
frame.revalidate();
frame.repaint();
}
}
});
controlPanel.add(changeImage);
frame.add(iScroll, BorderLayout.CENTER);
frame.add(controlPanel, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
frame.revalidate(); //Shouldn't really be necessary, but seems to be helping
}
}

After some heavy digging, the Scrollable interface saved me. Implementing this and it's respective methods following this example as well as removing the preferredSize references from paintComponent fixes the issues that I was having.

Related

Is it possible to set a background image inside JTextArea (including JScrollPane) not all the frame window? [duplicate]

This question already has answers here:
Inserting an image under a JTextArea
(2 answers)
Closed 8 years ago.
I want to set background in JTextArea (having transparency), but I don't have any idea. Maybe it's not very important, but I just want have characteristically program. Please help.
This part of code, I create JTextArea.
notatnik_k = new JTextArea();
JScrollPane scrollPane2 = new JScrollPane(notatnik_k);
scrollPane2.setBounds(20,30, 263,200);
notatnik_k.setEditable(false);
add(scrollPane2);
This photo showing my problem:
Is there a simply way, to do it?
You will need to extend your JTextArea class and create a setBackground(Image image) method. This method would set a field to the image you want to use and then invoke the the repaint method (this.repaint()).
You should then override the paintComponent(Graphics) method to paint the component with the image you set using setBackground(Image image).
I found here on the site this sample of code, and I did a little change but I have one error and don't know why it's incorrect? It's shows error: "The method setBackgroundImage(Image) is undefined for the type JTextArea"
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class BackgroundDemo {
public JTextArea notatnik;
private static void createAndShowUI() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
final JFrame frame = new JFrame("BackgroundDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel buttonsPanel = new JPanel();
final JTextArea notatnik = new JTextArea();
JScrollPane scrollPane1 = new JScrollPane(notatnik);
scrollPane1.setBounds(20,270, 380,110);
JButton loadButton = new JButton("Set background");
buttonsPanel.add(loadButton);
loadButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JFileChooser fc = new JFileChooser(System.getProperty("user.home"));
int returnVal = fc.showOpenDialog(frame);
if (returnVal == JFileChooser.APPROVE_OPTION) {
try {
Image image = ImageIO.read(fc.getSelectedFile());
if (image != null)
notatnik.setBackgroundImage(image);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
});
JPanel content = new JPanel(new BorderLayout());
content.add(buttonsPanel, BorderLayout.SOUTH);
frame.add(scrollPane1);
frame.add(content);
frame.setSize(new Dimension(800, 500));
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
static class MyTextArea extends JTextArea {
private Image backgroundImage;
public MyTextArea() {
super();
setOpaque(false);
}
public void setBackgroundImage(Image image) {
this.backgroundImage = image;
this.repaint();
}
#Override
protected void paintComponent(Graphics g) {
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
if (backgroundImage != null) {
g.drawImage(backgroundImage, 0, 0, this);
}
super.paintComponent(g);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}

Java ScrollPane on JPanel

I wrote JPanel class where I load image. I'm trying to add a scrolls to this panel, but it didn't work. Can someone help me? Sorry for my bad language.
browser.setFileFilter(imgFilter); // ustawienie filtra
browser.setAcceptAllFileFilterUsed(false);
browser.setCurrentDirectory(new File("."));
int result = browser.showOpenDialog(imagePanel);
if (result == JFileChooser.APPROVE_OPTION) {
// tworzenie obrazu
imagePanel = new ImagePanel(browser.getSelectedFile());
JScrollPane scrollPane = new JScrollPane(imagePanel);
scrollPane.setSize(new Dimension(300, 400));
//add(imagePanel);
add(scrollPane);
//imagePanel.repaint();
scrollPane.repaint();
}
And this is my imagePanel class:
private class ImagePanel extends JPanel {
private Image img;
private File file;
public ImagePanel(File file) {
this.file = file;
setSize(SCREEN_HEIGHT / 2, SCREEN_WIDTH * 3/4);
try {
img = ImageIO.read(file);
}
catch(IOException e) {
System.out.println("Wystąpił błąd podczas wczytywanie obrazu.");
e.printStackTrace();
}
}
public void paintComponent(Graphics g) {
if(img == null) return;
g.drawImage(img, 0, 0, null);
}
}
You should be overriding the getPreferredSize() of the ImagePanel to give the panel a preferred size, which the scroll pane will use to determine whether or not to add scrolls. Generally, when doing custom painting, you always want to override the getPreferredSize of the drawing canvas panel, as the default is 0x0
Example:
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
// image is 256 x 256
Image image = new ImageIcon("stackoverflow.png").getImage();
JPanel imagePanel = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(image.getWidth(this),
image.getHeight(this));
}
};
JScrollPane pane = new JScrollPane(imagePanel);
pane.setPreferredSize(new Dimension(200, 200));
JOptionPane.showMessageDialog(null, pane);
}
});
}
}
With getPreferredSize
Without getPreferredSize
UPDATE
A couple thing I see wrong with your current code.
Creating a new ImagePanel when you want to set the image. Instead just have a method like setImage in the ImagePanel class where you can just set the image and repaint.
Trying to add(scrollPane); at runtime without revalidate().
See full example here.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileNameExtensionFilter;
public class Test {
public Test() {
JFrame frame = new JFrame();
ImagePanel panel = new ImagePanel();
JScrollPane pane = new JScrollPane(panel);
pane.setPreferredSize(new Dimension(200, 200));
JButton button = createButton(panel, pane);
frame.add(pane);
frame.add(button, BorderLayout.PAGE_END);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JButton createButton(ImagePanel panel, JScrollPane pane) {
JButton button = new JButton("Change image");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFileChooser chooser = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter(
"JPG & GIF Images", "jpg", "gif");
chooser.setFileFilter(filter);
int returnVal = chooser.showOpenDialog(null);
if (returnVal == JFileChooser.APPROVE_OPTION) {
Image image = new ImageIcon(
chooser.getSelectedFile().getAbsolutePath()).getImage();
panel.setImage(image);
pane.revalidate();
}
}
});
return button;
}
private class ImagePanel extends JPanel {
Image image;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) {
g.drawImage(image, 0, 0, this);
}
}
#Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(150, 150)
: new Dimension(image.getWidth(this),
image.getHeight(this));
}
public void setImage(Image img) {
this.image = img;
repaint();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Test();
}
});
}
}

How do I create a JPanel with two images where only a part of the one below is shown on mouse over?

I am trying to create a button panel where the button that was clicked becomes 'differently colored'; i.e show the background image. p.s I only need this approach(with 2 images), and not anything else. Thanks !
Eg:
public class TestPane extends JPanel {
private BufferedImage imgUnclicked;
private BufferedImage imgClicked;
private Point mousePoint;
public TestPane() {
try {
imgUnclicked = ImageIO.read(new File("C:\\Users\\Me\\Desktop\\tmp\\Uncolored.png"));
imgClicked = ImageIO.read(new File("C:\\Users\\Me\\Desktop\\tmp\\Colored.png"));
} catch (IOException ex) {
Logger.getLogger(Spotlight.class.getName()).log(Level.SEVERE, null, ex);
}
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
mousePoint = e.getPoint();
repaint();
}
});
}
}
#Override
protected void paintComponent(Graphics g) {
//Draw imgClicked
//Draw imgUnclicked with some rectangular area around mouse click subtracted
}
}
No need to reinvent the wheel. Instead use a JToggleButton (appropriately configured). A button will react to both mouse and keyboard input.
import java.awt.*;
import java.net.*;
import javax.imageio.ImageIO;
import javax.swing.*;
class ChangeImageOnClick {
public static void main(String[] args) throws Exception {
URL url1 = new URL("http://i.stack.imgur.com/gJmeJ.png");
final Image img1 = ImageIO.read(url1);
URL url2 = new URL("http://i.stack.imgur.com/wCF8S.png");
final Image img2 = ImageIO.read(url2);
Runnable r = new Runnable() {
#Override
public void run() {
JToggleButton btn = new JToggleButton("Click me!");
btn.setIcon(new ImageIcon(img1));
btn.setSelectedIcon(new ImageIcon(img2));
btn.setContentAreaFilled(false);
btn.setBorderPainted(false);
JOptionPane.showMessageDialog(null, btn);
}
};
SwingUtilities.invokeLater(r);
}
}
A different idea. Basically, load an image into a JLabel, set the Layout of the label and add two opaque components to it.
By using a simple MouseListener, you can either make the component invisible or transparent based on your needs...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
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;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class HideAndShow {
public static void main(String[] args) {
new HideAndShow();
}
public HideAndShow() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
try {
BufferedImage img = ImageIO.read(new File("/Users/swhitehead/Dropbox/MegaTokyo/Haibane_Miho___Take_2_by_garrbage.png"));
JLabel label = new JLabel(new ImageIcon(img.getScaledInstance(-1, 200, Image.SCALE_SMOOTH)));
add(label);
label.setLayout(new GridLayout(2, 1));
JPanel top = new JPanel();
top.add(new JLabel("Top"));
JPanel bottom = new JPanel();
bottom.add(new JLabel("Bottom"));
MouseAdapter ma = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
((JPanel)e.getComponent()).setOpaque(false);
repaint();
}
};
top.addMouseListener(ma);
bottom.addMouseListener(ma);
label.add(top);
label.add(bottom);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
Add an ActionListener to your button and call setIcon with the imgClicked.
Something like this:
JButton btn = new JButton();
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
btn.setIcon(imgClicked);
}
});

Deleting images from JFrame

I created one JFrame. and set layout shown in below code
this.setLayout(new GridLayout());
JPanel panel=new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(new PicturePanel1());
JTabbedPane jtp=new JTabbedPane();
jtp.addTab("show Images", panel);
jtp.addTab("Compare Image", new JButton());
this.add(jtp);
I created another class that draws Images from particular location.
protected void paintComponent(Graphics g) {
super.paintComponents(g);
Graphics2D g2 = (Graphics2D) g;
int k = 20,y=10;
for (int j = 0; j <= listOfFiles.length - 1; j++) {
g2.drawImage(b[j], k, y, 100, 100, null);
// add(new javax.swing.JCheckBox());
k = k + 120;
if(k>=960)
{
k=20;
y=y+120;
}
}
Its working fine. I want to delete Images when user clicks on particular Image.
This is my output window. I want to delete Image from list.
Here is an example I made (bored and tired of studying :)). It is by no means the best just a quick thing to show you an example, click the image you want to delete and then press the delete button or DEL to remove and image from the panel:
When app starts up (orange just shows focused label for hovering):
Image to delete is selected by clicking on the Label (Border becomes green highlighted and will remain this way until another label is clicked):
After delete button or key is pressed:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
public class JavaApplication5 {
public static void main(String[] args) {
createAndShowJFrame();
}
public static void createAndShowJFrame() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = createJFrame();
frame.setVisible(true);
}
});
}
private static JFrame createJFrame() {
JFrame frame = new JFrame();
//frame.setResizable(false);//make it un-resizeable
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Test");
ArrayList<BufferedImage> images = null;
try {
images = getImagesArrayList();
} catch (Exception ex) {
ex.printStackTrace();
}
final ImageViewPanel imageViewPanel = new ImageViewPanel(images);
JScrollPane jsp = new JScrollPane(imageViewPanel);
jsp.setPreferredSize(new Dimension(400, 400));
frame.add(jsp);
JPanel controlPanel = new JPanel();
JButton addLabelButton = new JButton("Delete Selected Image");
addLabelButton.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
imageViewPanel.removeFocusedImageLabel();
}
});
controlPanel.add(addLabelButton);
frame.add(controlPanel, BorderLayout.SOUTH);
frame.pack();
return frame;
}
private static ArrayList<BufferedImage> getImagesArrayList() throws Exception {
ArrayList<BufferedImage> images = new ArrayList<>();
images.add(resize(ImageIO.read(new URL("http://icons.iconarchive.com/icons/deleket/sleek-xp-software/256/Yahoo-Messenger-icon.png")), 100, 100));
images.add(resize(ImageIO.read(new URL("https://upload.wikimedia.org/wikipedia/commons/6/64/Gnu_meditate_levitate.png")), 100, 100));
return images;
}
public static BufferedImage resize(BufferedImage image, int width, int height) {
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TRANSLUCENT);
Graphics2D g2d = (Graphics2D) bi.createGraphics();
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(image, 0, 0, width, height, null);
g2d.dispose();
return bi;
}
}
class ImageViewPanel extends JPanel {
JLabel NO_IMAGES = new JLabel("No Images");
ArrayList<BufferedImage> images;
ArrayList<MyLabel> imageLabels;
public ImageViewPanel(ArrayList<BufferedImage> images) {
this.images = images;
imageLabels = new ArrayList<>();
for (BufferedImage bi : images) {
imageLabels.add(new MyLabel(new ImageIcon(bi), this));
}
layoutLabels();
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0, true), "Delete pressed");
getActionMap().put("Delete pressed", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
removeFocusedImageLabel();
}
});
}
void removeFocusedImageLabel() {
if (focusedLabel == null) {
return;
}
imageLabels.remove(focusedLabel);
remove(focusedLabel);
layoutLabels();
}
private void layoutLabels() {
if (imageLabels.isEmpty()) {
add(NO_IMAGES);
} else {
remove(NO_IMAGES);
for (JLabel il : imageLabels) {
add(il);
}
}
revalidate();
repaint();
}
private MyLabel focusedLabel;
void setFocusedLabel(MyLabel labelToFocus) {
if (focusedLabel != null) {
focusedLabel.setBorder(null);
focusedLabel.setClicked(false);
}
focusedLabel = labelToFocus;
focusedLabel.setBorder(new LineBorder(Color.GREEN));
}
}
class MyLabel extends JLabel {
private final ImageViewPanel imageViewPanel;
private boolean clicked = false;
public MyLabel(Icon image, ImageViewPanel imageViewPanel) {
super(image);
this.imageViewPanel = imageViewPanel;
initLabel();
}
public MyLabel(String text, ImageViewPanel imageViewPanel) {
super(text);
this.imageViewPanel = imageViewPanel;
initLabel();
}
private void initLabel() {
setFocusable(true);
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
clicked = true;
imageViewPanel.setFocusedLabel(MyLabel.this);
}
#Override
public void mouseEntered(MouseEvent me) {
super.mouseEntered(me);
if (clicked) {
return;
}
setBorder(new LineBorder(Color.ORANGE));
//call for focus mouse is over this component
requestFocusInWindow();
}
});
addFocusListener(new FocusAdapter() {
#Override
public void focusLost(FocusEvent e) {
super.focusLost(e);
if (clicked) {
return;
}
setBorder(null);
}
});
}
public void setClicked(boolean clicked) {
this.clicked = clicked;
}
public boolean isClicked() {
return clicked;
}
}
simply find the location (x, and y) and the size(width, and height) of image, then with the Graphics object (g2) fill a rectangle over the image drawn, like this
g2.setColor(this.getBackground());//set the color you want to clear the bound this point to JFrame/JPanel
g2.fillRect(x, y, width, height);
where x and y where is the location that images is located, and width and height are size of the picture

Browse for image file and display it using Java Swing

My problem here is,
after clicking Browse button it displays all files in a directory to choose,
then the chosen image is displayed in GUI correctly. But When i click Browse button
for the second time, it shows the old image only instead of showing the new one. Please help me in this.
For reference, i uploaded the UI.
package GUI;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
#SuppressWarnings("serial")
public class MainAppFrame extends JFrame {
private JPanel contentPane;
File targetFile;
BufferedImage targetImg;
public JPanel panel,panel_1;
private static final int baseSize = 128;
private static final String basePath =
"C:\\Documents and Settings\\Administrator\\Desktop\\Images";
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainAppFrame frame = new MainAppFrame();
frame.setVisible(true);
frame.setResizable(false);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public MainAppFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 550, 400);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new BorderLayout(0, 0));
panel = new JPanel();
panel.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 1, true));
contentPane.add(panel, BorderLayout.WEST);
JButton btnBrowse = new JButton("Browse");
btnBrowse.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
browseButtonActionPerformed(e);
}
});
JLabel lblSelectTargetPicture = new JLabel("Select target picture..");
JButton btnDetect = new JButton("Detect");
btnDetect.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
JButton btnAddDigit = new JButton("Add Digit");
btnAddDigit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
JButton button = new JButton("Recognize");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
panel_1 = new JPanel();
panel_1.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 1, true));
GroupLayout gl_panel = new GroupLayout(panel);
gl_panel.setHorizontalGroup(
gl_panel.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel.createSequentialGroup()
.addGap(6)
.addGroup(gl_panel.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel.createSequentialGroup()
.addComponent(lblSelectTargetPicture)
.addGap(6)
.addComponent(btnBrowse))
.addGroup(gl_panel.createSequentialGroup()
.addGap(10)
.addComponent(btnDetect)
.addGap(18)
.addComponent(btnAddDigit))))
.addGroup(gl_panel.createSequentialGroup()
.addGap(50)
.addComponent(button))
.addGroup(gl_panel.createSequentialGroup()
.addContainerGap()
.addComponent(panel_1, GroupLayout.PREFERRED_SIZE, 182, GroupLayout.PREFERRED_SIZE))
);
gl_panel.setVerticalGroup(
gl_panel.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel.createSequentialGroup()
.addGroup(gl_panel.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel.createSequentialGroup()
.addGap(7)
.addComponent(lblSelectTargetPicture))
.addGroup(gl_panel.createSequentialGroup()
.addGap(3)
.addComponent(btnBrowse)))
.addGap(18)
.addComponent(panel_1, GroupLayout.PREFERRED_SIZE, 199, GroupLayout.PREFERRED_SIZE)
.addGap(22)
.addGroup(gl_panel.createParallelGroup(Alignment.BASELINE)
.addComponent(btnDetect)
.addComponent(btnAddDigit))
.addGap(18)
.addComponent(button)
.addContainerGap())
);
panel.setLayout(gl_panel);
}
public BufferedImage rescale(BufferedImage originalImage)
{
BufferedImage resizedImage = new BufferedImage(baseSize, baseSize, BufferedImage.TYPE_INT_RGB);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, baseSize, baseSize, null);
g.dispose();
return resizedImage;
}
public void setTarget(File reference)
{
try {
targetFile = reference;
targetImg = rescale(ImageIO.read(reference));
} catch (IOException ex) {
Logger.getLogger(MainAppFrame.class.getName()).log(Level.SEVERE, null, ex);
}
panel_1.setLayout(new BorderLayout(0, 0));
panel_1.add(new JLabel(new ImageIcon(targetImg)));
setVisible(true);
}
private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {
JFileChooser fc = new JFileChooser(basePath);
fc.setFileFilter(new JPEGImageFileFilter());
int res = fc.showOpenDialog(null);
// We have an image!
try {
if (res == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
setTarget(file);
} // Oops!
else {
JOptionPane.showMessageDialog(null,
"You must select one image to be the reference.", "Aborting...",
JOptionPane.WARNING_MESSAGE);
}
} catch (Exception iOException) {
}
}
}
//JPEGImageFileFilter.java
package GUI;
import java.io.File;
import javax.swing.filechooser.FileFilter;
/*
* This class implements a generic file name filter that allows the listing/selection
* of JPEG files.
*/
public class JPEGImageFileFilter extends FileFilter implements java.io.FileFilter
{
public boolean accept(File f)
{
if (f.getName().toLowerCase().endsWith(".jpeg")) return true;
if (f.getName().toLowerCase().endsWith(".jpg")) return true;
if(f.isDirectory())return true;
return false;
}
public String getDescription()
{
return "JPEG files";
}
}
Each time a new image is selected, you're creating components unnecessarily and in error here:
public void setTarget(File reference) {
//....
panel_1.setLayout(new BorderLayout(0, 0));
panel_1.add(new JLabel(new ImageIcon(targetImg)));
setVisible(true);
Instead I would recommend that you have all these components created from the get-go, before any file/image has been selected, and then in this method, create an ImageIcon from the Image, and then simply use this Icon to set the Icon of an already existng JLabel rather than a new JLabel. This is done simply by calling myLabel.setIcon(new ImageIcon(targetImg));
Create an ImageViewer with method like ImageViewer.setImage(Image), display the image in a JLabel.
ImageViewer
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.util.Random;
public class ImageViewer {
JPanel gui;
/** Displays the image. */
JLabel imageCanvas;
/** Set the image as icon of the image canvas (display it). */
public void setImage(Image image) {
imageCanvas.setIcon(new ImageIcon(image));
}
public void initComponents() {
if (gui==null) {
gui = new JPanel(new BorderLayout());
gui.setBorder(new EmptyBorder(5,5,5,5));
imageCanvas = new JLabel();
JPanel imageCenter = new JPanel(new GridBagLayout());
imageCenter.add(imageCanvas);
JScrollPane imageScroll = new JScrollPane(imageCenter);
imageScroll.setPreferredSize(new Dimension(300,100));
gui.add(imageScroll, BorderLayout.CENTER);
}
}
public Container getGui() {
initComponents();
return gui;
}
public static Image getRandomImage(Random random) {
int w = 100 + random.nextInt(400);
int h = 50 + random.nextInt(200);
BufferedImage bi = new BufferedImage(
w,h,BufferedImage.TYPE_INT_RGB);
return bi;
}
public static void main(String[] args) throws Exception {
Runnable r = new Runnable() {
#Override
public void run() {
JFrame f = new JFrame("Image Viewer");
// TODO Fix kludge to kill the Timer
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final ImageViewer viewer = new ImageViewer();
f.setContentPane(viewer.getGui());
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
ActionListener animate = new ActionListener() {
Random random = new Random();
#Override
public void actionPerformed(ActionEvent arg0) {
viewer.setImage(getRandomImage(random));
}
};
Timer timer = new Timer(1500,animate);
timer.start();
}
};
SwingUtilities.invokeLater(r);
}
}
I modified your code , I hope it will fulfill your requirement. I use MigLayout (it is a Layout manager) to arrange the component.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
public class MyFileChooser
{
JFrame frame;
JPanel panel;
JButton btnBrowse;
JButton change;
JLabel imglabel;
File targetFile;
BufferedImage targetImg;
private static final int baseSize = 128;
private static final String basePath ="/images/fimage";
JPanel panel_1;
ImageIcon icon;
public MyFileChooser()
{
// TODO Auto-generated constructor stub
frame =new JFrame();
frame.setLayout(new MigLayout());
frame.setSize(300, 300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel=new JPanel(new MigLayout());
panel_1 = new JPanel();
panel_1.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(5, 5, 5), 1, true));
panel_1.setBackground(Color.pink);
btnBrowse=new JButton("browse");
btnBrowse.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
browseButtonActionPerformed(e);
}
});
change=new JButton("Delete");
change.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e)
{
// TODO Auto-generated method stub
changeButtonActionPerformed(e);
}
private void changeButtonActionPerformed(ActionEvent e)
{
// TODO Auto-generated method stub
imglabel.revalidate(); //ADD THIS AS WELL
imglabel.repaint(); //ADD THIS AS WELL
imglabel.setIcon(null);
System.out.println("delete button activated");
}
});
imglabel=new JLabel("Image");
imglabel.setSize(100, 100);
imglabel.setBackground(Color.yellow);
frame.add(panel_1,"span,pushx,pushy,growx,growy");
frame.add(btnBrowse);
frame.add(change,"");
//frame.pack();
}
protected void browseButtonActionPerformed(ActionEvent e)
{
JFileChooser fc = new JFileChooser(basePath);
fc.setFileFilter(new JPEGImageFileFilter());
int res = fc.showOpenDialog(null);
// We have an image!
try {
if (res == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
imglabel.setIcon(null);
setTarget(file);
} // Oops!
else {
JOptionPane.showMessageDialog(null,
"You must select one image to be the reference.", "Aborting...",
JOptionPane.WARNING_MESSAGE);
}
} catch (Exception iOException) {
}
}
public BufferedImage rescale(BufferedImage originalImage)
{
BufferedImage resizedImage = new BufferedImage(baseSize, baseSize, BufferedImage.TYPE_INT_RGB);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, baseSize, baseSize, null);
g.dispose();
return resizedImage;
}
public void setTarget(File reference)
{
try {
targetFile = reference;
targetImg = rescale(ImageIO.read(reference));
} catch (IOException ex) {
// Logger.getLogger(MainAppFrame.class.getName()).log(Level.SEVERE, null, ex);
}
panel_1.setLayout(new BorderLayout(0, 0));
icon=new ImageIcon(targetImg);
imglabel=new JLabel(icon);
panel_1.add(imglabel);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
new MyFileChooser();
}
});
}
}
JPEGImageFileFilter class , you can keep this class in same pakage
import java.io.File;
import javax.swing.filechooser.FileFilter;
public class JPEGImageFileFilter extends FileFilter implements FileFilter
{
public boolean accept(File f)
{
if (f.getName().toLowerCase().endsWith(".jpeg")) return true;
if (f.getName().toLowerCase().endsWith(".jpg")) return true;
if(f.isDirectory())return true;
return false;
}
public String getDescription()
{
return "JPEG files";
}
}

Categories

Resources