Images not painting/loading right away in Swing Java Desktop Application - java

When I run my Java Desktop Application created with Netbean's Swing, the JLabel icon images load right away but the background images on my JPanel don't paint to the screen until I wake-up (re-size) the window.
Here is the custom code on my JPanel:
Image image = java.awt.Toolkit.getDefaultToolkit().getImage(getClass().getResource("/images/background.gif"));
javax.swing.JPanel panelBackground = new BackgroundPanel(image);
Is there a better way to call the image? Is there image handling code I should be implementing?
How should I fix it?

Works fine for me. I tested it using the Background Panel. Post your SSCCE if you still have a problem.
import java.awt.*;
import javax.swing.*;
public class BackgroundSSCCE extends JPanel
{
public BackgroundSSCCE()
{
setLayout( new BorderLayout() );
Image duke = java.awt.Toolkit.getDefaultToolkit().getImage(getClass().getResource("dukeWaveRed.gif"));
BackgroundPanel test = new BackgroundPanel(duke, BackgroundPanel.ACTUAL, 1.0f, 0.5f);
add(test);
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("BackgroundSSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new BackgroundSSCCE() );
frame.setSize(200, 200);
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}

Got it!
Many thanks to Hovercraft Full Of Eels for the pointer
"What happens if you use ImageIO.read(...) to get your image? Also, are you adding the image-displaying component to the GUI after it has been rendered?"
And to camickr for the code to think on.
I resolved it by using:
Image imgBackground = ImageIO.read(getClass().getResourceAsStream("/images/background.gif"));
Creating and assigning the image to the variable at the beginning of my class instead of in the JPanels custom code section also worked. That is because the image had more time to be created..

Related

how to put my background image at the bottom

I want to put my background image at the very bottom in this frame, and the button on top. However the code I wrote below doesn't work. Can anyone see where the problems are?
Another thing is that even though I set the location for my button, it keep showing at the top center on the frame.
Please ignore the comment lines. (I was just guessing, and hoping them will work, but they don't apparently.)
public class Menu extends JFrame{
private JLayeredPane pane;
private JLayeredPane pane2;
public Menu(){
final JFrame f = new JFrame("Chinese Chess");
JButton play = new JButton("Play vs. AI");
f.setLayout(new FlowLayout());
f.setLocationRelativeTo(null);
f.setSize(800, 800);
f.setVisible(true);
f.setResizable(false);
//f.pack();
pane = new JLayeredPane();
pane2 = new JLayeredPane();
f.add(pane);
f.add(pane2);
//background image
JLabel background = new JLabel(new ImageIcon("res/img/background.png"));
background.setLocation(0, 0);
background.setSize(800, 800);
pane.add(background, JLayeredPane.FRAME_CONTENT_LAYER);
pane2.add(play, JLayeredPane.DEFAULT_LAYER);
//pane.moveToBack();
//button PlayAI
play.setLocation(500,500);
play.setPreferredSize(new Dimension(100,50));
//f.setLayout(new FlowLayout());
//frame menu
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//f.getContentPane().add(play);
play.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
new PlayAI();
}
});
}
public static void main(String[] args){
new Menu();
}
Problems/Solutions:
setLocation(...) and setBounds(...) types of calls are ignored by most layout managers. The only way to use them is to set the layout of the container to null via .setLayout(null);
But having said that, while null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
So in sum -- don't do this, don't use null layouts or setBounds, but rather nest JPanels, each using its own layout manager, and thereby create easy to maintain and decent GUI's.
If you want an image to be in the background, then draw it in a JPanel that you use as a container for your GUI components by drawing it in the JPanel's paintComponent(Graphics g) method as has been demonstrated in many many similar questions on this site -- I'll find you some of mine in a second.
If you add any JPanels on top of this image drawing JPanel, be sure that you can see through them by calling setOpaque(false) on these overlying JPanels. Otherwise you'll cover up the image.
Your code has two JFrames when only one is needed. Get rid of the one you don't use.
You call setVisible(true) too early on the JFrame, before components have been added to the GUI -- don't. Call it only after adding everything to the GUI so all display OK.
You're creating two JLayedPanes, and completely covering one by the other by adding them to the JFrame without understanding how the JFrame's BorderLayout handles added components.
I suggest that you not even use one JLayeredPane but instead draw in the JPanel as noted above, and use that as your container.
Your code looks to be opening a completely new GUI window when the play button is pressed, and if so, this can get annoying to the user fast. Consider swapping views instead with a CardLayout.
For example:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
// extend JPanel so you can draw to its background
#SuppressWarnings("serial")
public class Menu2 extends JPanel {
private BufferedImage bgImage = null; // our background image
private JButton playButton = new JButton(new PlayVsAiAction("Play Vs. AI", KeyEvent.VK_P));
public Menu2(BufferedImage bgImage) {
this.bgImage = bgImage;
setLayout(new GridBagLayout()); // center our button
add(playButton);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bgImage != null) {
g.drawImage(bgImage, 0, 0, this);
}
}
// to size our GUI to match a constant or the image.
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
// if you want to size it based on the image
if (bgImage != null) {
int width = bgImage.getWidth();
int height = bgImage.getHeight();
return new Dimension(width, height);
} else {
return super.getPreferredSize();
}
// if you want to size the GUI with constants:
// return new Dimension(PREF_W, PREF_H);
}
private class PlayVsAiAction extends AbstractAction {
public PlayVsAiAction(String name, int mnemonic) {
super(name); // have our button display this name
putValue(MNEMONIC_KEY, mnemonic); // alt-key to press button
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO code to start program
}
}
private static void createAndShowGui() {
BufferedImage img = null;
String imagePath = "res/img/background.png";
try {
// TODO: fix this -- use class resources to get image, not File
img = ImageIO.read(new File(imagePath));
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
Menu2 mainPanel = new Menu2(img);
JFrame frame = new JFrame("Chinese Chess");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
}
Apart from the solution above... you should create and launch your swing application this way:
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() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
// Instantiate your JFrame and show it
}

