I have an icon in a JLabel as shown below:
Is it possible to add another icon (e.g. a flag representing a country) between the color icon and the text? For example, I want to add an icon depicting the U.S. flag between the red icon and US. Thanks!
Yes, use nested JLabel with BoxLayout in the container label:
JLabel container = new JLabel();
container.setLayout(new BoxLayout(container, BoxLayout.X_AXIS));
JLabel icon1Label = new JLabel();
JLabel icon2Label = new JLabel();
icon1Label.setIcon(icon1);
icon2Label.setIcon(icon2);
container.add(icon1Label);
container.add(icon2Label);
Try CompoundIcon
Edit: Heisenbug's layout-based solution is the
trivial answer.
I just did this recently - I wanted to be able to combine multiple icons in a single row into a single icon. The way I did it was to go down to the BufferedImage level and compose the two images manually into a single image, and then use that as my JLabel icon. There are other ways of achieving the same effect, but I didn't want to have to change my UI component hierarchy.
I ended up creating a class that combines multiple images and caches them. I used it like this:
ImageIcon icon1 = ...;
ImageIcon icon2 = ...;
ImageIcon labelIcon = new CachedCompositeIcon( icon1, icon2 ).getIcon();
jLabel.setIcon( labelIcon );
Here's the source:
/** This is a convenience class to handle creating a single composite icon from several icons, and caching the
* created icons to eliminate duplicate work. This class is basically used as a key into a map, allowing us to
* define both a hashCode and equals in a single place.
*/
public class CachedCompositeIcon
{
private static final byte ICON_PADDING = 2;
private static final HashMap<CachedCompositeIcon, ImageIcon> CACHED_ICONS =
new HashMap<CachedCompositeIcon, ImageIcon>( 4 );
private final ImageIcon[] m_icons;
public CachedCompositeIcon(final ImageIcon... icons) {
m_icons = icons;
}
public ImageIcon getIcon() {
if ( !CACHED_ICONS.containsKey( this ) ) {
CACHED_ICONS.put( this, lcl_combineIcons() );
}
return CACHED_ICONS.get( this );
}
/** Generates an icon that is a composition of several icons by appending each icon together with some
* padding between them.
*
* #return An icon that is the concatenation of all the icons this was constructed with.
*/
private ImageIcon lcl_combineIcons() {
// First determine how big our composite icon will be; we need to know how wide & tall to make it.
int totalWidth = (m_icons.length - 1) * ICON_PADDING; // Take into account the padding between icons
int minHeight = 0;
for ( int i = 0; i < m_icons.length; ++i ) {
totalWidth += m_icons[i].getIconWidth();
if ( m_icons[i].getIconHeight() > minHeight ) {
minHeight = m_icons[i].getIconHeight();
}
}
// Create an image big enough and acquire the image canvas to draw on
final BufferedImage compositeImage = new BufferedImage( totalWidth, minHeight, BufferedImage.TYPE_INT_ARGB );
final Graphics graphics = compositeImage.createGraphics();
// Iterate over the icons, painting each icon and adding some padding space between them
int x = 0;
for ( int i = 0; i < m_icons.length; ++i ) {
final ImageIcon icon = m_icons[ i ];
graphics.drawImage( icon.getImage(), x, 0, null );
x += icon.getIconWidth() + ICON_PADDING;
}
return new ImageIcon( compositeImage );
}
/** Generates a hash that takes into account the number of icons this composition includes and the hash &
* order of those icons.
*
* #return A hash code.
*/
#Override
public int hashCode() {
int weakHash = m_icons.length;
for ( int i = 0; i < m_icons.length; ++i ) {
weakHash += m_icons[i].hashCode() * (i + 1);
}
return weakHash;
}
/** Two instances are equal if and only if they include the same icons and they're in the same order.
*
* #param obj An object to check for equality with this.
*
* #return true if the two objects are equal, false otherwise.
*/
#Override
public boolean equals(final Object obj) {
if ( !(obj instanceof CachedCompositeIcon) ) {
return false;
}
final CachedCompositeIcon other = (CachedCompositeIcon) obj;
if ( m_icons.length != other.m_icons.length ) {
return false;
}
for ( int i = 0; i < m_icons.length; ++i ) {
if ( m_icons[i].hashCode() != other.m_icons[i].hashCode() ) {
return false;
}
}
return true;
}
}
this is pretty possible, JLabel is Swing JComponent and you can add any JComponent to the another JComponent, that's same for JLabel
label.setLayout(new GridLayout(0, 2, 10, 10));
label.add(myIcon1);
label.add(myIcon2);
if you add f.e. JPanel to the JLabel then don't forget to setOpaque(false);
Related
I have the weirdest bug ever.
I have this puzzle game that moves puzzle pieces (which really are buttons with images attached to them).
Everything worked fine until I tried to change the text of some label (to indicate how many steps the player has done).
Everytime I call someControl.setText("text");, the puzzle pieces that moved are set back to the their first position. I have no idea why, but they just do.
Here's my window:
It consists of two panels, each uses a GridBagLayout.
The main frame uses a gridBagLayout as well, which consists of the two panels.
I know it's weird as hell, but I can't figure out what may cause this GUI bug. Any idea?
The pieces of code:
increaseSteps which is called everytime I click a puzzle button
void increaseSteps() {
_steps++;
_lblSteps.setText("Steps: " + _steps);
}
Creation of the puzzle panel (the left panel)
private JPanel puzzlePanel() {
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
for (int i = 0; i < _splitImage.getSize(); i++)
for (int j = 0; j < _splitImage.getSize(); j++) {
int valueAtPos = _board.getMatrix()[i][j];
if (valueAtPos == 0)
continue;
int imageRow = _board.getImageRowFromValue(valueAtPos);
int imageCol = _board.getImageColFromValue(valueAtPos);
ImageIcon imageIcon = new ImageIcon(_splitImage.getImages()[imageRow][imageCol]);
JButton btn = new JButton(imageIcon);
_tileButtons[i][j] = new TileButton(btn, i, j);
btn.setPreferredSize(new Dimension(_splitImage.getImages()[i][j].getWidth(null),
_splitImage.getImages()[i][j].getHeight(null)));
// add action listener
btn.addActionListener(this);
btn.addKeyListener(this);
gbc.gridx = j;
gbc.gridy = i;
panel.add(_tileButtons[i][j].getButton(), gbc);
}
return panel;
}
actionPerformed:
#Override
public void actionPerformed(ActionEvent e) {
if (!(e.getSource() instanceof JButton))
return;
JButton btn = (JButton) e.getSource();
TileButton tile = getTileButtonFromBtn(btn);
if (tile == null)
return;
// check if we can move the tile
String moveDir = _board.canMoveTile(tile.getRow(), tile.getCol());
if (moveDir.equals("no"))
return;
increaseSteps();
int dirx = 0;
int diry = 0;
if (moveDir.equals("left")) {
dirx = -1;
_board.move("left", true);
tile.setCol(tile.getCol() - 1);
} else if (moveDir.equals("right")) {
dirx = 1;
_board.move("right", true);
tile.setCol(tile.getCol() + 1);
} else if (moveDir.equals("up")) {
diry = -1;
_board.move("up", true);
tile.setRow(tile.getRow() - 1);
} else { // down
diry = 1;
_board.move("down", true);
tile.setRow(tile.getRow() + 1);
}
moveButton(btn, dirx, diry, MOVE_SPEED);
if (_board.hasWon())
win();
}
moveButton: (moves the button in a seperate thread, calling btn.setLocation())
private void moveButton(JButton btn, int dirx, int diry, int speed) {
Point loc = btn.getLocation();
// get start ticks, calculate distance etc...
StopWatch stopper = new StopWatch();
int distance;
if (dirx != 0)
distance = _splitImage.getImages()[0][0].getWidth(null) * dirx;
else
distance = _splitImage.getImages()[0][0].getHeight(null) * diry;
if (speed > 0) {
// run the animation in a new thread
Thread thread = new Thread() {
public void run() {
int currentTicks;
int elapsed;
do {
int newX = loc.x;
int newY = loc.y;
elapsed = stopper.getElapsed();
int moved = (int) ((double) distance * (double) (elapsed / (double) speed));
if (dirx != 0)
newX += moved;
else
newY += moved;
btn.setLocation(newX, newY);
} while (elapsed <= MOVE_SPEED);
// make sure the last location is exact
btn.setLocation(loc.x + (dirx == 0 ? 0 : distance), loc.y + (diry == 0 ? 0 : distance));
}
};
thread.start();
}
else
btn.setLocation(loc.x + (dirx == 0 ? 0 : distance), loc.y + (diry == 0 ? 0 : distance));
}
You're trying to set the absolute position of a component via setLocation(...) or setBounds(...), one that is held by a container that uses a layout manager. This may work temporarily, but will fail if the container's layout manager is triggered to re-do the layout of its contained components. When that happens, the GridBagConstraints will take over and the components will move to their gridbag constraints assigned location.
The solution is to not do this, and instead to place the location of your components in concert with the layout managers used.
Another problem is that your current code is not Swing thread-safe since you're making Swing state changes from within a background thread. This won't always cause problems, but since it's a threading issue, risks causing intermittent hard to debug problems (ones that usually only occur when your boss or instructor are trying to run your code).
Possible solutions:
For a grid of images, you could use a grid of JLabels (or JButtons if you must) held in a container that uses GridLayout. When you need to reposition components, remove all components held by that JPanel, and then re-add, using the order of addition to help you position the components.
Easiest though would be to use a grid of non-moving JLabels, give them MouseListeners, and instead of moving the JLabels, remove and add Icons to them, including a blank Icon.
If you need to do Swing animation, use a Swing Timer to drive the animation. This will allow your code to make repetitive calls with delay between the calls, and with these calls being made on the Swing event thread, the EDT (event dispatch thread).
Demo proof of concept example code that shows swapping icons, but without animation, and without test of solution yet:
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class ImageShuffle extends JPanel {
private static final int SIDES = 3;
public static final String IMG_PATH = "https://upload.wikimedia.org/wikipedia/commons/"
+ "thumb/5/5a/Hurricane_Kiko_Sep_3_1983_1915Z.jpg/"
+ "600px-Hurricane_Kiko_Sep_3_1983_1915Z.jpg";
private List<Icon> iconList = new ArrayList<>(); // shuffled icons
private List<Icon> solutionList = new ArrayList<>(); // in order
private List<JLabel> labelList = new ArrayList<>(); // holds JLabel grid
private Icon blankIcon;
public ImageShuffle(BufferedImage img) {
setLayout(new GridLayout(SIDES, SIDES, 1, 1));
fillIconList(img); // fill array list with icons and one blank one
Collections.shuffle(iconList);
MyMouseListener myMouse = new MyMouseListener();
for (Icon icon : iconList) {
JLabel label = new JLabel(icon);
label.addMouseListener(myMouse);
add(label);
labelList.add(label);
}
}
private class MyMouseListener extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
JLabel selectedLabel = (JLabel) e.getSource();
if (selectedLabel.getIcon() == blankIcon) {
return; // don't want to move the blank icon
}
// index variables to hold selected and blank JLabel's index location
int selectedIndex = -1;
int blankIndex = -1;
for (int i = 0; i < labelList.size(); i++) {
if (selectedLabel == labelList.get(i)) {
selectedIndex = i;
} else if (labelList.get(i).getIcon() == blankIcon) {
blankIndex = i;
}
}
// get row and column of selected JLabel
int row = selectedIndex / SIDES;
int col = selectedIndex % SIDES;
// get row and column of blank JLabel
int blankRow = blankIndex / SIDES;
int blankCol = blankIndex % SIDES;
if (isMoveValid(row, col, blankRow, blankCol)) {
Icon selectedIcon = selectedLabel.getIcon();
labelList.get(selectedIndex).setIcon(blankIcon);
labelList.get(blankIndex).setIcon(selectedIcon);
// test for win here by comparing icons held by labelList
// with the solutionList
}
}
private boolean isMoveValid(int row, int col, int blankRow, int blankCol) {
// has to be on either same row or same column
if (row != blankRow && col != blankCol) {
return false;
}
// if same row
if (row == blankRow) {
// then columns must be off by 1 -- they're next to each other
return Math.abs(col - blankCol) == 1;
} else {
// or else rows off by 1 -- above or below each other
return Math.abs(row - blankRow) == 1;
}
}
public void shuffle() {
Collections.shuffle(iconList);
for (int i = 0; i < labelList.size(); i++) {
labelList.get(i).setIcon(iconList.get(i));
}
}
}
private void fillIconList(BufferedImage img) {
// get the width and height of each individual icon
// which is 1/3 the image width and height
int w = img.getWidth() / SIDES;
int h = img.getHeight() / SIDES;
for (int row = 0; row < SIDES; row++) {
int y = (row * img.getWidth()) / SIDES;
for (int col = 0; col < SIDES; col++) {
int x = (col * img.getHeight()) / SIDES;
// create a sub image
BufferedImage subImg = img.getSubimage(x, y, w, h);
// create icon from the image
Icon icon = new ImageIcon(subImg);
// add to both icon lists
iconList.add(icon);
solutionList.add(icon);
}
}
// create a blank image and corresponding icon as well.
BufferedImage blankImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
blankIcon = new ImageIcon(blankImg);
iconList.remove(iconList.size() - 1); // remove last icon from list
iconList.add(blankIcon); // and swap in the blank one
solutionList.remove(iconList.size() - 1); // same for the solution list
solutionList.add(blankIcon);
}
private static void createAndShowGui(BufferedImage img) {
JFrame frame = new JFrame("ImageShuffle");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ImageShuffle(img));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
URL imgUrl = null;
BufferedImage img;
try {
imgUrl = new URL(IMG_PATH);
img = ImageIO.read(imgUrl);
SwingUtilities.invokeLater(() -> createAndShowGui(img));
} catch (IOException e) {
e.printStackTrace();
}
}
}
If I wanted animation, again, I'd raise the icon into the JFrame's glasspane, animate it to the new position using a Swing Timer, and then place the icon into the new JLabel. I'd also disable the MouseListener using a boolean field, a "flag", until the animation had completed its move.
So, I want to update every icon of a JLabel ArrayList, to its own individual icon based off of an outside ArrayList. The outside ArrayList is called board, and the JLabel ArrayList is called tiles. I want to update every icon to its corresponding item in board, how can I do that efficiently? I need it to update every icon of a huge list, we're talking like 100 - 200 items long. Right now, at a hundred items long, it takes about 4 seconds before displaying all of the icons at the same time:
for (int i = 0; i < board.size(); i++) {
//this is all one line:
tiles.get(i).setIcon(resizeIcon(displayTile(board.get(i),
tiles.get(i).getHeight(), tiles.get(i).getHeight()));
}
//this resizes the ImageIcon and returns the risized icon:
public static ImageIcon resizeIcon(ImageIcon i, int x, int y) {
Image image = i.getImage();
Image newimg = image.getScaledInstance(x, y, java.awt.Image.SCALE_SMOOTH);
i = new ImageIcon(newimg);
return i;
}
//this returns an ImageIcon based off of the number that is put in:
public static ImageIcon displayTile(int num) {
if (num != 0) {
ImageIcon i = new ImageIcon("src/resources/" + num + ".png");
return i;
}
ImageIcon i = new ImageIcon("src/resources/0.png");
return i;
}
How do I make it more effecient?
So I am making this ABC learning game , What I want to do is if I click on the A button more than once then , the three Images will change their position, What I want to do is this
![enter image description here][1]
When I click on A button, the three image will appear on the screen, the first is apple as I set it that way in the loop, but the second two images will appear randomly, though sometimes one o them is apple again, I could fix that.
My Question is, how can I change that position of the Apple to the second and second image to the first and third image to the second position if the "A" button is clicked more than once.
SO, the result will be the apple will change position based on the click "A" button and other two picture changes their position and chosed randomly from the array.
So, here is my code for the JPanel, where everything takes place.Most of the code is explained in the comments
import java.awt.*;
import java.awt.event.ActionListener;
import javax.swing.*;
import java.awt.event.*;
import java.text.AttributedCharacterIterator;
import java.util.Random;
import javax.swing.ImageIcon;
/**
*
* #author Dip
*/
public class AbcGeniusPanel extends JPanel implements ActionListener {
//Declare the necessary Variables here
private JButton[] buttons; //create an array for buttons
private BorderLayout layout; //Declare object of BorderLayout
private Image image = null;
private boolean showImage = false;
//Initialize all the variables here
static int index = 0;
int randNumber = 0, id = 0;
int q = 0, w = 0;
int buttonClick = 0;
//Store all the imahges that will appear on the screen into an String type array
private static String[] imageList = {"src/Images/1.png", "src/Images/2.png", "src/Images/3.png", "src/Images/4.png", "src/Images/5.png", "src/Images/6.png", "src/Images/7.png", "src/Images/8.png", "src/Images/9.png", "src/Images /10.png",
"src/Images/11.png", "src/Images/12.png", "src/Images/13.png", "src/Images /14.png", "src/Images/15.png",
"src/Images/16.png", "src/Images/17.png", "src/Images/18.png", "src/Images /19.png", "src/Images/20.png",
"src/Images/21.png", "src/Images/22.png", "src/Images/23.png", "src/Images /24.png", "src/Images/25.png",
"src/Images/26.png"
};
//Define the constructor here
public AbcGeniusPanel() {
ImageIcon[] alphabets = new ImageIcon[26];
setBackground(Color.yellow);
//Load the images for alphabet images into the alphabets array using a for loop
for (int i = 0; i < alphabets.length; i++) {
alphabets[i] = new ImageIcon("C:\\Users\\Dip\\Desktop\\Java Projects\\AbcGeniusApp\\src\\Alphabets\\" + (i + 1) + ".png");
}
//Create a JPnael object
JPanel panel = new JPanel();
//Set a layoutManager on the panel
//panel.setLayout(new FlowLayout(FlowLayout.CENTER)); //This is not workling good
panel.setLayout(new GridLayout(2, 13, 5, 5)); //This is good for now
//Create an array for holdoing the buttons
buttons = new JButton[26];
//This Loop will Store the buttons in the buttons array attatching each image for each button
//Try passing Images inside the JButton parameter later.
for (int i = 0; i < 26; i++) {
buttons[i] = new JButton(alphabets[i]);
}
// Now Setting up a new Borderlayout so that we can set the whole gridLayout at the botton of the panel
setLayout(new BorderLayout(2, 0));
//add the panel to the Border layout
add(panel, BorderLayout.SOUTH);
//Add evenHandling mechanism to all the buttons
for (int k = 0; k < 26; k++) {
buttons[k].addActionListener(this);
}
for (int count1 = 0; count1 < 26; count1++) {
panel.add(buttons[count1]);
}
}
//This Method will generate a random Number and return it
public int random_number() {
int rand_num;
Random generator = new Random(System.currentTimeMillis());
rand_num = generator.nextInt(26);
return rand_num;
}
//This method will draw the font on the Panel
public void paintComponent(Graphics g) {
Font font; //Declare Font object here
font = new Font("Wide Latin", Font.BOLD, 22); //Set font
super.paintComponent(g); //Ensure the drawing in super class
g.setFont(font); //Set the font
g.setColor(Color.RED);
String text = "CLICK ON THE RIGHT IMAGE!"; //Display the text
g.drawString(text, 255, 20);
}
//To draw the picture on the screen we need to override the paint Method
#Override
public void paint(Graphics g) {
super.paint(g);
//Here, x and y will determine the x and y position os each image
int x = 0, y = 0;
// the varibale q is declared above
for (q = 0; q < 3; q++) //This loop will generate three images on the screen
{
if (showImage) {
x = x + 265; //X-Position of the image
y = 90; //Y-Position of the image
//q is declared as q=0, so this will always be true
if (w == 1 || q == 0) {
g.drawImage(image, x, y, image.getWidth(null), image.getHeight(null), null); //This method will put the image on the screen
showImage = true;
w = 0;
}
while (true) //this loop will run anyway
{
//go inside this loop only when the generated random
//doesn't match with the index of the button that was pressed
while ((randNumber = random_number()) != index) {
index = randNumber; //Now put the randomVlaue in the index
this.image = new ImageIcon(imageList[randNumber]).getImage();
showImage = true;
//make w=1 so that we can break from the outer loop
w = 1;
//break from the inner loop
break;
}
//Since we have made the w=1, so we are breaking out of the outer loop
if (w == 1) {
break;
}
}
}
}
}
#Override
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
id = 0;
while (true) {
//id is set to zero, for example if the button A (buttons[0])is not pressed then it will go below
//to increase id until it matches the index of the button that we pressed
if (source == buttons[id]) {
//get the image of that same index of the buttons and then set the showImage true
//SO the the paint function above can draw the image
this.image = new ImageIcon(imageList[id]).getImage();
showImage = true;
//save the index of the button that is presed in another variable
//then break from the while loop
index = id;
break;
} else {
id++;
//This is necessary to make sure that id will cross 26
//becasue we have only 26 letters or the array index is 26
//so highest value can be 26 only
id = id % 26;
}
}
repaint();
}
}
Add 3 JLabels or JButtons (whatever will be displaying the images) into a JPanel container. The JPanel will likely use a GridLayout(1, 3, horizontal_gap, 0) layout.
Place all images as ImageIcons into an ArrayList.
Shuffle the ArrayList when needed
After shuffling place the Icons into the JLabels/JButtons in a for loop using the setIcon(...) method.
Note that
your JPanel should override paintComponent, not paint. The paint method is responsible for painting a component's children and borders, and it does not use double buffering by default, making a more dangerous method to override.
Putting in a while (true) loop into your Swing GUI without regard to threading is extremely dangerous.
Putting this into a painting method such as paint is GUI suicide. Never do this since a painting method is a major determinant in the perceived responsiveness of your program. If you slow it down, the program will be perceived as being slow and poorly responsive, and thus it must be lean and fast as possible, and you should have painting and only painting code within it.
Your paint method has program logic in it, something that also shouldn't be done. You don't have full control over whether or even if a painting method will be called, and so program logic should never be placed inside one of these.
As MadProgrammer well notes, don't use the src path for your images as this won't exist once you build your program into a jar file. Better to Create a resource directory in the jar file, and to refer to your images as resources, not as files.
I am currently designing an image editor in a GUI which has several buttons which, when clicked, should apply different effects on the loaded image. I have the effects working with an ActionListener but if I try to click an effect after already clicking another effect, the image turns black instead of applying the desired effect. How do I apply multiple effects to the same image? Here is my code for the ButtonPanel class, which includes the ActionListener and code for the effects(only three of the effects have been implemented as of yet):
class ButtonPanel extends JPanel
{
//JButton makeBlue;
BufferedImage img;
ImagePanel ip = new ImagePanel();
ButtonPanel(ImagePanel x)
{
final JButton makeBlue = new JButton ("Make Blue");
final JButton makeRed = new JButton ("Make Red");
final JButton makeGreen = new JButton ("Make Green");
final JButton invertColors = new JButton ("Invert Colors");
final JButton makeGreyscale = new JButton ("Greyscale");
final JButton makeWarhol = new JButton ("Warhol");
final JButton flipVertical = new JButton ("Flip Vertical");
final JButton flipHorizontal = new JButton ("Flip Horizontal");
final JButton rotateClockwise = new JButton ("Rotate Clockwise");
setBackground(Color.RED);
ip = x;
//int width, height;
//setBackground(Color.RED);
//int height = 0;
add(makeBlue);
add(makeRed);
add(makeGreen);
add(invertColors);
add(makeGreyscale);
add(makeWarhol);
add(flipVertical);
add(flipHorizontal);
add(rotateClockwise);
ActionListener action =
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
BufferedImage img = ip.getImg();
if (e.getSource()== makeBlue)
{
int width = img.getWidth(); //# of pixel columns
int height = img.getHeight(); //# of pixels rows
for(int i=0; i<width;i++)
{
for(int j=0; j<height; j++)
{
int value = img.getRGB(i,j);
int y = 0xFF0000FF;
value = value & y;
img.setRGB(i,j,value);
}
}
ip.setImage(img);
setBackground(Color.GREEN);
repaint();
}
else if(e.getSource()== makeRed)
{
int width = img.getWidth(); //# of pixel columns
int height = img.getHeight(); //# of pixels rows
for(int i=0; i<width;i++)
{
for(int j=0; j<height; j++)
{
//fill in code here
int value = img.getRGB(i,j);
int y = 0xFFFF0000;
value = value & y;
//System.out.println(value);
img.setRGB(i,j,value);
}
}
ip.setImage(img);
repaint();
}
else if(e.getSource()== makeGreen)
{
int width = img.getWidth(); //# of pixel columns
int height = img.getHeight(); //# of pixels rows
for(int i=0; i<width;i++)
{
for(int j=0; j<height; j++)
{
//fill in code here
int value = img.getRGB(i,j);
int y = 0xFF00FF00;
value = value & y;
img.setRGB(i,j,value);
}
}
ip.setImage(img);
repaint();
}
}
};
makeBlue.addActionListener(action);
makeRed.addActionListener(action);
makeGreen.addActionListener(action);
makeWarhol.addActionListener(action);
flipVertical.addActionListener(action);
flipHorizontal.addActionListener(action);
rotateClockwise.addActionListener(action);
makeGreyscale.addActionListener(action);
invertColors.addActionListener(action);
}
}
Any help would be appreciated. Thanks.
Your problem is that you're extracting all of one color out of the image, and then replacing the original image in your ImagePanel with the new extracted image that is, say if the green button is pressed, all green. Then when you try to extract red from the ImagePanel's image, you get all black because the image is now only green.
You need to save the original image somewhere if you want to extract the original colors. Perhaps you should give ImagePanel a method, getOriginalImage() or some such, and have it store two images, one the displayed image and one the changed one.
Better still, use an Model-View-Control pattern and store your images elsewhere off the GUI.
There are two ways to accomplish this. You can either have your class be the ActionListener (which is the way you have it set up now), or you can have a unique ActionListener for each button. As a design decision I prefer the latter, as you can have more precise control and easier to read code this way.
Each of your buttons, menu items, and any other Object you want to have a unique effect should each have it's own ActionListener. You can either write a new class file for each ActionListener, an inner class, or an anonymous inner class for each. I prefer anonymous inner classes placed in line of your constructor or setup method like this:
JButton testButton = new JButton("Test");
testButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// do stuff here
System.out.println("You clicked me!");
}
});
This method allows you to ignore huge conditional branches and unnecessary comparisons. Implement the interface uniquely for each component that needs the listener.
If I have many JLabels on the screen and I know their names how would I go about selecting finding them?
For example I know that I previously (dynamically) created a new JLabel with the name 2340. Is there something like
JLabel image = findJlabel ("2340");
In order to select the JLabel component?
Thanks,
Neco
EDIT: Just want to show how I am creating these JLabels
// Initially creates all the imagelabels
public static void createImageLabels (){
int xcord, ycord;
JLabel image;
String imageLabelName;
xcord = 0;
ycord = yOffset;
for (int row = 0 ; row < map.length; row++) {
xcord = 0;
for (int col = 0 ; col < map[0].length; col++) {
imageLabelName = Integer.toString(row);
imageLabelName += Integer.toString(col);
image = new JLabel(new ImageIcon(space));
image.setName(imageLabelName);
image.setLocation(xcord, ycord);
image.setSize(24, 24);
imagePanel.add(image);
System.out.println ("Created a Jlabel Named "+imageLabelName);
xcord += 24;
}
ycord += 24;
}
}
I create a tile of imageIcons on the screen and then later on if I want to change the image displayed by them I want to select it and change it.
Well, assuming you have different names for all labels, i would recommend you using HashMaps.
HashMap<String, JLabel> labels = new HashMap<String,JLabel>();
Inside you "for" sicle, use:
labels.put("1233", new JLabel(new ImageIcon(space)));
To use your the label you want, use:
labels.get("1233");
For more information, check:
http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html
If you only want to find the component with the concept of the current container it easy, if you want to search child or parent containers, it becomes little more complicated...
public JLabel findLabelByName(Container parent, String name) {
JLabel found = null;
if (name != null) {
for (Component child : parent.getComponents()) {
if (child instanceof JLabel) {
JLabel label = (JLabel)child;
if (name.equals(label.getName()) {
found = label;
break;
}
}
}
}
return found;
}
Now, if you want to search up or down the container hierarchy, you would need to perform a recursive call to this method, passing in the new parent, but I'm sure you can figure that out, don't want to rob you of all the fun ;)
In order to select the JLabel component?
how are you 'selecting' the label?
if it's via the mouse, just add a mouseListener and use getSource()