Cannot draw transparent Component backgrounds - java

I have tried several tutorials and searches to figure out how to accomplish what I am trying to do. Basically I have a JLayeredPane with two Jpanels inside it. One for my game's drawing surface and one for my gui, like a pause menu. I have a png file with transparencies that I want to be the background of my gui panel that popups when the user hits escape. No matter what I do, the background of the panel (even tried making it just a component) is always grey with my png file drawn over it.
I have tried what others have recommended such as the following.
setBackground(new Color(0,0,0,0));
and
setOpaque(false);
Neither of these has seemed to help and perhaps I am failing to do something else after these. I have traditionally done them after the constructor or within the constructor of a class that extends jpanel.
I am almost to the point where I am going to have one panel and draw everything myself but I would much rather use the built in java functions like boxlayouts, etc.
Edit Adding Working Example:
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
public class Example {
private MyWindow gWindow;
public static void main(String argv[]) {
Example g = new Example();
g.gameLoop();
}
public Example() {
gWindow = new MyWindow();
// Initialize the keyboard listener
gWindow.frame().addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ESCAPE) // escape key, show menu
{
System.exit(0);
}
}
#Override
public void keyReleased(KeyEvent e) {
}
#Override
public void keyTyped(KeyEvent e) {
}
});
}
public void gameLoop() {
long lastLoopTime = System.currentTimeMillis();
while(true) {
// Used to calculate movement of sprites
long delta = System.currentTimeMillis() - lastLoopTime;
lastLoopTime = System.currentTimeMillis();
// Clear the canvas
Graphics2D g = (Graphics2D) gWindow.getBufferStrategy().getDrawGraphics();
g.setColor(Color.black);
g.fillRect(0,0,gWindow.frame().getWidth(), gWindow.frame().getHeight());
// Clean up graphics and flip buffer
g.dispose();
gWindow.getBufferStrategy().show();
// Small delay before next cycle
try { Thread.sleep(10); } catch (Exception e) {}
}
}
public class MyWindow {
private JFrame frame;
private JLayeredPane container;
private MyPanel gui;
private JPanel surface;
private Canvas canvas;
private GraphicsDevice vc;
private Dimension dm;
BufferedImage menuImg = null;
BufferedImage menuImgHighlight = null;
BufferedImage gSettings = null;
Font font = null;
public MyWindow() {
frame = new JFrame("Jumper");
vc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
DisplayMode display = vc.getDisplayMode();
dm = new Dimension(display.getWidth(), display.getHeight());
container = new JLayeredPane();
gui = new MyPanel();
gui.setLayout(new BoxLayout(gui, BoxLayout.Y_AXIS));
surface = new JPanel(new BorderLayout(0,0));
frame.add(container, BorderLayout.CENTER);
container.add(surface, new Integer(0), 0);
container.add(gui, new Integer(1), 0);
init_resources();
canvas = new Canvas();
surface.add(canvas);
gui.setBackground(new Color(0,0,0,0));
gui.setVisible(true);
gui.setOpaque(false);
surface.setVisible(true);
setFullScreen(display);
frame.setResizable(false);
frame.setVisible(true);
frame.pack();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
setScreen(new Dimension(frame.getWidth(), frame.getHeight()));
frame.repaint();
}
});
canvas.setIgnoreRepaint(true);
canvas.createBufferStrategy(2);
canvas.setFocusable(false);
}
public JFrame frame() {
return frame;
}
public BufferStrategy getBufferStrategy () {
return canvas.getBufferStrategy();
}
public void setScreen(Dimension dim) {
int width = (int) dim.getWidth();
int height = (int) dim.getHeight();
this.dm = dim;
container.setPreferredSize(dm);
gui.setPreferredSize(dm);
surface.setPreferredSize(dm);
canvas.setBounds(0,0,width,height);
if(gSettings == null) {
gui.setBounds((int) ((dm.getWidth() - 200) / 2),
(int) ((dm.getHeight() - 200) / 2),
200,
200);
}
else {
gui.setBounds((int) ((dm.getWidth() - gSettings.getWidth()) / 2),
(int) ((dm.getHeight() - gSettings.getHeight()) / 2),
gSettings.getWidth(),
gSettings.getHeight());
}
gui.setBackground(gSettings);
surface.setBounds(0,0,width,height);
container.setBounds(0,0,width,height);
frame.validate();
}
public void setFullScreen(DisplayMode display) {
setScreen( Toolkit.getDefaultToolkit().getScreenSize());
frame.setUndecorated(true);
vc.setFullScreenWindow(frame);
if(dm != null && vc.isDisplayChangeSupported()) {
try {
vc.setDisplayMode(display);
}
catch(Exception e) {}
}
frame.validate();
}
private void init_resources() {
try {
gSettings = ImageIO.read(getClass().getResourceAsStream("/gui/settingsWindow.png"));
}
catch(Exception e)
{
System.out.print("Failed to load resources");
System.out.println();
}
}
}
public class MyPanel extends JPanel {
BufferedImage img = null;
public MyPanel() {
super();
setOpaque(false);
}
public void setBackground(BufferedImage img) {
this.img = img;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(img != null) {
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(img, 0, 0, null);
}
}
}
}

