Why can't I draw an ellipse with this code? - java

package test;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class test_bmp extends JPanel implements MouseListener,MouseMotionListener,ActionListener
{
static BufferedImage image;
Color color;
Point start=new Point();
Point end =new Point();
JButton elipse=new JButton("Elipse");
JButton rectangle=new JButton("Rectangle");
JButton line=new JButton("Line");
String selected;
public test_bmp()
{
color = Color.black;
setBorder(BorderFactory.createLineBorder(Color.black));
addMouseListener(this);
addMouseMotionListener(this);
}
public void paintComponent(Graphics g)
{
//super.paintComponent(g);
g.drawImage(image, 0, 0, this);
Graphics2D g2 = (Graphics2D)g;
g2.setPaint(Color.black);
if(selected=="elipse")
{
g2.drawOval(start.x, start.y, (end.x-start.x),(end.y-start.y));
System.out.println("Start : "+start.x+","+start.y);
System.out.println("End : "+end.x+","+end.y);
}
if(selected=="line")
g2.drawLine(start.x,start.y,end.x,end.y);
}
//Draw on Buffered image
public void draw()
{
Graphics2D g2 = image.createGraphics();
g2.setPaint(color);
System.out.println("draw");
if(selected=="line")
g2.drawLine(start.x, start.y, end.x, end.y);
if(selected=="elipse")
{
g2.drawOval(start.x, start.y, (end.x-start.x),(end.y-start.y));
System.out.println("Start : "+start.x+","+start.y);
System.out.println("End : "+end.x+","+end.y);
}
repaint();
g2.dispose();
}
public JPanel addButtons()
{
JPanel buttonpanel=new JPanel();
buttonpanel.setBackground(color.lightGray);
buttonpanel.setLayout(new BoxLayout(buttonpanel,BoxLayout.Y_AXIS));
elipse.addActionListener(this);
rectangle.addActionListener(this);
line.addActionListener(this);
buttonpanel.add(elipse);
buttonpanel.add(Box.createRigidArea(new Dimension(15,15)));
buttonpanel.add(rectangle);
buttonpanel.add(Box.createRigidArea(new Dimension(15,15)));
buttonpanel.add(line);
return buttonpanel;
}
public static void main(String args[])
{
test_bmp application=new test_bmp();
//Main window
JFrame frame=new JFrame("Whiteboard");
frame.setLayout(new BorderLayout());
frame.add(application.addButtons(),BorderLayout.WEST);
frame.add(application);
//size of the window
frame.setSize(600,400);
frame.setLocation(0,0);
frame.setVisible(true);
int w = frame.getWidth();
int h = frame.getHeight();
image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = image.createGraphics();
g2.setPaint(Color.white);
g2.fillRect(0,0,w,h);
g2.dispose();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
#Override
public void mouseClicked(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent event)
{
start = event.getPoint();
}
#Override
public void mouseReleased(MouseEvent event)
{
end = event.getPoint();
draw();
}
#Override
public void mouseDragged(MouseEvent e)
{
end=e.getPoint();
repaint();
}
#Override
public void mouseMoved(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==elipse)
selected="elipse";
if(e.getSource()==line)
selected="line";
draw();
}
}
I need to create a paint application. When I draw ellipse by dragging mouse from left to right it displays nothing. Why? Should I use any other function here?

Your program does draw an ellipse when you drag the mouse down and to the right. It's dragging up and/or left that does not work, because Graphics.drawOval does not work with a negative width or height.
Try adding a method like this:
private Shape createEllipse() {
Ellipse2D e = new Ellipse2D.Double();
e.setFrameFromDiagonal(start, end);
return e;
}
Then call it from draw and paintComponent like this:
if(selected=="elipse") {
g2.draw(createEllipse());
}
Also you probably do not need the call to draw() at the end of actionPerformed. If you switch between line and ellipse mode it will draw an ellipse with the same coordinates as the most recent line or vice-versa.
And one coding style issue: Using string literals for selected is confusing (although it does work.) I would define an enum instead.

Related

Java swing. Painting program. Filling gaps?

