drawing your own buffered image on frame - java

I have a buffered image with the sizes of my frame:
public BufferedImage img;
public static int WIDTH = 800;
public static int HEIGHT = 600;
img=new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
How can I draw it so I can see just a black image filling the frame? without using Canvas
I want to use only the drawImage function from graphics without using the paint or paintComponent functions
If it is possible, how can i assign an 1D array [WIDTH*HEIGHT] to that image?
SIMPLY: I want to create an image ,convert the values from an array to pixels (0=black,999999999=lightblue etc.) and draw it to the screen.
EDIT:
This is the code that does not work as expected (it should be a frame with a black drawn image on it) but is just a blank frame.Why the image is not added tot the frame?
import javax.swing.*;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
public class test extends Canvas{
public static JFrame frame;
public static int WIDTH = 800;
public static int HEIGHT = 600;
public test(){
}
public static void main(String[] a){
test t=new test();
frame = new JFrame("WINDOW");
frame.add(t);
frame.pack();
frame.setVisible(true);
frame.setSize(WIDTH, HEIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
t.start();
}
public void start(){
BufferedImage img = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
int[] pixels = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();
boolean running=true;
while(running){
BufferStrategy bs=this.getBufferStrategy();
if(bs==null){
createBufferStrategy(4);
return;
}
for (int i = 0; i < WIDTH * HEIGHT; i++)
pixels[i] = 0;
Graphics g= bs.getDrawGraphics();
g.drawImage(img, 0, 0, WIDTH, HEIGHT, null);
g.dispose();
bs.show();
}
}}

As far as I understand what you are trying to achieve (which is 'not a lot'), this might give you some tips. The construction of the frame and image still seems untidy to me, but have a look over this.
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.*;
public class TestImageDraw {
public static JFrame frame;
BufferedImage img;
public static int WIDTH = 800;
public static int HEIGHT = 600;
public TestImageDraw() {
}
public static void main(String[] a){
TestImageDraw t=new TestImageDraw();
frame = new JFrame("WINDOW");
frame.setVisible(true);
t.start();
frame.add(new JLabel(new ImageIcon(t.getImage())));
frame.pack();
// frame.setSize(WIDTH, HEIGHT);
// Better to DISPOSE than EXIT
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
public Image getImage() {
return img;
}
public void start(){
img = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
int[] pixels = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();
boolean running=true;
while(running){
BufferStrategy bs=frame.getBufferStrategy();
if(bs==null){
frame.createBufferStrategy(4);
return;
}
for (int i = 0; i < WIDTH * HEIGHT; i++)
pixels[i] = 0;
Graphics g= bs.getDrawGraphics();
g.drawImage(img, 0, 0, WIDTH, HEIGHT, null);
g.dispose();
bs.show();
}
}
}
General Tips
Please use a consistent and logical indent for code blocks.
Please learn common Java naming conventions (specifically the case used for the names) for class, method & attribute names & use it consistently.
Give test classes a meaningful name e.g. TestImageDraw.
Create and update Swing GUIs on the EDT.
Don't mix Swing & AWT components without good reason.

Related

Set image background java

I started programming in SWING class recently and I try to set Image (like Space) and on it image(like spaceShip) like background. I
would love for you to help me,
Here is my code
public class SpaceWar {
static JFrame frame = new JFrame("Space War");
static JPanel panel = new JPanel();
public static void main(String[] args) {
new SpaceWar();
//frame.setResizable(false);
frame.setVisible(true);
}
public SpaceWar() {
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
Dimension size
= Toolkit.getDefaultToolkit().getScreenSize();
frame.setPreferredSize(size);
frame.setLayout(null);
panel.setLayout(null);
panel.setBounds(frame.getPreferredSize().width/4,0,
frame.getPreferredSize().width/2,frame.getPreferredSize().height);
frame.add(panel);
frame.add(new Background());
spaceShip sp1 = new spaceShip();
panel.setBackground(Color.black);
panel.add(sp1);
System.out.println(panel.getPreferredSize().width);
}
}
class spaceShip extends JLabel{
static ImageIcon img = new ImageIcon("spaceShip.png");
public spaceShip(){
sizeIcon(100,100,img);
setIcon(img);
}
public static ImageIcon sizeIcon(int w,int h,ImageIcon image1){
Image image = image1.getImage(); // transform it
Image newimg = image.getScaledInstance(w,h, java.awt.Image.SCALE_SMOOTH); // scale it the smooth way
ImageIcon img1 = new ImageIcon(newimg); // transform it back
return img1;
}
}
class Background extends JPanel{
public void paint(Graphics g) { // paint() method
super.paint(g);
ImageIcon image = new ImageIcon("space.jpg");
Image bg = image.getImage();
g.drawImage(bg,0,0,null);
}
}
So, your "core" problem is the use of null layouts and a lack of understand of how components are sized and positioned. Having said that, if your aim is to make a game, this probably isn't the best approach anyway.
Instead, I'd focus on creating a "surface", onto which you can paint all your assets directly, this will give you much greater control.
Start by taking a look at Painting in AWT and Swing and Performing Custom Painting to get a better understanding how the paint system works and how you can work with it to perform custom painting.
I'd also avoid ImageIcon, it's not the best way to handle images, instead, take a look at ImageIO (Reading/Loading an Image), it will generate an IOException if the image can't be loaded and will return a fully realised image (unlike ImageIcon which off loads the image loading to a background thread).
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.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
JFrame frame = new JFrame();
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public class MainPane extends JPanel {
private BufferedImage ufo;
private BufferedImage background;
private int horizontalPosition = 106;
public MainPane() throws IOException {
ufo = ImageIO.read(getClass().getResource("/images/ufo.png"));
background = ImageIO.read(getClass().getResource("/images/starfield.png"));
System.out.println("background = " + background);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
paintBackground(g2d);
paintUFO(g2d);
g2d.dispose();
}
protected void paintBackground(Graphics2D g2d) {
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g2d.drawImage(background, x, y, this);
}
protected void paintUFO(Graphics2D g2d) {
int x = (getWidth() - ufo.getWidth()) / 2;
int y = (getHeight() - ufo.getHeight()) / 2;
g2d.drawImage(ufo, x, y, this);
}
}
}
The example makes use of embedded resources (something to read up on). Managing your assets this way will save you countless hours of wondering why they aren't loading/working. How you achieve this will come down to your IDE and build system, for example, Netbeans and Eclipse will allow you to add resources directly to the src directory, when you're not using maven.
At some point, you're going to want to learn about How to Use Swing Timers and How to Use Key Bindings

Graphics - Use a parameter (getSize()) to draw a line throughout the whole window

I need help here. I want to give a parameter to the drawLine() method which I get from getSize(). I want to draw a line throughout the whole window by using the getSize() method.
package PROG2;
import java.awt.*;
import javax.swing.*;
class MyComponent extends JComponent {
#Override
public void paintComponent(Graphics g) {
g.drawLine(100, 100, 200, 200);
}
}
public class Übung1 extends JFrame{
public static void berechnen() {
int height = frame.getHeight(); //Here it says it doesn't know "frame" variable but I don't know how to declare it here.
int width = frame.getWidth();
}
public static void main(String[] args){
JFrame frame = new JFrame("First window");
berechnen();
frame.add(new MyComponent());
frame.setSize(400, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Graphics g = frame.getGraphics();
// int width = frame.getWidth();
// int height = frame.getHeight();
System.out.println("Größe:" + frame.getSize());
//System.out.println(width);
}
}
As Andrew already stated,
you don't want to get the dimensions or size of the JFrame but rather the component that is being displayed within the JFrame's contentPane, here your MyComponent instance.
The best place to get that information is inside of the paintComponent method itself, just prior to drawing the line.
And always call the super's painting method first
I also recommend:
Draw within a JPanel's paintComponent method, not a JComponent, if you want an opaque image
Avoid static methods and fields unless absolutely needed
Note that in the code below, the red line draws through the JPanel's diagonal, and continues to draw the diagonal, even when the JFrame is manually resized:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import javax.swing.*;
public class DrawLine extends JPanel {
private static final Stroke LINE_STROKE = new BasicStroke(15f);
private static final Dimension PREF_SIZE = new Dimension(800, 650);
public DrawLine() {
setPreferredSize(PREF_SIZE);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// code to make the line smooth (antialias the line to remove jaggies)
// and to make the line thick, using a wider "stroke"
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(LINE_STROKE);
// if we want a red line
g2.setColor(Color.RED);
// this is the key code here:
int width = getWidth();
int height = getHeight();
// draw along the main diagonal:
g2.drawLine(0, 0, width, height);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
DrawLine mainPanel = new DrawLine();
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}

Java - Missing pixels at the right side of JFrame

I noticed that every JFrame I create doesnt show a few pixels - ~10px at the right side.
I dont know why that happens, but it could be very problematic for my game if I dont fix that.
Here is the code with which I am experimenting:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Resizer {
int width = 500;
int height = 500;
JFrame frame;
JLabel screen;
BufferedImage image;
ImageIcon icon;
public static void main(String[] args) {
Resizer r = new Resizer();
r.runCode();
}
private void runCode() {
createFrame();
javax.swing.Timer t = new javax.swing.Timer(1000/60, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
checkResize();
drawSomething();
}
});
t.start();
}
private void createFrame() {
frame = new JFrame("Resize Experiment");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
screen = new JLabel();
screen.setSize(width, height);
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
icon = new ImageIcon(image);
screen.setIcon(icon);
frame.add(screen);
frame.pack();
frame.setVisible(true);
}
private void checkResize() {
if (frame.getWidth() != width || frame.getHeight() != height) {
screen.setSize(frame.getWidth(), frame.getHeight());
image = new BufferedImage(frame.getWidth(), frame.getHeight(), BufferedImage.TYPE_INT_ARGB);
frame.pack();
width = frame.getWidth();
height = frame.getHeight();
}
}
private void drawSomething() {
Graphics2D pen = image.createGraphics();
pen.setColor(Color.BLACK);
pen.fillRect(0, 0, width, height);
pen.setColor(Color.RED);
pen.drawLine(width, height/2, width-10, height/2);
addImage();
}
private void addImage() {
icon = new ImageIcon(image);
screen.setIcon(icon);
}
}
I noticed it because of the following statement:
pen.drawLine(width, height/2, width-10, height/2);
It should draw a line from the right side of the JFrame to a place 10 pixel further to the left. In reality, I can't see any line at all. It appears once I raise the distance value.
My question is: Why does this happen, and how can I fix this?
I noticed that every JFrame I create doesnt show a few pixels - ~10px at the right side
That is because you are attempting to make your BufferedImage the size of the frame.
The problem is the frame contains "borders". Your image can only be painted inside the borders.
You should NOT be attempting to make the BufferedImage the size of the frame.
As suggested above the custom painting should be done in the paintComponent() method of a JPanel. Then you add the panel to the frame. Inside the paintComponent() method you can use the getWidth() and getHeight() methods of the panel to make sure you paint on the complete area.
I really like how with Graphics2D things aren't stuffed in one method but can be split up
The custom painting done in the paintComponent() method is done with a Graphics2D object, so you can do anything you want. All Swing components are painted in the paintComponent() method.

Java JPanel tiled background image

I currently have the code for creating a JOptionPane that tiles an image to the background no matter the size I set it to :)
package test;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;
public class TiledImage extends JPanel {
BufferedImage tileImage;
public TiledImage(BufferedImage image) {
tileImage = image;
}
protected void paintComponent(Graphics g) {
int width = getWidth();
int height = getHeight();
for (int x = 0; x < width; x += tileImage.getWidth()) {
for (int y = 0; y < height; y += tileImage.getHeight()) {
g.drawImage(tileImage, x, y, this);
}
}
}
public Dimension getPreferredSize() {
return new Dimension(240, 240);
}
public static void main(String[] args) throws IOException {
BufferedImage image = ImageIO.read(new File("./resource/patterngrey.png"));
TiledImage test = new TiledImage(image);
JOptionPane.showMessageDialog(null, test, "", JOptionPane.PLAIN_MESSAGE);
}
}
the problem I am having is using the same code to add an image to a JPanel background in a JFrame
here is what I have:
package test;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;
public class TiledImage extends JPanel {
BufferedImage tileImage;
static JFrame mainFrame = new JFrame("Program Name");
static JPanel userDetailsPanel = new JPanel();
public TiledImage(BufferedImage image) {
tileImage = image;
}
protected void paintComponent(Graphics g) {
int width = getWidth();
int height = getHeight();
for (int x = 0; x < width; x += tileImage.getWidth()) {
for (int y = 0; y < height; y += tileImage.getHeight()) {
g.drawImage(tileImage, x, y, this);
}
}
}
public static void main(String[] args) throws IOException {
mainFrame.setSize(400,400);
mainFrame.setLayout(new BorderLayout());
mainFrame.add(userDetailsPanel, BorderLayout.CENTER);
BufferedImage image = ImageIO.read(new File("./resource/patterngrey.png"));
TiledImage backgroundImage = new TiledImage(image);
// userDetailsPanel.setComponent(backgroundImage); //i know this line is wrong
//but i dont know how to correct it
mainFrame.setVisible(true);
}
}
Any and all help is appreciated if there is a better way of doing it that is a lot less code that would also be great. I do need to add labels and buttons on top of the background once i have my background sorted.
The background needs to be tiled as the application will have a couple of different JPanels in the JFrame with different pattern backgrounds and i would like to make the frame resizable
An instance of java.awt.TexturePaint provides a convenient way to tile a BufferedImage. Related examples may be seen here. Given a TexturePaint, you can fill a component's background fairly easily, as shown here.
private TexturePaint paint;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setPaint(paint);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
You state:
Any and all help is appreciated if there is a better way of doing it that is a lot less code that would also be great.
That's not a lot of code actually. The only thing else I could suggest is that if the JPanel is not going to vary in size, create a background BufferedImage, draw your tiled images in that, and then draw the one background image in either your JPanel's paintComponent method, or in a JLabel's icon. If you go the latter route, then give the JLabel a layout manager so that it can act as a well-behaved container for your components. And make sure that anything on top of your tiled containers is not opaque if the image needs to show through, especially JPanels.
To correct the issue you're currently having, you can set your TiledImage object as the content pane of your JFrame, and then ensure any panels that get added onto it are not opaque.
That is,
public static void main(String[] args) throws IOException {
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BufferedImage image = ImageIO.read(new File("./resource/patterngrey.png"));
TiledImage backgroundImage = new TiledImage(image);
// Make backgroundImage the content pane.
mainFrame.setContentPane(backgroundImage);
mainFrame.setLayout(new BorderLayout());
// Make the userDetailsPanel not opaque.
userDetailsPanel.setOpaque(false);
mainFrame.add(userDetailsPanel, BorderLayout.CENTER);
mainFrame.setSize(400,400);
mainFrame.setVisible(true);
}