I've not tested this, but, instead of calling super.paintComponent at the end of you paint method, try calling at the start....
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(img != null) {
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(img, 0, 0, null);
}
}
The reasoning for this, is one of the jobs of paintComponent is clear the graphics context and ready it to be painted on. Event if the component is transparent, it must still clear/wipe the graphics context of anything that has previously been painted on it. The graphics context is a shared resource, meaning that all the components within a given window may share the same graphics context, so it gets a little dirty if it's not "wiped" first ;)
You may also have issues with mixing heavy and light weight components, but seen as you adding the light weight components to the heavy weight component, it may not be an issue, but it's worth putting in the back of your mind... ;)
JComponent is transparent by default ;)

Try to apply some Physics over here...
The visible white color is combination of RGB max values...
If you are keeping RGB values to Minimum it will give you dark color (Black) and not the transparent one..
try to implement below methods..
(your component).setOpaque(false);
(your component).setContentAreaFilled(false);
(your component).setBorderPainted(false);
Hope so this will help you...

Related

Adding markers on a map - labels on a lable, on button click Java Netbeans [duplicate]

I used JFrame to import and display an image, and used mousemotionlistener to detect the mouse clicks, and I want to be able to draw on top of the image. I want to be able to, if the user makes a click, make that pixel a certain color while preserving the rest of the image, however, I couldn't find out how to use Graphics to do so without deleting the rest of the image or opening a new window.
public class Simple extends JFrame{
static ImageIcon icon;
static JFrame myframe;
static JLabel mylabel;
static BufferedImage image = null;
public static void main(String[] args) {
try{
image = ImageIO.read(new File("mypic.png"));
}
catch (IOException e) {
e.printStackTrace();
}
icon=new ImageIcon(image);
myframe=new JFrame();
myframe.setSize(200,200);
myframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mylabel=new JLabel();
mylabel.setIcon(icon);
myframe.getContentPane().add(mylabel);
myframe.pack();
Container container = myframe.getContentPane();
MouseMotionEvents3 mousemotion = new MouseMotionEvents3();
container.add(mousemotion);
myframe.setVisible(true);
while(1 == 1) {
if(mousemotion.signal == true) {
System.out.println("second message");
mousemotion.signal = false;
}
}
}
}
class MouseMotionEvents3 extends JPanel implements MouseListener,
MouseMotionListener {
public boolean signal;
public MouseMotionEvents3() {
addMouseListener(this);
addMouseMotionListener(this);
signal = false;
}
public void mouseClicked(MouseEvent me) {
// System.out.println("i hate you");
}
public void mouseEntered(MouseEvent me) {
}
public void mouseExited(MouseEvent me) {
}
public void mousePressed(MouseEvent me) {
signal = true;
System.out.println("message");
}
public void mouseReleased(MouseEvent me) {
}
public void mouseDragged(MouseEvent me) {
}
public void mouseMoved(MouseEvent me) {
}
}
I would highly recommend that you start by having a read through Performing Custom Painting and the 2D Graphics Trail, they will provide you with a starting point.
There are a number of ways you might achieve this, this example simply keeps track of the click points and draws dots over the top of the image
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private List<Point> points;
private BufferedImage image;
public TestPane() {
points = new ArrayList<>(25);
try {
image = ImageIO.read(new File("/Users/shanewhitehead/Desktop/Screen Shot 2017-03-09 at 1.55.18 pm.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
points.add(e.getPoint());
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(200, 200) : new Dimension(image.getWidth(), image.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (image != null) {
g2d.drawImage(image, 0, 0, this);
}
g2d.setColor(Color.RED);
for (Point p : points) {
g2d.fillOval(p.x - 4, p.y - 4, 8, 8);
}
g2d.dispose();
}
}
}
This example draws the dots directly to the image itself...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
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;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage image;
public TestPane() {
try {
image = ImageIO.read(new File("/Users/shanewhitehead/Desktop/Screen Shot 2017-03-09 at 1.55.18 pm.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (image != null) {
Point p = e.getPoint();
Graphics2D g2d = image.createGraphics();
g2d.setColor(Color.RED);
g2d.fillOval(p.x - 4, p.y - 4, 8, 8);
g2d.dispose();
repaint();
}
}
});
}
#Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(200, 200) : new Dimension(image.getWidth(), image.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(image, 0, 0, this);
g2d.dispose();
}
}
}
In both cases, they simply make use of the Graphics2D API
The simplest method would be to have a list of points that represent the pixels you wish to colour. Then override the paint method for the label to first call super.paint (to display the image) and then paint the pixels that have been clicked.
List<Point> points = new ArrayList<>();
myLabel = new JLabel() {
#Override
public void paint(Graphics g) {
super.paint(g);
points.forEach(p -> g.fillRect(p.x, p.y, 1, 1));
}
};
In your mouse handling just add the current point to the list and repaint the label.
public void mouseClicked(MouseEvent me) {
points.add(me.getPoint());
myLabel.repaint();
}
There are more sophisticated methods that involve buffered images but this is likely good enough to get you started.
I figured it out, I can use the getGraphics() method of the JFrame to allow myself to draw on top of the image.
edit: Andrew Thompson is right, minimizing the window removes the changes.

