Can't get image to show up in swing - java

I'm a college student and this is my first time I have ever created a gui in Java. Right now I looked at this answer GUI in Java using Swing and followed the instructions and still nothing happens. Here is the code. I cut out all the irrelevant junk.
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Lab4Shell
{
// this holds the current game board
private char[][] gameBoard = new char[7][8];
private JButton[][] gameButtons = new JButton[7][8];
private ImageIcon red = new ImageIcon("Red.jpg");
private ImageIcon black = new ImageIcon("Black.jpg");
private ImageIcon empty = new ImageIcon("Empty.jpg");
private JPanel panel = new JPanel();
private int currentPlayer = 1;
private int numMoves = 0;
//Why do you want everything in constructor?
public Lab4Shell()
{
CreateWindow();
ResetGame();
// set layout
// loop through buttons array creating buttons, registering event handlers and adding buttons to panel
// add panel to frame
// do other initialization of applet
}
public static void CreateWindow()
{
//Sets window title and create window object.
JFrame aWindow = new JFrame("Connect Four");
//Set window position and size
aWindow.setBounds(500,100,400,400);
//What close button does.
aWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Make window visible.
aWindow.setVisible(true);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
Lab4Shell game = new Lab4Shell();
}
});
}
void ResetGame()
{
JLabel label = new JLabel();
label.setIcon(empty);
for(int r=0;r<gameBoard.length;r++)
{
java.util.Arrays.fill(gameBoard[r],0,gameBoard[r].length,'0');
//loop through board columns
for(int c=0;c<gameBoard[r].length;c++)
{
}
}
// loop through array setting char array back to ' ' and buttons array back to empty pic
// reset currentPlayer and numMoves variables
}

You have to add the created ImageIcons to the panel as Manos said, and being the images at the src folder of Eclipse project, do that:
java.net.URL url = getClass().getResource("red.JPEG");
ImageIcon red = new ImageIcon(url);

If the resources are embedded with the application (within in the jar), the you need to use Class#getResource to load them.
The preferred mechanism for loading images is through the ImageIO API. It supports more image formats (as well as providing a pluggable architecture) and guarantees an image that is ready to be displayed once the read method returns
BufferedImage redImage;
// ...
URL url = getClass().getResource("red.JPEG");
if (url != null) {
redImage = ImageIO.read(url);
} else {
throw new NullPointerException("Unable to locate red image resource");
}

You can try this
BufferedImage myPicture = ImageIO.read(new File("path-to-file"));
JLabel picLabel = new JLabel(new ImageIcon( myPicture ));
add( picLabel );

You've never adding anything to your frame - which is causing your problem. So in you createWindow method, you need to call:
aWindow.setContentPane(panel);
Then later on (like in your resetGame method), you'll add your content (like the JLabel) to the panel:
panel.add(empty);
Where it's added to your panel is determined by the LayoutManager of the panel (there are many of them - the default is BorderLayout)
Other helpful things:
Generally, when it makes sense, create/initialize your objects in the constructor and add/remove/update them in the runtime.
For troubleshooting, use the .setOpaque(true) and .setBackground(Color.blue) methods on what you want to see. If you don't see it then, either something is covering it up, or it was never added
Good luck.

Related

why is importing a font breaking other parts of code?

