JLabel unusable from other class - java

I got a problem with two problematics classes. One for drawing things, and other for implementing pan and zoom onto the previously drawn objects.
Imagine my interface as only two spitted panels, one empty(top) and one with a slider(bot):
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import java.awt.BorderLayout;
import javax.swing.JSplitPane;
import javax.swing.JPanel;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JSlider;
import java.awt.FlowLayout;
public class Interface {
private JFrame mainFrame;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {Interface window = new Interface();window.mainFrame.setVisible(true);
} catch (Exception e) { e.printStackTrace();}
}
});
}
public Interface() {initialize();}
private void initialize() {
mainFrame = new JFrame();
mainFrame.setTitle("LXView");
mainFrame.setMinimumSize(new Dimension(800, 600));
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setExtendedState(mainFrame.getExtendedState()| JFrame.MAXIMIZED_BOTH);
mainFrame.getContentPane().setBackground(Color.WHITE);
mainFrame.getContentPane().setLayout(new BorderLayout(0, 0));
JSplitPane splitPane = new JSplitPane();
splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
splitPane.setOneTouchExpandable(true);
splitPane.setBackground(Color.WHITE);
mainFrame.getContentPane().add(splitPane, BorderLayout.CENTER);
splitPane.setResizeWeight(0.99);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setEnabled(false);
splitPane.setLeftComponent(scrollPane);
Render topPane = new Render();
scrollPane.setViewportView(topPane);
topPane.setLayout(new BoxLayout(topPane, BoxLayout.X_AXIS));
JPanel botPane = new JPanel();
splitPane.setRightComponent(botPane);
botPane.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
JLabel zoomLevel = new JLabel("Zoom level:");
botPane.add(zoomLevel);
JSlider slider = new JSlider(JSlider.HORIZONTAL, 25, 100, 100);
slider.setMajorTickSpacing(15);
slider.setMinorTickSpacing(5);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.setPreferredSize(new Dimension(600,40));
botPane.add(slider);
PanAndZoom zoomer=new PanAndZoom(topPane.getLabel());
slider.addChangeListener(zoomer);
}
The top panel uses the render class which was made to draw graphics. Simplifying:
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Render extends JPanel {
JLabel envContainer;
Render() {
super();
ImageIcon imageIcon = new ImageIcon("/path/to/img1");
JLabel envContainer = new JLabel(imageIcon);
super.add(envContainer);
}
#Override
public void paint(Graphics g) {
super.paint(g);
/*Render stuff*/
}
public JLabel getLabel() {
return envContainer;
}
}
And the third class which is giving me the trouble, listens on the slider and sets the JLabel icon according to it:
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class PanAndZoom implements ChangeListener {
private JLabel label;
private BufferedImage image;
public PanAndZoom(JLabel lab){
this.label=lab;
try {
image = ImageIO.read(new File("/path/to/img1"));
} catch (IOException e) {
e.printStackTrace();
}
label.setIcon(new ImageIcon("/path/to/img2"));//To test another img. It gives runtime errors.
}
public void stateChanged(ChangeEvent e) {
int value = ((JSlider) e.getSource()).getValue();
double scale = value / 100.0;
BufferedImage scaled = getScaledImage(scale); // It also gives runtime errors.
System.out.println("Scale:"+scale+" Value:"+value);
label.setIcon(new ImageIcon(scaled));
label.revalidate();
}
private BufferedImage getScaledImage(double scale) {
int w = (int) (scale * image.getWidth());
int h = (int) (scale * image.getHeight());
BufferedImage bi = new BufferedImage(w, h, image.getType());
Graphics2D g2 = bi.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC);
AffineTransform at = AffineTransform.getScaleInstance(scale, scale);
g2.drawRenderedImage(image, at);
g2.dispose();
return bi;
}
}
Why cant i use the JLabel if it was successfully returned by the getLabel method?

