I'm struck in a what it seems to be a minor problem. I tried to add MouseListener to Line2D object but it's not working. Is the method or tried is invalid or I can do it another way. Help me figure out what I'm doing wrong here.
public class DrawingLines {
public static void main(String[] args){
LineFrame lf = new LineFrame();
lf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
lf.setVisible(true);
}
}
class LineFrame extends JFrame{
public LineFrame(){
setTitle("Line test");
setSize(500, 500);
LinesPanel lp = new LinesPanel();
Container contentpane = getContentPane();
contentpane.add(lp);
}
}
class LinesPanel extends JPanel{
public LinesPanel(){
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
Line2D line = new Line2D.Double(105.5, 306.6, 350.8, 4.9);
g2.draw(line);
line.addMouseListener(new MouseListener(){
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Line Clicked !");
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
});
}
}
Add the MouseListener to the LinesPanel. And use the MouseEvent coordinates to check whether the click is close to the line.
See How to select a line
The Line component doesn't have a clickable area so a mouselistener won't work properly, what you might want to do is add an invisible square/rectangle/polygon over it to handle the mouse instead.
Related
I have been trying to accomplish how to move the jframe when I drag it using the mouse. But I couldn't find a solution to it.
I have tried to implement listeners on the Jframe but it doesn't work the way I have intended it to.
JFrame jframe = new JFrame();
jframe.setSize(500,500);
jframe.setLocation(400, 100);
jframe.setVisible(true);
jframe.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
});
You could use MouseMotionListener. Get the position of the mouse when you move the mouse using mouseMoved event method and use it with the drag event to position the frame accordingly. :
jframe.addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseDragged(MouseEvent e) {
xDrag = e.getX();
yDrag = e.getY();
JFrame sFrame = (JFrame) e.getSource();
sFrame.setLocation(sFrame.getLocation().x+xDrag-xPress,
sFrame.getLocation().y+yDrag-yPress);
}
#Override
public void mouseMoved(MouseEvent e) {
xPress = e.getX();
yPress = e.getY();
}
});
Declare the variables xDrag, yDrag, xPress, yPress in your class. I hope this helps.
I am here making a menu for my game where I can press 'Start' button to navigate through the screens. I am trying to implement a seperate button for the class however the way I have laid out the CustomButtons class, it works in a way where I can only make one button which has a function, in order to tackle this issue I decided to make a separate 'Buttons' method which contains the parameters for the button. I have called this within the paint component to ensure that it is being displayed to the screen however only the text 'START' is being displayed to the screen. The background color of the button, the borders, the font etc. isn't being changed alongside the call.
public class CustomButton extends JButton implements MouseListener {
Dimension size = new Dimension(100, 50);
boolean hover = false;
boolean click = false;
boolean isMethodCalled = false;
String text = "";
public CustomButton(String text, Button bb) {
setVisible(true);
setFocusable(true);
setContentAreaFilled(false);
setBorderPainted(false);
this.text = text;
addMouseListener(this);
}
public void Button(Graphics g) {
g.setColor(new Color(255, 255, hover ? 180 : 102 ));
g.fillRect(0, 0, 250, 7);
g.fillRect(0, 0, 7, 150);
g.setColor(Color.ORANGE); // button background color
g.fillRect(14, 14, 222, 122);
g.setColor(Color.WHITE); // text color
g.setFont(Font.decode("arial-BOLD-24"));
FontMetrics metrics = g.getFontMetrics();
int width = metrics.stringWidth(text);
g.drawString(text, 17, 40);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Button menu = new Button();
}
public void setButtonText(String text) {
this.text = text;
}
public String getButtonText(String text) {
return text;
}
public void mouseEntered(MouseEvent e) {
hover = true;
}
public void mouseExited(MouseEvent e) {
hover = false;
}
public void mousePressed(MouseEvent e) {
click = true;
}
public void mouseReleased(MouseEvent e) {
click = false;
}
public void mouseClicked(MouseEvent e) {
}
}
Anyone have any idea how I can make it so the button once it is called from the 'Buttons' method works so it is displayed exactly as it should be if all the graphics settings were to be set within the paintComponent method?
This is not what is currently happening. I do not want this to happen:
This is what I want to happen to the button:
To have the custom appearance you need, it's better that your custom button extends JLabel. Below code demonstrates how we can write a custom button by extending JLabel.
This button supports click events. We can add ActionListeners to listen to click events. It changes the background color to brown when user hovers mouse over it.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
public class CustomButton extends JLabel implements MouseListener {
private List<ActionListener> actionListeners = new ArrayList<>();
public CustomButton(String text) {
super(text);
setOpaque(true);
setForeground(Color.white);
setBackground(Color.orange);
setFont(getFont().deriveFont(40.0f));
addMouseListener(this);
}
public void addActionListener(ActionListener listener) {
actionListeners.add(listener);
}
public void removeActionListener(ActionListener listener) {
actionListeners.remove(listener);
}
#Override
public void mouseClicked(MouseEvent e) {
for (ActionListener listener : actionListeners) {
listener.actionPerformed(new ActionEvent(this, 0, "click"));
}
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
setBackground(new Color(185, 122, 87));
}
#Override
public void mouseExited(MouseEvent e) {
setBackground(Color.orange);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setBackground(Color.darkGray);
frame.getContentPane().setLayout(new FlowLayout());
CustomButton customButton = new CustomButton("START");
customButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(frame, "Button clicked");
}
});
frame.getContentPane().add(customButton);
frame.setBounds(300, 200, 400, 300);
frame.setVisible(true);
}
}
I am only posting the relevant code. I am fairly new to java and right now I am building a program that will allow the user to use a draw method. However, when I click the button for drawing in the interface, it automatically generates a random line anywhere on the page and does not allow user interaction. I think the error is occurring in my mouseListener method, but I am not sure as this is my first time doing anything like this. Any help would be greatly appreciated. Thank you!
Also, the error that prints out is: Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
public class SimplePaint extends JFrame {
JButton drawing = new JButton();
Line2D draw = new Line2D.Float();
Point start = null;
Point end = null;
public SimplePaint() {
JPanel panel = new JPanel() {
{
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
start = e.getPoint();
}
public void mouseReleased(MouseEvent e) {
start = e.getPoint();
//start = null;
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
end = e.getPoint();
}
public void mouseDragged(MouseEvent e) {
end = e.getPoint();
repaint();
}
});
}
};
drawing.setText("Draw");
panel.add(drawing);
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == drawing) {
draw = new Line2D.Float(start.x, start.y, end.x, end.y);
}
repaint();
}
};
drawing.addActionListener(actionListener);
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
Line2D line = new Line2D.Float(0, 250, 2000, 300);
g2.draw(draw);
}
}
I have an undecorated JFrame with JPanel which is for dragging the window on the screen. It works, but when I want to drag it completely to the top of the screen it can't go there. There is space between window and top bar. I'm enclosing the screenshot and code. I'm using Ubuntu 14.04. Is there a way how to fix that?
public class Window extends JFrame {
private int mouse_x_offset;
private int mouse_y_offset;
public Window() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(250, 250);
JPanel panel = new JPanel();
panel.setBackground(Color.BLACK);
setUndecorated(true);
setVisible(true);
panel.addMouseMotionListener(new PanelListener());
panel.addMouseListener(new PanelListener());
add(panel);
}
class PanelListener implements MouseMotionListener, MouseListener {
#Override
public void mouseDragged(MouseEvent e) {
int x = e.getXOnScreen();
int y = e.getYOnScreen();
setLocation(x - mouse_x_offset, y - mouse_y_offset);
}
#Override
public void mouseMoved(MouseEvent e) {
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
mouse_x_offset = e.getX();
mouse_y_offset = e.getY();
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
public static void main(String[] args) {
Window window = new Window();
}
}
when the Thread thread is running, (after clicking record) it only displays the position the mouse was in when the thread started? how can i make it constantly update, displaying where the mouse is even if i move it around the frame?
#Override public void actionPerformed(ActionEvent e)
{
thread = new Thread(this);
if(e.getSource() == record)
{
thread.start();
System.out.println("record");
}
if(e.getSource() == stopRecording)
{
setVisible(false);
System.out.println("stop recording");
}
}
#Override public void run()
{
setTitle("979");
setSize(screen.width, screen.height);
addMouseListener(this);
setLocationRelativeTo(null);
setLayout(transFlo);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(stopRecording);
setOpacity(0.50f);
setVisible(true);
while(true)
{
repaint();
}
}
#Override public void paint(Graphics g)
{
g.drawString(mousePOS + x + space + y, 250, 250);
}
Okay, just to reiterate; PLEASE read The Event Dispatching Thread,
then read Concurrency in Swing
and finally have a read of How to Write a Mouse Listener
ADDINTIONAL
If you want to monitor the global mouse events (all mouse events that pass through the system), then you will want to take a look at Toolkit.addAWTEventListener
This will allow you to monitor all the mouse events without the need to attach mouse listeners to all the components
SIMPLE MOUSE EXAMPLE
Here is a simple example of a panel that monitors the mouse :P
public class CrayPanel extends javax.swing.JPanel implements MouseMotionListener, MouseListener {
private List<Point> lstPoints;
/**
* Creates new form CrayPanel
*/
public CrayPanel() {
lstPoints = new ArrayList<Point>(25);
addMouseListener(this);
addMouseMotionListener(this);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (lstPoints.size() > 1) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
Point startPoint = lstPoints.get(0);
for (int index = 1; index < lstPoints.size(); index++) {
Point toPoint = lstPoints.get(index);
g2d.drawLine(startPoint.x, startPoint.y, toPoint.x, toPoint.y);
startPoint = toPoint;
}
}
}
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
lstPoints.add(e.getPoint());
repaint();
}
#Override
public void mouseClicked(MouseEvent e) {
lstPoints.clear();
lstPoints.add(e.getPoint());
repaint();
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
lstPoints.add(e.getPoint());
repaint();
}
#Override
public void mouseExited(MouseEvent e) {
lstPoints.add(e.getPoint());
repaint();
}
}
I put together another example. This is essentially a mouse monitor, it shows that, if done correctly, you don't need the Thread
public class MouseFrame extends javax.swing.JFrame implements AWTEventListener, ActionListener {
private boolean monitor = false;
private Point mousePoint;
/**
* Creates new form MouseFrame
*/
public MouseFrame() {
setLayout(new GridBagLayout());
JButton btnToggle = new JButton("Start");
add(btnToggler);
btnToggle.addActionListener(this);
setSize(400, 400);
}
public void actionPerformed(java.awt.event.ActionEvent evt) {
monitor = !monitor;
if (monitor) {
btnTrigger.setText("Stop");
Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.MOUSE_MOTION_EVENT_MASK);
} else {
btnTrigger.setText("Start");
Toolkit.getDefaultToolkit().removeAWTEventListener(this);
}
}
#Override
public void paint(Graphics grphcs) {
super.paint(grphcs);
Graphics2D g2d = (Graphics2D) grphcs;
if (monitor) {
g2d.setColor(Color.RED);
FontMetrics fm = g2d.getFontMetrics();
g2d.drawString(mousePoint.x + "x" + mousePoint.y, 25, fm.getHeight() + 25);
}
}
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
/*
* Create and display the form
*/
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MouseFrame().setVisible(true);
}
});
}
#Override
public void eventDispatched(AWTEvent evt) {
if (evt instanceof MouseEvent) {
MouseEvent me = (MouseEvent) evt;
mousePoint = SwingUtilities.convertPoint(me.getComponent(), me.getPoint(), this);
repaint();
}
}
}