Displaying an image in a JFrame

I am currently learning Java, and I am stuck with something at the moment.
I was looking for a way to add an image to my JFrame.
I found this on the internet:
ImageIcon image = new ImageIcon("path & name & extension");
JLabel imageLabel = new JLabel(image);
And after implementing it to my own code, it looks like this (this is only the relevant part):
class Game1 extends JFrame
{
public static Display f = new Display();
public Game1()
{
Game1.f.setSize(1000, 750);
Game1.f.setResizable(false);
Game1.f.setVisible(true);
Game1.f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Game1.f.setTitle("Online First Person Shooter");
ImageIcon image = new ImageIcon("C:\\Users\\Meneer\\Pictures\\image.png");
JLabel imageLabel = new JLabel(image);
add(imageLabel);
}
}
class Display extends JFrame
{
}
When running this code, it doesn't give me any errors, but it also doesn't show the picture. I saw some questions and people having the same problem, but their code was completely different from mine, they used other ways to display the image.
You don't need to use another JFrame instance inside the Game JFrame:
Calling setVisible(flag) from the constructor is not preferable. Rather initialize your JFrame from outside and put your setVisible(true) inside event dispatch thread to maintain Swing's GUI rendering rules using SwingUtilities.invokeLater(Runnable)
Do not give size hint by setSize(Dimension) of the JFrame. Rather use proper layout with your component, call pack() after adding all of your relevant component to the JFrame.
Try using JScrollPane with JLabel for a better user experience with image larger than the label's size can be.
All of the above description is made in the following example:
class Game1 extends JFrame
{
public Game1()
{
// setSize(1000, 750); <---- do not do it
// setResizable(false); <----- do not do it either, unless any good reason
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Online First Person Shooter");
ImageIcon image = new ImageIcon("C:\\Users\\Meneer\\Pictures\\image.png");
JLabel label = new JLabel(image);
JScrollPane scrollPane = new JScrollPane(label);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
add(scrollPane, BorderLayout.CENTER);
pack();
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Game1().setVisible(true);
}
});
}
}
do this after creating Jlabel
imageLabel.setBounds(10, 10, 400, 400);
imageLabel.setVisible(true);
also set the layout to JFrame
Game.f.setLayout(new FlowLayout);
You are adding the label to the wrong JFrame. Also, move the setVisible() to the end.
import javax.swing.*;
class Game1 extends JFrame
{
public static Display f = new Display();
public Game1()
{
// ....
Game1.f.add(imageLabel);
Game1.f.setVisible(true);
}
}
Also try to use image from resources, and not from hardcoded path from your PC
You can look in here, where sombody asked similar question about images in Jframe:
How to add an ImageIcon to a JFrame?
Your problem in next you add your JLabel to Game1 but you display another Frame(Display f). Change add(imageLabel); to Game1.f.add(imageLabel);.
Recommendations:
1)according to your problem: Game1 extends JFrame seems that Display is also a frame, use only one frame to display content.
2) use pack() method instead of setSize(1000, 750);
3)call setVisible(true); at the end of construction.
4)use LayoutManager to layout components.

JFrame Icon Image Not Working