You're local version of envContainer in class Render's constructor is overriding the class instance envContainer.
public class Render extends JPanel {
JLabel envContainer; //<---- class instance
Render() {
super();
ImageIcon imageIcon = new ImageIcon("/path/to/img1");
JLabel envContainer = new JLabel(imageIcon); //<---- overriden by local instance, hence class instance remains null
super.add(envContainer);
}
My guess is that you didn't mean to make it a local version since you're not using it within the constructor for anything. Make the following change to your Render constructor.
Render() {
..
this.envContainer = new JLabel(imageIcon);
...
}

Related

Problem with Java GridLayout and adding Buttons

I want to add 100 buttons into an GridLayout and my code works but sometimes it only adds one button and if I click where the other buttons belong the button where I clicked appears.
it happens totally randomly and I don't get it.
Here is my code:
public class GamePanel extends JPanel {
GameUI controler;
GridLayout gameLayout = new GridLayout(10,10);
JButton gameButtons[] = new JButton[100];
ImageIcon ice;
JButton startButton;
JButton exitButton;
ImageIcon startIcon;
ImageIcon exitIcon;
URL urlIcon;
private int i;
public GamePanel(GameUI controler) {
this.setLayout(gameLayout);
this.controler = controler;
urlIcon = this.getClass().getResource("/icons/Overlay.png");
ice = new ImageIcon(urlIcon);
makeButtons();
}
#Override
public void paint(Graphics g) {
super.paint(g);
}
public void makeButtons() {
for(i = 0; i< 100; i++) {
gameButtons[i] = new JButton(ice);
this.add(gameButtons[i]);
revalidate();
}
repaint();
}
}
update:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.net.URL;
public class GameUI extends JFrame {
ImageIcon i;
Image jFrameBackground;
JButton startButton;
JButton exitButton;
ImageIcon startIcon;
ImageIcon exitIcon;
public GameUI() {
setResizable(false);
this.setSize(1200, 800);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(null);
BackGroundPanel backGroundPanel = new BackGroundPanel();
GamePanel panel = new GamePanel(this);
ButtonPanel buttonPanel = new ButtonPanel();
panel.setSize(500,500);
panel.setLocation(100, 150);
backGroundPanel.setSize(this.getWidth(),this.getHeight());
backGroundPanel.setLocation(0,0);
buttonPanel.setSize(390,50);
buttonPanel.setLocation(100,100);
this.add(backGroundPanel);
this.add(panel);
this.add(buttonPanel);
backGroundPanel.setBackground(Color.BLACK);
}
public static void main(String[] args) throws InvocationTargetException, InterruptedException {
javax.swing.SwingUtilities.invokeAndWait(
new Runnable(){
#Override
public void run() {
GameUI ui = new GameUI();
ui.setVisible(true);
}
}
);
}
}
As I mentioned in comments, you're using a null layout, and this is the source of your problems.
You're using the null layout to try to layer JPanels, one on top of the other, and that is not how it should be used or what it is for, nor how you should create backgrounds. This is having the effect of the background covering your buttons until your mouse hovers over them.
Instead if you wish to create a background image, I would recommend that you:
create a JPanel, say called BackgroundPanel,
override its paintComponent method,
call its super.paintComponent(g); on your method's first line
then draw the image it should display
then give it a decent layout manager
and add your GUI components to it
Make sure that any JPanels added to it are made transparent via .setOpaque(false)
Other options include using a JLayeredPane, but you really don't need this just to have a background.
For example, the following code produces:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class GameUI2 {
private static final String IMG_PATH = "https://upload.wikimedia.org/wikipedia/commons/3/3f/"
+ "Butterfly_Nebula_in_narrow_band_Sulfur%2C_Hydrogen_and_Oxygen_Stephan_Hamel.jpg";
private static final String BTN_IMG_PATH = "https://upload.wikimedia.org/wikipedia/commons/5/54/Crystal_Project_Games_kids.png";
private static void createAndShowGui() {
BufferedImage bgImg = null;
BufferedImage btnImg = null;
try {
URL bgImgUrl = new URL(IMG_PATH);
URL btnImgUrl = new URL(BTN_IMG_PATH);
bgImg = ImageIO.read(bgImgUrl);
btnImg = ImageIO.read(btnImgUrl);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
BackgroundPanel2 mainPanel = new BackgroundPanel2(bgImg);
mainPanel.setLayout(new GridBagLayout());
GamePanel2 gamePanel = new GamePanel2(btnImg);
mainPanel.add(gamePanel);
JFrame frame = new JFrame("Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.setResizable(false);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
#SuppressWarnings("serial")
class BackgroundPanel2 extends JPanel {
private Image backgroundImg;
public BackgroundPanel2(Image backgroundImg) {
this.backgroundImg = backgroundImg;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (backgroundImg != null) {
g.drawImage(backgroundImg, 0, 0, this);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || backgroundImg == null) {
return super.getPreferredSize();
} else {
int w = backgroundImg.getWidth(this);
int h = backgroundImg.getHeight(this);
return new Dimension(w, h);
}
}
}
#SuppressWarnings("serial")
class GamePanel2 extends JPanel {
public static final int MAX_BUTTONS = 100;
private static final int IMG_WIDTH = 40;
JButton[] gameButtons = new JButton[MAX_BUTTONS];
public GamePanel2(Image buttonImg) {
setOpaque(false);
if (buttonImg.getWidth(this) > IMG_WIDTH) {
buttonImg = buttonImg.getScaledInstance(IMG_WIDTH, IMG_WIDTH, Image.SCALE_SMOOTH);
}
Icon icon = new ImageIcon(buttonImg);
setLayout(new GridLayout(10, 10, 4, 4));
for (int i = 0; i < gameButtons.length; i++) {
int finalIndex = i;
JButton btn = new JButton(icon);
btn.addActionListener(e -> {
String text = String.format("Button: %02d", finalIndex);
System.out.println(text);
});
add(btn);
gameButtons[i] = btn;
}
}
}

Speed up/Mask Blur

I am using code from this website to blur my photos in a Java application.
The problem with it is that it is not fast enough to do the blurring effect in real-time. This means when the area it is blurring changes size, there is a large black box whilst it renders a new blur. Is there a way to mask this gap whilst it renders the new blur?
Example GUI
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.LayoutManager;
import java.awt.MultipleGradientPaint.CycleMethod;
import java.awt.RadialGradientPaint;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import blur.GaussianFilter;
#SuppressWarnings("serial")
public class GUI extends JFrame {
private GUI() {
super("Example");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
Overlay layers = new Overlay();
add(layers);
pack();
setMinimumSize(getSize());
getContentPane().setBackground(Color.WHITE);
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new GUI());
}
private class Overlay extends JLayeredPane {
JPanel base;
JPanel overlay;
BufferedImage bi, blurredImage;
BufferedImageOp op = new GaussianFilter(4);
private Overlay() {
addComponentListener(new Resize());
setPreferredSize(new Dimension(800, 100));
createBase();
createOverlay();
add(base, new Integer(0));
bi = ComponentPainter.paintComponent(base);
blurredImage = op.filter(bi, null);
add(overlay, new Integer(1));
}
private void createBase() {
base = new JPanel();
base.setLocation(0, 0);
base.setPreferredSize(new Dimension(800, 100));
base.setSize(800, 100);
base.setBackground(Color.WHITE);
base.setVisible(false);
base.add(new JLabel("Hello"));
base.add(new JButton("Hello"));
}
private void createOverlay() {
overlay = new Over(new GridBagLayout());
overlay.setLocation(0, 0);
overlay.setPreferredSize(new Dimension(800, 100));
overlay.setSize(800, 100);
overlay.add(new JLabel("Hi"));
}
private class Resize extends ComponentAdapter {
#Override
public void componentResized(ComponentEvent e) {
base.setSize(new Dimension(getParent().getWidth(), getParent().getHeight()));
overlay.setSize(new Dimension(getParent().getWidth(), getParent().getHeight()));
bi = ComponentPainter.paintComponent(base);
blurredImage = op.filter(bi, null);
}
}
private class Over extends JPanel {
private Over() {
super();
}
private Over(LayoutManager layout) {
super(layout);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(blurredImage, 0, 0, this);
int alpha = 128;
Point2D center = new Point2D.Float(getWidth()/2f, getHeight()/2f);
float radius = (getWidth() / 16F) * 13;
float[] dist = {0f, 1f};
Color[] colors = {new Color(245, 251, 255, alpha), new Color(255, 255, 255, alpha)};
RadialGradientPaint p = new RadialGradientPaint(center, radius,
dist, colors,
CycleMethod.NO_CYCLE);
g2d.setPaint(p);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
}
#Override
public boolean isOptimizedDrawingEnabled() {
return true;
}
}
private static class ComponentPainter {
public static BufferedImage paintComponent(Component c) {
layoutComponent(c);
BufferedImage img = new BufferedImage(c.getWidth(), c.getHeight(),
BufferedImage.TYPE_INT_RGB);
c.paint(img.createGraphics());
return img;
}
private static void layoutComponent(Component c) {
synchronized (c.getTreeLock()) {
c.doLayout();
if (c instanceof Container)
for (Component child : ((Container) c).getComponents())
layoutComponent(child);
}
}
}
}
Other code used in example GUI:
SO Answer
Blur Download

Brightness implementation for JPanel in Swing

I want to create brightness functionality in Swing. JPanel and its component's brightness level will be adjust in this functionality.
To achieve this I used JLayeredPane and added JPanel as BrightNessPanel on the top of my JPanel called MainPanel. I am giving brightness effect by changing the opacity of BrightNessPanel. This will simulate Brightness effect for my MainPanel.
Now problem is that, I am not able to click the buttons present on MainPanel because of layer of BrightNessPanel.
How do I pass through clicks from BrightNessPanel to the buttons present on MainPanel??
You might be able to make use the JLayer API which allows you to perform painting operations ontop of other components.
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLayer;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.LayerUI;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
TestPane testPane = new TestPane();
BrightnessLayerUI layerUI = new BrightnessLayerUI();
JLayer<JComponent> layer = new JLayer<>(testPane, layerUI);
JSlider slider = new JSlider(0, 100);
slider.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
int value = slider.getValue();
float brightness = (100 - value) / 100f;
layerUI.setBrightness(brightness);
testPane.repaint();
}
});
slider.setValue(100);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(layer);
frame.add(slider, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(new JTextField(10), gbc);
add(new JButton("Hello"), gbc);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.dispose();
}
}
public class BrightnessLayerUI extends LayerUI<JComponent> {
private float brightness = 0f;
public void setBrightness(float brightness) {
this.brightness = brightness;
}
public float getBrightness() {
return brightness;
}
#Override
public void paint(Graphics g, JComponent c) {
super.paint(g, c);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(c.getBackground());
g2d.setComposite(AlphaComposite.SrcOver.derive(getBrightness()));
g2d.fillRect(0, 0, c.getWidth(), c.getHeight());
g2d.dispose();
}
}
}
One of the advantages of this is you could actually introduce a "brightness" algorithm, rather than faking it, by using a backing buffer, which is demonstrated the link above (this use to to blur the UI)

