I am trying to implement a graphics modelling tool.
On a mouse click a red vertex is generated. When mouse is dragged from one vertex to another, a line should be drawn. This is what I would like to achieve. But my code does not effectively do it. Following is my code and problem
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
public class NewClass extends JPanel {
Point source,dest;
BufferedImage image;
Graphics2D imageGraphics;
NewClass(){
image= new BufferedImage(400,400, BufferedImage.TYPE_INT_ARGB);
imageGraphics=image.createGraphics();
this.addMouseListener(new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent e){
if(e.getButton() == MouseEvent.BUTTON1){
Point p=e.getPoint();
paintPoint(p);
}
}
#Override
public void mousePressed(MouseEvent e){
if(e.getButton() == MouseEvent.BUTTON1){
source=e.getPoint();
}
}
#Override
public void mouseReleased(MouseEvent e){
if(e.getButton() == MouseEvent.BUTTON1){
dest=e.getPoint();
paintLine();
}
}
});
}
public void paintPoint(Point r){
imageGraphics.setColor(Color.red);
imageGraphics.fillOval(r.x,r.y,5,5);
repaint();
}
public void paintLine(){
imageGraphics.setColor(Color.black);
imageGraphics.drawLine(source.x,source.y,dest.x,dest.y);
repaint();
}
}
However the problem I am facing is, when a mouseClickedEvent is generated, it generates pressed and released as well. Especially when more than three vertices are used, wrong lines are generated.
I want the line to be drawn only when pressed on a vertex, moved to the next vertex and then released there.
How can this problem be solved?
In the mouseReleased check the location of the release, if it is the same as your source you have a click not a drag. You can also get rid of the mouseClicked completely using this method
You can simply override mouseDragged(MouseEvent e), it's made for your usage.
Related
I am making a launcher application, i wish to change the button depending on the action taken, right now i want to change the button when the following actions happen, either the player hovers over the image, clicks on the image, releases the image click or exits the hover. The issue i have is that it doesn't always load correctly, which is odd.
package LostStory;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.SystemTray;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
#SuppressWarnings("serial")
public class LaunchPanel extends JComponent {
Image image;
JButton play;
SystemTray tray;
ImageIcon icon = new ImageIcon("res/images/buttons/playNonHover.png");
ImageIcon iconHover = new ImageIcon("res/images/buttons/playHover.png");
ImageIcon iconClick = new ImageIcon("res/images/buttons/playClick.png");
public LaunchPanel(Image img) {
this.image = img;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
init();
}
public void init() {
play = new JButton("Play Lost Story", icon);
play.setBounds(85, 210 - 75, getWidth() - 165, 50);
play.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
Runtime run = Runtime.getRuntime();
try {
run.exec("notepad");
if (SystemTray.isSupported()) {
tray = SystemTray.getSystemTray();
play.setIcon(play.getIcon());
// Main.getClient().getJFrame().setVisible(false);
// tray.add(img);
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
play.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent arg0) {
} // no use
#Override
public void mouseEntered(MouseEvent e) {
if (iconHover.getImageLoadStatus() == 8) {
play.setIcon(iconHover);
play.setIcon(play.getIcon());
System.out.println("Entered");
}
System.out.println(iconHover.getImageLoadStatus());
} // use
#Override
public void mouseExited(MouseEvent arg0) {
if (icon.getImageLoadStatus() == 8) {
play.setIcon(icon);
play.setIcon(play.getIcon());
System.out.println("Exited");
}
System.out.println(icon.getImageLoadStatus());
} // use
#Override
public void mousePressed(MouseEvent arg0) {
if (iconClick.getImageLoadStatus() == 8) {
play.setIcon(iconClick);
play.setIcon(play.getIcon());
System.out.println("Pressed");
}
System.out.println(iconClick.getImageLoadStatus());
} // use
#Override
public void mouseReleased(MouseEvent arg0) {
if (icon.getImageLoadStatus() == 8) {
play.setIcon(icon);
play.setIcon(play.getIcon());
System.out.println("Released");
}
System.out.println(icon.getImageLoadStatus());
} // use
});
add(play);
}
}
The first button always loads (because it is the default one) it returned an '8' when i tried using the IconImage.getImageLoadStatus() so i expected that to be '8' if it was succesfully loaded. (This is not the case though, it will always return 8 as far as i know).
So TL;DR: How do i make sure the ImageIcons are always loaded and will apply correctly?
Don't try to manipulate the icon using the setIcon() method.
A JButton has methods to set the icon for various states setRolloverIcon, setPressedIcon, etc.
Read the API for other properties.
Also, a painting method is for painting only. Never create components from a painting method. Get rid of the init() method from your paintComponent() method.
Components should be created and added to the panel in the constructor of the panel.
I want to make a simple painting program. So,when you drag your mouse a line will draw in a GUI. The problem is when the user drags the mouse, it will paint automatically, but my code doesn't work. Can someone please tell me how do this? Sorry for my English and if you don't understand my question, look at my code maybe you will than.
My main class:
import javax.swing.JFrame;
public class MainClass {
public static void main(String args[]){
tuna kip = new tuna();
kip.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
kip.setSize(800,600);
kip.setVisible(true);
}
}
This is my other class:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class tuna extends JFrame {
JPanel jpanel = new JPanel();
public tuna(){
super("Painting Program");
jpanel.setBackground(Color.WHITE);
add(jpanel);
hand handler = new hand();
jpanel.addMouseListener(handler);
jpanel.addMouseMotionListener(handler);
}
private class hand implements MouseListener ,MouseMotionListener { //THE ERRORS START TO APPEAR HERE
public void mouseDragged(MouseEvent event){
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(event.getX(), event.getY(), 5, 5);
}
}
}
}
When I try to run the code I get too much error messages:
You mean when you try to compile the code you get compile errors.
class hand implements MouseListener ,MouseMotionListener
Your class does not implement all the methods in those listeners. You only implement one method.
Read the section from the Swing tutorial on How to Write a MouseMotionListener for a working example.
If you only care about the mouseDragged() method then you only need to implement the MouseMotionListener.
Or as a simpler solution you can extend MouseMotionAdapter. This class implements all the methods of the MouseMotionListener so you only need to override the methods you want to change. The tutorial also discusses adapters.
Finally class names SHOULD start with an upper case character. Look at the Java API and you will notice this. Follow the Java conventions and don't make up your own.
Yes, there are so many issues in your codes. I just edited it and make it runnable at least. Just study and experiment on it. I hope you will learn something out of this even if I don't explain all of the changes.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class tuna extends JFrame {
int x, y, w, h;
MyPanel jpanel = new MyPanel();
public tuna(){
super("Painting Program");
setLayout(new BorderLayout());
jpanel.setBackground(Color.WHITE);
add(jpanel);
hand handler = new hand();
jpanel.addMouseListener(handler);
jpanel.addMouseMotionListener(handler);
}
private class hand implements MouseListener , MouseMotionListener { //THE ERRORS START TO APPEAR HERE
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
x=e.getX();
y=e.getY();
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseDragged(MouseEvent e) {
w = e.getX() - x;
h = e.getY() - y;
jpanel.repaint();
}
public void mouseMoved(MouseEvent e) {
}
}
class MyPanel extends JPanel {
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(x, y, w, h);
}
}
}
I am trying to create a program that allows the user to drag and draw lines and also delete the lines after it have been drawn. Is there any ways i can do it? I have the code that draws the line but i am not sure how i could delete the lines after i have drawn it. Im looking to click any of the lines drawn and delete it with the delete button.
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Drawing {
public Drawing() {
JFrame jf=new JFrame("Free Hand Drawing Example");
Board draw=new Board();
jf.add(draw);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setSize(600,500);
jf.setVisible(true);
}
public static void main(String a[]){
new Drawing();
}
}
class Board extends JPanel implements MouseListener,MouseMotionListener {
ArrayList<pts> list = new ArrayList<pts>();
Point start,end;
public Board() {
start=null; /*Initializing*/
end=null;
//this.setBackground(Color.BLACK);
this.addMouseListener(this);
this.addMouseMotionListener(this);
}
#Override
public void paint(Graphics g)
{ Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
super.paint(g2);
//g.setColor(Color.BLACK);
for (pts p : list)
g.drawLine((int)p.getStart().getX(), (int)p.getStart().getY(), (int)p.getEnd().getX(), (int)p.getEnd().getY());
if(start!=null)
{
g.drawLine(start.x,start.y,end.x,end.y);
}
}
#Override
public void mouseClicked(MouseEvent arg0) {}
#Override
public void mouseEntered(MouseEvent arg0) {}
#Override
public void mouseExited(MouseEvent arg0) {}
#Override
public void mousePressed(MouseEvent me) {
start = me.getPoint();
}
#Override
public void mouseReleased(MouseEvent me) {
end = me.getPoint();
pts pt = new pts(start,end);
list.add(pt);
repaint();
for(pts p : list)
{
System.out.println(p.getStart()+""+p.getEnd());
}
start = null;
end = null;
}
#Override
public void mouseDragged(MouseEvent me) {
end = me.getPoint();
repaint();
}
#Override
public void mouseMoved(MouseEvent arg0) {}
}
class pts{
Point start = null;
Point end = null;
public pts(Point start, Point end){
this.start = start;
this.end = end;
}
public Point getStart(){
return this.start;
}
public Point getEnd(){
return this.end;
}
}
There is more than one way to go about this, but one simple approach would be to add a 'delete' button with an ActionListener that clears out the list of points you have when the button is pressed. You could also associate the clearing action with something like a MouseDragged event, but that doesn't seem very user friendly.
UPDATE:
So, to delete the line when the user clicks on it, you could use a simple function like this one:
public boolean intersects(Point linePoint1,
Point linePoint2,
Point usersClickPoint) {
return new Line2D.Float(linePoint1, linePoint2).
ptLineDist(usersClickPoint) <= 0.01;//some margin of error
}
in your MousePressed method.
Side Note: The way you've chosen to interpret the mouse events is a bit strange. You record the first point on MousePressed, and the second one on MouseReleased. Why not use MouseClicked and simply keep track of the first and second clicks when drawing the line?
One approach would be to create a Line object for each line your user draws and have the object store the locations on the screen where the line is drawn. Then when in delete mode, have an onClickListener that will select a line based upon the coordinates of the click matching up to a point contained in a line. Then just delete the line (probably could redraw using the same endpoints but with the pen set to the background color). There would need to be some logic for the possible case where lines intersect and you don't want to delete a portion of the other line, but that could be solved fairly easily. Keep in mind, I'm not a big graphics programmer. This is just my idea.
i have to check if i pressed left, right or both buttons on my mouse, here is a sample code:
package sandbox;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Sandbox extends JFrame {
public static void main(String[] args) {
Sandbox s = new Sandbox();
s.setVisible(true);
}
public Sandbox() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(300, 200);
setResizable(false);
setTitle("Frame");
setLayout(null);
JButton but = new JButton("click me");
but.setBounds(0, 0, 120, 50);
but.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
if(SwingUtilities.isLeftMouseButton(e) | SwingUtilities.isRightMouseButton(e))
System.out.println("both");
else if(SwingUtilities.isLeftMouseButton(e))
System.out.println("left");
else if(SwingUtilities.isRightMouseButton(e))
System.out.println("right");
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
});
add(but);
}
}
i have to make it using SwingUtilities, but there is a problem if i press left or right single button it will print "both", not "left" or "right", if i used MouseEvent class it was working properly but i need it with SwingUtilities class if it's possible, thanks.
EDIT: using MouseEvent class it's working right:
if(e.getModifiersEx() == (MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON3_DOWN_MASK))
...
Don't check using OR (|) but use AND (& or better the short cut version &&) instead:
if(SwingUtilities.isLeftMouseButton(e) && SwingUtilities.isRightMouseButton(e))
...
Update:
For checking if both buttons are pressed, SwingUtilities doesn't seem to be the right tool. The isXxxxMouseButton(...) methods do the same as you do, they check the button masks, but use different masks which seem not be set when both buttons are pressed.
As an example, isRightMouseButton() is implemented as follows:
public static boolean isRightMouseButton(MouseEvent anEvent) {
return ((anEvent.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK);
}
As you can see, the implementation isn't that complext, so you might be better off to just do the mask check yourself.
mouse listene event on button
but.addMouseListener(new MouseListener() {
mouse listener event on fame.
this.addMouseListener(new MouseListener() {
Please check with '||' not '|', don't use the && because it is not possible to press both buttons at the same time
if(SwingUtilities.isLeftMouseButton(e) || SwingUtilities.isRightMouseButton(e))
You will get result
both
left
both
left
both
right
My ultimate goal is to be able to make use of additional mouse buttons in Java. Currently, LWJGL's JInput doesn't seem capable of detecting more than three buttons. To make use of Java's System.setProperty("sun.awt.enableExtraMouseButtons", "true"), I've tried mounting the Display onto an AWT Canvas, within a JFrame. Unfortunately, this does not appear to work, and I am unsure why. [I should note that I've been away from Java for a some time]
import java.awt.Canvas;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
public class MainCanvas extends Canvas implements MouseListener
{
private static final long serialVersionUID = 1L;
public void mouseClicked(MouseEvent e)
{
System.out.println(e.getButton());
}
public void mouseEntered(MouseEvent e)
{
System.out.println(e.getButton());
}
public void mouseExited(MouseEvent e)
{
System.out.println(e.getButton());
}
public void mousePressed(MouseEvent e)
{
System.out.println(e.getButton());
}
public void mouseReleased(MouseEvent e)
{
System.out.println(e.getButton());
}
public void init()
{
}
public static void main(String[] args)
{
MainCanvas mainCanvas = new MainCanvas();
JFrame mainFrame = new JFrame("Simplify");
mainFrame.setSize(640, 480);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.getContentPane().add(mainCanvas);
mainFrame.setVisible(true);
mainCanvas.addMouseListener(mainCanvas);
try
{
DisplayMode mainDisplay = new DisplayMode(640, 480);
Display.setDisplayMode(mainDisplay);
Display.setParent(mainCanvas);
Display.create();
}
catch (LWJGLException le)
{
System.out.println("Oh dear.");
}
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, 640, 480, 0, 1, -1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
while (!Display.isCloseRequested())
{
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glColor3f(0.5f,0.5f,1.0f);
GL11.glBegin(GL11.GL_QUADS);
GL11.glVertex2f(100,100);
GL11.glVertex2f(100+200,100);
GL11.glVertex2f(100+200,100+200);
GL11.glVertex2f(100,100+200);
GL11.glEnd();
Display.update();
}
Display.destroy();
}
}
I spoke with the fellows in the FreeNode IRC some months back. The gist is because the canvas is a heavyweight component, events would not rise to the JFrame level. A Frame has to be used in its stead.
Basically, the answer is you can't: i.e with lwjgl 2.8.2 on Windows only.
The reason is that the Windows implementation of lwjgl clobbers a key data structure that AWT requires for event handling.
http://www.java-gaming.org/topics/cannot-add-mouselistener-to-java-awt-canvas-with-lwjgl-on-windows/24650/msg/208505/view.html#msg208505
Try adding the mouse listener to the JFRame instead. I ran into this before, and I think that's how I solved it.