Modifiers.java:
package game;
import java.awt.*;
import java.io.*;
import javax.swing.*;
public class Modifiers extends Data{
public static void setupJcomponents(){
frame.setUndecorated(true);
frame.setSize(MW,MH);
frame.setResizable(false);
frame.setVisible(true);
frame.setLayout(null);
for(int btn=0; btn<4; btn++) {
Buttons[btn] = new JPanel();
Buttons[btn].setBounds(btn*100,0,100,100);
Buttons[btn].setVisible(true);
Buttons[btn].setBackground(new Color(btn*50,btn*50,btn*50));
frame.getContentPane().add(Buttons[btn]);
}
menuBackground.setBounds(0,0,MW,MH);
menuBackground.setVisible(true);
menuBackground.setBackground(Color.black);
healthIndicator.setText(String.valueOf(healthValue));
healthIndicator.setFont(new Font("Terminal", Font.PLAIN, 100));
healthIndicator.setBounds(600,600,100,100);
healthIndicator.setForeground(Color.blue);
try{
PixelFont = Font.createFont(Font.TRUETYPE_FONT, new File("PixelFont.ttf"));
} catch (IOException e) {
PixelFont = new Font("Terminal", Font.PLAIN, 100);
} catch(FontFormatException e) {
PixelFont = new Font("Terminal", Font.PLAIN, 100);
}
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
ge.registerFont(PixelFont);
frame.getContentPane().add(healthIndicator);
frame.getContentPane().add(menuBackground);
}
}
Data.java:
package game;
import java.awt.*;
import javax.swing.*;
public class Data {
// this is where I will declare and alter all variable that will be used
public static JFrame frame = new JFrame();
public static JLabel healthIndicator = new JLabel();
public static JPanel Buttons[] = new JPanel[5];
public static JPanel menuBackground = new JPanel();
public static final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
public static final int MW = (int) screenSize.getWidth();
public static final int MH = (int) screenSize.getHeight();
public static Font PixelFont;
public static int maxHealth = 100;
public static int healthValue = maxHealth;
}
Frame.java:
package game;
public class Frame {
public static void main(String[] args) {
Modifiers.setupJcomponents();
}
}
whenever i rum Frame.java the menu Background disappears and the text altogether stops showing up. but if the path to the .ttf file is wrong it just skips over the font and uses the default instead. How do i get this font to load properly as well as not cause my background background to disappear? I have tried changing the path to the .ttf file and turning various parts of the code into comments, but even if the font of the health indicator is a default font, these errors will still occur, however if i try removing the try-catch loop then the errors aren't there anymore.
There are all kinds of problems with the code. Not exactly sure why the Fonts is causing an issue, but it has something to do with the overall structure of your code and you aren't using Swing the way it was designed to be used.
whenever i rum Frame.java the menu Background disappears and the text altogether stops showing up
What appears to be directly related to the above question is that the setVisible(true) statement should be executed AFTER all the components have been added to the frame. This will make sure all the components are painted.
Note this will still only work by chance because you happen to add the "background" panel to the frame last. Swing paints components in the reverse order that are added to any given panel.
Regarding other problems.
your painting code only works by chance. You should not be adding all your components directly to the frame. Swing is not designed to paint components in 3 dimensions directly when the components overlap one another. Swing is designed to have a parent child relationship. So that would mean you add your "background" panel to the frame. Then you add a panel containing the buttons to the "background" and you add the "health" component to the background.
Related to above you should NOT be using a null layout. Swing was designed to be used with a layout manager. This will make sure components don't overlap. So in your case you can use a BorderLayout for the "background" panel. Then you can add the "buttons" panel to the BorderLayout.PAGE_Start and the "health" component to the `BorderLayout.PAGE_END. This will ensure that the components are at the top/bottom of the background panel.
Don't set the size of the frame. Instead you use the setExtendedState(JFrame.MAXIMIZED_BOTH) property. The frame will be the size of the screen. The "GamePanel" will be take up all the space of the frame. So there is no need to set or use hardcoded values.
Don't use static variables and method. This indicates poor design. What you should be doing is creating a GamePanel class, which would essentially be your background panel. This class would contain the instance variables needed for the game. It would create the "buttons" panel and the "health" component and add it to itself.
Variable names should NOT start with upper case characters.

Images not visible in JList