I have been searching around the internet trying to find out how to add an Icon Image to my JFrame, but I keep getting errors. I understand this has been asked on stack overflow but the solutions are not working for me. Here is my code:
ImageIcon imageIcon = new ImageIcon("src/slime.png");
ImageIcon image = new ImageIcon("src/slime.gif");
JLabel label = new JLabel(image, JLabel.CENTER);
label.setAlignmentX(0);
label.setAlignmentY(0);
label.setIcon(image);
JFrame window = new JFrame("Slime");
window.setVisible(true);
window.setSize(250, 200);
window.setResizable(false);
window.setIconImage(newImageIcon(getClass().getResource("src/slime.png")).getImage());
window.add(label);
here is the error I get:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.ImageIcon.<init>(ImageIcon.java:205)
at MainJFrame.<init>(MainJFrame.java:39)
at MainJFrame$1.run(MainJFrame.java:18)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:727)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:688)
at java.awt.EventQueue$3.run(EventQueue.java:686)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:697)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
Help would be very much appreciated. Note: I have tried window.setIconImage(imageIcon.getImage()); but that doesn't work and makes my other image that I have printed on the screen disapear.
First, just for safety reasons, don't try and make your JFrame in your main method. That is why you are getting some of the static errors from some of the solutions. Static is just a big problem in my opinion because as soon as you make one static, you make them all static. Try and initelize the JFrame in the constructor instead of the main method. Just make a new MainJFrame object in the main method:
public static void main(String[] args){
MainJFrame frame = new MainJFrame();
}
And put all of your code in the constructor, if you don't know what this is, which you should know then this is what one looks like:
public MainJFrame(){
//This is a constructor
//All frame init code in here
}
Then put the same code in there but put a space between the new and ImageIcon in your setIconImage() argument. So the whole constructor should look like this:
public MainJFrame(){
ImageIcon imageIcon = new ImageIcon("src/slime.png");
ImageIcon image = new ImageIcon("src/slime.gif");
JLabel label = new JLabel(image, JLabel.CENTER);
label.setAlignmentX(0);
label.setAlignmentY(0);
label.setIcon(image);
JFrame window = new JFrame("Slime");
window.setVisible(true);
window.setSize(250, 200);
window.setResizable(false);
window.setIconImage(new ImageIcon(getClass().getResource("src/slime.png")).getImage());
window.add(label); }
If that still doesn't work then try to use ImageIO to load the image. This won't work on applets though since it will give you a security error.
window.setIconImage(ImageIO.read(new File("folder/to/file.png")));
You also need to surround this line in a throw/catch block and if you are working in eclipse then make sure the file is in a folder outside of your main package. Other than that you should be good.
Use getClass to get the image:
window.setIconImage(new ImageIcon(
getClass().getResource("src/slime.png")).getImage());
But if you want to add image to your label an then add the label to your frame use this instead:
Image img = (new ImageIcon(getClass().getResource("src/slime.png"))).getImage();
JLabel lblIcon = new JLabel(new ImageIcon(newimg));
window.add(lblIcon);
and if you want to resize the image size to be the size of window do this (put the code before adding it to window):
Image newimg = img.getScaledInstance(window.getWidth() , window.getHeight(), java.awt.Image.SCALE_SMOOTH);// resizing image to the window size
EDIT:
of course you cannot use getClass() in public static void main() method you should put your code somewhere non-static like a class constructor for example.
public class MainForm extends javax.swing.JFrame {
/**
* Creates new form MainForm
*/
public MainForm() {
//put your code here...
window.setIconImage(new ImageIcon(
getClass().getResource("src/slime.png")).getImage());
}
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new MainForm().setVisible(true);
}
});
}
It is always good to try-catch block to check if you getting the image correctly. albeit in this situation when you are getting the code from inside your packages is not that necessary but if you are going to get any resource from outside of your project make sure of your opening process.
Try this, it has to work
frame.setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/src/slime.gif")));
You wrote,
newImageIcon()
This might be a method because it compiled for you. I think you might have to write it as new ImageIcon() This might be the problem. The javax.swing.ImageIcon is not being created.
Simply, why dont you use
setIconImage(imageIcon.getImage());
Here is the full code,
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class IconImageDemo1 extends JFrame
{
public IconImageDemo1()
{
createAndShowGUI();
}
private void createAndShowGUI()
{
setTitle("IconImage Demo");
setLayout(new FlowLayout());
setSize(400,400);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("icons/camera.png")));
setLocationRelativeTo(null);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable(){
public void run()
{
new IconImageDemo1();
}
});
}
}
Try this. Pretty the same as sajjad's answer just has a check to make sure the image url isn't null before using it.
java.net.URL imageUrl = YourClass.class.getResource("/IconImage.png");
if(imageUrl != null){
setIconImage(new ImageIcon(imageUrl));
}