So i have been trying to learn swing and trying to make a painting program.
The problem ive been having is that if you move your mouse to fast it doesnt fill the gaps (Run code if you dont undetstand)
Im thinking it might be where its filling up the arraylist.
So i was woundering how i can fix this, Thanks!
My code:
import javax.swing.*;
import java.util.ArrayList;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseAdapter;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class Window extends JPanel implements MouseListener{
//new array list
private ArrayList<Point> dots;
static JFrame frame;
Font f;
static int Dx1=0, Dx2=0, Dy1=0, Dy2=0; //fill void dots
static int v=0;
static int posX = 250;
static int posY = 250;
static double winX=0;
static double winY=0;
public Window() {
dots = new ArrayList<Point>();
frame = new JFrame();
f = new Font("Calibri", Font.BOLD, 30);
this.setBackground(Color.white);
frame.add(this);
frame.setResizable(true);
frame.setVisible(true);
frame.setSize(500, 500);
frame.setTitle("Minigameshuehu");
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
// MOVE BALL DEPENDING ON "Dragging"
this.addMouseListener(this);
this.addMouseListener(new MouseAdapter() {
});
this.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
dots.add(new Point(e.getX(), e.getY())); // adding pos to to array to make dots
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
posX = e.getX() - 3;
posY = e.getY() - 3;
repaint();
}
}
);
//End of moving ball
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(new Color(0,0,0));
g2.fillOval(posX, posY, 6, 6);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.black);
for (Point point : dots) {
g2.fillOval(point.x-3, point.y-3, 6, 6);
}
}
public static void main(String[] args) throws InterruptedException {
Window applikation = new Window();
}
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
// posX=(e.getX()-25);
// posY=(e.getY()-25);
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent arg0) {
v=0;
// TODO Auto-generated method stub
}
}
if you move your mouse to fast it doesnt fill the gaps
That is correct, a MouseEvent is not generated for every pixel, so you can't just draw an oval for every point generated.
Instead, you need to draw a line between two points in your ArrayList.
for (int i = 0; i < dots.size() - 1; i++)
{
Point p1 = dots.get(i);
Point p2 = dots.get(i + 1);
g2.drawLine(...);
}
You will also want to change the size of the line drawn by using something like:
g2.setStroke(new BasicStroke(15, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
This will draw a line with a rounded edge so it looks like the end of an oval.

Parent Panel not repainting correctly

I have a panel which contains custom components that have been added to it. It paints correctly except when the components (which have their own mouselisteners) are being dragged it starts to paint weirdly.
Interestingly if I slightly re-size the parent panel it will now paint as intended. I know that the parent panel is being repainted through
super.paintComponent(g);
and a print statement inside the panels
paintComponent(Graphics g):
method. I tried revalidating when the component is dragged around (as the component is having its bounds re-set) it becomes invalidated. Still I am having no success and was wondering if anyone could help.
Is there some place where i am not repainting correctly that might be causing this behavior?
Also as an addendum I have a mouse listener on both the panel and its components, is there a way so that when a component is clicked the panel mouse listener also responds (beyond going back up to the parent class from the component)
Here is a working example of the issue I am having
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Line2D;
import javax.swing.*;
public class testHome {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
testHome window = new testHome();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public testHome() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new myPanel();
frame.getContentPane().add(panel, BorderLayout.CENTER);
}
}
class myPanel extends JPanel {
MyComponent comp;
public myPanel() {
super(null);
comp = new MyComponent(5, 5);
this.add(comp);
revalidate();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
Line2D.Double line = new Line2D.Double(10, 10, comp.getX(), comp.getY());
System.out.println(comp.getX() + " " + comp.getY());
g2d.draw(line);
}
}
class MyComponent extends JComponent implements MouseListener, MouseMotionListener {
int x;
int y;
int mx;
int my;
public MyComponent(int x, int y) {
this.setVisible(true);
this.setBounds(x, y, 15, 15);
this.x = x;
this.y = y;
addMouseMotionListener(this);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.black);
g2d.fillRect(this.x, this.y, 15, 15);
}
#Override
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
System.out.println("dragging");
int dx = e.getX() - mx;
int dy = e.getY() - my;
this.setBounds(this.getX() + dx, this.getY() + dy, 15, 15);
}
#Override
public void mousePressed(MouseEvent e) {
mx = e.getX();
my = e.getY();
}
#Override
public void mouseMoved(MouseEvent e) {}
#Override
public void mouseClicked(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {}
}
The parent panel does not actually get automatically repainted completely. paintComponent() is called, but if you check the clipping, for example by:
System.out.println(g.getClipBounds());
you'll see that only the area below the smaller component is painted. (The component is not opaque, so the parent component needs to paint the area below it). You need to call repaint() explicitly for the parent panel:
getParent().repaint();
(Or using the repaint() variants that specify the region, if the parent component is expensive to draw and can optimize partial draws).

