Adding image to JLabel, and displaying Labels in a GridLayout - java

My current code, interestingly works with another IDE(JGrasp), although I am currently trying to create a game which uses networking. Eclipse allows networking on a single computer. For some reason, this method Im posted, which adds imagines to an array of JLabel, does not work with eclipse? I am new with eclipse and not sure why this is happening?
private JPanel createBoard()
{
// Instantiate Panel with a GridLayout
board = new JPanel();
board.setLayout(new GridLayout(10,10));
// Fill the Panel with an Array of Labels
// Checks for exception
boardSpotArray = new JLabel[100];
try
{
for (int x = 0; x < boardSpotArray.length; x++)
{
boardSpotArray[x] = new JLabel();
boardSpotArray[x].setIcon(new ImageIcon(x + ".jpg"));
board.add(boardSpotArray[x]);
}
}
catch (IndexOutOfBoundsException exception)
{
System.out.println("Array drawer not available, " + exception.getMessage());
}
// return panel
return board;
}

If for example boardSpotArray[0] is "firstImage", then your relative file path will be "firstImage.jpg". In such a case with Eclipse, and without using any special loaders or resource getters, the IDE will first look for the image in the project root. So your file structure should look like this
ProjectRoot
firstImage.jpg <-- image as direct child of project root
src
bin
Edit:
If your images are in the src folder
ProjectRoot
src
0.jpg <-- image in src
1.jpg
2.jpg
Then your path should look like this
new ImageIcon("src/" + x + ".jpg")

Complete code in Eclipse for you
import java.awt.GridLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class oo {
public static JPanel createBoard()
{
// Instantiate Panel with a GridLayout
JPanel board = new JPanel();
board.setLayout(new GridLayout(10,10));
// Fill the Panel with an Array of Labels
// Checks for exception
JLabel[] boardSpotArray = new JLabel[100];
try
{
for (int x = 0; x < boardSpotArray.length; x++)
{
boardSpotArray[x] = new JLabel();
boardSpotArray[x].setIcon(new ImageIcon("healthy-heart.jpg"));
board.add(boardSpotArray[x]);
}
}
catch (IndexOutOfBoundsException exception)
{
System.out.println("Array drawer not available, " + exception.getMessage());
}
// return panel
return board;
}
public static void main(String[] args){
JFrame frame=new JFrame();
JPanel panel=createBoard();
frame.getContentPane().add(panel);
frame.setSize(100, 100);
frame.pack();
frame.setVisible(true);
}
}
"healthy-heart.jpg" can be replaced with any other image.

Related

Jpanel first item centers despite position of 0,0

I am trying to programmatically create a background grid for a project I am working on. The problem is that the first item I add to the jpanel is always painted at center of the jpanel. I am expressly trying to put it at the top right. I have even tried just placing a dummy jlabel down first and going from there but then the second and third element just overlap each other. This bug has me thoroughly dumbfounded. Any help would be great.
private void evalWindow(){
window.removeAll();
window.setBorder(BorderFactory.createLineBorder(Color.black));
JLabel p = new JLabel(new ImageIcon(tiles[0][0].getImage()));
p.setLocation(0,0);
System.out.println("1: " + p.getLocation());
p.setSize(64,64);
window.add(p);
System.out.println("2: " + p.getLocation());
for(int i = 0; i < x; i++){
for (int j = 0; j < y; j++){
JLabel piclabel = new JLabel(new ImageIcon(tiles[i][j].getImage()));
piclabel.setSize(64,64);
piclabel.setLocation(64*j, 64*i);
System.out.println("1: " + piclabel.getLocation());
window.add(piclabel);
}
}
}
sample image:
As mentioned elsewhere, a GridLayout would be the easiest way to layout the grid positions. It can be as simple as:
public void initUI(Image img) {
ui = new JPanel(new GridLayout(0,8));
ImageIcon icon = new ImageIcon(img);
for (int ii=0; ii<32; ii++) {
ui.add(new JLabel(icon));
}
}
This is the effect:
Here is the MCVE that produces the above GUI. In future, please post code in the form of an MVCE.
import java.awt.*;
import java.awt.image.*;
import java.io.IOException;
import javax.swing.*;
import javax.imageio.*;
import java.net.URL;
public class ImageGrid {
private JComponent ui = null;
String imageURL = "https://i.stack.imgur.com/DlSgb.png";
ImageGrid() {
try {
BufferedImage img = ImageIO.read(new URL(imageURL));
BufferedImage subImg = img.getSubimage(2, 2, 64, 64);
initUI(subImg);
} catch (IOException ex) {
ex.printStackTrace();
}
}
final public void initUI(Image img) {
ui = new JPanel(new GridLayout(0,8));
ImageIcon icon = new ImageIcon(img);
for (int ii=0; ii<32; ii++) {
ui.add(new JLabel(icon));
}
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = () -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
ImageGrid o = new ImageGrid();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
};
SwingUtilities.invokeLater(r);
}
}
You do not tell us the type of the variable "window", but I'll assume it's a JFrame or something else that will take a layout manager. Components on Swing windows are not normally placed with absolute positions like 0,0; they are added to containers which are set to use an extension of LayoutManager, and the LayoutManager class manages where the components added to it will go.
FlowLayout adds things in order; GridLayout puts things in equal-size cells on a grid; BorderLayout allows placement in one of 5 areas, etc. The LayoutManager scheme saves you from having to mess with positioning while the user changes the size of the outer window, allows some elements to grow and shrink with available overall size, etc.
If you must place things with absolute positions, there is a NullLayoutManager, but in over 20 years of Java programming and a number of different Swing applications, I've never seen one.
Read about LayoutManagers. I'm sure whatever one is default for your window variable is placing your component in the center and ignoring the absolute placement.

