Jittering when trying to move undercorated JFrame - java

I have made a custome JFrame called mainWindow that is undecorated. I have added a JLabel named dragBar at the top of it and gave it desired dimensions (as shown below). When I click on the label I make the window move according to my mouse by using two listeners; one MouseListener and one MouseMotionListener.
The problem is that whenever I click on the label the window does move according to my mouse's location but it spazzes all over my screen until I stop moving the mouse or let go of the click button.
Is my method wrong? What is causing this issue?
Here is my code:
//what i use to make the dragBar
private JLabel dragBar = new JLabel();
private Point initialClick; //the initial point where I click on the label
//my mainWindow JFrame
private JFrame mainWindow = new JFrame();
private Dimension mainWindowSize = new Dimension(680,410);
//the code I use to set up my mainWindow JFrame
mainWindow.setUndecorated(true);
mainWindow.setShape(new RoundRectangle2D.Double(0, 0, 670, 400, 5, 5));
mainWindow.setSize(mainWindowSize);
mainWindow.setMinimumSize(mainWindowSize);
mainWindow.setResizable(false);
mainWindow.setLocation((screen_size.width/2)- mainWindow.getWidth()/2, (screen_size.height/2)- mainWindow.getHeight()/2);
mainWindow.getContentPane().setBackground(new Color(46, 48, 50, 255));
//the code I use to set up my dragBar label
topContainer.add(dragBar,3); //a Jlayeredpane that contains the dragBar label and is added to the mainWindow
dragBar.setSize(topContainer.getSize());
dragBar.setLocation(0,0);
dragBar.addMouseListener(new MouseListener() {
#Override public void mouseClicked(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e) {
initialClick = e.getPoint();
}
#Override public void mouseReleased(MouseEvent e) {}
#Override public void mouseEntered(MouseEvent e) {}
#Override public void mouseExited(MouseEvent e) {}
});
dragBar.addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseDragged(MouseEvent e) {
int changeX = e.getX()-initialClick.x;
int changeY = e.getY()-initialClick.y;
mainWindow.setLocation(mainWindow.getX()+changeX, mainWindow.getY()+changeY);
}
#Override public void mouseMoved(MouseEvent e) {}
});

a Jlayeredpane that contains the dragBar label
Don't think I would use a JLayeredPane for this. Just add a component to the BorderLayout.PAGE_START of the frame.
The basic logic for dragging a component is something like:
public class DragListener extends MouseInputAdapter
{
Point location;
MouseEvent pressed;
public void mousePressed(MouseEvent me)
{
pressed = me;
}
public void mouseDragged(MouseEvent me)
{
Component component = me.getComponent();
location = component.getLocation(location);
int x = location.x - pressed.getX() + me.getX();
int y = location.y - pressed.getY() + me.getY();
component.setLocation(x, y);
}
}
However in your case you don't want to drag the label, but instead drag the window, you your logic needs to forward the events to the window.
Check out Moving Windows for a more complex implementation of the above code that also adds additional features that easily allow you to move a window.

Related

Java - Cursor position relative to JFrame