Display Images in JFrame from JComboBox event

I want to achieve following functionality :
Eg :
When user selects "Profile Pic"item from JComboBox releted images from "Profile Pic" folder should be loaded on same frame.
Again when user selects "Product Img" item related images from "Product Img" folder should be loaded replacing previous images.
Following is code snippet , please suggest any changes
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
public class NewClass1 {
public static void main(String[] args) {
createAndShowJFrame();
}
public static void createAndShowJFrame() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = createJFrame();
frame.setVisible(true);
}
});
}
private static JFrame createJFrame() {
JFrame frame = new JFrame();
//frame.setResizable(false);//make it un-resizeable
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Test");
ArrayList<BufferedImage> images = null;
try {
images = getImagesArrayList();
} catch (Exception ex) {
ex.printStackTrace();
}
final ImageViewPanel imageViewPanel = new ImageViewPanel(images);
JScrollPane jsp = new JScrollPane(imageViewPanel);
jsp.setPreferredSize(new Dimension(400, 400));
frame.add(jsp);
final javax.swing.JComboBox filter = new javax.swing.JComboBox<>();
filter.addItem("All");
filter.addItem("Profile Pic");
filter.addItem("Company Logo");
filter.addItem("Product Img");
JPanel controlPanel = new JPanel();
JButton addLabelButton = new JButton("Delete Selected Image");
addLabelButton.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
imageViewPanel.removeFocusedImageLabel();
}
});
JLabel label =new JLabel("Filter By :");
filter.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
String cat=(String) filter.getSelectedItem();
createJFrame(cat);
}
});
controlPanel.add(addLabelButton);
controlPanel.add(label);
controlPanel.add(filter);
frame.add(controlPanel, BorderLayout.NORTH);
frame.pack();
return frame;
}
private static ArrayList<BufferedImage> getImagesArrayList(String cat) throws Exception {
System.out.println(cat);
ArrayList<BufferedImage> images = new ArrayList<>();
if(cat.equals("Profile Pic"))
images.add(resize(ImageIO.read(new URL("http://192.168.1.25:8080/pic/ProfilePic/1.jpg")), 100, 100));
else if(cat.equals("Product Img"))
{
images.add(resize(ImageIO.read(new URL("http://192.168.1.25:8080/pic/ProductImg/2.jpg")), 100, 100));
}
return images;
}
private static ArrayList<BufferedImage> getImagesArrayList() throws Exception {
ArrayList<BufferedImage> images = new ArrayList<>();
images.add(resize(ImageIO.read(new URL("http://localhost:8080/pic/All/a.jpg")), 100, 100));
images.add(resize(ImageIO.read(new URL("http://localhost:8080/pic/All/b.jpg")), 100, 100));
return images;
}
public static BufferedImage resize(BufferedImage image, int width, int height) {
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TRANSLUCENT);
Graphics2D g2d = (Graphics2D) bi.createGraphics();
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(image, 0, 0, width, height, null);
g2d.dispose();
return bi;
}
}
I would urge you to have another look at the code I posted (which you seem to be using) Deleting images from JFrame.
However:
In your code I see:
filter.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
String cat=(String) filter.getSelectedItem();
createJFrame(cat);
}
});
I cannot even find the method createJFrame(String cat);?
As far as I see you should be doing this:
filter.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
String cat=(String) filter.getSelectedItem();
ArrayList<BufferedImage> images=getImagesArrayList(cat);//get the new images for the selected item in combo
//refresh the layout by removing old pics and itertating the new array and adding pics to the panel as you iterate
layoutLabels(images);
}
});
....
private JLabel NO_IMAGES=new JLabel("No Images");
private void layoutLabels(ArrayList<BufferedImage> images) {
removeAll();//remove all components from our panel (the panel should only have the images on if not use setActionCommand("Image") on your images/JLabels and than use getComponents of JPanel and iterate through them looking for getActionCommand.equals("Image")
if (images.isEmpty()) {//if the list is empty
add(NO_IMAGES);//add Jlabel to show message of no images
} else {
remove(NO_IMAGES);
for (BufferedImage i : images) {//iterate through ArrayList of images
add(new JLabel(new ImageIcon(i)));//add each to the panel using JLabel as container for image
}
}
revalidate();
repaint();
}

