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);
}
Related
I'm trying to get the x and y coordinates of a mouse click to do some calculations I need to do. I can't seem to find anything online with how to get the vars outside the anonymous method.
MouseListener listener = new MouseListener()
{
public void mousePressed(MouseEvent me) { }
public void mouseReleased(MouseEvent me) { }
public void mouseEntered(MouseEvent me) { }
public void mouseExited(MouseEvent me) { }
public void mouseClicked(MouseEvent me)
{
int x,y;
x = me.getX();
y = me.getY();
System.out.println("X:" + x + " Y:" + y);
}
};
frame.addMouseListener(listener);
//calculations with the x and y coordinates
You can declare the x and y variables outside of the anonymous class and initialize them inside the mouseClicked method. Here's an example:
int x;
int y;
MouseListener listener = new MouseListener()
{
public void mousePressed(MouseEvent me) { }
public void mouseReleased(MouseEvent me) { }
public void mouseEntered(MouseEvent me) { }
public void mouseExited(MouseEvent me) { }
public void mouseClicked(MouseEvent me)
{
x = me.getX();
y = me.getY();
System.out.println("X:" + x + " Y:" + y);
}
};
frame.addMouseListener(listener);
// calculations with the x and y coordinates
// you can now use the values of x and y here
By declaring the variables outside of the anonymous class, you can access them outside of the mouseClicked method.
I'm experimenting on a GUI that I programmed and I don't understand how I can fix my problem:
My GUI contains a jPanel that on receiving a mouseclick, paints a point with filloval command.
private void myPnlMousePressed(java.awt.event.MouseEvent evt) {
changed = true;
p.x = evt.getX();
p.y = evt.getY();
drewPoints(p.x, p.y);
}
private void drewPoints (int x, int y) {
if (gf == null) {
gf = (Graphics)myPnl.getGraphics();
}
myPointsList.add(new Point(x, y));
gf.fillOval(x, y, 5, 5);
xVal.setText("X = " + x);
yVal.setText("Y = " + y);
}
everything works fine but when I want to open an XML file that I created to save all the points it doesn't work.
The problem is that when I use the repaint method on the jPanel after choosing a file, all the points loads fine but the panel can't draw the points.
If I put the repaint method in the open button listener (before the choosing file) it works, but then if the user cancels the open option so the panel stays blank and I don't want to draw the points again.
I think it happens because the repaint process is not finished.
All the points added to a private List.
private void OpenFile() {
try {
File thisFile;
JFileChooser of = new JFileChooser();
int option = of.showOpenDialog(of);
if (option == JFileChooser.APPROVE_OPTION){
thisFileName = of.getSelectedFile().getPath();
thisFile = new File(thisFileName);
if (!of.getSelectedFile().getName().endsWith(".xml")) {
String error = "Error, You didn't select XML file";
JOptionPane.showMessageDialog(this, error, "Wrong type of file", JOptionPane.INFORMATION_MESSAGE);
return;
}
myPnl.repaint();
myPointsList.clear();
....
....
....
for (int i = 0; i < pointsList.getLength(); i++) {
Element point = (Element) pointsList.item(i);
p.x = Integer.parseInt(point.getElementsByTagName("X").item(0).getTextContent());
p.y = Integer.parseInt(point.getElementsByTagName("Y").item(0).getTextContent());
drewPoints(p.x, p.y);
}
....
how can I make it work??
Don't use gf = (Graphics)myPnl.getGraphics();, this is not how painting in Swing works. The getGraphics method can return null and is nothing more then a snap shot of the last paint cycle, any thing you paint to it will be erased on the next paint cycle (repaint).
Instead, override the JPanels paintComponent and put all you painting logic there. There is an expectation that when called, you are expected to fully re-paint the current state of the component.
See Painting in AWT and Swing and Performing Custom Painting for more details about how painting works in Swing
You have to use the repaint() and override the paint() method:
class MyPanel extends JPanel implements MouseListener
{
private int x;
private int y;
public MyPanel() {
super();
addMouseListener(this);
}
#Override public void mouseEntered(MouseEvent e) { }
#Override public void mouseExited(MouseEvent e) { }
#Override public void mouseClicked(MouseEvent e) { }
#Override public void mousePressed(MouseEvent e) { }
#Override public void mouseReleased(MouseEvent e) {
x = e.getX();
y = e.getY();
repaint();
}
#Override public void paint(Graphics g) {
super.paint(g);
g.fillOval(x, y, 10, 10);
}
}
If you want to draw all points, don't use x and y but a list of points:
class MyPanel extends JPanel implements MouseListener
{
private ArrayList<Point> points = new ArrayList<>();
public MyPanel() {
super();
addMouseListener(this);
}
#Override public void mouseEntered(MouseEvent e) { }
#Override public void mouseExited(MouseEvent e) { }
#Override public void mouseClicked(MouseEvent e) { }
#Override public void mousePressed(MouseEvent e) { }
#Override public void mouseReleased(MouseEvent e) {
points.add(new Point(e.getX(), e.getY()));
repaint();
}
#Override public void paint(Graphics g) {
super.paint(g);
for (Point p : points)
g.fillOval(p.getX(), p.getY(), 10, 10);
}
}
where:
class Point
{
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
Then use it:
public static void main(String[] args) {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
MyPanel myPanel = new MyPanel();
frame.add(myPanel);
frame.setVisible(true);
}
I'm trying to create a simple Java applet that can detect both the location of the mouse within the applet and detect whether the shift key has been released or pressed. When I add a KeyListener, though, the program ignores the mouseMove event. How can I get the mouseMove event to work while also using KeyListener?
public class Test extends java.applet.Applet implements java.awt.event.KeyListener {
String message;
int moveX, moveY;
public Test() { this.addKeyListener(this); }
public void init() {
message = "";
moveX = moveY = 0;
}
public void paint(java.awt.Graphics g) {
new Test();
g.drawString(message,15,15);
g.drawString("(" + moveX + "," + moveY + ")",900,630);
}
#Override
public void keyPressed(java.awt.event.KeyEvent e) {
if (e.getKeyCode() == java.awt.event.KeyEvent.VK_SHIFT)
message = "Shift key pressed";
repaint();
}
#Override
public void keyReleased(java.awt.event.KeyEvent e) {
message = "Shift key released";
repaint();
}
#Override
public void keyTyped(java.awt.event.KeyEvent e) {}
public boolean mouseMove(java.awt.Event e, int x, int y) {
moveX = x;
moveY = y;
repaint();
return true;
}
}
If you want to check if someone was holding shift or another key while clicking, MouseEvent has a method called getModifiers()
I fixed the issue by replacing mouseMove(java.awt.Event e, int x, int y) with mouseMoved(java.awt.event.MouseEvent e), so now the coordinates change when the mouse's location changes and the message changes when the shift key is held down.
So I have been researching Applets and using Canvas and BufferStrategy on the applet. I have gotten it to buffer and show correctly but I'm thinking that it is somehow interfering with the MouseListener. When I run the Applet and re-size the screen, the MouseListener works outside my specified canvas. So when I move the mouse over where it is drawing, the mouse coordinates freeze. Then when I move the mouse off the canvas, it works. So it is nothing wrong with the MouseListener. I will include it anyway.
MouseMotion class:
public class MouseMotion implements MouseMotionListener{
private int x;
private int y;
public MouseMotion()
{
x = 0;
y = 0;
System.out.println("MouseMotion initialized");
}
public void mouseDragged(MouseEvent e) {}
public void mouseMoved(MouseEvent e)
{
x = e.getX();
y = e.getY();
}
//Return methods...
}
Mouse class:
public class Mouse implements MouseListener{
private int clickedX;
private int clickedY;
private int clickedButton;
private boolean pressed;
private int pressedX;
private int pressedY;
private int pressedButton;
public Mouse()
{
//Instantiates all the variables
System.out.println("Mouse initialized");
}
public void mouseClicked(MouseEvent e) {
clickedX = e.getX();
clickedY = e.getY();
clickedButton = e.getButton();
}
public void mousePressed(MouseEvent e) {
pressed = true;
pressedX = e.getX();
pressedY = e.getY();
pressedButton = e.getButton();
}
public void mouseReleased(MouseEvent e) {
pressed = false;
pressedX = 0;
pressedY = 0;
pressedButton = 0;
}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
//Methods that return each variable...
}
The AppletMain class:
public class AppletMain extends Applet implements Runnable{
//Constants
private final int WIDTH = 720;
private final int HEIGHT = WIDTH / 16 * 9;
//Applet objects
private BufferStrategy bs;
private Canvas canvas;
//Game loop variables
...
//Engine objects
private Mouse mouse;
private MouseMotion mouseMotion;
public void init()
{
canvas = new Canvas();
mouse = new Mouse();
mouseMotion = new MouseMotion();
addMouseListener(mouse);
addMouseMotionListener(mouseMotion);
}
public void render()
{
//Setup graphics
Graphics2D g = (Graphics2D)bs.getDrawGraphics();
g.clearRect(0,0,WIDTH,HEIGHT);
//Just prints out the debugging stuff
g.setColor(Color.BLACK);
g.drawRect(0,0,WIDTH-1,HEIGHT-1);
g.drawString("TPS: " + Integer.toString(tps) + " FPS: " + Integer.toString(fps), 2,20);
g.drawString("MouseMotion: X - " + Integer.toString(mouseMotion.getX()) + " Y - " + Integer.toString(mouseMotion.getY()), 2,40);
g.drawString("Mouse(PRESSED): X - " + Integer.toString(mouse.getPressedX()) + " Y - " + Integer.toString(mouse.getPressedY()) + " button - " + Integer.toString(mouse.getPressedButton()), 2,60);
g.drawString("Mouse(CLICKED): X - " + Integer.toString(mouse.getClickedX()) + " Y - " + Integer.toString(mouse.getClickedY()) + " button - " + Integer.toString(mouse.getClickedButton()), 2,80);
//Cleanup graphics
g.dispose();
bs.show();
}
public void tick()
{
//Ticks the game
}
public void start()
{
if(bs == null)
{
setIgnoreRepaint(true);
canvas.setIgnoreRepaint(true);
canvas.setSize(WIDTH,HEIGHT);
setLayout(null);
add(canvas);
canvas.setLocation(0,0);
canvas.createBufferStrategy(3);
bs = canvas.getBufferStrategy();
}
new Thread(this).start();
canvas.requestFocus();
}
public void stop()
{
running = false;
}
public void destroy()
{
if(running)
running = false;
}
public void run()
{
init();
//Game loop that calls tick() and render() 60 times per second
}
}
In my code I drew black box around the canvas, and as I said before, when my mouse enters the black box the coordinates stop changing. The "fps" and "tps" keep going which are incremented by the game loop so I know that it is still running. When mouse exits the box, though, the coordinates again start changing as I move it around the window.
I tried to follow examples of other people and I believe I have. Maybe my approach to this is all wrong, I don't know, but any help, answers, comments, tips anything are greatly appreciated.
I've added this listener to a JLabel, and I am able to drag the image around perfectly, However, as soon as I click on the panel(in an area where a JLabel is not present) the label returns back to it's original location. I can't figure out why that would happen. Please help me out, I've spent hours working on this. Thanks!
public class CardLabelListener extends MouseAdapter {
private MouseEvent initiateEvent = null;
#Override
public void mouseReleased(MouseEvent me) {
System.err.println("mouse release");
int dx = me.getX() - initiateEvent.getX();
int dy = me.getY() - initiateEvent.getY();
if (Math.abs(dx) > 5 || Math.abs(dy) > 5) {
Rectangle oldBound = me.getComponent().getBounds();
int newX = oldBound.x + dx;
int newY = oldBound.y + dy;
me.getComponent().setBounds(newX, newY, oldBound.width, oldBound.height);
}
initiateEvent = null;
}
public void mousePressed(MouseEvent me) {
GreetingCard.setBackground.findComponentAt(me.getX(), me.getY());
System.err.println("mouse pressed");
initiateEvent = me;
me.consume();
}
public void mouseDragged(MouseEvent me) {
System.err.println(me.getSource());
if (initiateEvent == null) return;
me.consume();
JComponent jc = (JComponent) me.getSource();
TransferHandler handler = jc.getTransferHandler();
handler.exportAsDrag(jc, me, TransferHandler.MOVE);
initiateEvent = null;
}
}
Firstly, you're not dragging the icon, your dragging the component itself.
Secondly, you're fighting against the layout manager which contains the label component. When ever the panel is invalidated, the labels are returned to their original layout positions.
Trying using something like a JLayeredPane to put your labels in
UPDATED with example based on feedback
public class MoveMe {
public static void main(String[] args) {
new MoveMe();
}
public MoveMe() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new MoveMePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MoveMePane extends JLayeredPane {
public MoveMePane() {
int width = 400;
int height = 400;
for (int index = 0; index < 10; index++) {
String text = "Label " + index;
JLabel label = new JLabel(text);
label.setSize(label.getPreferredSize());
int x = (int) Math.round(Math.random() * width);
int y = (int) Math.round(Math.random() * height);
if (x + label.getWidth() > width) {
x = width - label.getWidth();
}
if (y + label.getHeight() > width) {
y = width - label.getHeight();
}
label.setLocation(x, y);
add(label);
}
MoveMeMouseHandler handler = new MoveMeMouseHandler();
addMouseListener(handler);
addMouseMotionListener(handler);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
public class MoveMeMouseHandler extends MouseAdapter {
private int xOffset;
private int yOffset;
private JLabel draggy;
private String oldText;
#Override
public void mouseReleased(MouseEvent me) {
if (draggy != null) {
draggy.setText(oldText);
draggy.setSize(draggy.getPreferredSize());
draggy = null;
}
}
public void mousePressed(MouseEvent me) {
JComponent comp = (JComponent) me.getComponent();
Component child = comp.findComponentAt(me.getPoint());
if (child instanceof JLabel) {
xOffset = me.getX() - child.getX();
yOffset = me.getY() - child.getY();
draggy = (JLabel) child;
oldText = draggy.getText();
draggy.setText("What a drag");
draggy.setSize(draggy.getPreferredSize());
}
}
public void mouseDragged(MouseEvent me) {
if (draggy != null) {
draggy.setLocation(me.getX() - xOffset, me.getY() - yOffset);
}
}
}
}
For this to work you would need use a null layout on the container where the JLabel is located, otherwise the position will reset to that where the current layout manager positions the label.
A better approach would be to use DragLayout
DragLayout was designed to replace a null layout. It will respect the location of a component. By default it will use the preferred size of the component to determines its size. Finally, it will automatically calculate the preferred size of the Container.