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
Related
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.
I'm new to programming world, and I need some help. I will try to be as clear as possible.
This is my current situation:
I'm programming a simple game.
On a Jframe, I've added a Jlabel on which I attached an image. I've also added a Jbutton on the Jframe.
I would like that when I click on the Jbutton, the image appears and on the next click the image hides.
How could I do it?
Thanks in advance and excuse me for the possible english mistakes.
EDIT
Following some instructions given by people, I've reached this point:
button.addActionListener(new Actionbox());
final class Actionbox implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
if (label.getIcon() == null)
label.setIcon(new ImageIcon(myimage));
else
label.setIcon(null);
}
}
Eclipse is giving me an error message on the left side of the code editor, near the number lines. It says "Actionbox cannot be resolved to a type".
How could I solve it?
I would like that when I click on the Jbutton, the image appears and on the next click the image hides
add/remove an Icon from the label:
public void actionPerformed(ActionEvent e)
{
if (label.getIcon() == null)
label.setIcon(...);
else
label.setIcon( null );
}
Or instead of setting the Icon null, you may want to have a blank Icon so that the size of the label doesn't keep changing every time you show an image.
Don't fiddle with your button's visibility, and don't make it a final local variable. For something like this, the label should be a field. Place it in your GUI and leave it visible, since if it doesn't hold an icon or have text, nothing will show on it. Instead in your button's ActionListener, simply change the JLabel's ImageIcon via its setIcon(...) method. Pass in an Icon if you want to show an image and pass in null if you want to show nothing. Make your JLabel a field of the class, not a final local variable.
Regarding your code, one way to create your JButton's ActionListener is to use an anonymous inner class rather than a static private class. I'd also recommend reading in the image just once perhaps in your class's constructor and not each time the button is pressed. For example,
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial") // have GUI extend JPanel
public class ButtonSwapImageGui extends JPanel {
private static final String IMAGE_PATH = "https://duke.kenai.com/iconSized/duke.gif";
private Icon imageIcon; // hold our image
private Icon nullImageIcon; // hold a blank image as a placeholder
private JLabel label = new JLabel("", SwingConstants.CENTER);
// throw an exception if image can't be read
public ButtonSwapImageGui() throws IOException {
// read in an image from the internet
URL imageUrl = new URL(IMAGE_PATH);
BufferedImage image = ImageIO.read(imageUrl);
// create a blank placeholder image the same size as
// the image read in from internet
int width = image.getWidth();
int height = image.getHeight();
BufferedImage nullImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
// create ImageIcon objects with images read in above
imageIcon = new ImageIcon(image);
nullImageIcon = new ImageIcon(nullImage);
// set JLabel with the placeholder nullImageIcon
label.setIcon(nullImageIcon);
// create our button
JButton button = new JButton("Swap Image");
// add an anonymous inner class ActionListener to button
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// get the JLabel's Icon
Icon currentIcon = label.getIcon();
// if the Icon matches the null icon
if (currentIcon == nullImageIcon) {
// set label with image
label.setIcon(imageIcon);
} else {
// otherwise the label is displaying the image
// so now set label with the null (blank) icon
label.setIcon(nullImageIcon);
}
}
});
// JPanel to hold our button
JPanel buttonPanel = new JPanel();
buttonPanel.add(button);
// set our GUI's layout to BorderLayout
setLayout(new BorderLayout());
// add the JLabel to the BorderLayout.CENTER position
add(label, BorderLayout.CENTER);
// add button JPanel to the bottom
add(buttonPanel, BorderLayout.PAGE_END);
}
private static void createAndShowGui() {
// declare our GUI JPanel
ButtonSwapImageGui mainPanel = null;
try {
mainPanel = new ButtonSwapImageGui();
} catch (IOException e) {
// if we're here, the image could not be read in
e.printStackTrace();
System.exit(-1); // can't get image -- exit program
}
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel); // add GUI to JFrame
frame.pack(); // tell layout managers to layout components
frame.setLocationRelativeTo(null); // center GUI
frame.setVisible(true); // display GUI
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
You can do something like this:
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
jLabel.setVisible(!jLabel.isVisible()); //Note! jLabel has to be a final variable.
}
}
You should note that any variables used inside coming from outside the ActionListener have to be final ones. This largely restricts you into working with objects
I usually use set bounds (0,0,0,0); whenever I want to hide swing components
button.addActionListener(new Actionbox());
final class Actionbox implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
if (label.getIcon() == null) {
label.setIcon(new ImageIcon(myimage));
else{
label.setIcon(null);
}
}
I'm trying to display images (as image icons for JLabels).
Everything works fine when I am NOT trying to display images, i.e.:
for (int i=0;i<value;i++)
{
for (int j=0;j<value;j++)
{
c.gridx=i;
c.gridy=j;
JLabel element = new JLabel("!");
pane.add(element,c);
}
}
However if I do this:
for (int i=0;i<value;i++)
{
for (int j=0;j<value;j++)
{
c.gridx=i;
c.gridy=j;
JLabel element = new JLabel();
element.setIcon(wall);
pane.add(element,c);
}
}
It will produce a good amount of error messages.
Console output: http://pastebin.com/teuuWjRX
The code: (pastebin version w/ syntax highlighting: http://pastebin.com/2utFJ0UM)
package tut;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
public class Main extends JFrame{
//private static int value;
public Main()
{
int value=151;//151
ImageIcon wall = new ImageIcon();
try
{
BufferedImage tempImage = ImageIO.read(this.getClass().getResource(("/resources/images/test.png")));
wall = new ImageIcon(tempImage.getScaledInstance(4, 4, Image.SCALE_DEFAULT));
}
catch (IOException e){}
Container pane = getContentPane();
pane.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
for (int i=0;i<value;i++)
{
for (int j=0;j<value;j++)
{
c.gridx=i;
c.gridy=j;
JLabel element = new JLabel();
element.setIcon(wall);
pane.add(element,c);
}
}
//Main Frame
setTitle("Example1");
setSize(value*8,value*8);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main (String[] args)
{
Main test1= new Main();
}
}
My questions are:
Why does it raise the exception in comparison? (Everything seems to
be fine from my point of view)
Can stackOverFlow problem be caused because of each time object declaration? (As I don't see any other problem in the loop).
P.s.: Is getScaledInstance okay to use or there's a better method?
Any help would be greatly appreciated.
EDIT: Overall, I did not find any real problem with the code, the only thing I can say that the problem is not with scaling. Parsing little-sized images (like 8x8 or 4x4) w/o scaling also produces an error, however everything is fine for parsing images of size 16x16 or higher or scaling to 16x16. It could be kind of a problem with placing/adding little-sized images (i.e. elements) to the layout.
You are using wall as an Icon. And wall is created in a try block where you don't even log exceptions raised.
The problem could be here : maybe you have an exception (IOException) raised at the icon creation and you can't see it.
you can try the JLabel constructor public JLabel(Icon image) instead of empty constructor
Apolo
for(i=0; i<16; i++){
images[i]=new ImageIcon(getClass()
.getResource("/images/1 ("+i+").jpg"));
}
for( i=0; i<buttons.length; i++){
for (j=0; j<buttons[i].length;j++){
n=i*buttons.length+buttons[i].length;
buttons[i][j]=new JButton();
label[n].setIcon((images[i*buttons.length+j]));
buttons[i][j].add(label[n]);
label[n].setVisible(false);
panel.add(buttons[i][j]);
buttons[i][j].addActionListener(this);
}
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() instanceof JButton){
JButton pressedButton = (JButton) e.getSource();
opens[open]=(JButton) e.getSource(); //i want to put label[n] into array?
if((pressedButton.getIcon() == null)){
label[n].setVisible(true);
open=open++;
} else {
//pressedButton.setIcon(null);
}
}
if (open==1){
opens[0].setVisible(false);
opens[1].setVisible(false);
}
}
hello friends.i am making a memory game, if buttons have same icon, they will stay open.
i made frame in it panel, in it buttons and each button has label. If facing is true and user click, they will open by setvisible(true)
but in void actionperformed, how can i take label[n]? Not button[][]?
label[n].setIcon((images[i*buttons.length+j]));
i think error is that.is not it correct? because it doesnot execute.
edit after suggestions:
for(i=0; i<16; i++){
images[i]=new ImageIcon(getClass().getResource("/images/1 ("+i+").jpg"));
} //adding images to local variables
for( i=0; i<buttons.length; i++){
for (j=0; j<buttons[i].length;j++){
n=i*buttons.length+buttons[i].length;
buttons[i][j]=new JButton();
//buttons[i][j].setIcon((images[i*buttons.length+j]));
//if i make this code, all icons are displayed at first?
panel.add(buttons[i][j]);
buttons[i][j].addActionListener(this);
}
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() instanceof JButton){
JButton pressedButton = (JButton) e.getSource();
if(pressedButton.getIcon() == null){
pressedButton.setIcon((images[i*buttons.length+j]));
} else {
pressedButton.setIcon(null);
}
}
}
I made this code how you suggested. but now images dont display and clicks doesnot work.
I think this post is related to this question. Maybe an assignment?
Couple of tips:
label[n].setIcon((images[i*buttons.length+j]));
How many images do you have in images array? A quick math would say that if you have for instance a 4x4 array then you'll need i*buttons.lenght+j == 4*4+4 == 20 images at last iteration. And you only would need i*j/2 == 8 images, assuming is a pair match game.
if buttons have same icon, they will stay open. i made frame in it
panel, in it buttons and each button has label.
Why do you need labels? I think if two button matches you can disable those buttons so user won't be able to click them again and dispatch an actionPerformed event.
If it's not strictly necessary use arrays, you could use ArrayList instead and get benefits of its methods.
Update
I post this code because I think you still stuck using arrays. I just want to show you that there's no need to use them to keep references, you just need think a little more under objects paradigm and delegate this task to appropriate object.
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
public class Demo {
/*
* This variable will point to a pressed button to keep reference.
*/
JButton _alreadyPressedButton = null;
/**
* Initializes the GUI
*/
private void initGUI(){
/*
* Create needed icons - As this example uses 6 buttons, then I need 3 icons
*/
ImageIcon icon1 = (ImageIcon) UIManager.getIcon("OptionPane.errorIcon");
ImageIcon icon2 = (ImageIcon) UIManager.getIcon("OptionPane.informationIcon");
ImageIcon icon3 = (ImageIcon) UIManager.getIcon("OptionPane.warningIcon");
/*
* Make a list with 6 icons (add each icon twice)
*/
List<ImageIcon> iconsList = new ArrayList<>();
iconsList.add(icon1);
iconsList.add(icon1);
iconsList.add(icon2);
iconsList.add(icon2);
iconsList.add(icon3);
iconsList.add(icon3);
Collections.shuffle(iconsList); /* Shuffle the list */
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() instanceof JButton){
final JButton pressedButton = (JButton) e.getSource();
/*
* Execute this code in a SwingWorker to prevent block EDT at "Thread.sleep(500)" line
* Google for EDT (Event Dispatch Thread)
*/
SwingWorker sw = new SwingWorker() {
#Override
protected Object doInBackground() throws Exception {
if(_alreadyPressedButton != pressedButton){
pressedButton.setIcon(pressedButton.getPressedIcon());
if(_alreadyPressedButton != null){
Thread.sleep(500);
if(_alreadyPressedButton.getIcon() == pressedButton.getIcon()){
_alreadyPressedButton.setEnabled(false);
pressedButton.setEnabled(false);
} else {
_alreadyPressedButton.setIcon(null);
pressedButton.setIcon(null);
}
_alreadyPressedButton = null;
} else {
_alreadyPressedButton = pressedButton;
}
}
return null;
}
};
sw.execute();
}
}
};
JPanel panel = new JPanel(new GridLayout(3, 2));
panel.setPreferredSize(new Dimension(200, 200));
for(ImageIcon icon : iconsList){
JButton button = new JButton();
button.setPressedIcon(icon);
button.addActionListener(actionListener);
panel.add(button);
}
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Demo().initGUI();
}
});
}
}
You appear to be adding a JLabel to a JButton?? If this is what in fact you're doing, don't. Instead, why not simply set the JButton's ImageIcon when you desire to show or change what image the button displays, if any. You would do this simply via myButton.setIcon(fooIcon).
Edit
You state in comment:
and how will it show the image from jbutton and hide it?
You can simply swap icons. If you want to show an image, set its ImageIcon as the JButton's Icon via setIcon(myIcon). and when done, swap it out via either setIcon(otherIcon) or setIcon(null).
The link that you've provided does not put JLabels on top of JButtons which it appears that you're trying to do, and which is why I'm telling you this information.
Please excuse me if this is a very simple solution or stupid mistake - this is my first time attempting to implement graphics in Java! :)
I'm attempting to make a board of tiles, each is a Tile object, and all positions of the tiles are stored in a triple array of Tiles called 'content' (content[][][]).
In order to make each tile "clickable", I'm basically creating a label with each tile icon and positioning that tile on the board based on the Tile object's x,y coordinates. I do this for each of the non-null Tile objects in the content array.
This works fine when I use the graphics.drawImage function, but when I position each label using the setBorders() function it:
Creates the layout of tiles, but not perfectly - it seems some are missing or below others.
and
It creates a duplicate unpositioned layer above the other tiles that are in their sort-of correct positions.
The code for the function I'm calling is:
public void paintComponent(Graphics graphics) {
// let superclass paint to fill in background
super.paintComponent(graphics);
Tile[][][] content = b.getContent();
if (content==null || tileImages==null) {
return;
}
/* Set dummy previous label */
prevT.setBounds(-1,-1,1,1);
// draw tiles back to front
for (int i = 0; i<content.length; i++) {
for (int y = 0; y<content[i].length; y++) {
for (int x = 0; x<content[i][y].length; x++) {
final Tile t = content[i][y][x];
if (t!=null) {
if (y>0 && content[i][y-1][x]!=null && t.equals(content[i][y-1][x])) {
continue;
}
if (x>0 && content[i][y][x-1]!=null && t.equals(content[i][y][x-1])) {
continue;
}
Image image = tileImages[t.getValue()][t.getSubindex()];
if (b.free(t)) {
image = tileImagesHL[t.getValue()][t.getSubindex()];
}
/* Mouse event magic */
graphics.drawImage(image, x*TILEW+TILEW/2+i*TILESKEW, (y+1)*TILEH/2-i*TILESKEW, null);
/* Create icon to be displayed */
ImageIcon icon = new ImageIcon(image);
/* Label that acts as the clickable tile */
final JLabel label = new JLabel();
/* Associate image with label */
label.setIcon(icon);
/* Allow mouse events to interact with label */
label.addMouseListener(this);
/* Position labels according to tile coordinates */
label.setBounds(x*TILEW+TILEW/2+i*TILESKEW, (y+1)*TILEH/2-i*TILESKEW, image.getWidth(null), image.getHeight(null));
/* Associate label with specified tile */
t.setLabel(label);
/* Add label to list*/
labels.add(label);
this.setVisible(true);
this.add(label);
}
}
}
}
}
Any explanation for why this is happening would be greatly greatly appreciated! I've tried to re-write this function SO many times and am out of ideas!
Thank you! :)
1) don't create Object inside paintComponent(Graphics graphics), prepare these Object before
my view, simple comtainer with Mouse event magic without MouseListener
2) create JPanel and put there JButton#setBackground(someColor), and add JButton#setRolloverIcon(someIcon), no longer any MouseListener needed
3) if you create Tiles then look for GridLayout
4) prepare Icons and add these Icon to the JButton, nothing else, any Array of Objects, no code more than I described
import java.awt.*;
import javax.swing.*;
public class TilesWithButton {
private Icon warningIcon = UIManager.getIcon("OptionPane.warningIcon");
private Icon infoIcon = UIManager.getIcon("OptionPane.informationIcon");
private Icon errorIconRoll = UIManager.getIcon("OptionPane.errorIcon");
private JPanel myPanel = new JPanel();
public TilesWithButton() {
myPanel.setLayout(new GridLayout(1, 2, 1, 1));
JButton btn = new JButton();
btn.setBackground(Color.white);
btn.setIcon(infoIcon);
btn.setRolloverIcon(errorIconRoll);
btn.setFocusPainted(false);
myPanel.add(btn);
JButton btn1 = new JButton();
btn1.setBackground(Color.white);
btn1.setIcon(warningIcon);
btn1.setRolloverIcon(errorIconRoll);
btn1.setFocusPainted(false);
myPanel.add(btn1);
JFrame frame = new JFrame("Tiles");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(myPanel);
frame.pack();
frame.setLocation(150, 100);
frame.setVisible(true);
}
public static void main(final String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
TilesWithButton tilesWithButton = new TilesWithButton();
}
});
}
}