Trying to have an object follow the cursor using:
int mx =(int) MouseInfo.getPointerInfo().getLocation().getX()-50;
Player.setX(mx);
in my tick method. However, this returns cursor position on screen, how can I make it relative to the JFrame itself? Is there maybe a way to read the position of the top-left point in the canvas so i can add an offset ?
Create a mouse listener, and fetch the coordinates from there:
public class SimpleFrame extends JFrame {
public static void main(String[] args) {
SimpleFrame frame = new SimpleFrame();
frame.setSize(new Dimension(200, 300));
frame.setLocation(new Point(500, 600));
frame.setVisible(true);
frame.addMouseListener(new MouseListener() {
#Override
public void mouseReleased(MouseEvent e) {
System.out.println(e.getX() + " / " + e.getY());
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseClicked(MouseEvent e) {
}
});
}
}
When you test this, you probably realize that you want to have the coordinates relative to something else, for example the main panel of your application. Then you create the mouselistener for that component:
SimpleFrame frame = new SimpleFrame();
JPanel mainPanel = new JPanel();
frame.add(mainPanel, ...);
mainPanel.addMouseListener(...
It is much better to do it this way, than to start substracting constants from the coordinates you get from the JFrame's mouseListener, since those "constants" will differ depending on OS etc.
And if you want to have event whenever the user moves the mouse, not only when he/she clicks it, use this:
frame.addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseMoved(MouseEvent e) {
System.out.println(e.getX() + " / " + e.getY());
}
#Override
public void mouseDragged(MouseEvent e) {
});

Placing an invisible button on top of an Image

I'm making a small java game for fun to practice with my GUI programming. I want to have the center of my content pane's borderLayout be an image, and I would like to put "invisible" buttons on top of the image in specific places (to be placed later, I just want to get one working for now). My issue is getting the button to actually be invisible, it seems to leave a white square where it is now. I looked around but the only things that seem to be suggested were the .setOpaque, .setContentAreaFilled, and .setBorderPainted. (game is space related, explains the names)
galaxyButton1 = new JButton();
galaxyButton1.setFont(starSystem);
galaxyButton1.setBorder(BorderFactory.createEmptyBorder(25,25,25,25) );
galaxyButton1.setOpaque(false);
galaxyButton1.setContentAreaFilled(false);
galaxyButton1.setBorderPainted(false);
Color invis = new Color(Color.TRANSLUCENT);
galaxyButton1.setForeground(invis);
galaxyButton1.setBackground(invis);
galaxyButton1.addActionListener( new ButtonHandler() );
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new BorderLayout());
JPanel buttons = new JPanel();
buttons.setLayout(new GridLayout( 1,0,5,5 ) );
buttons.setOpaque(false);
buttons.add(galaxyButton1);
centerPanel.add(buttons,BorderLayout.CENTER);
centerImg.setLayout(new GridBagLayout());
centerImg.add(centerPanel);
contentPane.add(centerImg, BorderLayout.CENTER);
Here is a code outline of how to make your own button. You will need to set up a the actual mouse in some other class.
public class InvisibleButton implements MouseListener{
private final Rectangle rectangle;
public InvisibleButton(int x, int y, int width, int height){
rectangle = new Rectangle(x,y,width,height);
}
#Override
public void mouseClicked(MouseEvent e) {
int x = 0; // Set this to Mouse X
int y = 0; // Set this to Mouse Y
if(rectangle.contains(x,y)){
//Set Something to True or do action here
}
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}

How do I click a JLabel using MouseListener?

I am trying to make this program for minecraft, and now im just getting started. I want that if you click a label, it will check what label is it and will do something.
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
System.out.println(me.getX()+", "+me.getY()+".");
Object source = me.getSource();
int intx = me.getX();
int inty = me.getY();
if(me.getX()>=1 && me.getY()>=1 && me.getX()<=70 && me.getY()<=45){
permissionsframe.setLocation(810,250);
System.out.println(p1p.length);
permissionsframe.pack();
permissionsframe.setSize(200, 200);
permissionsframe.setVisible(true);
JLabel playerperms = new JLabel("Player "+p1s+" has "+p1p.length+" permissions.");
playerperms.setBounds(1, 1, 150, 150);
permissionsframe.add(playerperms);
System.out.println("You chose "+player1.getText()+".");
}
else{
System.out.println("You did not click any label.");
}
}
});
This selection area is adapted to the name I have now - NonameSL. But if the name will be longer or shorter, the selection area will obviuosly be different...
Is there a way to get the excact label? I tried if(source.equals(player1))(Player 1 is the label) but I placed the label in 1, 1 and I have to click the excact point that I defined the label in, X=1, Y=1. How can I make a mouse listener listen to a label?
There is no need to check if the mouse coordinates are inside your JLabel.
You can bind a Listener to every JLabel an process the click/press event in your MyMouseListener.class
To do so:
You have to add the MouseListener to every JLabel:
MyMouseListener myMouseListener = new MyMouseListener();
label01.setName("name01");
label01.addMouseListener(myMouseListener);
label02.setName("name02");
label02.addMouseListener(myMouseListener);
To identify the JLabel you could do something like this:
class MyMouseListener extends MouseAdapter {
#Override
public void mouseClicked(MouseEvent e) {
JLabel l = (JLabel) e.getSource();
if(l.getName().equals("name01"))
doSomething01();
else if(l.getName().equals("name02"))
doSomething02();
}
}
The correct way to do this is to use the .getComponent() method instead of the .getSource() since this is MouseEvent which is something different than ActionEvent.
Implement the Listener to your class:
public class Main implements MouseListener {
public static void main(String[] args) {
//setup JFrame and some label and then
label.addMouseListener(this);
}
#Override
public void mousePressed(MouseEvent e) {
if (e.getComponent().equals(label)) {
System.out.println("clicked");
}
}
//the other orderride methods..

Swing Jbutton: showing border and background only when it is hovered

I want to add a hovering-effect to my customized Swing.JButton similar to the icon on my Chrome Browser:
Before hover >>
After hover >>
I am able to set the button in the "before" status when it is created, but I am not able to create the "border + raised-background" when it is hovered. When I try to re-add the border to the button, I got a moving effect as after repainting a new border is inserted.
This is my current code:
public class MyButton extends JButton implements MouseListener {
public MyButton(String iconPath, String toolTip) {
super(new ImageIcon(TipButton.class.getResource(iconPath)));
addMouseListener(this);
setBorder(null);
setBorderPainted(false);
setFocusPainted(false);
setOpaque(false);
setContentAreaFilled(false);
setToolTipText(toolTip);
}
public MyButton(String iconPath, String name, String toolTip) {
this(observers, iconPath, toolTip);
setText(name);
}
#Override
public void mouseClicked(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {
if (e.getSource() != this) return;
setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
}
#Override
public void mouseExited(MouseEvent e) {
if (e.getSource() != this) return;
setBorder(null);
}
}
I suppose the main logic should be in the methods mouseEntered/mouseExited but I don't know how to get the wanted effect. Any idea?
I think I have found a solution. Using EmptyBorder with the same sizes (insets) of a raised border does the trick. Code:
public class SwingUtils {
public static JButton createMyButton (String iconPath, String toolTip) {
final JButton b = new JButton (new ImageIcon(SwingUtils.class.getResource(iconPath)));
final Border raisedBevelBorder = BorderFactory.createRaisedBevelBorder();
final Insets insets = raisedBevelBorder.getBorderInsets(b);
final EmptyBorder emptyBorder = new EmptyBorder(insets);
b.setBorder(emptyBorder);
b.setFocusPainted(false);
b.setOpaque(false);
b.setContentAreaFilled(false);
b.setToolTipText(toolTip);
b.getModel().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
ButtonModel model = (ButtonModel) e.getSource();
if (model.isRollover()) {
b.setBorder(raisedBevelBorder);
} else {
b.setBorder(emptyBorder);
}
}
});
return b;
}
}
Note: as mKorbel says it would be using ChangeListener and the button created in a factory method instead of subclass JButton.
Use different images for every state. You can set a different Icon for selected, disabled selected, disabled, pressed, rollover, rolloverEnabled, rolloverSelected. More info here.
In java 7 there is a BevelBorder class that looks to be what you are looking for. The 2 methods you will probably be interested in are
paintRaisedBevel(Component c, Graphics g, int x, int y, int width, int height)
and
paintLoweredBevel(Component c, Graphics g, int x, int y, int width, int height)
Here is the documentation on the class: http://docs.oracle.com/javase/7/docs/api/javax/swing/border/BevelBorder.html
there (maybe) no reason to create extends JButton implements MouseListener {, there aren't overroaded any of JButtons methods, and use composition with returns instead,
better could be to create a local variable and to use methods implemented in API
don't to use MouseListener for Buttons Components, all these events are implemented in JButtons API and correctly
use set(Xxx)Icon for JButton
easiest of ways is to use JButton.getModel from ChangeListener, for example

Moving undecorated window by clicking on JPanel

Is there a possibility to move window by clicking on one of the panels in the window when that window is undecorated?
I have a main panel with matte border 40 pixels size, and few panels with controls inside, and I would like to move the window when clicking on that border. Is that possible?
You can place another panel over the panel with the border, leaving the border visible.Use the following code to move your window.
public class MotionPanel extends JPanel{
private Point initialClick;
private JFrame parent;
public MotionPanel(final JFrame parent){
this.parent = parent;
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
initialClick = e.getPoint();
getComponentAt(initialClick);
}
});
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
// get location of Window
int thisX = parent.getLocation().x;
int thisY = parent.getLocation().y;
// Determine how much the mouse moved since the initial click
int xMoved = e.getX() - initialClick.x;
int yMoved = e.getY() - initialClick.y;
// Move window to this position
int X = thisX + xMoved;
int Y = thisY + yMoved;
parent.setLocation(X, Y);
}
});
}
}
I've been working with this code for a while now to make a custom titlebar for undecorated windows.
P.S.:You can generalize this example by extending JComponent instead of JPanel.
I have a main panel with matte border 40 pixels size, and few panels with controls inside, and I would like to move the window when clicking on that border
I think that ComponetMover by #camickr is right class for you
Yes, it is very possible. You need a MouseListener to listen on mouse events. you start moving on mousedown and stop moving on mouseup. Then you simply translate the window position by the same amount the mouse translates during that phase (calculate the delta bewteen old mouse position and new mouse position and add that to the frames position). You should be able to do this with a mouse listener fairly easily.
I have a simple solution from my project. Here is my undecorated JDialog class.
public class TimerDialog extends JDialog {
// some fields here
private Point mouseClickPoint; // Will reference to the last pressing (not clicking) position
private TimerDialog() {
initComponents();
addEventsForDragging();
}
private void addEventsForDragging() {
// Here is the code does moving
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
mouseClickPoint = e.getPoint(); // update the position
}
});
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
Point newPoint = event.getLocationOnScreen();
newPoint.translate(-mouseClickPoint.x, -mouseClickPoint.y); // Moves the point by given values from its location
setLocation(newPoint); // set the new location
}
});
}
private void initComponents() {
setLayout(new FlowLayout());
// adding components
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setAlwaysOnTop(true);
setUndecorated(true);
setResizable(false);
pack();
}
}
int xMoved = (thisX + e.getX()) - (thisX + initialClick.x);
thisX + -thisX = 0
int xMoved = e.getX()-initialClick.x;
What i'm using.
public class MouseLiestenerX implements MouseListener,MouseMotionListener{
private theFrame;
public MouseLiestenerX(Frame theFrame){
this.theFrame = theFrame;
}
private Point startClick;
public void mouseDragged(MouseEvent e) {
int deltaX = e.getX()-startClick.x;
int deltaY = e.getY()-startClick.y;
Core.getSp().setLocation(theFrame.getLocation().x+deltaX, theFrame.getLocation().y+deltaY);
}
public void mousePressed(MouseEvent e) {
startClick = e.getPoint();
}
public void mouseMoved(MouseEvent e){
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
}
}
and in your Frame constructor
MouseLiestenerX IMove = new MouseLiestenerX(this);
addMouseListener(IMove);
addMouseMotionListener(IMove);

Categories

Resources