How can I make my GUI Frame larger?

The problem is, I am unable to make it a dimension with 800x600. In other words, when I run the program, the frame is so small that I can not do anything with it.
How can I make the frame larger?
I have set the preferred size already ans set the canvas bounds.
Then what is the problem?
public class GameCanvas extends Canvas
{
private BufferStrategy buffer = null;
public GameCanvas()
{
setBounds(0, 0, 800, 600);
setIgnoreRepaint(true);
addKeyListener(new KeyInputHandler());
requestFocus();
}
public void addNotify()
{
super.addNotify();
this.createBufferStrategy(2);
buffer = this.getBufferStrategy();
setBounds(0, 0, 800, 600);
}
}
public class GameGuiFrame extends JFrame
{
private JPanel panel = new JPanel();
private GameCanvas canvas = new GameCanvas();
public GameGuiFrame()
{
this.setName("My Game");
this.pack();
this.setResizable(false);
this.setVisible(true);
panel = (JPanel) this.getContentPane();
panel.setPreferredSize(new Dimension(750,500));
panel.setLayout(null);
panel.add(canvas);
}
}
public class GameManager
{
public static void runGameLoop()
{
GameGuiFrame container = new GameGuiFrame();
container.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
}
}
public class Main
{
public static void main(String [] args)
{
GameManager.runGameLoop();
}
}
Try packing the Frame after you set the preferred size of the content pane.
Not related to your question but based on the code you posted it looks like you've copied some old AWT code and are trying to use it in a Swing application.
I would suggest you only use Swing components. There is no need to use a Canvas with a BufferStrategy. Just use a JPanel it is double buffered by default. The code snippet you copied is old and that is not the way it is done in Swing.
Don't use a null layout. Swing was designed to be using with layout managers. Then the pack() method will be able to do its job properly.
There is no need to use a WindowListener to close the frame. These days people just use:
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Also, the frame should be made visible AFTER components have been added to the frame.
Generally you should be use Key Bindings, not a KeyListener to listen for key events in a Swing application.
I suggest you look at the Swing tutorial for more information about the above concepts.
You call to pack() will set the frame (and components within it) to their preferred size. However, you haven't specified a preferred size. I would suggest removing your two calls to setBounds() and calling setBounds() within the main method instead of pack().

java panel with png background

i found this link.. LINK what i want is there's a JPanel that has a background and another JPanel with half the size of the first JPanel but with an image that is transparent and with a face or a ball at the middle.. :) just like the screenshot from the link.. is that possible to code in java? :) im just thinking it like for web programming. just a sort of DIV's to have that but i dont know in java.. :) sorry for bad english.. :D i have this as a background..
package waterKing;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
#SuppressWarnings("serial")
public class Main extends JFrame {
MainData data = new MainData();
public static void main(String[] args) {
Main frmMain = new Main();
frmMain.setExtendedState(Frame.MAXIMIZED_BOTH);
frmMain.setVisible(true);
}
public Main() {
data.tk = getToolkit();
data.d = data.tk.getScreenSize();
data.jP = new JPanel() {
protected void paintComponent(Graphics g) {
data.e = getSize();
data.iI = new ImageIcon("images/mainBG.png").getImage();
g.drawImage(data.iI,0, 0, data.d.width, data.d.height, null);
super.paintComponent(g);
}
};
data.jP.setOpaque(false);
data.jSp = new JScrollPane(data.jP);
data.jB = new JButton("EXIT");
data.jB.setBounds(10,10,200,40);
data.jB.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
data.jP.setLayout(null);
data.jP.add(data.jB);
this.setTitle("Water King Inventory System");
this.setUndecorated(true);
this.getContentPane();
this.add(data.jSp);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
}
}
i dont know how to add another JPanel to show in the middle with this background
i dont know how to add another JPanel to show in the middle with this background
Its just like adding components to a panel. You need to use a layout manager and then the component will be positioned properly based on the rules of the layout manager. In your case you can set the layout manager of the background panel to be a BorderLayout. Then you can add a JLabel with the appropriate Icon to the center of the BorderLayout.
You will need to set the preferred size (or override the getPreferredSize() method of your panel since you add it to a scroll pane. Scrollbars will only appear when the preferred size of the panel is greater than the size of the scroll pane.
You should not be reading the image in your paintComponent() method since this method is called multiple times.
You should not be using the "screen size" to determine the width/height of the image because the frame will contain a border. You need to use the size of the panel.
Get rid of all the setBounds() code. Learn to use layout managers.
For a general purpose background panel that takes into account most of the suggestions made here check out Background Panel.

Categories