JFrame inside another JFrame

I have a game of chess.
I have written 3 classes.
1st if for game. (chessboard, pieces, and so on)
And another one is for menu. (buttons like new, open, set time)
Both of them use JFrame.
I would like to put both classes mentioned above into the 3rd class. For example the Game window would be on the left, and the menu on the right.
The third class would also show the whole app by JFrame.
How to do that?
You can't put one JFrame inside another. You have a couple of design choices here. You can change your JFrames to JPanels. This is probably the easiest change. On the other hand, you can look at using Internal Frames instead.
In your case i suggest you to use JInternalFrame which can be added inside Jframe try out this code i hope it will work:
package demo;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
public class Demo {
public static void main(String[] args) {
JFrame jf=new JFrame();
jf.setLayout(null);
jf.setSize(1280, 720);
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JInternalFrame jInternalFrame=new JInternalFrame();
jInternalFrame.setLocation(100, 100);
jInternalFrame.setSize(500, 300);
jInternalFrame.setTitle("Internal frame");
jInternalFrame.setVisible(true);
jInternalFrame.setClosable(true);
jInternalFrame.setResizable(true);
jf.add(jInternalFrame);
jf.repaint();
}
}
You can use JPanels for that. It's easier that way... use a JFrame for the main window and for menu items use a JPanel inside it. Search for tutorials on JPanel usage.
The best thing to do would be to leave the outer frame as it is and change the inner contents to JPanels. When I wrote Chess, I had an outer frame which extended JFrame, and inner panel that extended JPanel on which I placed the board. The board itself was comprised of 64 JButtons.
Given your description, I think this would be a good starting point:
package data_structures;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Chess extends JFrame implements ActionListener {
private JButton[][] tiles;
public Chess() {
setTitle("Chess");
setSize(500, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setLayout(new BorderLayout());
JPanel board = new JPanel();
board.setLayout(new GridLayout(8, 8));
tiles = new JButton[8][8];
for(int y = 0; y < tiles.length; y++) {
for(int x = 0; x < tiles[y].length; x++) {
tiles[x][y] = new JButton();
tiles[x][y].setActionCommand(x + " " + y);
tiles[x][y].addActionListener(this);
board.add(tiles[x][y]);
}
}
add(board, BorderLayout.CENTER);
JPanel options = new JPanel();
options.setLayout(new GridLayout(1, 3));
JButton newGame = new JButton("New");
newGame.addActionListener(this);
options.add(newGame);
JButton openGame = new JButton("Open");
openGame.addActionListener(this);
options.add(openGame);
JButton setTime = new JButton("Set Time");
setTime.addActionListener(this);
options.add(setTime);
add(options, BorderLayout.SOUTH);
revalidate();
}
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
System.out.println(command);
revalidate();
}
public static void main(String[] args) {
new Chess();
}
}
Also, a word of warning:
Fully implementing the logic of Chess is very difficult, no matter what you do for the graphics.
Hope this helps!
I guess that's what you want to do.
public class OuterFrame extends JFrame {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
OuterFrame outerFrame = new OuterFrame();
outerFrame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public OuterFrame() {
JFrame innerFrame = new JFrame();
innerFrame.setVisible(true);
}
}
You have a MainFrame (OuterFrame), and you create it. But, you create a JFrame inside this MainFrame. That's not a beautiful thing to do, but it's certainly a way of opening a "JFrame inside the other". This will give you two "windows" on the screen. You could create countless JFrames inside the MainFrame.

