MouseInputAdapter on JMenuBar - not all methods get called - java

I have a JComponent with JMenuBar in it. I would like to be able to drag the component by clicking on it and dragging the mouse to the desired location. I have already implemented this functionality by adding the MouseInputAdapter methods to its Border and it works great.
However, I would like to apply the same functionality on the JMenuBar, the mouseDragged() method does not get called.
Here is the menu listener (stripped version for testing):
menuBar.addMouseListener(new MouseInputAdapter() {
private Point startPos = null;
#Override
public void mousePressed(MouseEvent me) {
startPos = me.getPoint();
// works fine
System.out.println("startPos: " + startPos.toString());
}
#Override
public void mouseDragged(MouseEvent me) {
// this does not get called...
System.out.println("dragging.............");
}
});
I dont think that this is the problem, but here is the Listener used for the whole component. Could these two listeners somehow collide? I tried removingthis listener but it did not solve anything:
// this works with the border
this.addMouseListener(resizeListener);
MouseInputListener resizeListener = new MouseInputAdapter() {
#Override
public void mouseEntered(MouseEvent me) {
// put this widget on top when mouse moves across it
putOnTop();
}
#Override
public void mouseMoved(MouseEvent me) {
// put this widget on top when mouse moves across it
putOnTop();
WidgetBorder border = (WidgetBorder) getBorder();
setCursor(Cursor.getPredefinedCursor(border.getResizeCursor(me)));
}
#Override
public void mouseExited(MouseEvent mouseEvent) {
setCursor(Cursor.getDefaultCursor());
}
private int cursor;
private Point startPos = null;
#Override
public void mousePressed(MouseEvent me) {
WidgetBorder border = (WidgetBorder) getBorder();
cursor = border.getResizeCursor(me);
startPos = me.getPoint();
}
#Override
public void mouseDragged(MouseEvent me) {
if (startPos != null) {
// widget cant be resized under its minimum size
if (widget.getWidth() < WidgetConstants.MIN_WIDTH) {
widget.setBounds(widget.getX(), widget.getY(), WidgetConstants.MIN_WIDTH + 1, widget.getHeight());
return;
}
if (widget.getHeight() < WidgetConstants.MIN_HEIGHT) {
widget.setBounds(widget.getX(), widget.getY(), widget.getWidth(), WidgetConstants.MIN_HEIGHT + 1);
return;
}
int dx = me.getX() - startPos.x;
int dy = me.getY() - startPos.y;
switch (cursor) {
case Cursor.SE_RESIZE_CURSOR:
setBounds(getX(), getY(), getWidth() + dx, getHeight() + dy);
startPos = me.getPoint();
repaintParent();
break;
case Cursor.MOVE_CURSOR:
Rectangle bounds = getBounds();
bounds.translate(dx, dy);
setBounds(bounds);
repaintParent();
}
// cursor shouldn't change while dragging
setCursor(Cursor.getPredefinedCursor(cursor));
}
}
#Override
public void mouseReleased(MouseEvent mouseEvent) {
startPos = null;
}
};
What am I missing here? Thanks for any help...

MouseInputAdapter implements many interfaces (e.g. MouseListener, MouseMotionListener etc.).
You have to add this with multiple methods, e.g. with Component.addMouseListener() if you want mouseClicked() to be called, Component.addMouseMotionListener() if you want mouseDragged() to be called and Component.addWheelListener() if you want mouseWheelMoved() to be called.
You can pass the same reference of course, but you have to add your listener implementation with multiple methods. The reason is because for example Component.addMouseListener() expects a MouseListener interface, and will only call the methods defined in the MouseListener interface, even if you pass an object that implements other methods from other interfaces.

Related

How do I make a graphics change place randomly everytime I click on it

