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();
}
}
}
Related
I am trying to create a graphics drawing program that allows the user to draw red pixels on the screen by dragging their mouse over it. So in a way, you can think of this program as Microsoft's Paint program but with only the pencil drawing tool and color red.
Unfortunately the mouseDragged() function in my program is not working properly. It will skip some of the pixels on the screen if I move my mouse too fast, like this:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FrameView extends JFrame {
JPanel panel;
Graphics2D drawingContext;
public static void main(String[] args) {
new FrameView();
}
public FrameView() {
panel = new JPanel();
panel.addMouseMotionListener(new MouseControls());
panel.setBackground(Color.WHITE);
this.add(panel);
this.setSize(new Dimension(500, 500));
this.setTitle("Drawing Program");
this.setVisible(true);
drawingContext = (Graphics2D)panel.getGraphics();
}
private class MouseControls extends MouseAdapter {
#Override
public void mouseDragged(MouseEvent e) {
int x = e.getX();
int y = e.getY();
final int WIDTH = 1;
final int HEIGHT = 1;
Shape pixel = new Rectangle(x, y, WIDTH, HEIGHT);
drawingContext.setColor(Color.RED);
drawingContext.draw(pixel);
}
}
}
getGraphics is NOT how painting works in Swing, instead, you should be overriding the paintComponent method of the component and performing your custom painting there.
Painting is destructive, it is expected that when ever paintComponent is called, you will completely repaint the current state of the component.
Have a look at Painting in AWT and Swing and Performing Custom Painting for more details
As to you "mouse" problem, this is actually how it works, you won't be notified of EVERY pixel position the mouse has to pass through, your mouse would lag horribly across the screen if it did. Instead, the OS moves the mouse in ever increasing steps based on the speed of the movement of the user input.
Instead of drawing just the points, draw lines between them, for example
nb: I've deliberately painted the points larger so you can see where they are been reported, you will see that all the dots (for a single drag) are connected
import java.awt.Color;
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.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
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();
}
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 List<List<Point>> points = new ArrayList<>(25);
private List<Point> activeList;
public TestPane() {
MouseAdapter ma = new MouseAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
if (activeList != null) {
activeList.add(e.getPoint());
repaint();
}
}
#Override
public void mousePressed(MouseEvent e) {
activeList = new ArrayList<>(25);
points.add(activeList);
}
#Override
public void mouseReleased(MouseEvent e) {
if (activeList != null && activeList.isEmpty()) {
points.remove(activeList);
}
activeList = null;
}
};
addMouseMotionListener(ma);
addMouseListener(ma);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
for (List<Point> group : points) {
Point previous = null;
for (Point p : group) {
// You can get rid of this, it's simply to show
// where the points would actually be rendered
g2d.fill(new Ellipse2D.Float(p.x - 2, p.y - 2, 4, 4));
if (previous != null) {
g2d.draw(new Line2D.Float(previous, p));
}
previous = p;
}
}
g2d.dispose();
}
}
}
Many custom Swing components are made of JPanel. Sometimes these components are required to be selectable.
How is it possible to make JPanel look selected? It should be selected like other items do, like menu items, or JTable cells. I.e. entire JPanel should be covered with transparent blue. It would be excellent, if this would made exactly like other items in L&F / theme,
Is it possible?
You could consider taking a look at JXLayer/JLayer, which would allow you to paint an overlay on top the component.
import java.awt.AlphaComposite;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Map;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.QualityHints;
import org.jdesktop.jxlayer.plaf.AbstractBufferedLayerUI;
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();
}
SelectablePane pane = new SelectablePane();
SelectableUI ui = new SelectableUI();
JXLayer<JPanel> layer = new JXLayer<>(pane, ui);
layer.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
ui.setSelected(!ui.isSelected());
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(layer);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class SelectablePane extends JPanel {
public SelectablePane() {
setLayout(new GridBagLayout());
add(new JLabel("Hello world"));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public static class SelectableUI extends AbstractBufferedLayerUI<JPanel> {
public static Map<RenderingHints.Key, Object> mapRenderHints = new QualityHints();
private boolean selected = false;
public SelectableUI() {
mapRenderHints.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); // okay
mapRenderHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // bad
mapRenderHints.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); // okay
mapRenderHints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
mapRenderHints.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
mapRenderHints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
mapRenderHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
}
public void setSelected(boolean value) {
if (selected != value) {
selected = value;
firePropertyChange("selected", !selected, selected);
repaint();
}
}
public boolean isSelected() {
return selected;
}
#Override
protected void paintLayer(Graphics2D g2, JXLayer<? extends JPanel> l) {
super.paintLayer(g2, l);
if (isSelected()) {
Graphics2D g2d = (Graphics2D) g2.create();
g2d.setColor(UIManager.getColor("List.selectionBackground"));
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
g2d.fillRect(0, 0, l.getWidth(), l.getHeight());
g2d.dispose();
}
}
#Override
protected Map<RenderingHints.Key, Object> getRenderingHints(JXLayer<? extends JPanel> l) {
return mapRenderHints;
}
public void repaint() {
setDirty(true);
}
public void invalidate() {
setDirty(true);
}
public void revalidate() {
setDirty(true);
}
}
}
I am very new to graphics with Java, so just ask if any additional information is needed :)
I am trying to paint shapes based on where the mouse clicks on the screen. Because of this, I need to pass the x and y coordinates of where I clicked to the paintComponent() method so that it will know where to paint the shape.
public void mouseClicked(MouseEvent e) {
System.out.println("Adding Shape");
repaint();
}
class CanvasDrawArea extends JPanel{
//this should run when the program first starts
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
canvas.setBackground(CANVAS_COLOR);
}
//here is where the question is
public void paintComponent(Graphics g, int x, int y){
super.paintComponent(g);
g.fillRect(x, y, RECTANGLE_WIDTH, RECTANGLE_HEIGHT);
}
}
basically I am trying to overload the paintComponent by having one that runs right when the program starts by calling the repaint() / pack() method, and one that will run when I give it the x and y coordinates. I am unsure, however, how I am supposed to go about passing the x and y parameters, as there is no way to pass them in the repaint() method.
You should never have the need to call paintComponent or paint directly these are called automatically by the repaint manager when required...
Create java.util.List and store the Point of each mouse click in it, call repaint from the mouseClicked method after you have done this.
In your paintComponent(Graphics) method, iterate over the List of points and paint the shape you need.
As a simple example...
import java.awt.Color;
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.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Dotty {
public static void main(String[] args) {
new Dotty();
}
public Dotty() {
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 DottyPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DottyPane extends JPanel {
private List<Point> points;
public DottyPane() {
points = new ArrayList<>(25);
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
points.add(e.getPoint());
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
for (Point p : points) {
g2d.fillOval(p.x - 5, p.y - 5, 10, 10);
}
g2d.dispose();
}
}
}
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.
I am trying to use KeyListener in my code.... But it's not working, the KeyListener not responding I think...
If you guys see anything wrong please tell me. I don't know why it's not working.
Thanks in advance.
Here is the code.
import javax.swing.*;
import java.awt.*;
import java.util.Scanner;
public class Main extends JFrame {
static void drawFrame(JFrame frame) {
frame.setSize(610, 805);
frame.setLocation(145, 15);
frame.setResizable(false);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
JFrame frame = new JFrame("PacMan");
drawFrame(frame);
MyPanel panel = new MyPanel();
panel.setBounds(00, 00, 610, 800);
frame.setLayout(null);
frame.getContentPane().setLayout(null);
frame.getContentPane().add(panel);
}
}
MyPanel Class
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class MyPanel extends JPanel implements KeyListener {
private int xpac = 285, ypac = 570;
public MyPanel() {
this.requestFocus();
this.requestFocusInWindow();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
drawMap1(g);
drawPacman(g);
addKeyListener(this);
}
void drawMap1(Graphics g) {
BufferedImage image = null;
try {
image = ImageIO.read(new File("pacmap1.png"));
} catch (IOException e) {
System.out.println("Can't find the Image.");
}
setBackground(Color.BLACK);
g.drawImage(image, 0, 0, null);
}
void drawPacman(Graphics g) {
int x = xpac, y = ypac;
BufferedImage image = null;
try {
image = ImageIO.read(new File("pacright.png"));
} catch (IOException e) {
System.out.println("Can't find the Image.");
}
g.drawImage(image, x, y, null);
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
System.out.println("Hi there Buddy");
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
System.out.println("Hi there Buddy");
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
System.out.println("Hi there Buddy");
}
}
You should just comment out the addKeyListener in the MyPanel class and do this in the Main class after you instantiate the MyPanel:
frame.addKeyListener(panel);
You should put the this.addKeyListener(this); in your MyPanel class constructor, not the paintComponent method.
Please always use a KeyBindings for such Tasks. See: http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html
As a little tip, I would recommend you to implement KeyListener as an AnonymousClass.