Changing JLabel icon dynamically after already adding to GUI?

I'm having trouble changing an icon deep in my GUI using Swing components. I'm creating a chess game for fun with Java and want the right side of the GUI to respond when a piece is taken by showing the taken piece in a grid. My problem is that whenever I call the setIcon() function within JLabel with a new image and add it to the appropriate JPanel, it does not update. It works when I setIcon() the first time, but after it is added to the GUI, I can't change it the way I have been trying to. Here is screenshots so you know what I'm getting at:
Initial State
After
As you can tell, a pawn has been taken but the right panel does not reflect this despite my efforts.
I did some research and the following question was similar: Relevant Question
Camickr responded in that saying it could be two instances of the JLabel I am trying to update which I believe is what is going in my case. I initially set all of my icons on the right panel to null when setting the GUI up for initial state. Here is the code that does this:
for (int i = 0; i < 16; i++)
{
piece1Labels[i] = new JLabel();
piece2Labels[i] = new JLabel();
piece1Panels[i] = new ChessSpace(playerDeadPieceTile);
piece2Panels[i] = new ChessSpace(playerDeadPieceTile);
piece1Labels[i].setPreferredSize(new Dimension(67,66));
piece2Labels[i].setPreferredSize(new Dimension(67,66));
piece1Labels[i].setIcon(null);
piece2Labels[i].setIcon(null);
piece1Panels[i].add(piece1Labels[i]);
piece2Panels[i].add(piece2Labels[i]);
player1PiecePanel.add(piece1Panels[i]);
player2PiecePanel.add(piece2Panels[i]);
}
and here is me trying to change one of those panels after the initialization has been called on the first panel in the piece1Panels array of ChessSpace which extend JPanel:
//Try to change right panel icon after GUI setup
piece1Labels[0] = new JLabel();
piece1Panels[0] = new ChessSpace(playerDeadPieceTile);
piece1Labels[0].setPreferredSize(new Dimension(67,66));
piece1Labels[0].setIcon(new ImageIcon("C:/Users/Shasta/workspacejava/chess/images/terranpawn.jpg"));
piece1Panels[0].add(piece1Labels[0]);
piece1Labels and piece1Panels are variables of a class extending JFrame. I believe that the problem is that I'm just updating the class variable and not updating the instance that was added to the GUI.
EDIT:
As Alican Ozgoren & Hovercraft Full Of Eels pointed out I shouldn't have declared new instances of the JLabel, they were redundant.
The following line of code seems to do what I want:
//Try to change right panel icon after GUI setup
piece1Labels[0].setIcon(new ImageIcon("C:/Users/Shasta/workspacejava/chess/images/terranpawn.jpg"));
As we noted, simply set the Icon of the JLabel. But one more thing -- don't keep reading in the Icons as you're doing here:
piece1Labels[0].setIcon(new ImageIcon(
"C:/Users/Shasta/workspacejava/chess/images/terranpawn.jpg"));
Instead read the Icons in once at the beginning of your program, and store them in variables so that you get:
piece1Labels[0].setIcon(terranpawnIcon);
I would also read them in as resources not Files so that you can later store your images in your jar file and use them.
Just Create a thread which will update the JLable Icone please see the code below
package self.wing.practice.image;
import javax.swing.*;
/**
*
* #author ASHISH KUMAR MISHRA
*
*/
public class ImageDemo {
public ImageDemo() {
JFrame jfrm = new JFrame("Image Demo");
jfrm.setSize(200, 150);
jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel();
jfrm.add(label);
new ImageUpdator(label).start();
jfrm.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// TODO Auto-generated method stub
new ImageDemo();
}
});
}
}
i have created a thread to whom i am passing a Jlabel in Constructur. see below the what my thread is doing
package self.wing.practice.image;
import java.io.File;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
/**
*
* #author ASHISH KUMAR MISHRA
*
*/
public class ImageUpdator extends Thread {
String imagePath = "C:\\Users\\Public\\Pictures\\Sample Pictures";
File imageDir = new File(imagePath);
JLabel label = null;
ImageUpdator(JLabel label) {
this.label = label;
}
public void run() {
ImageIcon imageIcon = null;
if (imageDir.isDirectory()) {
File[] files = imageDir.listFiles();
for (int i = 0;; i++) {
i = i % files.length;
File currentFile = files[i];
if (currentFile.getName().endsWith(".jpg"))
;
{
imageIcon = new ImageIcon(currentFile.getAbsolutePath());
label.setName(currentFile.getName().substring(0,
currentFile.getName().indexOf('.')));
label.setIcon(imageIcon);
label.setHorizontalAlignment(JLabel.CENTER);
try {
Thread.sleep(700);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
Heading

change jlabel with method

I am writing a small program that converts files, and I wanted to have a box pop up that asks the user to please wait while the program loops through and converts all the relevant files, but I am running into a small problem. The box that pops up should have a JLabel and a JButton, while the user is "waiting" I wanted to display a message that says please wait, and a disabled "OK" JButton, and then when its finished I wanted to set the text of the JLabel to let them know that It successfully converted their files, and give them a count of how many files were converted. (I wrote a method called alert that sets the text of the label and enables the button.) The problem is That while the program is running, the box is empty, the Label and the Button are not visible, when it finishes, label appears with the final text that I want and the button appears enabled. I am not sure exactly what is going on, I tried changing the modifiers of the JLabel and JButton several times but I cant seem to get it to work correctly. Here is the code for the box that pops up, any help is greatly appricated.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class PleaseWait extends javax.swing.JFrame{
private static final int height = 125;
private static final int width = 350;
final static JLabel converting = new JLabel("Please Wait while I convert your files");
private static JButton OK = new JButton("OK");
public PleaseWait(){
// creates the main window //
JFrame mainWindow = new JFrame();
mainWindow.setTitle("Chill For A Sec");
mainWindow.setSize(width, height);
mainWindow.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
// creates the layouts//
JPanel mainLayout = new JPanel(new BorderLayout());
JPanel textLayout = new JPanel(new FlowLayout());
JPanel buttonLayout = new JPanel(new FlowLayout());
// Sets Text //
converting.setText("Please wait while I convert your files");
// disables button //
OK.setEnabled(false);
// adds to the layouts //
textLayout.add(converting);
buttonLayout.add(OK);
mainLayout.add(textLayout, BorderLayout.CENTER);
mainLayout.add(buttonLayout, BorderLayout.SOUTH);
// adds to the frame //
mainWindow.add(mainLayout);
// sets everything visible //
mainWindow.setVisible(true);
}
public static void alert(){
OK.setEnabled(true);
String total = String.valueOf(Convert.result());
converting.setText("Sucsess! " + total + " files Converted");
}
}
Okay here's the issue. You are extending the JFrame . That means your class IS a JFrame.
When you create the PleaseWait frame you don't do anything to it. This is the empty box you are seeing. You are instead creating a different JFrame in your constructor. Remove your mainWindow and instead just use this. Now all of your components will be added to your PleaseWait object. That should fix your blank box issue.
You need an application to create your frame first. This is a simple example of such application.
import javax.swing.UIManager;
import java.awt.*;
public class Application {
boolean packFrame = false;
//Construct the application
public Application() {
PleaseWait frame = new PleaseWait();
//Validate frames that have preset sizes
//Pack frames that have useful preferred size info, e.g. from their layout
if (packFrame) {
frame.pack();
}
else {
frame.validate();
}
//Center the window
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = frame.getSize();
if (frameSize.height > screenSize.height) {
frameSize.height = screenSize.height;
}
if (frameSize.width > screenSize.width) {
frameSize.width = screenSize.width;
}
frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
frame.setVisible(true);
frame.convert();
}
//Main method
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e) {
e.printStackTrace();
}
new Application();
}
}
You have to slightly modify your frame to add controls to the content pane. You can do some work after frame is created, then call alert.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class PleaseWait extends JFrame {
private static final int height = 125;
private static final int width = 350;
final static JLabel converting = new JLabel();
private static JButton OK = new JButton("OK");
BorderLayout borderLayout1 = new BorderLayout();
JPanel contentPane;
int count;
public PleaseWait(){
contentPane = (JPanel)this.getContentPane();
contentPane.setLayout(borderLayout1);
this.setSize(new Dimension(width, height));
this.setTitle("Chill For A Sec");
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
// creates the layouts//
JPanel mainLayout = new JPanel(new BorderLayout());
JPanel textLayout = new JPanel(new FlowLayout());
JPanel buttonLayout = new JPanel(new FlowLayout());
// Sets Text //
converting.setText("Please wait while I convert your files");
// disables button //
OK.setEnabled(false);
OK.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
// adds to the layouts //
textLayout.add(converting);
buttonLayout.add(OK);
mainLayout.add(textLayout, BorderLayout.CENTER);
mainLayout.add(buttonLayout, BorderLayout.SOUTH);
// adds to the frame //
contentPane.add(mainLayout);
}
public void convert(){
count = 0;
for (int i = 0; i <10; i++){
System.out.println("Copy "+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
count++;
}
alert();
}
public void alert(){
OK.setEnabled(true);
// String total = String.valueOf(Convert.result());
converting.setText("Sucsess! " + count + " files Converted");
}
}

Java problem cant find image file

I am a student working on a homework project. I spent DAYS trying to get the following code to display an image on my new windows 7 laptop. I compiled it and ran it on my old xp pc and it worked! I really want to use my laptop. Any suggestions on how to get it to display the image? The java code. HTML and immage are all in the same sub directory on my flash drive. I tried moving them to the c:Program Files (x86)\Java\jdk1.5.0_02\bin directory but it still didn't work.
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import java.awt.image.*;
public class MoveIt extends Applet implements ActionListener
{
// set variables and componets
private Image cup;
Panel keypad = new Panel();
public int top = 15;
public int left = 15;
private Button keysArray[];
public void init()
{
cup = getImage(getDocumentBase(), "cup.gif");
Canvas myCanvas = new Canvas();
keysArray = new Button[5];
setLayout(new BorderLayout(5,5));
setBackground(Color.blue);
// set up keypad layout
keypad.setLayout(new BorderLayout(0,0));
keysArray[0] = new Button("Up");
keysArray[1] = new Button("Left");
keysArray[2] = new Button("Center");
keysArray[3] = new Button("Right");
keysArray[4] = new Button("Down");
// add buttons to the keypad panel
keypad.add(keysArray[0], BorderLayout.NORTH);
keysArray[0].addActionListener(this);
keypad.add(keysArray[1], BorderLayout.EAST);
keysArray[1].addActionListener(this);
keypad.add(keysArray[2], BorderLayout.CENTER);
keysArray[2].addActionListener(this);
keypad.add(keysArray[3], BorderLayout.WEST);
keysArray[3].addActionListener(this);
keypad.add(keysArray[4], BorderLayout.SOUTH);
keysArray[4].addActionListener(this);
// add canvas and keypad to the BorderLayout
add(myCanvas, BorderLayout.NORTH);
add(keypad, BorderLayout.SOUTH);
}
public void paint(Graphics g)
{
g.drawImage( cup, left, top, this );
}
public void actionPerformed(ActionEvent e)
{
// test for menu item clicks
String arg = e.getActionCommand();
if (arg == "Up")
top -=15;
else
if (arg == "Down")
top +=15;
else
if (arg == "Left")
left -=15;
else
if (arg == "Right")
left +=15;
else
{
top = 60;
left =125;
}
repaint();
}
}
I'm not the Applet guy, but putting cup.gif alongside MoveIt.html and MoveIt.classseemed to work. Also, you're overriding the paint() method of Applet, not that of Canvas. As an aside, arg == "Up" happens to work because Java strings are interned, but "Up".equals(arg) is the more reliable predicate.

Categories

Resources