How to draw on top of an image in Java?

I used JFrame to import and display an image, and used mousemotionlistener to detect the mouse clicks, and I want to be able to draw on top of the image. I want to be able to, if the user makes a click, make that pixel a certain color while preserving the rest of the image, however, I couldn't find out how to use Graphics to do so without deleting the rest of the image or opening a new window.
public class Simple extends JFrame{
static ImageIcon icon;
static JFrame myframe;
static JLabel mylabel;
static BufferedImage image = null;
public static void main(String[] args) {
try{
image = ImageIO.read(new File("mypic.png"));
}
catch (IOException e) {
e.printStackTrace();
}
icon=new ImageIcon(image);
myframe=new JFrame();
myframe.setSize(200,200);
myframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mylabel=new JLabel();
mylabel.setIcon(icon);
myframe.getContentPane().add(mylabel);
myframe.pack();
Container container = myframe.getContentPane();
MouseMotionEvents3 mousemotion = new MouseMotionEvents3();
container.add(mousemotion);
myframe.setVisible(true);
while(1 == 1) {
if(mousemotion.signal == true) {
System.out.println("second message");
mousemotion.signal = false;
}
}
}
}
class MouseMotionEvents3 extends JPanel implements MouseListener,
MouseMotionListener {
public boolean signal;
public MouseMotionEvents3() {
addMouseListener(this);
addMouseMotionListener(this);
signal = false;
}
public void mouseClicked(MouseEvent me) {
// System.out.println("i hate you");
}
public void mouseEntered(MouseEvent me) {
}
public void mouseExited(MouseEvent me) {
}
public void mousePressed(MouseEvent me) {
signal = true;
System.out.println("message");
}
public void mouseReleased(MouseEvent me) {
}
public void mouseDragged(MouseEvent me) {
}
public void mouseMoved(MouseEvent me) {
}
}
I would highly recommend that you start by having a read through Performing Custom Painting and the 2D Graphics Trail, they will provide you with a starting point.
There are a number of ways you might achieve this, this example simply keeps track of the click points and draws dots over the top of the image
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private List<Point> points;
private BufferedImage image;
public TestPane() {
points = new ArrayList<>(25);
try {
image = ImageIO.read(new File("/Users/shanewhitehead/Desktop/Screen Shot 2017-03-09 at 1.55.18 pm.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
points.add(e.getPoint());
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(200, 200) : new Dimension(image.getWidth(), image.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (image != null) {
g2d.drawImage(image, 0, 0, this);
}
g2d.setColor(Color.RED);
for (Point p : points) {
g2d.fillOval(p.x - 4, p.y - 4, 8, 8);
}
g2d.dispose();
}
}
}
This example draws the dots directly to the image itself...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
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;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage image;
public TestPane() {
try {
image = ImageIO.read(new File("/Users/shanewhitehead/Desktop/Screen Shot 2017-03-09 at 1.55.18 pm.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (image != null) {
Point p = e.getPoint();
Graphics2D g2d = image.createGraphics();
g2d.setColor(Color.RED);
g2d.fillOval(p.x - 4, p.y - 4, 8, 8);
g2d.dispose();
repaint();
}
}
});
}
#Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(200, 200) : new Dimension(image.getWidth(), image.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(image, 0, 0, this);
g2d.dispose();
}
}
}
In both cases, they simply make use of the Graphics2D API
The simplest method would be to have a list of points that represent the pixels you wish to colour. Then override the paint method for the label to first call super.paint (to display the image) and then paint the pixels that have been clicked.
List<Point> points = new ArrayList<>();
myLabel = new JLabel() {
#Override
public void paint(Graphics g) {
super.paint(g);
points.forEach(p -> g.fillRect(p.x, p.y, 1, 1));
}
};
In your mouse handling just add the current point to the list and repaint the label.
public void mouseClicked(MouseEvent me) {
points.add(me.getPoint());
myLabel.repaint();
}
There are more sophisticated methods that involve buffered images but this is likely good enough to get you started.
I figured it out, I can use the getGraphics() method of the JFrame to allow myself to draw on top of the image.
edit: Andrew Thompson is right, minimizing the window removes the changes.

