0

I'm trying to write a code that does the following: If I click on the String C(JLabel) whose starting position is (100,100), the String moves WITHIN the boundaries of JFrame. The code itself wasn't hard to implement but I'm having issues with setting the (x,y) for JLabel so that any Part of the String "C" doesn't get cut off.

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class adfadf extends JFrame{
    JLabel text = new JLabel("C");
    Container container = getContentPane();
    public adfadf(){
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        container.setLayout(null);
        MyMouseListener mml = new MyMouseListener();
        text.addMouseListener(mml);
        text.setLocation(100,100);
        text.setSize(30,30);
        add(text);
        setSize(400,400);
        setVisible(true);
    }


    public static void main(String[] args) {
        new adfadf();

    }

}
class MyMouseListener extends MouseAdapter{
    @Override
    public void mouseClicked(MouseEvent e){
        JLabel text = (JLabel)e.getSource();
        int x = (int)(Math.random()*(400-30));
        int y = (int)(Math.random()*(400-30));
        text.setLocation(x,y);
    }

}

How should I change

int x = (int)(Math.random()*(400-30));
int y = (int)(Math.random()*(400-30));

in order to achieve what I want?

1 Answers1

2

First, understanding that a JFrame is much more complex then it seems

To start with, a JFrame has a JRootPane, that contains the contentPane and JMenuBar and glassPane

RootPane

This is further complicated by the fact the window's decorations are actually painted WITHIN the visible bounds of the frame, meaning that the visible area available to your content is actually smaller than the frame's size.

You can have a look at How can I set in the midst?, Graphics rendering in title bar and How to get the EXACT middle of a screen, even when re-sized for more details and examples of this.

But how does this help you? Well, now you know that you have a space of less than 400x400 to display your label in, but how much?

The simple solution is to stop using "magic" numbers, and take a look at something which is been used by the frame, the contentPane. The contentPane is managed by the the JFrame (via the JRootPane) so that it sits within the frame decorations, so you could do something more like...

JLabel text = (JLabel)e.getSource();
int width = getContentPane().getSize().width;
int height = getContentPane().getSize().height;
int x = (int)(Math.random()*(width-30));
int y = (int)(Math.random()*(height-30));
text.setLocation(x,y);

The reason for looking at the contentPane in this instance is simply because, that's the container that the label is actually added to.

This is one of the reasons why we suggest you don't use "magic" numbers, but look at the actual known values at the time you need them.

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thank you so much for the help! I was not aware of the compositions of JFrame and the fact that the displayed size is actually smaller than I set it to be. –  Jan 17 '16 at 07:16
  • It's the reason you will find that we suggest overriding `getPreferredSize` of your "base" component and using `JFrame#pack`, then you can guarantee (at least the starting) size of the window, but you shouldn't rely on magic numbers – MadProgrammer Jan 17 '16 at 07:19
  • exactly what I wanted :D –  Jan 17 '16 at 07:22
  • just to follow up on the question... If i were to use the getContentPane() method in order to get the content pane of the adfadf() inside the indepndent class MyMouseListener. How would I go about it ? –  Jan 17 '16 at 07:34
  • You could use the `MouseEvent#source`, but then I'd do it a little differently, `((JComponent)e.getSource()).getParent()`, which will return a `Container`, the `Container` which contains the `JLabel` (equally, you could use `MouseEvent#getComponent` to get the source of the event (the `JLabel`)) – MadProgrammer Jan 17 '16 at 07:36
  • Thank you for the quick answer. Greatly appreciated! –  Jan 17 '16 at 07:39