I'm writing a little photo application (asked some questions before) and I have one problem which I cannot resolve. The idea is that there are two sections: the upper one is for an overview (using thumbnails) and the lower one shows the selected image in it's full size. I cannot use ImageIO (required by my lecturer).
I'm using a JList for the overview but most images are not visible. I chose a folder with about 20 images and only 2 show up. And one of them isn't even centered.
For some reason, if I delete those lines:
thumbnaillist.setFixedCellWidth(thumbW);
thumbnaillist.setFixedCellHeight(thumbH);
One image shows up that wasn't visible before, but now the other two disappear.
This is my code:
public class PVE extends JFrame {
private JFileChooser fileChoose;
//MenuBar
private JMenuBar menubar;
private JMenu file;
private JMenuItem openFolder;
private JMenuItem exit;
//Thumbnails
private JList thumbnaillist;
private DefaultListModel<ImageIcon> listmodel;
private JScrollPane tscroll;
private ImageIcon thumbs;
private int thumbW = 100;
private int thumbH = 100;
//for full size view
private JPanel imgview;
public PVE() {
setLayout(new BorderLayout());
//MenuBar
menubar = new JMenuBar();
file = new JMenu("File");
openFolder = new JMenuItem("Open folder...");
exit = new JMenuItem("Quit");
file.add(openFolder);
file.addSeparator();
file.add(exit);
menubar.add(file);
setJMenuBar(menubar);
fileChoose = new JFileChooser();
openFolder.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
fileChoose.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fileChoose.showOpenDialog(null);
File chosenDir = fileChoose.getSelectedFile();
loadToThumbView(chosenDir);
}
});
//Thumbnail view
listmodel = new DefaultListModel();
thumbnaillist = new JList(listmodel);
thumbnaillist.setLayoutOrientation(JList.HORIZONTAL_WRAP);
thumbnaillist.setFixedCellWidth(thumbW);
thumbnaillist.setFixedCellHeight(thumbH);
thumbnaillist.setVisibleRowCount(1);
tscroll = new JScrollPane(thumbnaillist, JScrollPane.VERTICAL_SCROLLBAR_NEVER,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
tscroll.setPreferredSize(new Dimension(0, 100));
add(tscroll, "North");
//for full size view
imgview = new JPanel();
imgview.setBackground(Color.decode("#f7f7f7"));
add(imgview, "Center");
setTitle("Photo Viewer");
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
SwingUtilities.updateComponentTreeUI(this);
} catch (Exception e) {
}
setSize(700, 700);
setLocation(200, 200);
setVisible(true);
}
public void loadToThumbView(File folder) {
listmodel.removeAllElements();
File[] imgpaths = folder.listFiles();
for (int j = 0; j < imgpaths.length; j++) {
listmodel.addElement(resizeToThumbnail(new ImageIcon(imgpaths[j].toString())));
}
}
public ImageIcon resizeToThumbnail(ImageIcon icon) {
Image img = icon.getImage();
BufferedImage bf = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics g = bf.createGraphics();
g.drawImage(img, 0, 0, thumbW, thumbH, null);
ImageIcon kB = new ImageIcon(bf);
return kB;
}
public static void main(String argv[]) {
PVE pv = new PVE();
}
}
Your problem is because of the way you're scaling your images.
I'm not exactly sure why but I guess it has something to do with the BufferedImage#createGraphics() call and that I was able to reproduce the problem with .jpg images while .png files were correctly painted.
However if you scale your images instead of converting them to a BufferedImage and getting a new ImageIcon from it, you get the correct output:
public ImageIcon resizeToThumbnail(ImageIcon icon) {
Image img = icon.getImage();
Image scaled = img.getScaledInstance(thumbW, thumbH, Image.SCALE_SMOOTH);
return new ImageIcon(scaled);
}
This is the folder I used to test:
And the outputs with your code and mine:
Important notes
And as as a recommendation don't make a window that big if all you're using is that little bar above. If you're adding something else below, then it's ok but for now it's not that "user friendly" (IMHO). Instead of JFrame#setSize() you could try using JFrame#pack() method so your frame resizes to it's preferred size.
Some other things I noted in your program:
You're not placing it inside the Event Dispatch Thread (EDT) which is dangerous since your application won't be Thread safe that way. You can change that if you change your main method as follows:
public static void main(String argS[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
PVE pv = new PVE();
}
});
}
You're setting the JScrollPane preferred size, instead you should override its getPreferredSize() method, see Should I avoid the use of setPreferred|Maximum|MinimumSize methods in Java Swing? (YES)
You're extending JFrame, you should instead create an instance of it unless you're overriding one of its methods (and you're not, so don't do it) or you have any good reason to do it. If you need to extend a Container you should extend JPanel instead, as JFrame is a rigid container which cannot be placed inside another one. See this question and this one.
I think I'm not missing anything, and hope this helps
Your “scaled” images are actually images which are the same size as the original image, but are blank except for a scaled version drawn in the upper left corner. That upper left corner is clipped out of view in each rendered cell (at least for the somewhat large images I tested with).
The scaled image needs to be created with the thumbnail size, not the size of the original image. Meaning, change this:
BufferedImage bf = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
to this:
BufferedImage bf = new BufferedImage(thumbW, thumbH, BufferedImage.TYPE_INT_ARGB);

Changing layout/frame in response to a button press

