My image is like a frame which is transparent in the middle. I want to make it as background image of a JPanel. I have done this but for the transparent part of image, white color is coming. I want to remove this white color so that the components below this Jpanel become visible.
My code for custom JPanel is
public class JPanelWithBackground extends JPanel {
private static final long serialVersionUID = 1L;
Image imageOrg = null;
Image image = null;
{
addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
int w = JPanelWithBackground.this.getWidth();
int h = JPanelWithBackground.this.getHeight();
image = w>0&&h>0?imageOrg.getScaledInstance(w,h,
java.awt.Image.SCALE_SMOOTH):imageOrg;
JPanelWithBackground.this.repaint();
});
}
public JPanelWithBackground(Image image2) {
imageOrg=image2;
image=image2;
setOpaque(false);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (image!=null)
g.drawImage(image, 0, 0, null);
}
}
I don't have any particular problem with your code. The problem is probably that your image is not transparent as you expect.
Here is an example that seems to work perfectly (I only took the liberty to fix minor issues in your code):
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class JPanelWithBackground extends JPanel {
private static final long serialVersionUID = 1L;
Image imageOrg = null;
public JPanelWithBackground(Image image2) {
imageOrg = image2;
setOpaque(false);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(imageOrg.getWidth(this), imageOrg.getHeight(this));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (imageOrg != null) {
System.err.println("painting");
g.drawImage(imageOrg, 0, 0, getWidth(), getHeight(), this);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanelWithBackground panel = new JPanelWithBackground(new ImageIcon(new URL(
"http://www.lemondedemario.fr/images/dossier/bowser/bowser.png")).getImage());
JPanel greenPanel = new JPanel(new BorderLayout());
greenPanel.setBackground(Color.GREEN);
greenPanel.add(panel);
frame.add(greenPanel);
frame.pack();
frame.setVisible(true);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
Related
I been trying to figure out a way to re-load an image after it has suffer changes. For that I create a refresh button and my plan is, when clicking in this "reload" button re-load the original image so that we can see the new alterations that the file suffer(from an external software like W10 paint).
I tried quite a few things, one of them was using the flush method to attemp to reload the image, but to not avail.
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class ImageTest {
public static void main(String[] args) throws IOException {
new ApplicationView1();
}
static class ApplicationView1 extends JFrame{
JButton btnReload;
ImagePanel imagePanel;
public ApplicationView1() throws IOException {
initComponents();
addEventListeners();
setTitle("Pokemon Tile Creator");
setPreferredSize(new Dimension(200, 360));
setResizable(false);
setVisible(true);
pack();
}
private void initComponents() throws IOException {
btnReload = new JButton("Reload");
BufferedImage bufferedImage = ImageIO.read(new File("C:/Florest_PixelArt.png"));
imagePanel = new ImagePanel(bufferedImage);
setLayout(new BorderLayout());
add(btnReload, BorderLayout.PAGE_START);
add(imagePanel, BorderLayout.CENTER);
}
private void addEventListeners() {
btnReload.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
imagePanel.image = ImageIO.read(new File("C:/Florest_PixelArt.png"));
repaint();
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
});
}
}
static class ImagePanel extends JPanel{
public BufferedImage image;
public ImagePanel(BufferedImage image) {
this.image = image;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
}
}
I'm trying to print a string that the user can enter to a textbox, to a JFrame.
My problem is that the paintComponent method is never being called. Why?
PNGCreatorWindow Class:
public class PNGCreatorWindow {
private JFrame frame;
private JTextField txtText;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
PNGCreatorWindow window = new PNGCreatorWindow();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public PNGCreatorWindow() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 678, 502);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
txtText = new JTextField();
txtText.setBounds(121, 13, 216, 22);
frame.getContentPane().add(txtText);
txtText.setColumns(10);
JButton btnGenerate = new JButton("Generate");
btnGenerate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
}
});
btnGenerate.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
GeneratePNGImage();
}
});
btnGenerate.setBounds(436, 6, 183, 36);
frame.getContentPane().add(btnGenerate);
JPanel panel = new JPanel();
panel.setBounds(107, 151, 338, 160);
frame.getContentPane().add(panel);
}
protected void GeneratePNGImage() {
PNGImage img = new PNGImage(txtText.getText());
frame.getContentPane().add(img);
frame.getContentPane().validate();
frame.getContentPane().setVisible(true);
frame.repaint();
}
}
PNGImage Class:
public class PNGImage extends JComponent {
private String text;
public PNGImage(String text){
this.text = text;
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setColor(Color.red);
g2.drawString(this.text, 100,100);
g2.fillRect(50, 50, 1000, 1000);
}
}
I made a few changes to your code to get it to draw the text on the JPanel.
I put the JTextField and the JButton inside of a control panel (JPanel) and set a layout manager (FlowLayout) for the control panel. You should always use a layout manager for laying out Swing components.
I defined the image panel (PNGImage) as part of the laying out of the Swing components. First, you lay all of the Swing components out. Then, you change their state.
I removed the mouse adapter and just used an action listener on the JButton. The action listener works with the mouse.
In the PNGImage class, I added a setter, so I could pass the text to the class later, after the user typed the text in the JTextField.
I added a call to setPreferredSize so that I could set the size of the drawing canvas. I removed all other sizing, and used the pack method of JFrame to make the JFrame the appropriate size to hold the Swing components.
I added a null test to paintComponent, so that the text would only be drawn when there was some text to draw.
Here's the code. I put all the code in one module to make it easier to paste.
package com.ggl.testing;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class PNGCreatorWindow {
private JFrame frame;
private JTextField txtText;
private PNGImage imagePanel;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
new PNGCreatorWindow();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public PNGCreatorWindow() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel controlPanel = new JPanel();
controlPanel.setLayout(new FlowLayout());
txtText = new JTextField(10);
controlPanel.add(txtText);
JButton btnGenerate = new JButton("Generate");
btnGenerate.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
generatePNGImage();
}
});
controlPanel.add(btnGenerate);
imagePanel = new PNGImage();
frame.getContentPane().add(controlPanel, BorderLayout.NORTH);
frame.getContentPane().add(imagePanel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
protected void generatePNGImage() {
imagePanel.setText(txtText.getText());
imagePanel.repaint();
}
public class PNGImage extends JPanel {
private static final long serialVersionUID = 602718701626241645L;
private String text;
public PNGImage() {
setPreferredSize(new Dimension(400, 300));
}
public void setText(String text) {
this.text = text;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (this.text != null) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.red);
g2.drawString(this.text, 100, 100);
}
}
}
}
Edited to add an action listener that saves the contents of a JPanel as a .png file:
package com.ggl.crossword.controller;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import com.ggl.crossword.view.CrosswordFrame;
public class CreateImageActionListener implements ActionListener {
private CrosswordFrame frame;
private JPanel panel;
public CreateImageActionListener(CrosswordFrame frame,
JPanel panel) {
this.frame = frame;
this.panel = panel;
}
#Override
public void actionPerformed(ActionEvent event) {
writeImage();
}
public void writeImage() {
FileFilter filter =
new FileNameExtensionFilter("PNG file", "png");
JFileChooser fc = new JFileChooser();
fc.setFileFilter(filter);
int returnValue = fc.showSaveDialog(frame.getFrame());
if (returnValue == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
if (!file.getAbsolutePath().endsWith(".png")) {
file = new File(file.getAbsolutePath() + ".png");
}
RenderedImage image = createImage(panel);
try {
ImageIO.write(image, "png", file);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private BufferedImage createImage(JPanel panel) {
int w = panel.getWidth();
int h = panel.getHeight();
BufferedImage bi = new BufferedImage(w, h,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = bi.createGraphics();
panel.paint(g);
g.dispose();
return bi;
}
}
I didn't know how, and there is no background image property. I researched the answer but all I could find was to set a labels icon inside a panel with a null layout. This worked and my image is there, but it is covering all but a single text field. Can I change the Z value of this label? I do not see a 'move to back' option, if there is one.
This should solve your problem:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestImage {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ContentPane panel = new ContentPane();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
});
}
private static class ContentPane extends JPanel {
BufferedImage image = null;
public ContentPane() {
try {
String pathToImage = "C:/Users/Branislav/Pictures/sun.jpg";
image = ImageIO.read(new File(pathToImage));
} catch (IOException e) {
e.printStackTrace();
}
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
};
#Override
public Dimension getPreferredSize() {
return new Dimension(image.getWidth(), image.getHeight());
}
}
}
Basically, I set image on JPanel (ContentPane). Also, size of your JPanel depends on size of image (at least in this case).
Regards.
I have Code where I can move image.
Everything works well.
here I have only one ImagePanel (children of JPanel) on the frame.
Questions:
I need to drag and drop image from one JPanel to another JPanel.
Then I need to move dragged image to current panel.
Can you give me an example code, please?
class ImagePanel extends JPanel {
int x, y;
BufferedImage image;
ImagePanel() {
setBackground(Color.white);
setSize(450, 400);
addMouseMotionListener(new MouseMotionHandler());
Image img = getToolkit().getImage("C:\\2.png");
MediaTracker mt = new MediaTracker(this);
mt.addImage(img, 1);
try {
mt.waitForAll();
} catch (Exception e) {
System.out.println("Image not found.");
}
image = new BufferedImage(img.getWidth(this), img.getHeight(this),BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = image.createGraphics();
g2.drawImage(img, 0, 0, this);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
g2D.drawImage(image, x, y, this);
}
class MouseMotionHandler extends MouseMotionAdapter {
public void mouseDragged(MouseEvent e) {
x = e.getX();
y = e.getY();
repaint();
}
public void mouseMoved(MouseEvent e) {
}
}
}
I need to do that code, with this following design. I need to add image with some layout (I don't need to done this with Point pixels). or how to add image with some layout? for example Grid bag layout. I don't need Points (x,y). because I need to add another components too.
public class DragAndDrop {
private JFrame frame;
/* .. another component here .. */
private JPanel leftPanel; // here is my image
public JPanel rightContentPanel; // destination of dragable image
public static void main(String[] args) {
DragAndDrop window = new DragAndDrop();
}
public DragAndDrop() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.getContentPane().setLayout(new BorderLayout(0, 0));
leftPanel = new leftPanel();
/* add components to left panel */
rightContentPanel = new rightPanel();
/* add component to right panel */
frame.getContentPane().add(rightContentPanel, BorderLayout.CENTER);
frame.getContentPane().add(leftPanel, BorderLayout.WEST);
frame.setVisible(true);
frame.setResizable(false);
}
}
class leftPanel extends JPanel {
/ ... /
}
class rightPanel extends JPanel{
/ ... /
}
There's probably any number of ways to achieve what you want. You could use the glass pane or JXLayer or you could stop treating the two panels as separate elements and more like they were just windows into a large virtual space.
This example basically treats the parent component as the "virtual space" into which the two image panes are windows.
They both share the same image and image location details. They, individual, convert the image location (which is in virtual coordinates) to local coordinates and draw as much of the image as would appear on them...
Mouse control is maintained by the parent. This greatly simplifies the process, as it can notify both the panels simultaneously
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
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.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
public class CrossImage {
public static void main(String[] args) {
new CrossImage();
}
public CrossImage() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage img;
private ImagePane left;
private ImagePane right;
private Point imagePoint;
public TestPane() {
setBorder(new EmptyBorder(10, 10, 10, 10));
setLayout(new GridLayout(0, 2, 10, 10));
left = new ImagePane();
right = new ImagePane();
imagePoint = new Point(10, 10);
left.setImageLocation(imagePoint);
right.setImageLocation(imagePoint);
try {
img = ImageIO.read(new File("Background.jpg"));
left.setImage(img);
right.setImage(img);
} catch (IOException ex) {
ex.printStackTrace();
}
add(left);
add(right);
MouseAdapter mouseHandler = new MouseAdapter() {
private Point delta;
#Override
public void mousePressed(MouseEvent e) {
Point origin = e.getPoint();
Rectangle bounds = new Rectangle(imagePoint, new Dimension(img.getWidth(), img.getHeight()));
if (bounds.contains(origin)) {
delta = new Point(origin.x - imagePoint.x, origin.y - imagePoint.y);
}
}
#Override
public void mouseDragged(MouseEvent e) {
if (delta != null) {
imagePoint = e.getPoint();
imagePoint.translate(-delta.x, -delta.y);
left.setImageLocation(imagePoint);
right.setImageLocation(imagePoint);
}
}
#Override
public void mouseReleased(MouseEvent e) {
delta = null;
}
};
addMouseListener(mouseHandler);
addMouseMotionListener(mouseHandler);
}
}
public class ImagePane extends JPanel {
private Image image;
private Point imageLocation;
public ImagePane() {
setBorder(new LineBorder(Color.DARK_GRAY));
}
#Override
public Dimension getPreferredSize() {
return image == null ? super.getPreferredSize() : new Dimension(image.getWidth(this), image.getHeight(this));
}
public void setImage(Image image) {
this.image = image;
repaint();
}
public void setImageLocation(Point imageLocation) {
this.imageLocation = imageLocation;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null && imageLocation != null) {
Point p = SwingUtilities.convertPoint(getParent(), imageLocation, this);
g.drawImage(image, p.x, p.y, this);
}
}
}
}
How can I set the wall1.jpg as background to my JFrame or JPanel?
public class JBackGroundImageClass extends JFrame
{
Image img;
private final JPanel JPanel;
public JBackGroundImageClass()
{
setLayout (new BorderLayout ());
setBounds(22,33,400, 400);
setVisible(true);
img = Toolkit.getDefaultToolkit().createImage("wall1.jpg");
JPanel = new JPanel()
{
public void paintComponent(Graphics g)
{img = Toolkit.getDefaultToolkit().createImage("wall1.jpg");
g.drawImage(img, 0, 0, null);
}
};
this.add("North" , JPanel);
JPanel.setSize(400, 400);
JPanel.setBackground(Color.red);
JPanel.setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args)
{
new JBackGroundImageClass().setVisible(true);
}
}
Here's one common approach:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class JBackGroundImageClass extends JFrame {
private Image img;
public JBackGroundImageClass() {
this.setLayout(new BorderLayout());
try {
img = ImageIO.read(new File("image.jpg"));
} catch (IOException e) {
e.printStackTrace(System.err);
}
this.add(new JPanel() {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img, 0, 0, null);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(img.getWidth(null), img.getHeight(null));
}
});
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setVisible(true);
}
public static void main(String[] args) throws IOException {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new JBackGroundImageClass().setVisible(true);
}
});
}
}
In the answer by trashgod, there is no reason to do custom painting. The image is painted at its preferred size. Therefore you can just add an ImageIcon to a JLabel and add the label to the frame. You can set the layout manager of the label to be anything you want, the same as you can for a panel.
You would use custom painting is you want to scale the image in which case you would use:
drawImage(Image img, int x, int y, int width, int height, ImageObserver observer)