How do you use an image as background and place an image in front of that?

I have tried loads of ways, but none of them succeeded. they either didn't show the image, or they made the background image disappear... do you have any suggestions? Here is my code:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Main extends JFrame{
int x, y;
Image Dak;
Image Levels;
private Image dbImage;
private Graphics dbg;
public Main(){
setTitle("Help de Pieten");
setSize(2000, 720);
setResizable(true);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
this.setContentPane(
new JLabel(new ImageIcon(ImageIO.read(new File("Image1.gif")))));
} catch (IOException e) {}
validate();
ImageIcon i = new ImageIcon("Image2.gif");
Levels = i.getImage();
x = 100;
y = 100;
}
public void paint(Graphics g){
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g.drawImage(dbImage, 0, 0, this);
}
public void paintComponent(Graphics g){
g.drawImage(Levels, x, y, this);
repaint();
}
public static void main(String[] args) {
Main main = new Main();
}
}
So how do I get images in front of the background without making the background dissapear?
To start with, avoid overriding the paint methods of top level containers like JFrame, they aren't double buffered and they have a complex component hierarchy with which you don't want to get involved with
Instead, start by extending from something JPanel, Swing components are double buffered by default, so you don't need to worry about implementing it all yourself, and overriding it's paintComponent method and performing your custom painting within it.
Have a look at Performing Custom Painting and Painting in AWT and Swing for more details.
Paint in Swing follows the "painters canvas" paradigm, that is, whatever is painted first, will be covered over by whatever is painted next, so to this end, make sure you paint your background first, followed by each layer in order you want it to appear.
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 Images {
public static void main(String[] args) {
new Images();
}
public Images() {
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 BufferedImage background;
private BufferedImage foreground;
public TestPane() {
try {
background = ImageIO.read(new File("background image"));
foreground = ImageIO.read(new File("foreground image"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return background == null ? new Dimension(200, 200) : new Dimension(background.getWidth(), background.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (background != null) {
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g2d.drawImage(background, x, y, this);
}
if (foreground != null) {
int x = (getWidth() - foreground.getWidth()) / 2;
int y = (getHeight() - foreground.getHeight()) / 2;
g2d.drawImage(foreground, x, y, this);
}
g2d.dispose();
}
}
}

Window Resize event

I have a program that scales an image to the size of the screen. I currently have a component listener listening for a componentResized event, but this is not what I want. I would like the method to only be called one the user lift's there finger off their mouse, not as they are doing the resizing. This way, my image will not constantly be resizing to the user's specifications.
Thanks!
A solution is to supply a Swing Timer which is reset each time componentResized is called. This injects a small delay between the last resize event and the time you should perform the resize action.
import javax.swing.Timer;
//...
// Declare an instance variable...
private Timer resizeTimer;
//...
// Probably in you classes constructor
resizeTimer = new Timer(250, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// Actually perform the resizing of the image...
resizeBackgroundImage();
}
});
// Don't want a repeating event...
resizeTimer.setRepeats(false);
//...
public void componentResized(ComponentEvent evt) {
resizeTimre.restart();
}
This basically, sets it up so that it will require 250 milliseconds between resize events before an attempt is made to resize the image. You can play around with the value to suit your own needs.
Updated with runnable example
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
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.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class RescaleTest {
public static void main(String[] args) {
new RescaleTest();
}
public RescaleTest() {
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 master;
private Image scaled;
private Timer resizeTimer;
public TestPane() {
try {
master = ImageIO.read(new File("/path/to/your/image"));
scaled = master;
} catch (IOException exp) {
exp.printStackTrace();
}
resizeTimer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
resizeBackground();
}
});
resizeTimer.setRepeats(false);
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
resizeTimer.restart();
}
});
}
protected void resizeBackground() {
// This is not my preferred scaling process, I prefer to use
// a divide and conqure approach and do so in the background
// where possible, but this is beyond the scope of the question...
if (getWidth() < getHeight()) {
scaled = master.getScaledInstance(getWidth(), -1, Image.SCALE_SMOOTH);
} else {
scaled = master.getScaledInstance(-1, getHeight(), Image.SCALE_SMOOTH);
}
repaint();
}
#Override
public Dimension getPreferredSize() {
return master != null ? new Dimension(master.getWidth(), master.getHeight()) : new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (scaled != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - scaled.getWidth(this)) / 2;
int y = (getHeight() - scaled.getHeight(this)) / 2;
g2d.drawImage(scaled, x, y, this);
g2d.dispose();
}
}
}
}
nb: The scaling used in this example is not my preferred method and was done for demonstration purposes only. See The Perils of Image.getScaledInstance() for details and Scale the ImageIcon automatically to label size for an alterantive approach...
If you put Toolkit.getDefaultToolkit().setDynamicLayout(false); right inside of main it will disable the frame from updating dynamically as you increase/decrease it's size. The ui will only be updated after you stop resizing.
import MainMenu.GameManager;
import java.awt.*;
import java.io.IOException;
public class Main {
Main(){
}
public static void main(String[] args) throws IOException {
GameManager manager = new GameManager();
Toolkit.getDefaultToolkit().setDynamicLayout(false);
}
}

