Im making an application that should be able to read files in a given directory and then display all image files in a fullscreen borderless window, it should also display text files, but i havent started on that part yet, so never mind the system.out part. So far ive made the JFrame fullscreen and borderless, and ive made an Arraylist containing the files i want shown. I then add a jpanel with the file in the constructor, this jpanel adds the picture to a jlabel and displays it, afterward i remove the jpanel and start over with the next picture.
What i need is a way to make the images fade in from a given color, and then fade out to that same color.
this is where i add the panels and remove them again
for (File f : files) {
String fileName = f.getName();
if (fileName.endsWith(".txt")) {
System.out.println("Txt");
System.out.println(fileName);
System.out.println("--");
} else if (fileName.endsWith(".png") || fileName.endsWith(".jpg") || fileName.endsWith("bmp")) {
AlbumPanel albumpan = new AlbumPanel(connect, f, this);
add(albumpan, BorderLayout.CENTER);
pack();
try {
Thread.sleep(current.getFormat().getPicLength()*1000);
} catch (InterruptedException ex) {
}
remove(albumpan);
}
}
And this is the JPanel
public class AlbumPanel extends JPanel {
BufferedImage image;
ImageIcon icon;
IConnect connect;
File pic;
JFrame presWin;
public AlbumPanel(IConnect connect, File pic, JFrame presWin) {
this.connect = connect;
this.pic = pic;
this.presWin = presWin;
this.setLayout(new GridBagLayout());
try {
image = ImageIO.read(pic);
} catch (Exception e) {
System.out.println(e);
}
image = resize(image, presWin.getWidth(), presWin.getHeight());
icon = new ImageIcon(image);
JLabel picLabel = new JLabel();
picLabel.setIcon(icon);
add(picLabel);
setVisible(true);
}
private BufferedImage resize(BufferedImage image, int width, int height) {
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TRANSLUCENT);
Graphics2D g2d = (Graphics2D) bi.createGraphics();
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(image, 0, 0, width, height, null);
g2d.dispose();
return bi;
}
Override the rendering method (probably paintComponent) on the control you are using. Call super.paintComponent and then draw a semi-transparent rectangle of your "fade out" color over it.
Inside paintComponent you are passed a Graphics object. Methods on that object can be used to do things, including drawing a rectangle on the screen. You probably want fillRect.
Pick the opacity to be 0 when the image is fully displayed then move towards 1 when it's fully faded out.
You will need something to trigger redraws at regular intervals (a Swing Timer may be good enough).
You can use Color's transparency (the constructor public Color(int r, int g, int b, int a) where the last variable is alpha.
Start a Timer and change the Color's transparency from 0 to 255 and back filling the image (or the panel) with the Color.
Related
I am trying to set as background an aquarium (which is a class that extends JPanel and contain the aquarium img), and on top a fish (which is also a class that extends a JPanel and contain the fish img).
The problem is that it shows only one image instead of fish in top of the aquarium (either aquarium, or fish depending on which one is added first to the JFrame).
Main
public class Core {
JFrame window;
JLabel label;
ImageIcon img;
Aquarium aquarium = new Aquarium();
JavaFish javaFish = new JavaFish();
public void start() {
window = new JFrame();
window.setPreferredSize(new Dimension(600, 400));
window.setVisible(true);
window.setTitle("Java Game");
aquarium.add(javaFish);
window.add(aquarium);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
Core c = new Core();
c.start();
}
}
Aquarium
public class Aquarium extends JPanel {
private BufferedImage img;
//Initiate aquarium width
public int width;
//Initiate aquarium height
public int height;
#Override
protected void paintComponent(Graphics g) {
width = getSize().width;
height = getSize().height;
try {
img = ImageIO.read(new File("img/AquariumBackground.png"));
} catch (IOException e) {
e.printStackTrace();
System.out.println("Image not fount!");
}
g.drawImage(img, 0, 0, width, height, this);
}
}
Fish
public class JavaFish extends JPanel {
BufferedImage img;
int xPos = 50;
int yPos = 50;
public JavaFish() {
this.setOpaque(false);
}
#Override
protected void paintComponent(Graphics g) {
BufferedImage JavaFish = LoadImage("img/JavaFish.png");
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(JavaFish, xPos, yPos, 100, 100, null);
repaint();
}
BufferedImage LoadImage(String FileName) {
img = null;
try {
img = ImageIO.read(new File (FileName));
} catch (IOException e) {
e.printStackTrace();
}
return img;
}
}
The problem is that it shows only one image instead of fish in top of the aquarium (either aquarium, or fish depending on which one is added first to the JFrame).
By default a JPanel uses a FlowLayout which respects the preferred size of any component added to it.
By default a JFrame uses a BorderLayout and if you don't specify a constraint the component gets added to the CENTER of the BorderLayout, which means the component is automatically resized to fill the space of the frame.
So the component you add to the frame will be sized to fill the frame. The component you add to the panel will have a size of (0, 0) so there is nothing to paint.
So some custom painting tips:
Override the getPreferredSize() method of the panel to return the size of the image so the layout manager can do its job
Invoke super.paintComponent(..) as the first statement to make sure the background gets cleared.
Don't read the image in the paintComponent() method. This method can be called whenever Swing determines the component needs to be repainted, so it not efficient to keep reading the image. Instead the image should be read in the constructor of the class.
Don't invoke repaint() in a painting method. This will cause an infinite painting loop.
Also, components should be added to the frame BEFORE you make the frame visible.
Having said all of the above, Alerra's suggestion in the comment to paint both images in the same panel is a good idea. It simplifies the painting and you can even paint multiple fish easily by keeping an ArrayList of imgages that you want to paint. Then you would just paint the background and then iterates through the ArrayList to paint the individual fish.
Check out Custom Painting Approaches for a working example. The example only draws Rectangle, but the concept is the same.
This question already has answers here:
How to add an image to a JPanel?
(14 answers)
Closed 8 years ago.
I am trying to display a jpeg image to a panel in a JPanel. I have two panels panel, and panel1. I'm trying to display the image in one panel and then remove the panel to display another.
panel.g2d.drawImage(myimage, 0, 0, null);
It gives me about 50 errors and I can't type them all because I'm writing this on my phone because I don't have Internet right now.
Why not just use a JLabel instead?
Image image = ImageIO.read(getClass().getResource("/images/MyImage.png"));
JLabel label = new JLabel(new ImageIcon(image));
panel.add(label);
Use Buffered Image with JPanel. Here is an example
try{
BufferedImage myPicture = ImageIO.read(new File("c://pic.jpg"));
picLabel = new JLabel(new ImageIcon(myPicture));
picLabel.setHorizontalAlignment(SwingConstants.CENTER);
frame.getContentPane().add(picLabel);
}catch (IOException e){}
To display an image in a panel, override the paintComponent(Graphics) method and draw it there:
public class ImagePanel extends JPanel {
private Image image;
public void setImage (Image image) {
this.image = image;
revalidate();
repaint();
}
#Override
protected void paintComponent (Graphics g) {
super.paintComponent(g);
if (image != null)
g.drawImage(image, 0, 0, this);
}
}
you also should override the getPreferredSize() method to expose how large your image component should be (will be used by the layout manager of the parent container):
#Override
public Dimension getPreferredSize () {
if (image == null) {
return super.getPreferredSize();
}
Insets insets = getInsets();
return new Dimension(image.getWidth(this) + insets.left + insets.right, image.getHeight(this) + insets.top + insets.bottom);
}
Edit: JLabel (as pointed out by the other answers) is fine for displaying simple images or icons, but when you need advanced features such as automatic up-/downscaling (with or without keeping proportions), tiling (x, y, both), it's usually better to create a specialized image panel class for that.
I am trying to program a board game. I want to load an image of the game board and then load a transparent grid over it. I wrote a custom panel to draw the image and added it to a layered panel as level 0. Then I make a JPanel with a GridLayout and added it at level 1. The layered pane is then put into a scroll pane to account for the background image being kinda large. The hope is to have most of the grid be transparent at any given time but if a player piece enters a square then I will set that square to be a color representing the piece. However when I set the top panel to transparent (by making a call to setOpaque(false)) I just get a white background, no image is present. Why is this?
public class ImagePanel extends JPanel
{
private Image image;
public ImagePanel(Image image)
{
this.image = image;
this.setPreferredSize(new Dimension(936,889));
}
protected void paintComponent(Graphics g)
{
g.drawImage(image, 0, 0, null);
}
}
Here is the code in the main program which creates the panels and nests them. backBoard is the outer frame. It is setVisible later on so that's not an issue.
BufferedImage boardImage = null;
try
{
boardImage = ImageIO.read(new File("Clue Board.jpg"));
}
catch(IOException e)
{
}
ImagePanel background = new ImagePanel(boardImage); //load clue board image
JPanel gameBoard = new JPanel (new GridLayout(24,24)); //yet to add actual squares
gameBoard.setSize(936,889);
gameBoard.setOpaque(false);
JLayeredPane lPane = new JLayeredPane();
lPane.setPreferredSize(new Dimension(936,889));
lPane.add(background, new Integer(0));
lPane.add(gameBoard, new Integer(1));
JScrollPane layerScroller = new JScrollPane(lPane,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
backBoard.add(layerScroller, BorderLayout.CENTER);
Try calling super.paintComponent(..) like so:
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
Dont call JFrame#setSize(..) use an appropriate LayoutManager and override getPrefferedSize(..) of JPanel which will return the correct size and then call pack() on JFrame instance before setting it visible.
Here is an example of how your ImagePanel class should look:
public class ImagePanel extends JPanel
{
private int width,height;
private Image image;
public ImagePanel(Image image)
{
this.image = image;
//so we can set the JPanel preferred size to the image width and height
ImageIcon ii = new ImageIcon(this.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
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
}
How is it possible to store a JPanel as a jpeg image the solutions I could search takes a snapshot of the display, this does not capture all the contents of the JPanel as part of it is hidden. Is there any way of getting the entire image in jpeg.
This solution available here is not working fine at all solution
code I am currently using to take snapshot of JPanel
if (panelx == null) {
jButton3.setText("Generate Diagram");
} else {
jButton3.setText("Generate Diagram");
jTextPane1
.setText(Messages.getString("statement2")); //$NON-NLS-1$
JFrame win = (JFrame) SwingUtilities
.getWindowAncestor(panelx.panelx);
Dimension size = win.getSize();
// BufferedImage image = new BufferedImage(size.width, size.height,
// BufferedImage.TYPE_INT_RGB);
BufferedImage image = (BufferedImage) win.createImage(size.width,
size.height);
Graphics g = image.getGraphics();
win.paint(g);
g.dispose();
try {
ImageIO.write(
image,
Messages.getString("Statement38"), new File(Messages.getString("statement5"))); //$NON-NLS-1$ //$NON-NLS-2$
} catch (IOException e) {
System.out.println("Image cannot be created");
}
You don't explain why the example doesn't work.
Why are you using the window not the panel? If you were using the example answer you should refer to the panel within the scrollpane.
You're calling paint on the whole JFrame rather than just the panel you are interested in.
So im making a gui, and i have a background image for it. i dont know how to make it set as the background, so any help with that would be good. an explination would also be good. also, after we get that image as a background, how do we get the image resize to the size of the window. such as
image.setSize(frame.getHeight(), frame.getWidth());
but i dont know if that would work. the image name is ABC0001.jpg and the frame name is frame. thanks!
To get the image to resize, you can either use
public void paintComponent(Graphics g) {
g.drawImage(img, 0, 0, getWidth(), getHeight(), this); // draw the image
}
or you can use a componentlistener, implemented like:
final Image img = ...;
ComponentListener cl = new ComponentAdapter() {
public void componentResized(ComponentEvent ce) {
Component c = ce.getComponent();
img = im1.getScaledInstance(c.getWidth(), c.getHeight(), Image.SCALE_SMOOTH);
}
};
Image quality will degrade over time with the second solution, so it is recommended that you keep the original and the copy separate.
Create a class the extends JPanel. Have that class load the image by overriding paintComponent
class BackgroundPanel extends JPanel
{
Image img;
public BackgroundPanel()
{
// Read the image and place it in the variable img so it can be used in paintComponent
img = Toolkit.getDefaultToolkit().createImage("ABC0001.jpg");
}
public void paintComponent(Graphics g)
{
g.drawImage(img, 0, 0, null); // draw the image
}
}
Now that you have this class, simply add this to your JFrame (or whereever you want the background).
//create refrence if you want to add stuff ontop of the panel
private BackgroundPanel backGroundPanel;
//constructor
add(backGroundPanel, BorderLayout.CENTER);
The size of the background will fill the entire frame so no need to scale it unless you want it smaller