Saving a JPanel as an Image (object) and drawing it back onto a JPanel

I've had a look around and tried using other queries, but I just can't seem to get this to work.
I am trying to retain an image from a JPanel drawn via the g.draw/fill methods.
I've attempted to save the drawing in a buffered image, but when I display it in a messageDialog all I get is the background and none of the drawings
These two methods are the important code (from the DrawingPanel class):
public void loadDrawing(BufferedImage bi) {
//opens a message dialog and displays the image parameter
JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
System.out.println("w:" + bi.getWidth() + " h:" + bi.getHeight());
}
public BufferedImage getScreenShot() {
BufferedImage image = new BufferedImage(this.getWidth(),
this.getHeight(), BufferedImage.TYPE_INT_RGB);
// call the Panels's paint method, using
// the Graphics object of the image.
this.paint(image.getGraphics());
return image;
}
They get called here:
#Override
public void actionPerformed(ActionEvent ae) {
BufferedImage bi = dp.getScreenShot();
dp.loadDrawing(bi);
}
Here is the whole program, it should run.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class TestClass extends JFrame implements ActionListener {
DrawingPanel dp;
public TestClass() {
setSize(400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel top = new JPanel();
JButton load = new JButton("Load Image");
load.addActionListener(this);
top.add(load);
dp = new DrawingPanel();
dp.setBackground(Color.CYAN);
add(top, BorderLayout.NORTH);
add(dp, BorderLayout.CENTER);
setVisible(true);
}
public static void main(String[] args) {
new TestClass();
}
#Override
public void actionPerformed(ActionEvent ae) {
BufferedImage bi = dp.getScreenShot();
dp.loadDrawing(bi);
}
private class DrawingPanel extends JPanel implements
MouseListener, MouseMotionListener {
private int xPos, yPos;//mouse positions
private DrawingPanel() {
addMouseListener(this);
addMouseMotionListener(this);
}
#Override
public void mousePressed(MouseEvent me) {
xPos = me.getX();
yPos = me.getY();
}
#Override
public void mouseDragged(MouseEvent me) {
int x = me.getX(), y = me.getY();
Graphics g = getGraphics();
g.setColor(Color.BLACK);
g.drawOval(xPos, yPos, 30, 30);
xPos = x;
yPos = y;
}
public void loadDrawing(BufferedImage bi) {
//opens a message dialog and displays the image parameter
JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
System.out.println("w:" + bi.getWidth() + " h:" + bi.getHeight());
}
public BufferedImage getScreenShot() {
BufferedImage image = new BufferedImage(this.getWidth(),
this.getHeight(), BufferedImage.TYPE_INT_RGB);
// call the Panels's paint method, using
// the Graphics object of the image.
this.paint(image.getGraphics());
return image;
}
//unused abstract method
#Override
public void mouseClicked(MouseEvent me) {
}
#Override
public void mouseReleased(MouseEvent me) {
}
#Override
public void mouseEntered(MouseEvent me) {
}
#Override
public void mouseExited(MouseEvent me) {
}
#Override
public void mouseMoved(MouseEvent me) {
}
}
}
I need to be able to store the graphics from the panel and retrieve it.
Help would be heavily appreciated.
Every attempt to draw something into the Graphics object that was obtained from a Component by calling getGraphics will fail sooner or later. This Graphics object merely serves as a "path" to the actual screen (that is only valid while the component is actually painted on the screen). It is not a "buffer", and it does not "store" anything that was drawn.
If you want to create a simple painting program, you should draw to a BufferedImage. And when the DrawingPanel is to be painted, you only paint this BufferedImage. The additional advantage here is that when you want to make a screenshot, you basically just have to return a copy of this BufferedImage.
I sketeched the basic approach in your DrawingPanel class, with some in-lined comments. It could be cleaned up and beautified, and there are some aspects to consider (e.g. what should happen when the DrawingPanel is resized?), but it shows how it should work in general:
private class DrawingPanel extends JPanel implements
MouseListener, MouseMotionListener {
// The image that will store what was drawn. In the
// mouseDragged method, the painting operations will
// go directly to this image. When this panel is
// painted, then ONLY this image will be painted.
private BufferedImage bufferedImage;
private int xPos, yPos;//mouse positions
private DrawingPanel() {
addMouseListener(this);
addMouseMotionListener(this);
}
// Make sure that the "bufferedImage" is non-null
// and has the same size as this panel
private void validateImage()
{
if (bufferedImage == null)
{
bufferedImage = new BufferedImage(
getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics g = bufferedImage.getGraphics();
g.setColor(getBackground());
g.fillRect(0,0,getWidth(),getHeight());
g.dispose();
}
if (bufferedImage.getWidth() != getWidth() ||
bufferedImage.getHeight() != getHeight())
{
BufferedImage newBufferedImage = new BufferedImage(
getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics g = newBufferedImage.getGraphics();
g.setColor(getBackground());
g.fillRect(0,0,getWidth(),getHeight());
g.drawImage(bufferedImage, 0,0,null);
g.dispose();
bufferedImage = newBufferedImage;
}
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
validateImage();
// Paint the bufferedImage which stores
// what was drawn until now
g.drawImage(bufferedImage, 0, 0, null);
}
#Override
public void mousePressed(MouseEvent me) {
xPos = me.getX();
yPos = me.getY();
}
#Override
public void mouseDragged(MouseEvent me) {
int x = me.getX(), y = me.getY();
validateImage();
// Paint directly into the bufferedImage here
Graphics g = bufferedImage.getGraphics();
g.setColor(Color.BLACK);
g.drawOval(xPos, yPos, 30, 30);
repaint();
xPos = x;
yPos = y;
}
public void loadDrawing(BufferedImage bi) {
//opens a message dialog and displays the image parameter
JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
System.out.println("w:" + bi.getWidth() + " h:" + bi.getHeight());
}
public BufferedImage getScreenShot() {
// This basically returns a "copy" of the
// bufferedImage that stores what was drawn
BufferedImage image = new BufferedImage(
getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.drawImage(bufferedImage, 0, 0, null);
g.dispose();
return image;
}
//unused abstract method
#Override
public void mouseClicked(MouseEvent me) {
}
#Override
public void mouseReleased(MouseEvent me) {
}
#Override
public void mouseEntered(MouseEvent me) {
}
#Override
public void mouseExited(MouseEvent me) {
}
#Override
public void mouseMoved(MouseEvent me) {
}
}
Your getting your Graphics object by calling getGraphics() on a component, and images drawn with this will not persist. Why not instead draw to a BufferedImage with its Graphics object, and then simply save that BufferedImage. This would simplify things greatly, and your program would work.
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class TestClass2 extends JPanel {
private DrawingPanel drawingPanel = new DrawingPanel();
public TestClass2() {
JPanel northPanel = new JPanel();
northPanel.add(new JButton(new GetImageAction("Get Image")));
northPanel.add(new JButton(new ClearImageAction("Clear Image")));
setLayout(new BorderLayout(5, 5));
add(drawingPanel, BorderLayout.CENTER);
add(northPanel, BorderLayout.NORTH);
}
private class GetImageAction extends AbstractAction {
public GetImageAction(String name) {
super(name);
putValue(MNEMONIC_KEY, KeyEvent.VK_G);
}
#Override
public void actionPerformed(ActionEvent evt) {
BufferedImage img = drawingPanel.getMainImage();
ImageIcon icon = new ImageIcon(img);
JOptionPane.showMessageDialog(TestClass2.this, icon);
}
}
private class ClearImageAction extends AbstractAction {
public ClearImageAction(String name) {
super(name);
putValue(MNEMONIC_KEY, KeyEvent.VK_C);
}
#Override
public void actionPerformed(ActionEvent evt) {
drawingPanel.clearImage();
drawingPanel.repaint();
}
}
private static void createAndShowGui() {
TestClass2 mainPanel = new TestClass2();
JFrame frame = new JFrame("TestClass2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class DrawingPanel extends JPanel {
public static final int BI_WIDTH = 400;
public static final int BI_HEIGHT = BI_WIDTH;
private static final Color BACKGROUND = Color.CYAN;
public static final Color DRAW_COLOR = Color.black;
public static final int OVAL_WIDTH = 30;
private BufferedImage mainImage;
public DrawingPanel() {
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
clearImage();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (mainImage != null) {
g.drawImage(mainImage, 0, 0, this);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(BI_WIDTH, BI_HEIGHT);
}
public BufferedImage getMainImage() {
return mainImage;
}
public void clearImage() {
mainImage = new BufferedImage(BI_WIDTH, BI_HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics g = mainImage.getGraphics();
g.setColor(BACKGROUND);
g.fillRect(0, 0, BI_WIDTH, BI_HEIGHT);
g.dispose();
}
private class MyMouseAdapter extends MouseAdapter {
#Override
public void mousePressed(MouseEvent mEvt) {
draw(mEvt);
}
#Override
public void mouseDragged(MouseEvent mEvt) {
draw(mEvt);
}
private void draw(MouseEvent mEvt) {
Graphics2D g2 = mainImage.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(DRAW_COLOR);
g2.drawOval(mEvt.getX() - OVAL_WIDTH / 2, mEvt.getY() - OVAL_WIDTH / 2, OVAL_WIDTH, OVAL_WIDTH);
g2.dispose();
repaint();
}
}
}

Java moving a circle in a gui with arrow keys

I am trying to move a circle left with a keyEvent. So far, the circle is drawn on the window but it does not move left! I feel like the problem is where I add the Window() constructor to the container. The is no output on the console to tell me that it is working. So I dont think it even reaches the KeyEvent class. Here is my code:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import javax.swing.*;
public class Window extends JPanel {
private static Ellipse2D.Double circle;
public Window() {
super();
int width = 400;
int height = 400;
circle = new Ellipse2D.Double(0.5 * width, 0.9 * height,
0.1 * width, 0.05 * height);
addKeyListener(new MoveCircle());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponents(g);
Graphics2D brush = (Graphics2D) g;
int width = getWidth();
int height = getHeight();
g.clearRect(0, 0, width, height);
brush.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
brush.draw(circle);
}
public class MoveCircle implements KeyListener {
#Override
public void keyPressed(KeyEvent e) {
System.out.println("Working on top!");
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
System.out.println("Working on bottom!");
circle.x++;
repaint();
}
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
}
public static void main(String[] args) {
Window window = new Window();
JFrame frame = new JFrame();
Container container = frame.getContentPane();
container.add(new Window());
frame.addKeyEvent(window.new MoveCircle());
frame.setSize(800, 700);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
}
}
Actually what is happening is this, you are adding Window to the JFrame, but the focus lies with the JFrame, so when you type on your Keyboard that thing goes to the JFrame not the KeyListener attached to the Window class. So in order to get over it, you simply have to call requestFocusInWindow() on the Window class's Object. Try this code, I had done some modification regarding EDT and stuff.
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import javax.swing.*;
public class Window extends JPanel {
private static Ellipse2D.Double circle;
private JFrame frame;
public Window() {
super();
int width = 400;
int height = 400;
circle = new Ellipse2D.Double(0.5 * width, 0.9 * height,
0.1 * width, 0.05 * height);
}
public Dimension getPreferredSize()
{
return (new Dimension(frame.getWidth(), frame.getHeight()));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponents(g);
Graphics2D brush = (Graphics2D) g;
int width = getWidth();
int height = getHeight();
g.clearRect(0, 0, width, height);
brush.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
brush.draw(circle);
}
public class MoveCircle implements KeyListener {
#Override
public void keyPressed(KeyEvent e) {
System.out.println("Working on top!");
if (e.getKeyCode() == Event.ENTER) {
System.out.println("Working on bottom!");
double newX = circle.x - 1;
circle.x = newX;
repaint();
}
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
}
private void createAndDisplayGUI(Window window)
{
frame = new JFrame();
Container container = frame.getContentPane();
container.add(window);
window.addKeyListener(new MoveCircle());
frame.setSize(800, 700);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
window.requestFocusInWindow();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
Window window = new Window();
window.createAndDisplayGUI(window);
}
});
}
}
Only the focussed component will get key events. You need to call requestFocus() at some point.
A solution would be, to add the KeyListener to the JFrame. This way all the key strokes will throw an event, when the JFrame has the focus.

problem displaying mouse coordinates on the screen in java

I'm trying to display mouse coordinates (math coordinates) in my JPanel , but i get each coordinates on top of the other ,can' figure out why .
here's my code :
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.applet.*;
import javax.swing.JPanel;
import javax.swing.event.MouseInputAdapter;
public class drawarea extends JPanel {
int n;
private Point mouseCoords = null;
int UNIT = 20;
drawarea() {
super();
setBackground(Color.white);
addMouseMotionListener(new MouseInputAdapter() {
public void mouseMoved(MouseEvent e) {
super.mouseMoved(e);
mouseCoords = new Point(e.getX(), e.getY());
repaint();
}
/**
* #see java.awt.event.MouseListener#mouseExited(MouseEvent)
*/
public void mouseExited(MouseEvent e) {
super.mouseExited(e);
mouseCoords = null;
repaint();
}
});
setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
}
public void paint(Graphics g) {
//draw axis x and y
g.setColor(Color.red);
g.drawLine(0, r.height / 2, r.width, r.height / 2);
g.drawLine(r.width / 2, 0, r.width / 2, r.height);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
dessinBoule(g2);
}
private void dessinBoule(Graphics2D g) {
// if mouse isnt inside the ara where
// i want the coordinates to bes displayed
if (mouseCoords == null) {
return;
}
g.setColor(Color.BLACK);
int decPolice = 15;
g.drawString("x = " + getFormatedString("" + mouseCoords.x)
+ " , y = " + getFormatedString("" + mouseCoords.y), 2, 15);
}
private String getFormatedString(String s) {
if (s.length() > 4) {
return s.substring(0, 3);
}
return s;
}
}
thanks.
You're drawing on your graphics area, so g.drawString(...) draws a string on top of what is already there. You must either erase what is there first, by drawing a rectangle in the background colour, or use a separate component that you can manage with a separate paint(...) method.
An example of #richj's suggestion is shown below. Note that in Swing you should override paintComponent(). Also, the implementation of MouseInputAdapter is empty, so you don't need to invoke super().
import java.awt.*;
import java.awt.event.MouseEvent;
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
public class DrawArea extends JPanel {
private Point mouseCoords = new Point();
DrawArea() {
super();
this.setPreferredSize(new Dimension(320, 240));
setBackground(Color.white);
addMouseMotionListener(new MouseInputAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
mouseCoords = e.getPoint();
repaint();
}
#Override
public void mouseExited(MouseEvent e) {
mouseCoords = null;
repaint();
}
});
setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
}
#Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.clearRect(0, 0, getWidth(), getHeight());
g2.setColor(Color.red);
if (!(mouseCoords == null)) {
g2.drawString(mouseCoords.toString(), 10, getHeight() - 10);
}
}
private static void create() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new DrawArea());
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
create();
}
});
}
}

Categories