I am trying to create a form. there is a button that when clicking the button, a photo which is specified would appear. my problem is, when I click the button, the picture pops up and if the cursor passes the form boundary, the image disappears. here is my code:
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import static java.lang.Math.abs;
import static java.lang.Math.min;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
public class SeamCarving extends JFrame
{
public static void main(String[] args) throws IOException {
final BufferedImage input = ImageIO.read(new File("path"));
final BufferedImage[] toPaint = new BufferedImage[]{input};
final Frame frame = new Frame("Seams") {
#Override
public void update(Graphics g) {
final BufferedImage im = toPaint[0];
if (im != null) {
g.clearRect(0, 0, getWidth(), getHeight());
g.drawImage(im, 0, 0, this);
}
}
};
frame.setSize(input.getWidth(), input.getHeight());
frame.setVisible(true);
frame.add(startButton);
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
BufferedImage out = input;
out = deleteVerticalSeam(out);
toPaint[0] = out;
frame.repaint();
System.out.println("Do Something Clicked");
}
});
}
}
Don't override update, this isn't how painting is achieved in Swing. Attempting to paint directly to a top level container like JFrame is problematic at best.
Instead, start with a JPanel and use it's paintComponent method instead. Make sure you call super.paintComponent as well.
In fact, you could probably just use a JLabel to display the image instead.
Take a look at;
Performing Custom Painting
How to use labels
For more details
Updated with example
I still think a JLabel would be simpler solution, but what do I know.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class SeamCarving {
public static void main(String[] args) {
new SeamCarving();
}
public SeamCarving() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage input;
private BufferedImage[] toPaint;
public TestPane() {
try {
input = ImageIO.read(new File("C:\\hold\\thumbnails\\2005-09-29-3957.jpeg"));
toPaint = new BufferedImage[1];
} catch (IOException ex) {
ex.printStackTrace();
}
setLayout(new GridBagLayout());
JButton startButton = new JButton("Start");
startButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
BufferedImage out = input;
out = input; //deleteVerticalSeam(out);
toPaint[0] = out;
repaint();
System.out.println("Do Something Clicked");
}
});
add(startButton);
}
#Override
public Dimension getPreferredSize() {
return input == null ? new Dimension(400, 400) : new Dimension(input.getWidth(), input.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (toPaint[0] != null) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(input, 0, 0, this);
g2d.dispose();
}
}
}
}
The problem with overriding update is the paint subsystem can choose to avoid calling and end up calling paint directly, circumventing your painting.
Painting also involves painting child components (like your button) and borders, which you've conveniently discarded by not calling super.update.
Related
I can't figure out on how to fix the problem. Please help me. Thank you.
Here are the codes:
package com.gabriel.mvc.app;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import com.gabriel.mvc.shapeimpl.CarRenderer;
import com.gabriel.mvc.shapesfx.MyShape;
import com.gabriel.mvc.shapesfx.Renderer;
public class CarView extends JFrame {
Image image;
MyShape car;
Renderer renderer = new CarRenderer();
void init(MyShape car) {
this.car = car;
}
void initUI() {
setVisible(true);
image = new ImageIcon("2284910.jpg").getImage();
setBounds(300,100,500,500);
setSize(500,500);
}
public void paint(Graphics g)
{
g.clearRect(0,0,600,600);
g.drawImage(image, 0, 0, null);
renderer.draw(g, car);
}
}
Here's the output, only solid color. Image not set as background. :(
Here's my expected output, I edited it on Photoshop.
You may refer on this code just replace your image source and add your CarRenderer after the drawImage method of Graphics.
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import java.awt.Image;
import java.awt.Graphics;
public class SampleImageBg extends JFrame{
private JDesktopPane panel;
public SampleImageBg() {
panel = new javax.swing.JDesktopPane() {
private Image image;
{
try {
image = ImageIO.read(getClass().getResource("bg.jpeg"));// source of your background image
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
g.clearRect(50,0,300,300); // add your renderer here instead
}
};
add(panel);
setVisible(true);
setSize(400, 600);
}
public static void main(String[] args) {
new SampleImageBg();
}
}
How would I go and add an image on the mouse coordinates when the mouse clicks? I have looked at this :Adding Images on Mouse Click to JPanel
But I don't understand it and am trying to add it on mouse click in an applet
And please don't say, "Learn some basic java first! and provide me with a link to some oracle docs", I just can't get any info from those things.
Code:
> `import java.applet.Applet;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
`import java.net.URL;
import javax.imageio.ImageIO;
public class SHR extends Applet implements MouseListener{
int a;
int b;
#Override
public void mouseClicked(MouseEvent e) {
a = e.getX();
b = e.getY();
paint(null, a, b);/this is the part i am having trouble with
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent arg0) {
}
#Override
public void mouseReleased(MouseEvent arg0) {
}
public void paint(Graphics g, int x, int y){
BufferedImage photo = null;
try
{
URL u = new URL(getCodeBase(),"SilverHandRecruit.png");
photo = ImageIO.read(u);
}
catch (IOException e)
{
g.drawString("Problem reading the file", 100, 100);
}
g.drawImage(photo,x, y, 10, 30, null);
}
}
`
The problem is, I don't know what I am supposed to replace "null" with to get it to work
Thanks
Start by taking a look at Painting in AWT and Swing and Performing Custom Painting to understand how painting works in AWT/Swing.
Then, take a look at 2D Graphics for more details about how you can use the Graphics class to paint things with.
This is a really basic example which loads a single image and every time you click on the panel, moves it to that point.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DrawImage {
public static void main(String[] args) {
new DrawImage();
}
public DrawImage() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage image;
private Point drawPoint;
public TestPane() {
try {
image = ImageIO.read(getClass().getResource("/SmallPony.png"));
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
drawPoint = new Point(e.getPoint());
repaint();
}
});
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (drawPoint != null) {
g2d.drawImage(image, drawPoint.x, drawPoint.y, this);
}
g2d.dispose();
}
}
}
The below code is not my actual code but a concise, runnable remake of what I am trying to achieve. I want the JPanel CP, an instance of clickPanel, to appear when the user clicks on the image in JPanel hasAnImage. I can see in the Netbeans console that the is executing because of the Sys.out.print, but nothing appears on the screen. I have tried setting visible to false then true again and revalidate() in the mousePressed event; the image moves to the left, but nothing appears on the screen. The goal is for CP to appear. What am I missing? Hope my question is clear.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Testo extends JFrame{
public Testo(){
BufferedImage image = null;
try {
image = ImageIO.read(new File("C:\\Users\\someimage.jpg"));
} catch (IOException ex) {
ex.printStackTrace();
}
;
final JLabel label = new JLabel(new ImageIcon(image));
JPanel hasAnImage = new JPanel();
hasAnImage.addMouseListener(new MouseAdapter(){
#Override //I override only one method for presentation
public void mousePressed(MouseEvent e) {
clickPanel CP = new clickPanel();
hasAnImage.add(CP);
revalidate();
//setVisible(false);
//setVisible(true);
}
});
hasAnImage.add(label);
add(hasAnImage);
setVisible(true);
}
public static void main(String[] args) {
Testo frame = new Testo();
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.getContentPane().setBackground(Color.WHITE);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public class clickPanel extends JPanel{
public clickPanel() {
setPreferredSize(new Dimension(100,60));
setMaximumSize(new Dimension(100,60));
setBackground(new Color(1.0f,1.0f,1.0f,0.1f));
setBorder(BorderFactory.createMatteBorder(2,2,2,2,Color.GREEN));
System.out.println("This is being executed...");
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(new Font("Arial", Font.PLAIN, 12));
g.setColor(Color.GREEN);
g.drawString("CLICK", 2, 2);
}
}
}
Beyond revalidate();ing the pane, you also need to repaint(); it. Thus your mousePressed method should become:
public void mousePressed(MouseEvent e) {
clickPanel CP = new clickPanel();
hasAnImage.add(CP);
revalidate();
repaint();
}
For further reading: http://docs.oracle.com/javase/7/docs/api/java/awt/Component.html#repaint()
So, I know that images can be cropped, shrunk, and expanded, but can you adapt an image into the shape of a parallelogram? I'm using Java Swing to draw images. I was thinking maybe some class or some method of BufferedImage might do the trick, but I couldn't find anything. I have also searched Google for a while, but I cannot find an answer. Does anyone know of a way I could do this, or a webpage that explains it? Thanks in advance.
You could use AffineTransform.getShearInstance.
This example uses a AffineTransformOp to "filter" the original image
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class SkewImage {
public static void main(String[] args) {
new SkewImage();
}
public SkewImage() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridLayout(1, 2));
try {
BufferedImage original = ImageIO.read(new File("C:\\hold\\thumbnails\\Megatokyo_707___Torn_by_crusaderky.jpg"));
BufferedImage skew = new BufferedImage(original.getWidth(), original.getHeight(), BufferedImage.TYPE_INT_ARGB);
// Adjust the image width if we use a negative skew...
double skewX = 0.3d;
double x = (skewX < 0) ? -skewX * original.getHeight() : 0;
AffineTransform at = AffineTransform.getTranslateInstance(x, 0);
at.shear(skewX, 0);
AffineTransformOp op = new AffineTransformOp(at,
new RenderingHints(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC));
skew = op.filter(original, null);
add(new JLabel(new ImageIcon(original)));
add(new JLabel(new ImageIcon(skew)));
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
Just an example using a Java image processing framework.
Output:
public class SkewExample extends JFrame{
MarvinImagePlugin skew = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.transform.skew");
public SkewExample(){
super("Skew Example");
// Layout
setLayout(new GridLayout(6,1));
// Load Image
MarvinImage image = MarvinImageIO.loadImage("./res/chamaleon.jpg");
skew.setAttribute("skew", "Horizontal");
// Process the image multiple times with different angle.
for(int i=1; i<=6; i++){
add(new JLabel(new ImageIcon(skew(image, i*7).getBufferedImage())));
}
setSize(340,880);
setVisible(true);
}
private MarvinImage skew(MarvinImage imageIn, int angle){
skew.setAttribute("SkewAngle", angle);
MarvinImage ret = new MarvinImage(imageIn.getWidth(),imageIn.getHeight());
ret.fillRect(0, 0,imageIn.getWidth(),imageIn.getHeight(), new Color(238,238,238));
ret.update();
skew.process(imageIn, ret);
ret.update();
return ret;
}
public static void main(String[] args) {
new SkewExample().setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
This is how I want my app to look like.
Trouble is, if I drag the JLabel with the "Hello, I'm Myra" over another JLabel (whose icon is the speech bubble), rather than superimposing or layering, NetBeans shifts the JLabels to be adjacent.
How do I superimpose ie. place the text JLabel on top of another JLabel?
Do note, I'm using NetBeans. It doesn't allow me to edit much of the JFrame or JLabel code.
Netbeans won't let you add components to a JLabel, it doesn't see them as a valid Container.
This won't be easily achieved using component labels, as the icon placement is outside of your control. A better solution might be to use a custom component, such as a JPanel and manually draw the speech bubble image yourself, then using a combination of Border and LayoutManager it would allow you to add other components to it
This is a very basic example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class SpeechBubble {
public static void main(String[] args) {
new SpeechBubble();
}
public SpeechBubble() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
SpeechBubblePane bubble = new SpeechBubblePane();
JLabel hello = new JLabel("Hello, I'm Myra");
hello.setFont(hello.getFont().deriveFont(28f));
hello.setForeground(Color.CYAN);
JLabel message = new JLabel("<html>What would you like to know today?</html>");
message.setFont(message.getFont().deriveFont(22f));
message.setForeground(Color.WHITE);
bubble.setLayout(new GridLayout(2, 1));
bubble.add(hello);
bubble.add(message);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setBackground(Color.BLACK);
frame.add(bubble);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class SpeechBubblePane extends JPanel {
private BufferedImage background;
public SpeechBubblePane() {
setOpaque(false);
try {
background = ImageIO.read(getClass().getResource("/speechbubble.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
setBorder(new EmptyBorder(19, 19, 66, 19));
}
#Override
public Dimension getPreferredSize() {
Dimension size = new Dimension(200, 200);
if (background != null) {
size = new Dimension(background.getWidth(), background.getHeight());
}
return size;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight()- background.getHeight()) / 2;
g2d.drawImage(background, x, y, this);
g2d.dispose();
}
}
}
}
If I was doing this, I would consider developing up a "9-path" which would allow you to break the image down into 9 parts and scale the outer sections based on what the content requires, for example...
It sounds like you just want to add a z-order. If so, you need a LayeredPane:
http://docs.oracle.com/javase/7/docs/api/index.html
http://docs.oracle.com/javase/7/docs/api/javax/swing/JLayeredPane.html