I'm trying to make a little game on Java using the Swing components (Boggle-type game).
The way I have it set up right now, it basically opens up to the game right away - but I want to have a start up window with two buttons - "Tutorial" and "Play". I already have the functionality (my Tutorial button just opens a new Window with all the things on it) I'm just not sure how to create a second JFrame and then switch to it when I press Play (or rather, create a JFrame, then switch to the one I've already created when the JButton is pressed). I guess I could cause a new JFrame to open on the same location and the old one to become non-visible - but I was hoping for a simpler solution.
I also want to do this on completion of the game, switching again automatically to a little stat page - so any info will be appreciated.
This is what I have so far in case you guys want to see my code (I haven't yet hooked up the Enter key send the userWord to be validated and scored in my other classes, or filled in the tileGrid with Tile Objects, or the timer.... but that will all come later!)
public class Game implements Runnable {
public void run(){
final JFrame frame = new JFrame("Boggle");
frame.setLocation(500,200);
// Input - holds typing box
final JLetterField typingArea = new JLetterField(1);
typingArea.setFocusTraversalKeysEnabled(false);
typingArea.setEditable(true);
typingArea.setFocusable(true);
typingArea.requestFocusInWindow(); //also this request isn't being granted..
//if anyone could explain why i would love you
// I want the focus on the TextField on startup
frame.add(typingArea, BorderLayout.SOUTH);
typingArea.addKeyListener(new KeyAdapter() {
public void keyPressed (KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) { // enter key is pressed
String userWord = typingArea.getText().toLowerCase();
typingArea.setText("");
}
}
});
final JLabel status = new JLabel("Running...");
// Main playing area
GridLayout tileGrid = new GridLayout(4,4);
final JPanel grid = new JPanel(tileGrid);
frame.add(grid, BorderLayout.CENTER);
// Reset button
final JPanel control_panel = new JPanel();
frame.add(control_panel, BorderLayout.NORTH);
final ImageIcon img = new ImageIcon("Instructions.png", "My Instructions...");
final JButton info = new JButton("Help");
info.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
final JFrame infoFrame = new JFrame("Tutorial");
infoFrame.setLocation(500,50);
JLabel tutorialImg = new JLabel(img);
int w = img.getIconWidth();
int h = img.getIconHeight();
infoFrame.setSize(w, h);
infoFrame.add(tutorialImg);
infoFrame.setVisible(true);
}
});
control_panel.add(info);
// Put the frame on the screen
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Game());
}
}
use CardLayout instead of second JFrame, your concept is heading to OutOfMemory
use JFrame.pack(after switch betweens Cards in CardLayout) if you want to change JFrames bounds on runtime,

display imageicon in Jlabel

I'm doing a program in Netbeans
.. and I need to display the content of the folder (there are images) in a JPanel
... display every image in jlabel
.... I did this code, but its not working
...... I create a interface with a JButton and JPanel:
public class MyInterface extends javax.swing.JFrame
{
/** Creates new form NewJFrame1 */
public MyInterface()
{
initComponents();
}
private File files;
private JFileChooser es = new JFileChooser();
String path;
JLabel label;
public List<ImageIcon> pictures = new ArrayList<ImageIcon>();
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
{
if (es.showOpenDialog(jPanel1) == JFileChooser.APPROVE_OPTION)
{
files = es.getSelectedFile();
path = files.getAbsolutePath();
return;
}
label.setIcon(pictures.get(WIDTH));
files = null;
return;
}
private JLabel getLabel(BufferedImage[] images)
{
for (int j = 0; j < images.length; j++)
{
pictures.add(new ImageIcon(images[j]));
}
label = new JLabel(pictures.get(0));
label.setHorizontalAlignment(JLabel.CENTER);
return label;
}
private JPanel draw()
{
JPanel panl = new JPanel();
for (int j = 0; j < pictures.size(); j++)
{
panl.getBorder();
}
JPanel panel = new JPanel();
panl.addAncestorListener(null);
panl.add(panl);
return panel;
}
}
hard to say something and wise
1) maybe there isn't any reason for create JLabels and JPanels on the fly
2) if you want to display only one Image in one moment then
create JFrame
put there JLabel and JButton
use Icon for Image/BufferedImage, put this Icon to the JLabel
3) if you want to display more than one Images (let's to say up to 20-50 Images) then use GridLayout for JLabels contains Icon
4) if number of Images isn't limited somehow then use JList
It's not entirely clear what you are trying to do, your code doesn't compile as shown, and it's a bit of a mess. Some pointers though:
In draw(), you are adding a JPanel to itself, which is not a good sign. Then you return a different panel that has not been modified. Sort out the panel and panl naming to fix this.
In getLabel(), which isn't actually called anywhere, you return one label created from the first image. So you will only be able to display one of the images.
In jButton1ActionPerformed you return early if the user selects a file, so the path will be set but it's not clear that anything else happens.