The code I made won't change the coordinates of the ball every time I click on it.
public class AimTrainerPanel extends JPanel implements MouseListener {
static final int WIDTH = 1300;
static final int HEIGHT = 750;
static final int SIZE = 10;
Random rand;
JLabel cd;
int x;
int y;
boolean running = false;
Timer timer;
AimTrainerPanel() {
rand = new Random();
this.setPreferredSize(new Dimension(WIDTH, HEIGHT));
this.setBackground(Color.black);
this.setFocusable(true);
this.setLayout(null);
this.addMouseListener(this);
startGame();
}
public void startGame() {
newDot();
running = true;
timer = new Timer();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}
public void draw(Graphics g) {
if (running) {
g.setColor(Color.white);
g.fillOval(x, y, SIZE, SIZE);
}
}
public void newDot() {
x = rand.nextInt((int)(WIDTH/SIZE)) * SIZE;
y = rand.nextInt((int)(HEIGHT/SIZE)) * SIZE;
}
#Override
public void mouseClicked(MouseEvent e) {
int mx = e.getX();
int my = e.getY();
if (mx >= x && mx <= x + 10) {
if (my >= y && my <= y + 10) {
newDot();
}
}
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
The newDot() method is suppose to create new coordinates every time it is called but the ball won't change places. I don't know if it's because I misswrote something or because my what I did doesn't change the coordinates or if I'm suppose to add something.
I'm not sure what your Timer is supposed to be doing, but it doesn't appear to be a Swing Timer, and since this is a Swing GUI I'd get rid of it.
Now to the crux of your problems:
You're using mouseClicked which isn't called if the mouse moves even slightly between mouse pressed and mouse released, and so often it is better to use mousePressed or mouseReleased methods and not mouseClicked
You don't call repaint() after changing the state of your program. Swing won't know that a repaint is needed unless you suggested, and so in your mouseListener or in code called by it, you should call this method after changing GUI state. Here you can call it at the end of the newDot(...) method or in the mouse listener after you call the same method.
Your if blocks within your mouse listener appear to be quite restrictive as to where they will allow the listener to respond to a mouse click -- is it too restrictive? I don't know since I'm not familiar with your requirements, but possibly.

How to implement a mouse listener that will help drag a circle in java?

I am trying to figure out how to complete the assignment below
Write a method void move(Point p) for your Circle class that takes a Point and moves the circle so its center is at that point.
In the CirclePanel constructor, create a CirclesListener object and make it listen for both mouse events and mouse motion events.
Make the CirclesListener class implement the MouseMotionListener interface in addition to the MouseListener interface. This requires two steps: Note in the header that CirclesListener implements MouseMotionListener. Add bodies for the two MouseMotionListener methods, mouseDragged and mouseMoved. In mouseDragged, simply move the circle to the point returned by the getPoint method of the MouseEvent and repaint. Provide an empty body for mouseMoved.
I know what I need to do (for the most part), I just can't figure out how to do it. (New to programming). Thank you!
public class circlePanel extends JPanel {
private final int WIDTH = 600, HEIGHT = 400;
private Circle circle;
// -------------------------------------------------------------------
// Sets up this panel to listen for mouse events.
// -------------------------------------------------------------------
public circlePanel() {
addMouseListener(new CirclesListener());
setPreferredSize(new Dimension(WIDTH, HEIGHT));
}
// -------------------------------------------------------------------
// Draws the current circle, if any.
// -------------------------------------------------------------------
public void paintComponent(Graphics page) {
super.paintComponent(page);
if (circle != null)
circle.draw(page);
}
// ******************************************************************
// Represents the listener for mouse events.
// ******************************************************************
private class CirclesListener implements MouseListener, MouseMotionListener {
// ---------------------------------------------------------------
// Creates a new circle at the current location whenever the
// mouse button is pressed and repaints.
// ---------------------------------------------------------------
public void mousePressed(MouseEvent event) {
if (circle == null) {
circle = new Circle(event.getPoint());
} else if (circle.isInside(event.getPoint())) {
circle = null;
} else {
circle.move(getMousePosition());
}
repaint();
}
// -----------------------------------------------------------------
// Provide empty definitions for unused event methods.
// -----------------------------------------------------------------
public void mouseClicked(MouseEvent event) {
}
public void mouseReleased(MouseEvent event) {
}
public void mouseEntered(MouseEvent event) {
setBackground(Color.white);
}
public void mouseExited(MouseEvent event) {
setBackground(Color.blue);
}
}
}
Here is the circles class
public class Circles {
// ----------------------------------------------------------------
// Creates and displays the application frame.
// ----------------------------------------------------------------
public static void main(String[] args) {
JFrame circlesFrame = new JFrame("Circles");
circlesFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
circlesFrame.getContentPane().add(new circlePanel());
circlesFrame.pack();
circlesFrame.setVisible(true);
}
}
aannnddddd...here is the Circle class
public class Circle {
private int centerX, centerY;
private int radius;
private Color color;
static Random generator = new Random();
// ---------------------------------------------------------
// Creates a circle with center at point given, random radius and color
// -- radius 25..74
// -- color RGB value 0..16777215 (24-bit)
// ---------------------------------------------------------
public Circle(Point point) {
radius = Math.abs(generator.nextInt()) % 50 + 25;
color = new Color(Math.abs(generator.nextInt()) % 16777216);
centerX = point.x;
centerY = point.y;
}
// ---------------------------------------------------------
// Draws circle on the graphics object given
// ---------------------------------------------------------
public void draw(Graphics page) {
page.setColor(color);
page.fillOval(centerX - radius, centerY - radius, radius * 2,
radius * 2);
}
public void move(Point p) {
centerX = p.x;
centerY = p.y;
}
public boolean isInside(Point p) {
if (Math.sqrt(Math.pow(p.x - this.centerX, 2) + Math.pow(p.y -
this.centerY, 2)) < this.radius) {
return true;
} else {
return false;
}
}
}
So, basically, based on you code example, you need:
Implement the functionality of the MouseMotionListener, this will include the mouseDragged method
You need to register the CirclesListener to the circlePanel (JPanel#addMouseMotionListener)
When mouseDragged is called, you need to take the Point from the MouseEvent and call Circle#move and repaint the component
If you get stuck, best place to start is How to Write a Mouse Listener

Moving a JFrame with custom title bar

How can I move a JFrame having a custom title bar?
I remove the default title bar and I did my own design. This is how it looks like:
I want to know how to drag a JFrame when the cursor is placed on the title bar only and not the whole frame. I've searched already and I have seen a lot of samples but I still don't get it. Do you guys have any simple code that I can understand?
I haven't started the code yet since I don't know how to start it. All I know is that, it is about mouseDragged or MouseMotionListener.
I implemented the following:
public class DragFrame extends JFrame {
int mpX, mpY;
public DragFrame() {
addMouseListener( new MouseAdapter() {
#Override
public void mousePressed( MouseEvent e ) {
mpX = e.getX();
mpY = e.getY();
}
} );
addMouseMotionListener( new MouseMotionAdapter() {
#Override
public void mouseDragged( MouseEvent e ) {
setLocation(
getLocation().x + e.getX() - mpX,
getLocation().y + e.getY() - mpY );
}
} );
}
}
Thanks to #peeskillet for giving the crucial link to Drag and Resize undecorated JFrame with the inspiration to save the mouse position on mousePressed(...).
Your guess that you'll need to overwrite the MoseMotionListener.mouseDragged method was correct. Then, you need to call JFrame.setLocation to move your JFrame, like this:
class FrameMoveListener extends MouseAdapter
{
private Point lastPos;
private Frame frame;
public FrameMoveListener (Frame f)
{
frame = f; // mustn't be null
}
public void mouseDragged (MouseEvent evt)
{
if (lastPos != null)
{
int x = lastPos.x - evt.getX();
int y = lastPos.y - evt.getY();
f.setLocation(f.getLocationOnScreen().x + x,
f.getLocationOnScreen().y + y);
}
lastPos = new Point(evt.getX(), evt.getY());
}
}
use this method is simple and perfec
final Component obj - your JFrame, JLabel, any Component
final boolean info - if you want display the position when release de left click
public static void Move(final Component obj,final boolean info) {
MouseInputAdapter d=new MouseInputAdapter() {int x,X,y,Y;
#Override public void mousePressed(MouseEvent e){if(SwingUtilities.isLeftMouseButton(e)){x=e.getXOnScreen();X=obj.getLocation().x;y=e.getYOnScreen();Y=obj.getLocation().y;}}
#Override public void mouseDragged(MouseEvent e){if(SwingUtilities.isLeftMouseButton(e)){obj.setLocation(X+(e.getXOnScreen()-x), Y+(e.getYOnScreen()-y));}}
#Override public void mouseReleased(MouseEvent e){if(info && SwingUtilities.isLeftMouseButton(e)){System.err.println(obj.toString().substring(0,obj.toString().indexOf("["))+" ("+obj.getLocation().x+","+obj.getLocation().y+")");}}};
obj.addMouseListener(d);obj.addMouseMotionListener(d);
}
this is the format code:
public static void Mover(final Component obj, final boolean info) {
MouseInputAdapter d = new MouseInputAdapter() {
int x, X, y, Y;
#Override public void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
x = e.getXOnScreen();
X = obj.getLocation().x;
y = e.getYOnScreen();
Y = obj.getLocation().y;
}
}
#Override public void mouseDragged(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
obj.setLocation(X + (e.getXOnScreen() - x), Y + (e.getYOnScreen() - y));
}
}
#Override public void mouseReleased(MouseEvent e) {
if (info && SwingUtilities.isLeftMouseButton(e)) {
System.err.println(obj.toString().substring(0, obj.toString().indexOf("[")) + " (" + obj.getLocation().x + "," + obj.getLocation().y + ")");
}
}
};
obj.addMouseListener(d);
obj.addMouseMotionListener(d);
}