How to use paintComponent in Java to paint multiple things, but rotate one?

I'm making a program in Java for my CS class. My teacher has little experience with graphics programing in Java so I've turned to you. I'm currently using the paintComponent method of my main panel to draw two things, one, a rectangle (my cannon, possibly replaced with a image later), and two, a .png file of a cannon ball. I use the Graphics g (which I convert to Graphics2D) to paint the cannon and Ball on to the screen. I then rotate, but, the cannon and ball rotate, not just the cannon. Any tips, suggestions, or helpful tutorials are greatly appreciated.
Here is my code (the commented out links are where I got certain code, ignore them):
package Cannon;
import java.awt.geom.Point2D;
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class NewMain{
public static void main(String[] args) {
FraMainWindow frame = new FraMainWindow();
}
}
class FraMainWindow extends JFrame {
DrawCannon pnlCannon = new DrawCannon();
ButtonPannel pnlButtons = new ButtonPannel();
public FraMainWindow() {
this.setDefaultCloseOperation(JFrame.EXI…
this.setTitle("Super Mario Cannon Bro's");
this.setSize(900, 550);
this.setLayout(new BorderLayout());
this.add(pnlCannon, BorderLayout.CENTER);
this.add(pnlButtons, BorderLayout.SOUTH);
MouseMovement mouseMove = new MouseMovement();
MouseAction mouseClick = new MouseAction();
pnlCannon.addMouseMotionListener(mouseMo…
pnlCannon.addMouseListener(mouseClick);
FireButton actnFire = new FireButton();
pnlButtons.btnFire.addActionListener(act…
this.setVisible(true);
}
public class DrawCannon extends JPanel{
Rectangle.Float rectCannon = new Rectangle.Float(30, 450, 50, 10);
Image imgBall=new ImageIcon("ball.png").getImage();
double dAngle = 0;
boolean isFired = false;
public void addCannonBall(){
isFired=true;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_… RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_… RenderingHints.VALUE_RENDER_QUALITY);//A… Aliasing from http://www.java2s.com/Code/Java/2D-Graph…
g2d.rotate(0 - dAngle, rectCannon.getX(), rectCannon.getY() + 5);
g2d.fill(rectCannon);
if(isFired){
g2d.drawImage(imgBall, 0, 0, null);
}
//Dimension size = getSize();
}
}
public class ButtonPannel extends JPanel {
JButton btnFire = new JButton("Fire!");
ButtonPannel() {
this.add(btnFire);
}
}
public class FireButton implements ActionListener {
public void actionPerformed(ActionEvent e) {
pnlCannon.addCannonBall();
System.out.println("Fire ZE MISSILES");
}
}
public class MouseMovement implements MouseMotionListener {
public void mouseDragged(MouseEvent e) {
double dBase, dHeight, dAngle;
dBase = e.getX() - pnlCannon.rectCannon.getX();
dHeight = pnlCannon.rectCannon.getY() - 5 - e.getY() + 10;
dAngle = Math.atan2(dHeight, dBase);
pnlCannon.dAngle = dAngle;
pnlCannon.repaint();
}//http://download.oracle.com/javase/tutori…
public void mouseMoved(MouseEvent e) {
}
}
public class MouseAction implements MouseListener {
public void mousePressed(MouseEvent e) {
double dBase, dHeight, dAngle;
dBase = e.getX() - pnlCannon.rectCannon.getX();
dHeight = pnlCannon.rectCannon.getY() - 5 - e.getY() + 10;
dAngle = Math.atan2(dHeight, dBase);
pnlCannon.dAngle = dAngle;
pnlCannon.repaint();
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
} // From http://www.rgagnon
Try moving this bit:
if(isFired){
g2d.drawImage(imgBall, 0, 0, null);
}
before this line:
g2d.rotate(0 - dAngle, rectCannon.getX(), rectCannon.getY() + 5);
Any transformations you apply to your Graphics2D will affect anything from that point, so you have to either be careful to apply transforms when you need them, or to "un-apply" them before you don't need them.
You have to unrotate after drawing the cannon and before drawing the ball :)
You could try to save the transform before you do a rotate and then set it back again. This example is from setTransform in the Java Docs:
// Get the current transform
AffineTransform saveAT = g2.getTransform();
// Perform transformation
g2d.transform(...);
// Render
g2d.draw(...);
// Restore original transform
g2d.setTransform(saveAT);

Categories