Image Drawing Works for JFrame, But Not JPanel

I'm working through some simple applications to get familiar with Swing and running into problems.
I'm attempting to have a frame containing an image (in a panel) along with buttons to zoom in/out from the image.
I have been able to make a frame with the added image work fine (albeit with some frame sizing issues, but that is another story), however, when I call the same component class to add it to a panel, nothing appears. I'm hoping one of you can help shed light on the situation.
CODE:
Image Frame - Is working as shown
class ImageFrame extends JFrame{
public ImageFrame(){
setTitle("Java Image Machine");
init();
pack();
}
public final void init(){
//ZoomPanel zoomPanel = new ZoomPanel();
//ImagePanel imagePanel = new ImagePanel();
ImageComponent component = new ImageComponent();
//this.add(zoomPanel, BorderLayout.CENTER);
this.add(component);
//this.add(imagePanel, BorderLayout.SOUTH);
}
}
However, using the ImagePanel or adding the ZoomPanel simultaneously with the direct ImageComponent call, does not:
class ImagePanel extends JPanel{
public ImagePanel(){
//setBorder(BorderFactory.createLineBorder(Color.black));
ImageComponent component = new ImageComponent();
add(component);
}
}
Component class:
class ImageComponent extends JComponent{
public ImageComponent(){
try{
image = ImageIO.read(new File("test1.bmp"));
}
catch ( IOException e ){
e.printStackTrace();
}
System.out.println("W: " + image.getWidth(this) + " H: " + image.getHeight(this));
}
public void paintComponent( Graphics g ){
super.paintComponent(g);
if (image == null)
return;
width = image.getWidth(this);
height = image.getHeight(this);
//System.out.println("Image should be painted");
g.drawImage(image, 0, 0, null);
}
private Image image;
public int width;
public int height;
}
It works fine for me ( I just tested the ImageComponent class):
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class Test {
/**
* Default constructor Test.class
*/
public Test() {
initComponents();
}
public static void main(String[] args) {
/**
* Create GUI and components on Event-Dispatch-Thread
*/
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Test test = new Test();
}
});
}
/**
* Initialize GUI and components (including ActionListeners etc)
*/
private void initComponents() {
JFrame jFrame = new JFrame();
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//add ImageComponent to JFrame instance
jFrame.add(new ImageComponent());
//pack frame (size JFrame to match preferred sizes of added components and set visible
jFrame.pack();
jFrame.setVisible(true);
}
}
class ImageComponent extends JComponent {
private Image image;
public int width;
public int height;
public ImageComponent() {
try {
image = ImageUtils.scaleImage(300, 300, ImageIO.read(new URL("http://harmful.cat-v.org/software/_java/java-evil-edition.png")));
//image = ImageIO.read(new URL("http://harmful.cat-v.org/software/_java/java-evil-edition.png"));//uses images scale
} catch (Exception e) {
e.printStackTrace();
}
//so we can set the JPanel preferred size to the image width and height
ImageIcon ii = new ImageIcon(image);
width = ii.getIconWidth();
height = ii.getIconHeight();
}
//so our panel is the same size as image
#Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (image == null) {
return;
}
width = image.getWidth(this);
height = image.getHeight(this);
g.drawImage(image, 0, 0, null);
}
}
//class used for scaling images
class ImageUtils {
static Image scaleImage(int width, int height, BufferedImage filename) {
BufferedImage bi;
try {
bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = (Graphics2D) bi.createGraphics();
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(filename, 0, 0, width, height, null);
} catch (Exception e) {
return null;
}
return bi;
}
}
problem might be the path to your file, or the fact that JPanel width and height will not be the same as the pictures thus we override getPrefferedSize(...) of JPanel and return correct size according to Image
Have you tried adding repaint() calls after adding the appropriate components in?
i.e.
class ImagePanel extends JPanel{
public ImagePanel(){
//setBorder(BorderFactory.createLineBorder(Color.black));
ImageComponent component = new ImageComponent();
add(component);
repaint();
}
}
Also double check that you are adding the ImagePanel (containing the ImageComponent) to the ImageFrame, and calling .setVisible(True).

Categories

Resources