What is the best UI element dragging algorithm

I made a GUI application but I am stuck with a workaround algorithm to drag/move ui element relatively to another surface (screen, canvas, etc.). In my case I use it for a window relative to the screen, but that's beside the point because this algorithm should work anywhere possible. Here is my algorithm:
code-listing-1.
MouseMotionAdapter(){
int prevX = -1000, prevY = -1000, getX, getY;
public void mouseDragged(MouseEvent e) {
//if initial cursor position isn't set
if(prevX==-1000){
prevX = e.getLocationOnScreen().x;
prevY = e.getLocationOnScreen().y;
getX = e.getX();
getY = e.getY();
}
//move element to new position
theFrame.setBounds(theFrame.getBounds().x+e.getX()-getX, theFrame.getBounds().y+e.getY()-getY, 880, 583);
prevX=e.getLocationOnScreen().x;
prevY=e.getLocationOnScreen().y;
}
The trouble with this algorithm is that the mouse cursor position is definitely fixed relatively to the element and if I try to move/drag the element clicking in another position/part of the element the whole element moves so that the mouse cursor is positioned at the "initial position", which is not the behaviour I want (I want it to have the behaviour we mostly know like when we move an icon on desktop or a window on the screen, etc.)
Can anyone help with that? Thanks in advance.
The usual approach in such a case is to compute the difference between the current and the previous position. This difference is then "the movement", that is added to the position of the dragged object.
(BTW: You seem to not use the prev... values in your computation at all!)
Inside a MouseMotionListener, this could roughly look as follows:
class MouseDraggingControl implements MouseMotionListener
{
private Point previousPoint = new Point();
#Override
public void mouseMoved(MouseEvent e)
{
previousPoint = e.getPoint();
}
#Override
public void mouseDragged(MouseEvent e)
{
int movementX = e.getX() - previousPoint.x;
int movementY = e.getY() - previousPoint.y;
doMovement(movementX, movementY);
previousPoint = e.getPoint();
}
}
In your case, the doMovement method might be implemented like this:
private void doMovement(int movementX, int movementY)
{
int oldX = theFrame.getX();
int oldY = theFrame.getY();
int newX = oldX + movementX;
int newY = oldY + movementY;
theFrame.setLocation(newX, newY);
}
(or similar, using the getBounds/setBounds calls)
EDIT If the mouse motion listener is attached directly to the component that should be dragged, you might have to use the "location on screen" instead:
class MouseDraggingControl implements MouseMotionListener
{
private Point previousPoint = new Point();
#Override
public void mouseMoved(MouseEvent e)
{
previousPoint = e.getLocationOnScreen();
}
#Override
public void mouseDragged(MouseEvent e)
{
Point p = e.getLocationOnScreen();
int movementX = p.x - previousPoint.x;
int movementY = p.y - previousPoint.y;
doMovement(movementX, movementY);
previousPoint = e.getLocationOnScreen();
}
}
If this does not solve your issue, I'd like to emphasize the comment from MadProgrammer: An example that demonstrates your actual problem would help here.

Swing: Creating a draggable component...?

I searched the web for examples of draggable Swing components,
but I found either incomplete or non-working examples.
What I need is a Swing component that can be dragged by the mouse
inside an other component. While being dragged, it should already
change its position, not just 'jump' to its destination.
I would appreciate examples which work without non-standard APIs.
Thank you.
I propose a simple, but well-working solution, found out by myself ;)
What do I do?
When mouse is pressed, I record the cursor's position on screen, and
the component's position.
When mouse is dragged, I calculate the difference between new and
old cursor's position on screen, and move the
component by this difference.
Tested with latest JDK 6 unter Linux (OpenSuse, KDE3),
but hey, it's Java Swing, should work equally everywhere.
Here goes the code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class MyDraggableComponent
extends JComponent {
private volatile int screenX = 0;
private volatile int screenY = 0;
private volatile int myX = 0;
private volatile int myY = 0;
public MyDraggableComponent() {
setBorder(new LineBorder(Color.BLUE, 3));
setBackground(Color.WHITE);
setBounds(0, 0, 100, 100);
setOpaque(false);
addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) { }
#Override
public void mousePressed(MouseEvent e) {
screenX = e.getXOnScreen();
screenY = e.getYOnScreen();
myX = getX();
myY = getY();
}
#Override
public void mouseReleased(MouseEvent e) { }
#Override
public void mouseEntered(MouseEvent e) { }
#Override
public void mouseExited(MouseEvent e) { }
});
addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseDragged(MouseEvent e) {
int deltaX = e.getXOnScreen() - screenX;
int deltaY = e.getYOnScreen() - screenY;
setLocation(myX + deltaX, myY + deltaY);
}
#Override
public void mouseMoved(MouseEvent e) { }
});
}
}
public class Main {
public static void main(String[] args) {
JFrame f = new JFrame("Swing Hello World");
// by doing this, we prevent Swing from resizing
// our nice component
f.setLayout(null);
MyDraggableComponent mc = new MyDraggableComponent();
f.add(mc);
f.setSize(500, 500);
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setVisible(true);
}
}
Also, I found out that one could create an JInternalFrame inside an JFrame,
but the problem is: you get always an annoying window title bar.
To disable the title bar, sadly, a dirty workaround is necessary:
public class MyDraggableComponent extends JInternalFrame {
public MyDraggableComponent() {
InternalFrameUI thisUI = getUI();
if (thisUI instanceof BasicInternalFrameUI) {
((BasicInternalFrameUI) thisUI).setNorthPane(null);
}
}
I really miss a method like "someInternalFrame.setWindowTitleBar(false)"...
:'(

Categories

Resources