How to correctly update an Image in a JLabel?

I'm French so my English is quite bad but I have a real problem with java:
I'm trying to show an Image built manually with some fillRect & co.
It works. Next, I want to update this image as a function of the text I enter in the text field. And there is the problem: it doesn't change anything, and if I manually rescale the window of the JFrame, the image shows totally deformed or scaled badly.
I'm a beginner and I have difficulties with GUI, moreso when I want to couple it with Images.
Can you help me? Why doesn't it work as I want? This is my code below, a bit long but actually quite simple ! Thanks :)
I've changed it a bit, this is the 2e VERSION.
Now the problem s that I can't change a condition in order to modify the color of a simple rectangle, try "lol" in the entry field !
CODE VERSION 2
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.ImageIcon;
public class Fenetre extends JFrame {
private JFrame frame;
private JPanel container = new JPanel();
private JTextField jtf;
private JLabel label = new JLabel("Commandes ");
private JButton b = new JButton ("OK");
private Graphics graph;
private Image img;
private JLabel screen;
private boolean color;
/**
* Constructeur de l'objet
*/
public Fenetre(){
color = true;
frame = new JFrame();
frame.setTitle("Animation");
frame.setSize(1000, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
container.setBackground(Color.white);
container.setLayout(new BorderLayout());
JPanel top = new JPanel();
jtf = new JTextField();
jtf.setPreferredSize(new Dimension(800, 30));
b.addActionListener(new BoutonListener());
frame.setContentPane(top);
frame.setVisible(true);
paintComponent(graph);
screen = new JLabel( new ImageIcon(img));
top.add(screen);
top.add(label);
top.add(jtf);
top.add(b);
frame.setContentPane(top);
}
class BoutonListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
if(jtf.getText().equals("lol")) lol();
System.out.println("Entry : " + jtf.getText());
}
}
public void paintComponent(Graphics g)
{
if(img == null) {
img = frame.createImage(1000,300);
g = img.getGraphics();
}
g.setColor(Color.white);
g.fillRect(0,0,1000,300);
if(color) g.setColor(Color.orange); else g.setColor(Color.blue);
g.fillRect(8,25,200,100);
g.setColor(Color.green);
g.drawString("Text",10,10);
}
public void lol()
{
if(color) color = false; else color = true;
}
}
PREVIOUS CODE
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.ImageIcon;
public class Fenetre extends JFrame {
private JPanel container = new JPanel();
private JTextField jtf;
private JLabel label = new JLabel("Commandes ");
private JButton b = new JButton ("OK");
private Graphics g;
private Image img;
private JLabel screen;
/**
* Constructeur de l'objet
*/
public Fenetre(){
this.setTitle("Animation");
this.setSize(1000, 400);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
container.setBackground(Color.white);
container.setLayout(new BorderLayout());
JPanel top = new JPanel();
jtf = new JTextField();
jtf.setPreferredSize(new Dimension(800, 30));
b.addActionListener(new BoutonListener());
this.setContentPane(top);
this.setVisible(true);
paint(g);
screen = new JLabel( new ImageIcon(img));
top.add(screen);
top.add(label);
top.add(jtf);
top.add(b);
this.setContentPane(top);
}
class BoutonListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
System.out.println("Entry : " + jtf.getText());
if(jtf.getText().equals("lol")) lol();
}
}
#Override
public void paint(Graphics g)
{
if(img == null) {
img = createImage(1000,300);
g = img.getGraphics();
}
g.setColor(Color.white);
g.fillRect(0,0,1000,300);
g.setColor(Color.orange);
g.fillRect(8,25,200,100);
g.setColor(Color.green);
g.drawString("Text",10,10);
}
#Override
public void update(Graphics g)
{
g.setColor(Color.blue);
g.fillRect(8,25,300,100);
}
public void lol()
{
g.setColor(Color.blue);
g.fillRect(8,25,200,100);
}
}
I see several problems in your code:
You are confusing your g member variable with the g parameter of the paint method. When lol is called, g is null and you get a NullPointerException
You should never grab a hold on Graphics (only in really rare cases). Instead you override properly paintComponent() and you use the Graphics parameter to draw what you want. When you want to update the component, you call repaint()
Don't override paint, but override paintComponent()
Don't override paint of JFrame. Use a dedicate component for that. No need to use a JLabel for that, a simple JComponent is enough.
Don't extend JFrame if you are not extending its functionality.
After adding components to the component hierarchy, call revalidate()
Fix those issues and come back with another question if you still have problems.
You should probably consider reading this tutorial and the few next steps. It will show you basic examples of things similar to what you are trying to do.
EDIT:
I took your V2 code and patched it as I could. This is very far from perfect but you should get the gist of how you can do this:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Fenetre extends JComponent {
private boolean color;
/**
* Constructeur de l'objet
*/
public Fenetre() {
color = true;
setPreferredSize(new Dimension(1000, 300));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.white);
g.fillRect(0, 0, 1000, 300);
if (color) {
g.setColor(Color.orange);
} else {
g.setColor(Color.blue);
}
g.fillRect(8, 25, 200, 100);
g.setColor(Color.green);
g.drawString("Text", 10, 10);
}
public void lol() {
if (color) {
color = false;
} else {
color = true;
}
repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
initUI();
}
});
}
protected static void initUI() {
JFrame frame = new JFrame();
frame.setTitle("Animation");
frame.setSize(1000, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
JPanel container = new JPanel();
final JTextField jtf = new JTextField();
final Fenetre fenetre = new Fenetre();
JLabel label = new JLabel("Commandes ");
JButton b = new JButton("OK");
container.setBackground(Color.white);
container.setLayout(new BorderLayout());
JPanel top = new JPanel();
jtf.setPreferredSize(new Dimension(800, 30));
class BoutonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (jtf.getText().equals("lol")) {
fenetre.lol();
}
System.out.println("Entry : " + jtf.getText());
}
}
b.addActionListener(new BoutonListener());
top.add(fenetre);
top.add(label);
top.add(jtf);
top.add(b);
top.revalidate();
frame.setContentPane(top);
frame.setVisible(true);
}
}
Your Swing graphics programming has several significant problems, and I urge you to go through the tutorials to learn how to do this better. For example, you are
calling the paint method directly -- something you should almost never do except in very special situations (this is not one of them)
Drawing directly in the JFrame's paint(...) method. Instead you will want to draw in the paintComponent(...) method override of a class derived from JComponent such as JPanel.
Calling update unnecessarily as if this were an AWT program. You don't do this in Swing unless you're changing the Look & Feel.
Again, take a look at the tutorials on this -- you will not regret doing this, trust me.
edit -- too slow! 1+ to Guillaume

Categories

Resources