I made a game using NetBeans design tool, called WordHunt. It looks like this:
I need to make a class that will apply a mouseover effect to those 16 labels I have. This is the code that changes the icon B when enter the mouse:
private void b1MouseEntered(java.awt.event.MouseEvent evt) {
b1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/ip/imag/" +B+ ".png")));
}
I had applied a default icon to the label.
After making that class, instead of writing:
b1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/ip/imag/" +B+ ".png")));
to write className(b1 ,B);
For the next label, the same thing
className(b2 ,C);
Observation: b1 is a label and I have all letters icon in .png format from A to Z.
Can anybody give me an idea of how I can do that?
If I understand what you want to do, you can use this method:
public void setRolloverIcon(Icon rolloverIcon)
defined in the class JButton to configure the rollover icon.
Just create a simple class like this:
class HoverEffectButton extends JButton{
HoverEffectButton(Image img1, Image img2) {
super(new ImageIcon(img1));
this.setRolloverIcon(new ImageIcon(img2));
}
}
Hope this will help.
And of course you can create a helper class that permits to load an image according to the image name
class AssetsHelper{
private static final String DEFAULT_ASSETS_ROOT = "assets/";
private static final String DEFAULT_IMAGE_SUBFIX = ".png";
public static Image loadImage(String name){
BufferedImage img = null;
try {
img = ImageIO.read(new File(DEFAULT_ASSETS_ROOT + name + DEFAULT_IMAGE_SUBFIX));
} catch (IOException e) {
....
}
return img;
}
}
How about something like this: (rough draft)
// for storage so we don't load it for each mouse-over
HashMap<String, ImageIcon> images = new HashMap<String, ImageIcon>();
void setIcon(JLabel button, String image)
{
if (images.containsKey(image))
return images.get(image);
else
{
String path = "/ip/imag/" + image + ".png";
ImageIcon icon = new ImageIcon(getClass().getResource(path));
images.put(image, icon);
return icon;
}
}
And then:
setIcon(b1, "B");
But you should probably consider using buttons so you can use setRolloverIcon rather than MouseEntered.
public class MyButton extends JButton {
private ImageIcon normalIcon;
private ImageIcon hoverIcon;
public MyButton(String normalURL) {
String hoverURL = normalURL.replaceFirst("\\.png$", "-hover.png");
normalIcon = new ImageIcon(getClass().getResource("/ip/imag/" +B+ ".png"); // or so
hoverICon = ...
}
private void b1MouseEntered(MouseEvent evt) {
setIcon(hoverIcon);
}
}
Firstly at the top of your code add this import:
import javax.swing.ImageIcon;
//Then you only need to write
new ImageIcon(...);
Instead of:
new javax.swing.ImageIcon(...)
Already shorter :)
Then you can create a hashmap of the images preloaded where each instance of B is the key and the loaded icon is the value.
if i get u well i think you want just an image and not evry image to chang when mouse is on it right. if that is the case what u should do is to get the position of each image in a buffer and compare it with the mouse x n y position to know wc image to change. I hope this solve your problem
Related
SOLVED: The set setRoomImage method was never called on the RoomTile Object. Thanks to #sorifiend for noticing this!
I currently place JLabels using this method:
public void spawnItem(Entity e, int x, int y, int i, int j) {
bgLabel[i][j] = new JLabel();
bgLabel[i][j].setBounds(x,y,e.width,e.height);
bgLabel[i][j].setIcon(e.sprite);
layeredPane.add(bgLabel[i][j], e.layer);
}
Where bgLabel[][] is an array of JLabels and e.sprite is an imageIcon as shown in the Entity Class below. As well, e.layer is the appropriate Integer (i.e. 0, 100, 200).
The Entity Class looks like this:
import javax.swing.*;
public class Entity {
public int width, height;
ImageIcon sprite;
Integer layer;
}
And I extend the entity class like this:
import java.net.URL;
public class RoomTile extends Entity{
boolean light;
public RoomTile(boolean isLight) {
height = 52;
width = 52;
layer = 0;
light = isLight;
}
public void setRoomImage(String s) {
URL url;
if (light) {
url = getClass().getResource("Assets/" + s + ".png");
} else {
url = getClass().getResource("Assets/Dark" + s + ".png");
}
sprite = new ImageIcon(url);
}
}
All JLabels are placed by nested for loop iterating over a 2d array, the object is then added to the layered pane using the spawnItem method. This all works properly and a grid of objects, such as rooms, are placed and visible. However, when attempting to change the icon of these JLabels, they simply disappear.
I am using the method setLight to receive the label that is desired to be changed:
public void setLight(int i, int j) {
RoomTile lightRoom = new RoomTile(true);
bgLabel[i][j].setIcon(lightRoom.sprite);
repaint();
revalidate();
}
The setLight method is within a class which extends JFrame.
When setLight is called, the JLabel at the grid position provided, simply disappears, rather than its icon changing. I'm not sure where I've gone wrong and any help would be greatly appreciated.
How do I cover all my JButton with the ImageIcon given?
my JButtoon size is 90x90 and my Image as well
I also set a text to my JButton (the text is necessary for the program to work)
Code: (I get a padding inside mi button)
btnBoton[i][j].setText(Integer.toString(i)+","+Integer.toString(j));
btnBoton[i][j].setIcon(new ImageIcon("img//"+num+".jpg"));
(When I comment my setText):
//btnBoton[i][j].setText(Integer.toString(i)+","+Integer.toString(j));
btnBoton[i][j].setIcon(new ImageIcon("img//"+num+".jpg"));
I'm trying to acomplish as the second image but without commenting my setText
you can use these two methods to place text at the center of buttons
btnBoton[i][j].setHorizontalTextPosition(JButton.CENTER);
btnBoton[i][j].setVerticalTextPosition(JButton.CENTER);
and texts will be placed in center of buttons,
if you want to assign a value to buttons and don't showing any text, instead of .setText(),create a new class like MJButton which extends JButton and create a String field to it named tag or data or etc. then encapsulate the field and use .setTag() and .getTag() to do so.
class MJButton extends JButton {
private String tag;
public MJButton(String tag, Icon icon) {
super( icon);
this.tag = tag;
}
public MJButton() {
super();
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
}
so use this new class to create buttons, in two ways:
1: btnBoton[i][j] = new MJButton();
and call .setTag() for them:
btnBoton[i][j].setTag(Integer.toString(i)+","+Integer.toString(j));
2: assign icon and tag to button in one line using second constructor
btnBoton[i][j] = new MJButton((Integer.toString(i)+","+Integer.toString(j)), new ImageIcon("img//"+num+".jpg"));
I am working on a simple image guessing game. Instead of having a jLabel for each image, I'm using only one jLabel and it changes its icon using arrays when a button is clicked after the image has been guessed correctly.
But how can I code it so that the answer required in the jTextField (txtAnswer) is determined by the icon set in the jLabel?
So for instance, if the current icon is of the Aston Martin DBS and the user guesses correctly, the icon will then change to the Ferrari 458. What must I do then to ensure that the txtAnswer will now require the user to enter "Ferrari 458" to guess correctly based on the image icon that is set?
Here is the code I currently have:
private static String[] imageList = {"/carGuessPackage/2010 Aston Martin DBS.jpg", "/carGuessPackage/2010 Ferrari 458 Italia.jpg"};
//This method is called in the constructor to set the first image on startup
public void firstIcon()
{
ImageIcon image;
image = new javax.swing.ImageIcon(getClass().getResource(imageList[0]));
lblImage.setIcon(image);
}
private void btnCheckActionPerformed(java.awt.event.ActionEvent evt) {
ImageIcon image;
if(imageList[0].equals(true))
{
if("Aston Martin DBS".equals(txtAnswer.getText()))
{
image = new javax.swing.ImageIcon(getClass().getResource(imageList[1]));
lblImage.setIcon(image);
}
else
{
JOptionPane.showMessageDialog(this, "Incorrect");
}
}
}
Check out the JLabel.setIcon() method. You would need and array of Icon objects, and they would be passed to the existing JLabel.
I would like to have a special sort of tooltip appear when a user hovers the mouse cursor over a specific item in a treetable. This tooltip will be a thumbnail of a PDF that corresponds to the item in the treetable that the cursor is pointing at. In addition, I'd like the user to be able to then move the cursor over the thumbnail and click it, which should open up the full PDF in their system's default PDF reader (Acrobat, Adobe Reader, etc.).
I realize this is a tall order, but I've already done most of the work. I've discovered exactly where in my huge program that I need to have the setToolTip() method so that it can retrieve the appropriate thumbnail. In addition, since I've discovered that having Java create thumbnails from a PDF on the fly is far too difficult, I've already got things set up so there will be thumbnail JPGs pre-made. Thus, all the setToolTip() command will need to do is somehow retrieve the appropriate JPG. Now comes the hard part.
At first, it seemed easy. I tried this really convenient hack for putting an image in a tooltip, and it definitely gets the thumbnail showing up properly. However, surrounding the <img> tag with an anchor tag (...) doesn't quite seem to work. The thumbnail is surrounded by the tell-tale blue border, alright, but the image remains un-clickable. In addition, the tooltip sometimes just disappears before it's image can be clicked upon.
So I thought I might need to do something more deep than a simple html hack. I tried this more involved way of putting an image in a tooltip, but it seems that will only work for a static image. I need the image to be different depending on what's being hovered over with the mouse cursor. In addition, how do I set my method to use this 'custom version of a tooltip' rather than the built-in one?
To give a bit more context, the location where the setToolTip() method seems to work is inside of a getTreeCellRendererComponent() method, a part of a custom class that extends JPanel and implements TreeCellRenderer. I'll post the code if asked, but it will might be rather complicated and hard to follow. Any thoughts?
EDIT 10/09/2014, 4:57pm: Much of this code may be confusing, and for that, I apologize. Suffice it to say that it has to do with putting a tri-state checkbox inside of a JXTreeTable. Anyway, the parts that are important should be easy enough to pick out, I hope. As you can see, this class already extends JPanel, so I cannot have it extend JToolTip as well.
package info.chrismcgee.sky.treetable;
import info.chrismcgee.beans.OrderDetail;
import info.chrismcgee.components.ImageToolTip;
import info.chrismcgee.components.TristateCheckBox;
import info.chrismcgee.components.TristateState;
import info.chrismcgee.enums.OSType;
import java.awt.BorderLayout;
import java.io.File;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JToolTip;
import javax.swing.JTree;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;
import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode;
public class SkyCheckTreeCellRenderer extends JPanel implements
TreeCellRenderer {
/**
*
*/
private static final long serialVersionUID = -2728513730497144120L;
private SkyCheckTreeSelectionModel selectionModel;
private TreeCellRenderer delegate;
private boolean showRootNodeCheckBox;
private TristateCheckBox checkBox = new TristateCheckBox("");
protected SkyCheckTreeManager.CheckBoxCustomizer checkBoxCustomer;
private String jobsFolderStr = OSType.getOSType() == OSType.MAC
? "/Volumes/ArtDept/ArtDept/JOBS"
: "//SKYFS/ArtDept/ArtDept/JOBS";
public SkyCheckTreeCellRenderer(TreeCellRenderer delegate,
SkyCheckTreeSelectionModel selectionModel,
boolean showRootNodeCheckBox) {
this.delegate = delegate;
this.selectionModel = selectionModel;
this.showRootNodeCheckBox = showRootNodeCheckBox;
setLayout(new BorderLayout());
setOpaque(false);
checkBox.setOpaque(false);
}
public JToolTip createToolTip() {
return new ImageToolTip();
}
private String getToolTipText(DefaultMutableTreeTableNode node)
{
if (node.getUserObject() instanceof OrderDetail)
{
OrderDetail od = (OrderDetail) node.getUserObject();
String thousandsFolderStr = jobsFolderStr + "/"
+ od.getOrderId().substring(0, 3) + "000-"
+ od.getOrderId().substring(0, 3) + "999/";
String productFolderStr = thousandsFolderStr + od.getOrderId()
+ " Folder/";
if (!od.getProductDetail().equals(""))
productFolderStr = thousandsFolderStr + od.getOrderId() + "/";
String img = productFolderStr + od.getOrderId() + "_THUMB.jpg";
if (!od.getProductDetail().equals(""))
img = productFolderStr + od.getOrderId() + "_" + od.getProductDetail() + "_THUMB.jpg";
if (new File(img).exists())
return "<html><img src=\"file://" + img + "\"></html>";
}
return null;
}
public JComponent getTreeCellRendererComponent(JTree tree, Object value,
boolean selected, boolean expanded, boolean leaf, int row,
boolean hasFocus)
{
JComponent renderer = (JComponent) delegate.getTreeCellRendererComponent(tree, value,
selected, expanded, leaf, row, hasFocus);
if (!showRootNodeCheckBox && tree.getModel().getRoot() == value)
{
renderer.setToolTipText(getToolTipText((DefaultMutableTreeTableNode)value));
return renderer;
}
TreePath path = tree.getPathForRow(row);
if (path != null) {
if (checkBoxCustomer != null && !checkBoxCustomer.showCheckBox(path))
{
renderer.setToolTipText(getToolTipText((DefaultMutableTreeTableNode)value));
return renderer;
}
if (selectionModel.isPathSelected(path, selectionModel.isDigged()))
checkBox.getTristateModel().setState(TristateState.SELECTED);
else
checkBox.getTristateModel().setState(selectionModel.isDigged()
&& selectionModel.isPartiallySelected(path)
? TristateState.INDETERMINATE
: TristateState.DESELECTED);
}
removeAll();
add(checkBox, BorderLayout.WEST);
add(renderer, BorderLayout.CENTER);
setToolTipText(getToolTipText((DefaultMutableTreeTableNode)value));
return this;
}
}
I get that I need to somehow extend JToolTip, and that this SkyCheckTreeCellRenderer class needs to somehow reference that custom tooltip. I guess all of this is just getting so involved and complex that my simple brain is having trouble wrapping around it all. My apologies.
how do I set my method to use this 'custom version of a tooltip' rather than the built-in one?
As the example shows you need to extend the component to use the custom tool tip.
I need the image to be different depending on what's being hovered over with the mouse cursor
Then you will need to override the getToolTipText(MouseEvent) method to return a text string to represent the image you want to display.
However, surrounding the tag with an anchor tag (...) doesn't quite seem to work
You would need to use a JEditorPane if you want to respond to a hyperlink. Read the JEditorPane API for an example.
So basically I would suggest that you need to use a custom JToolTip, that uses a JEditorPane to display the appropriate Image with an appropriate Hyperlink. Here is an example that shows how to use a JLabel as an added component to a tool tip. You should be able to modify the code to use a JEditorPane.
Also, you need to extend your tree table to use this custom JToolTip.
import java.awt.*;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;
public class ToolTipImage extends JToolTip
{
private Image image;
public ToolTipImage(Image image)
{
this.image = image;
setLayout( new BorderLayout() );
add( new JLabel( new ImageIcon( image) ) );
}
#Override
public Dimension getPreferredSize()
{
return new Dimension(image.getWidth(this), image.getHeight(this));
}
private static void createAndShowGUI() throws Exception
{
final BufferedImage testImage = ImageIO.read(new File("dukewavered.gif"));
String[] columnNames = {"Column 0", "Column 1"};
Object[][] data =
{
{"Cell 0,0", "Cell 0,1"},
{"Cell 1,0", "Cell 1,1"}
};
JTable table = new JTable(data, columnNames)
{
public JToolTip createToolTip()
{
return new ToolTipImage( testImage );
}
};
// Set tool tip text so that table is registered w/ tool tip manager
table.setToolTipText(" ");
JFrame frame = new JFrame("Tool Tip Image");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new JScrollPane(table) );
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
createAndShowGUI();
}
catch(Exception e) { System.out.println(e); }
}
});
}
}
It sounds like you need to build a custom tooltip, as detailed in JToolTip.
When clicked, you should use Runtime to open your file from the commandline. The way to do this in windows is posted here. The way to do this on ubuntu is posted here
i am trying to load image from specified path, and list of files are stored inside List<>.
at first time when i initialize image it display but when i am trying to display next image from List instance which contain list of files, it doesn't repaint the image.
what's wrong going is i am initializing image in constructor first time that overwrite
the new image, now where to initialize image first time outside constructor i don't know.
my code :
public void nextImage(int cnt)
{
System.out.println(cnt);
if (cnt < imageFiles.size())
{
System.out.println(imageFiles.size());
try
{
bg = ImageIO.read(new File((imageFiles.get(cnt)).toString()));
scaled = getScaledInstanceToFit(bg, new Dimension(600, 600));
setBackground(Color.BLACK);
}
catch(Exception e)
{
e.printStackTrace();
}
}
MouseHandler handler = new MouseHandler();
addMouseListener(handler);
addMouseMotionListener(handler);
System.out.println(cnt);
System.out.println(imageFiles.get(cnt).toString());
}
menu item click code :
JMenuItem mntmRestoreImage = new JMenuItem("Next Image");
final ImagePane st = new ImagePane();
mntmRestoreImage.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent arg0)
{
st.nextImage(k);
k++;
}
});
mnEdit.add(mntmRestoreImage);
class code & constructor :
private BufferedImage bg;
private BufferedImage scaled;
java.util.List<Path> imageFiles= getFilesFromDirectory(FileSystems.getDefault().getPath("D:\\New folder"));
public ImagePane()
{
try
{
bg = ImageIO.read(getClass().getResource("/images/src11.jpg"));
scaled = getScaledInstanceToFit(bg, new Dimension(600, 600));
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
counter also increments, now the code inside ImagePane() constructor
overwrites the image of nextImage() function, so idea what happen out
in this code ??
any suggestion ?
I think I have the perfect solution for you! I wrote a little program for you so it is easier to understand.
First I have a method for you to check if the file is a picture:
public Stack<File> getFilesInFolder(String startPath) {
File startFolder = new File(startPath);
Stack<File> picturestack = new Stack<File>();
String extension;
int dotindex;
// Go through the folder
for (File file : startFolder.listFiles()) {
extension = "";
dotindex = file.getName().lastIndexOf('.'); // Get the index of the dot in the filename
if (dotindex > 0) {
extension = file.getName().substring(dotindex + 1);
// Iterate all valid file types and check it
for (String filetype : validpicturetypes) {
if (extension.equals(filetype)) {
picturestack.add(file);
}
}
}
}
return picturestack;
}
Very easy! Take the folder and iterate his files. Take the extension of the file and check if it is a valid file type. Define the file types in a array at the begining of your code.
String[] validpicturetypes = {"png", "jpg", "jpeg", "gif"};
At the end I push every file into a stack. Remember to fill the stack into a variable, do not read the files more than once because than you get the same problem as before:
Stack<File> pictures = getFilesInFolder("C:\\Users\\Admin\\Desktop");
After that use a Action for your JMenuItem! In my example I do not have much, you have to put your methods in!
Action nextpictureaction = new AbstractAction("Next Picture") {
private static final long serialVersionUID = 2421742449531785343L;
#Override
public void actionPerformed(ActionEvent e) {
if (!pictures.isEmpty()) {
System.out.println(pictures.pop().getName());
}
}
};
Add the Action at your JMenu and set the properties of your Frame.
/*
* Add Components to Frame
*/
setJMenuBar(menubar);
menubar.add(toolsmenu);
toolsmenu.add(nextpictureaction);
/*
* Frame Properties
*/
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationByPlatform(true);
setSize(1000, 700);
setTitle("PictureEditor");
setVisible(true);
At the end execute your program with the invokeLater method!
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new PictureEditor();
}
});
}
Summary
Basically you need a somthing to iterate through because values like integer are not saved the way you like. In my example I used a Stack and save at the beginning all pictures in it. Important is that, if you used or finished with the picture, you have to remove it (use stack.pop() for a Stack). I do not found a method where you check if the file is a picture (if it is the ImageIO catch it is bad). I wrote a method for that if you want you could use it.
This is not an answer, but I cannot paste that much code into a comment.
I would change your code to something along the lines of this piece of code. This seperates the image loading from the gui updating logic (like adding mousehandlers and the like, I pasted only image loading code).
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Arrays;
import java.util.Iterator;
import javax.imageio.ImageIO;
public class ImageLoader
{
public static class ImageContainer
{
BufferedImage bg = null;
BufferedImage scaled;
}
Iterator<File> imageFiles = Arrays.asList(
new File("D:\\New folder").listFiles()).iterator();
public ImageContainer nextImage(Dimension dimensionToFit) throws Exception
{
ImageContainer c = new ImageContainer();
if (imageFiles.hasNext())
{
File file = imageFiles.next();
//you might not need this, if only images are in this directory
if(file.isDirectory())
return null;
c.bg = ImageIO.read(file);
c.scaled = getScaledInstanceToFit(c.bg, dimensionToFit);
return c;
}
else
return null;
}
private BufferedImage getScaledInstanceToFit(BufferedImage bg,
Dimension dimensionToFit)
{
//do the risizing
}
}
This is not yet optimized though.