Displaying an image in Java Swing

public class MinesweeperMenu extends MinesweeperPanel{
private JPanel picture = new JPanel();
private JButton play = new JButton("Play");
private JButton highScores = new JButton("High Score and \nStatistics");
private JButton changeMap = new JButton("Create Custom \nor Change Map");
private JButton difficulty = new JButton("Custom or\nChange Difficulty");
private JButton user = new JButton("Change User");
Image img;
public MinesweeperMenu()
{
// Set Layout for the menu
LayoutManager menuLayout = new BoxLayout(menu, BoxLayout.Y_AXIS);
menu.setLayout(menuLayout);
// Set Layout for the window
LayoutManager windowLayout = new BorderLayout();
window.setLayout(windowLayout);
// Add buttons to the panels
menu.add(play);
menu.add(highScores);
menu.add(changeMap);
menu.add(difficulty);
menu.add(user);
// Add picture to the frame
try{
File input = new File("./setup/images/MineMenuPicture.jpg");
img = ImageIO.read(input);
}
catch(IOException ie)
{
System.out.println(ie.getMessage());
}
// Add action listeners
changeMap.addActionListener(new ChangeMapListener());
}
public void paintComponent(Graphics g)
{
// POSITION OF THE PICTURE
int x = 650;
int y = 585;
g.drawImage(img, x, y, null);
}
public void displayFrame()
{
// Display Frame
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
}
public static void main(String[] args)
{
MinesweeperMenu menu = new MinesweeperMenu();
window.pack();
menu.displayFrame();
window.repaint();
}
}
public class MinesweeperPanel extends JFrame{
public static final Color COLOR_KEY = new Color(220, 110, 0);
// Initialize all the objects
public static JFrame window = new JFrame("Minesweeper++");
public static JPanel menu = new JPanel();
// Close the current window
public static void close()
{
window.setVisible(false);
window.dispose();
}
}
I can't get my image to display in the frame. I've tried everything, but I'm getting the impression it's a mistake that I'm not realizing since I am new to Java Swing. Any help would be greatly appreciated.
You're making things difficult for yourself by having a very confusing program structure, and I suggest that you simplify things a lot.
For one, there's no need for your current MinesweeperMenu class to extend MinesweeperPanel, and for the latter class to extend JFrame. Then you have a static JFrame somewhere else -- that's too many JFrames, and to boot, you're trying to display your image in one JFrame but showing the other one that doesn't have the picture. Your program needs just one JFrame and it should probably be created, stuffed with its contents, packed and displayed in one place, not scattered here and there as you're doing.
You're trying to display the picture in a paintComponent override, but this method will never get called since your class extends JFrame (eventually) and JFrame doesn't have this method. You're using the right method, but the class should be extending JPanel, and you should have an #Override annotation above the paintComponent method block to be sure that you're actually overriding a parent method.
You should get rid of all static everything in this program. The only thing static here should be the main method and perhaps some constants, but that's it.
There are more errors here, and I have too little time to go over all of them. Consider starting from the beginning, starting small, getting small bits to work, and then adding them together.
For instance, first create a very small program that tries to read in an image into an Image object, place it in a ImageIcon, place the ImageIcon into a JLabel, and display the JLabel in a JOptionPane, that simple, just to see if you can read in images OK, for example, something like this:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
public class TestImages {
// *** your image path will be different *****
private static final String IMG_PATH = "src/images/image01.jpg";
public static void main(String[] args) {
try {
BufferedImage img = ImageIO.read(new File(IMG_PATH));
ImageIcon icon = new ImageIcon(img);
JLabel label = new JLabel(icon);
JOptionPane.showMessageDialog(null, label);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Then when you've done this, see if you can now create a JPanel that shows the same Image in its paintComponent method, and display this JPanel in a JOptionPane.
Then create a JFrame and display the image-holding JPanel in the JFrame.
Through successive iterations you'll be testing concepts, correcting mistakes and building your program.
File input = new File("./setup/images/MineMenuPicture.jpg");
If MineMenuPicture.jpg is an application resource, it should be in a Jar and accessed by URL obtained from Class.getResource(String).

Categories