import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class MainWindow extends JFrame{
public static void main(String[] args) {
JFrame mainWindow = new JFrame("Siege Arena");
mainWindow.setResizable(false);
mainWindow.setVisible(true);
mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainWindow.setSize(500, 500);
loadpics();
}
Image bg;
public void loadpics(){
bg = new ImageIcon("C:\\test\\Background.png").getImage();
repaint();
}
public void paint(Graphics g){
g.drawImage(bg,0,0,null);
}
}
All I am trying to do is create a JFrame and load a simple image on to it, How exactly do i do that. Here I tried, and failed. Can someone help me?
Can someone see what is wrong?
Extendng from JFrame, you're not adding any new functionality and you're locking yourself into a single use of the component
Override paint of top level containers, like JFrame, it's far to easy (like you have) to break the paint chain which gives no end of problems
Not calling super.paint and breaking the paint chain
Not passing a ImageObserver to ImageIcon
Referencing the wrong instance of MainWindow when you try and load the image.
If I "guess" correctly, you are trying to paint a background image into a window. If so, then the way you've tried is DEFIANTLY not the way to go about it.
Instead...
Start with a custom component which extends from something JPanel
Use the paintComponent method to draw the image
Consider using ImageIO instead of ImageIcon. ImageIO will throw an exception if the image can't be loaded.
For example...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
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.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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.setContentPane(new BackgroundPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class BackgroundPane extends JPanel {
private BufferedImage bg;
public BackgroundPane() {
try {
bg = ImageIO.read(new File("C:\\test\\Background.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return bg == null ? new Dimension(200, 200) : new Dimension(bg.getWidth(), bg.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bg == null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - bg.getWidth()) / 2;
int y = (getHeight() - bg.getHeight()) / 2;
g2d.drawImage(bg, x, y, this);
g2d.dispose();
}
}
}
}
Take a look at:
Painting in AWT and Swing
Performing Custom Painting
Reading/Loading an Image
for more details...
Related
I'm a beginner in Java and I would like to load an image with this script:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;
/**
* This class demonstrates how to load an Image from an external file
*/
public class LoadImageApp extends Component {
BufferedImage img;
public void paint(Graphics g) {
g.drawImage(img, 0, 0, null);
}
public LoadImageApp() {
try {
img = ImageIO.read(getClass().getResource("/resources/java.png"));//cannot found image
} catch (IOException e) {
}
}
public Dimension getPreferredSize() {
if (img == null) {
return new Dimension(100,100);
} else {
return new Dimension(img.getWidth(null), img.getHeight(null));
}
}
public static void main(String[] args) {
JFrame f = new JFrame("Load Image Sample");
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.add(new LoadImageApp());
f.pack();
f.setVisible(true);
}
}
Then I put a picture on a folder resource "resources", change the name of the location of the picture like "/resources/java.png" and when I compile, there is an empty window without image.
You can see error here : https://ibb.co/ysjNyQw
The first thing you're going to want to do is do some research into "embedded resources", for example
I don't use Eclipse, I use Netbeans, but the process should be the same
As you can see, I've placed my image in the resources package within the projects "sources". This will ensure that it's available at runtime via the class path search mechanism (and embedded within the resulting Jar file when I export it).
I then used a JLabel to display it...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
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 Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
BufferedImage image = ImageIO.read(getClass().getResource("/resources/java.png"));
JLabel label = new JLabel(new ImageIcon(image));
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(label);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
}
Now, if you want to continue using a custom painting route, I suggest having a read of:
Performing Custom Painting
Painting in AWT and Swing
to get a better understanding of how painting works in Swing and how you should work with it
This question already has answers here:
How to draw an image over another image?
(2 answers)
Closed 5 years ago.
I Have used JPanel to embed two images. One is png image and another is jpeg. I have to overlay png image over jpeg. I have tried out. Please fix me if, I am wrong.
import java.awt.*;
import java.io.IOException;
import javax.swing.*;
public class Test extends JFrame
{
public Test()
{
super();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(1366,768);
onInit();
setVisible(true);
}
private void onInit()
{
JPanel panel=new JPanel();
panel.setLayout(null);
panel.setBounds(0,0,1366,768);
panel.setBackground(new Color(0,0,0,0));
JLayeredPane lp = getLayeredPane();
lp.setBounds(0,0,1366,768);
JLabel adLabel1=new JLabel();
adLabel1.setBounds(0,0,1366,768);
Image img1=new ImageIcon("F:\\wall papers\\Download-High-Res-Crazy-Concrete-Textures.jpg").getImage();
ImageIcon ad1=new ImageIcon(img1.getScaledInstance(1366,768,Image.SCALE_SMOOTH));
adLabel1.setIcon(ad1);
JLabel adLabel2 = new JLabel();
adLabel2.setBounds(0, 0, 1366, 768);
Image img2=new ImageIcon("<path>\\A100004.png").getImage();
ImageIcon ad2=new ImageIcon(img2.getScaledInstance(1366,768,Image.SCALE_SMOOTH));
adLabel2.setIcon(ad2);
adLabel2.setBackground(new Color(0,0,0,0));
adLabel2.revalidate();
lp.add(adLabel1,JLayeredPane.MODAL_LAYER);
lp.add(adLabel2,JLayeredPane.DRAG_LAYER);
panel.add(lp);
}
public static void main(String args[])
{
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new Test();
}
});
}
}
If I do not use JPanel it is working, it shows only a blank panel. But I want it to be done in the JPanel.
Example:
and I tried with this png image:
You have a number of possible solutions, you could, for example try:
Using a GridBagLayout, although that would become insanely complex really quickly
Create you own LayoutManager, but that's probably overkill for the problem
Use a OverlayLayout manager, but since I don't have any experience with it, I can't say if it would solve your issue or not.
Or, you could...
Take control of the whole process and fallback to custom painting. This gives you the same level of flexibility as writing your own LayoutManager, but without the complexity and since you're only drawing images, makes a life a whole lot simpler.
If you need to display other components (like text or text fields) you could use a custom painting route to render the images as the background and one or layout mangers to deal with the other components.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
try {
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public class TestPane extends JPanel {
private BufferedImage background;
private BufferedImage foreground;
public TestPane() throws IOException {
background = ImageIO.read(getClass().getResource("Background.png"));
foreground = ImageIO.read(getClass().getResource("Foreground.png"));
}
#Override
public Dimension getPreferredSize() {
return background == null ? new Dimension(200, 200) : new Dimension(background.getWidth(), background.getHeight());
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int x = 0;
int y = 0;
int width = getWidth();
if (background != null) {
x = (getWidth() - background.getWidth()) / 2;
y = (getHeight() - background.getHeight()) / 2;
width = background.getWidth();
g2d.drawImage(background, x, y, this);
}
if (foreground != null) {
x = x + width - foreground.getWidth();
g2d.drawImage(foreground, x, y, this);
}
g2d.dispose();
}
}
}
I want to create a line and after 2 sec break another line and so on.
If i draw a line and pause program execution with Thread.sleep() and again draw a line within paintComponent() method then what happens is first the program stops for 2 second and then both lines are drawn simultaneously.
how to overcome this problem?
This is realitvely commong requirement and issue. You should start by having a look at Concurrency in Swing and How to use Swing Timers for some basic information on how to solve the your basic problem.
You should also have a look at Painting in AWT and Swing and Performing Custom Painting for more information about how painting works in Swing
The core design choices you want to focus on are:
Don't block the Event Dispatching Thread, this will prevent it from painting anything or responding to new events
Don't update the UI from outside the context of the EDT
Painting should paint state. It should not be focused on making logical decisions where possible, instead, it should reliant on one or more models to provide it the information it needs to paint itself
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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 {
private List<Shape> shapes;
private int yPos = 0;
public TestPane() {
shapes = new ArrayList<>(25);
Timer timer = new Timer(2000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
yPos += 10;
Line2D line = new Line2D.Double(0, yPos, getWidth(), yPos);
shapes.add(line);
repaint();
}
});
timer.setInitialDelay(2000);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (Shape line : shapes) {
g2d.draw(line);
}
g2d.dispose();
}
}
}
I am trying to load image in JPanel and after that I want to write an image caption also. At the moment I am not able to load the image. I do not want to use JLabel. Instead I want to use paint Component. Here is the code
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class imageCaptio extends JFrame {
private JPanel caption = new JPanel(){
ClassLoader cl = getClass().getClassLoader();
Image i;
{
try {
i = ImageIO.read(cl.getResourceAsStream("res/car.jpg"));
} catch (IOException ex) {
Logger.getLogger(imageCaptio.class.getName()).log(Level.SEVERE, null,
ex);
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g.create();
// get scaling instance to scale the image to the component
AffineTransform imageAdjust =
AffineTransform.getScaleInstance((float)getWidth()/i.getWidth(this),
(float)getHeight()/i.getHeight(this));
// draw the image using the separate transform
if (i != null)
g2.drawImage(i, imageAdjust, this);
}
};
private imageCaptio() {
// Invoke the JFrame superclass constructor and configure the frame
super("image caption");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(800,800);
this.setVisible(true);
// Add a panel to the frame and draw the face within it.
this.add(caption);
}
public static void main(String[] args) {
// Create on the Event Dispatch Thread.
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new imageCaptio();
}
});
}
}
I'm trying to make a simple GUI program without using JComponents.
Currently, I have a BufferedImage that I draw to off screen so that it doesn't flicker (or so I thought).
I made a new program here to replicate the issue:
package Main;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class Main {
private final static JFrame frame = new JFrame();
private final static Panel panel = new Panel();
public static void main(String[] args) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(new Dimension(1000, 750));
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
while (true) {
panel.setBackgroundColour(Color.WHITE);
panel.setBackgroundColour(Color.BLACK);
panel.repaint();
}
}
private static class Panel extends JPanel {
private final BufferedImage offScreen = new BufferedImage(1000, 750, BufferedImage.TYPE_INT_ARGB);
private final Graphics graphics = offScreen.getGraphics();
#Override
protected void paintComponent(Graphics graphics) {
graphics.drawImage(offScreen, 0, 0, null);
}
public void setBackgroundColour(Color colour) {
graphics.setColor(colour);
graphics.fillRect(0, 0, 1000, 750);
}
}
}
In the example above, I made the screen turn black, and then white (offscreen).
What I'd expect is that paintComponent() only displays the white screen.
Instead, a black screen is showed as well, but everything is flickered.
Am I just using Graphics2D incorrectly, or should I just use BufferStrategy to incorporate my double buffering needs?
My best guess is you have a race condition, where your while-loop is trying to update the BufferedImage, but Swing is also trying to paint it, meaning they are getting dirty updates between them. Also, you might be thrashing the Event Dispatching Thread, which could have it's own, long term issues.
After some playing around, I was able to get something like this to work...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main {
private final static JFrame frame = new JFrame();
private final static Panel panel = new Panel();
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(new Dimension(1000, 750));
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
}
});
while (true) {
panel.setBackgroundColour(Color.WHITE);
panel.setBackgroundColour(Color.BLACK);
panel.repaint();
try {
Thread.sleep(40);
} catch (InterruptedException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private static class Panel extends JPanel {
private BufferedImage offScreen = new BufferedImage(1000, 700, BufferedImage.TYPE_INT_ARGB);
#Override
protected void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
graphics.drawImage(offScreen, 0, 0, this);
}
public void setBackgroundColour(Color colour) {
Graphics graphics = offScreen.getGraphics();
graphics.setColor(colour);
graphics.fillRect(0, 0, 1000, 700);
graphics.dispose();
}
}
public static BufferedImage createCompatibleImage(int width, int height, int transparency) {
BufferedImage image = getGraphicsConfiguration().createCompatibleImage(width, height, transparency);
image.coerceData(true);
return image;
}
public static GraphicsConfiguration getGraphicsConfiguration() {
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
}
}
All it does is injects a small delay (25fps) between the updates, allowing Swing time to render the result.
You have to remember at two things with Swing, repaint doesn't happen immediately and may not happen at all, depending on what the RepaintManager decides to do. Second, you don't control the painting process.
Swing uses a passive rendering algorithm, meaning that painting will occur when it's needed, many times without your knowledge or intervention. The best you can do is make suggestions to the framework when you want something updated
See Painting in AWT and Swing and Performing Custom Painting for more details.