Java JPanel JFrame getting Height and Width - java

I'm currently working on a java project which consists of a frame , main panel, and 3 sub panels.On the north of the main panel i have my dataPanel, on the west i have my buttonPanel and on the center i have my drawPanel
My DrawPanel should display an initial of 5 circles and whenever create button is clicked it should draw X amount of circles specified by the user. However i want the circle center points to be all visible within DrawPanel only meaning no more than 1/2 of any circle is cut off the panel. I don't wish to set a length and width is there anyway to make it dynamic relative to the frame/panel size.
Here is my code
public class MainPanel extends JPanel{
private DataPanel data;
private JPanel buttonPanel;
private DrawPanel dPanel;
private JButton create;
private JButton sort;
private JButton coCenter;
private JButton reset;
public MainPanel()
{
setLayout(new BorderLayout());
data = new DataPanel();
add(data, BorderLayout.NORTH);
buttonPanelInitialize();
add(buttonPanel,BorderLayout.WEST);
int a,b,c;
a = data.getDataField();
b = data.getDataField1();
c = data.getDataField2();
dPanel = new DrawPanel(a,b,c);
add(dPanel, BorderLayout.CENTER);
}
private void buttonPanelInitialize()
{
buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(4,1));
buttonCreate();
buttonSort();
buttonCoCenter();
buttonReset();
buttonPanel.add(create);
buttonPanel.add(sort);
buttonPanel.add(coCenter);
buttonPanel.add(reset);
}
private void buttonCreate()
{
create = new JButton("Create");
class cListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent event) {
//int amount = 0;
int amount = data.getDataField();
int smallestR = data.getDataField1();
int largestR = data.getDataField2();
dPanel.create(amount,smallestR,largestR);
}
}
ActionListener createListener = new cListener();
create.addActionListener(createListener);
}
and
public class DrawPanel extends JPanel{
private ArrayList<ColorCircle> circles;
private int numberOfCircles;
private int smallestRadiusSize;
private int biggestRadiusSize;
private int width;
private int height;
public DrawPanel()
{
circles = new ArrayList<ColorCircle>();
}
public DrawPanel(int number, int smallestRadius, int biggestRadius)
{
circles = new ArrayList<ColorCircle>();
create(number,smallestRadius,biggestRadius);
width = (int)Math.random()*getWidth();
height = (int)Math.random()*getHeight();
}
public void create(int number, int smallestRadius, int biggestRadius)
{
numberOfCircles = number;
smallestRadiusSize = smallestRadius;
biggestRadiusSize = biggestRadius;
for(int i = 0; i < numberOfCircles ; i++)
{
int radius = (int) ((int)smallestRadiusSize+Math.random()*((int)biggestRadiusSize-(int)smallestRadiusSize+1));
width = (int) ((int)100+Math.random()*701); //the problem is here
height = (int) ((int)100+Math.random()*501); //and here this part should be dynamic
circles.add(new ColorCircle(width,height,radius));
System.out.println(smallestRadiusSize);
System.out.println(biggestRadiusSize);
System.out.println(radius+"-----");
System.out.println(circles.size());
System.out.println(width+" THis is x");
System.out.println(height+" THIs is Y");
repaint();
}
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for(ColorCircle c : circles)
{
c.fill(g2);
}
}

is there anyway to make it dynamic relative to the frame/panel size
You add a AncestorListener to the panel and handle the ancestorAdded event. This event will be generated when the panel is added to a visible GUI.
So this means your create(...) method needs to be invoked from this method (not the constructor). Then when the code is executed you can use the getWidth() and getHeight() methods of the panel to get the actual size of the panel and do your processing.

Related

GUI (view) start up is messed up

I previously had help with creating the GUI (Thank you #Hovercraft Full Of Eels).
Initially my GUI looked like this when start up.
and when you run the program, it looks like this.
Now after I edited it, it's start up looks like this.(Messed up)
and then when you run the program it looks like this.
Basically the startup screen looks messed up but when you press the button, it reverts back to normal but the background looks messed up.
Here is how the code looks like
The Main class:
public static void main(String[] args) {
JFrame f = new JFrame("Envrionment Stimulation");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(input.getGui()); //input is a class that takes the size of the grid and uses it to call the Layout class
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
This is the Layout class that input calls after getting the inputs for it
public class Layout extends JPanel {
private static final int WIDTH = 75;
private static final int SPACING = 15;
private final GridControls btnAndTxt;
private final Grid map;
public Layout(Earth earth, int xCount, int yCount) {
//Making our borders
setBorder(BorderFactory.createEmptyBorder(SPACING, SPACING, SPACING,SPACING));
setLayout(new BorderLayout(SPACING, SPACING));
//The Map
map = new Grid(WIDTH, xCount, yCount);
//Buttons and Text
btnAndTxt = new GridControls(map, earth);
//Adding the JPanels.
add(btnAndTxt, BorderLayout.PAGE_START);
add(map, BorderLayout.CENTER);
}
}
Next will be the Grid which is how our GUI will be initialized
public class Grid extends JPanel {
private final JLabel[][] label;
private final int xCount, yCount;
public Grid(int width, int xCount, int yCount) {
this.xCount = xCount;
this.yCount = yCount;
setBackground(Color.BLACK);
setBorder(BorderFactory.createLineBorder(Color.BLACK));
setLayout(new GridLayout(yCount, xCount, 1, 1));
label = new JLabel[yCount][xCount];
for (int y = 0; y < yCount; y++)
for (int x = 0; x < xCount; x++) {
label[y][x] = new JLabel(".", SwingConstants.CENTER);
label[y][x].setPreferredSize(new Dimension(width, width));
label[y][x].setBackground(Color.GREEN);
label[y][x].setOpaque(true);
label[y][x].setFont(new Font("Ariel", Font.PLAIN, 25));
add(label[y][x]);
}
}
public void updateGrid(Mappable[][] map) {
for (int y = 0; y < yCount; y++)
for (int x = 0; x < xCount; x++) {
label[y][x].setText(map[y][x] == null ? "." : map[y][x].toString());
}
}
public int getY() {
return yCount;
}
public int getX() {
return xCount;
}
}
For the GridControl class, it extends Jpanel. I used add() method for Button and Text (Button, Text, Button) order but I did not use any layout managers. Could this be the problem? The Initial GUI did not utilize layout manager for the Buttons and Text panel as well. (Layout class stayed the same)
*Edit1: Updated how grid looks like
I had getX() and getY() method while the class was extending JPanel. It override the methods that's why it was causing errors on the GUI.

How to "Paint" shapes from an arrayList to a JPanel? [duplicate]

This question already has answers here:
How to paint an arrayList of shapes Java
(2 answers)
Closed 7 years ago.
I am tasked with how to paint an arrayList of shapes in java.
I feel i have most of it right however
The final method in ShapeChooserPanel I cannot find out how to print the Shapes in the array, It should paint the current shape at the place the mouse was clicked.
My code is below
Main class:
import javax.swing.JFrame;
public class Lab2 {
public static void main (String[] args) {
JFrame myFrame = new JFrame("Lab 2");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.add(new ShapeChooserPanel());
myFrame.pack();
myFrame.setVisible(true);
}
}
ShapeChooserPanel
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.ArrayList;
public class ShapeChooserPanel extends JPanel {
private int currentX;
private int currentY;
private Color currentColor;
private int currentShape;
private JButton clearBtn;
private JRadioButton circle, square, triangle, box;
private DrawingPanel drawingPanel;
private JPanel controlsPanel;
//constants representing shape choice
private final int CIRCLE = 0;
private final int SQUARE = 1;
private final int TRIANGLE = 2;
private final int BOX = 3;
//constant delta used for setting distance between points
private final int DELTA = 25;
private int[] Xs;
private int[] Ys;
//store all the shapes to be painted UNCOMMENT when you have Shape.java defined
ArrayList<Shape> shapes;
public ShapeChooserPanel(){
//provide some default values paints a circle at (10,10) in blue
currentX = 10;
currentY = 10;
Xs = new int[4];//we will use all 4 points for the square, but only the first 3 for the triangle
Ys = new int[4];
setPoints(currentX,currentY);
currentShape = CIRCLE;
currentColor = Color.red;
shapes = new ArrayList<Shape>();
//instantiate the controls panel and set its layout to display everything in a single column
controlsPanel = new JPanel();
controlsPanel.setLayout(new BoxLayout(controlsPanel, BoxLayout.Y_AXIS));
//TODO: add clear button *
// TODO: define radio buttons *
clearBtn = new JButton("Clear");
clearBtn.addActionListener(new ClearListener());
circle = new JRadioButton("Red Circle");
circle.addActionListener(new ShapeListener());
square = new JRadioButton("Cyan Square");
square.addActionListener(new ShapeListener());
triangle = new JRadioButton("Green Triangle");
triangle.addActionListener(new ShapeListener());
box = new JRadioButton("Blue Box");
box.addActionListener(new ShapeListener());
ButtonGroup group = new ButtonGroup();
group.add(clearBtn);
group.add(circle);
group.add(square);
group.add(triangle);
group.add(box);
controlsPanel.add(clearBtn);
controlsPanel.add(circle);
controlsPanel.add(square);
controlsPanel.add(triangle);
controlsPanel.add(box);
//TODO: add radio buttons to group *
//TODO add listeners to radio buttons *
//TODO: add radio buttons to controls panel *
drawingPanel = new DrawingPanel();
drawingPanel.setBorder(BorderFactory.createLineBorder(Color.black));
//TODO: set a border around the drawing panel *
drawingPanel.setPreferredSize(new Dimension(200,200));
drawingPanel.addMouseListener(new PanelListener());
add(drawingPanel);
add(controlsPanel);
setPreferredSize(new Dimension (300,400));
}//end constructor
public void setPoints(int x, int y) {
//TODO: set Xs and Ys *
for(int i = 0; i < 4; i++) {
Xs[i] = x;
Ys[i] = y;
}
}
private class ClearListener implements ActionListener{
public void actionPerformed(ActionEvent ae){
shapes.removeAll(shapes);
drawingPanel.repaint();
}
}
private class PanelListener implements MouseListener {
public void mouseClicked(MouseEvent me) {
currentX = me.getX();
currentY = me.getY();
//TODO: find coordinates of this mouse click *
//TODO: add a new shape to the shapes list*
shapes.add(new Shape(currentX, currentY, SQUARE,Color.cyan));
setPoints(currentX, currentY);
//TODO: call setPoints with current x and y values *
drawingPanel.repaint();
}
public void mouseExited(MouseEvent me){}
public void mouseEntered(MouseEvent me){}
public void mouseReleased(MouseEvent me){}
public void mousePressed(MouseEvent me){}
}
//Class to listen for radio button changes
private class ShapeListener implements ActionListener{
public void actionPerformed(ActionEvent me){
//TODO: determine which radio button was clicked *
if(me.getActionCommand().equals("Red Circle")){
shapes.add(new Shape(currentX, currentY, CIRCLE, Color.red));
}
if (me.getActionCommand().equals("Cyan Square")){
shapes.add(new Shape(currentX, currentY, SQUARE, Color.cyan));
}
if(me.getActionCommand().equals("Green Triangle")){
shapes.add(new Shape(currentX, currentY, TRIANGLE, Color.green));
}
if(me.getActionCommand().equals("Blue Box")){
shapes.add(new Shape(currentX, currentY, BOX, Color.blue));
}
//TODO: set current shape and color *
drawingPanel.repaint();
}
}
private class DrawingPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
//TODO: paint all the shapes in our list
}
}
}
And Shape.java
import java.awt.Color;
import java.awt.Graphics;
public class Shape {
private int x,y;
private int type;
private Color c;
public Shape(int x, int y, int type, Color c) {
this.x = x;
this.y = y;
this.type = type;
this.c = c;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getType() {
return type;
}
public Color getColor() {
return c;
}
}
In your DrawingPanel class you need a method like addShape(...) which will add a Shape object to the ArrayList. Then in the paintComponent(...) method you iterate through the ArrayList to paint each shape in the list.
Check out the Draw On Component example found in Custom Painting Approaches for a working example.
The example only draws Rectangles so your code will be a little more involved as you will need to check which type of shape you want to paint.

A simple Java program- trouble adding shapes to a panel

I am a newcomer to the language of Java and to Stack Overflow. I want to add shapes to a Panel to mimic a map. The problem is explained in the title - I don't know how to add the shapes into my panel. Please note that I am about halfway through completing this program which means that it doesn't have all of the function that I intend for it yet. I have two classes for this program - Map.java and MapShapes.java
My first class.
/** Program that maps a room in the house and sees how things will look from an overhead, 2d perspective. ;
* #author: James ;
*
* */
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Map extends JPanel{
MapShapes[] shapeArray = new MapShapes[20];
int count = 0;
private JLabel askLength, askWidth, askX, askY;
private JTextField length, width, x, y;
private JButton addButton;
private DrawingPanel drawPanel = new DrawingPanel();
public static void main(String[] args){
JFrame frame = new JFrame("Map");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Map panel = new Map();
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}// end of main;
public Map(){
JPanel controlPanel = new JPanel();
addButton = new JButton("Add a shape");
askX = new JLabel("X coordinate: ");
askY = new JLabel("Y coordinate: ");
askLength = new JLabel("Length: ");
askWidth = new JLabel("Width: ");
x = new JTextField(3);
y = new JTextField(3);
length = new JTextField(3);
width = new JTextField(3);
length.addActionListener(new Listener());
width.addActionListener(new Listener());
x.addActionListener(new Listener());
y.addActionListener(new Listener());
controlPanel.add(askX);
controlPanel.add(x);
controlPanel.add(askY);
controlPanel.add(y);
controlPanel.add(askLength);
controlPanel.add(length);
controlPanel.add(askWidth);
controlPanel.add(width);
controlPanel.add(addButton);
controlPanel.setPreferredSize(new Dimension (100, 400));
add(controlPanel);
add(drawPanel);
}// end of constructor;
private class DrawingPanel extends JPanel{
/** This public DrawingPanel() constructor.* */
public DrawingPanel(){
setPreferredSize(new Dimension(400, 400));
setBackground(Color.pink);
} // End of DrawingPanel() method.
/** This public void paintComponent(Graphics g) method* */
public void paintComponent(Graphics g){
super.paintComponent(g);
for(int index = 0; index<count; index++)
shapeArray[index].display(g);
} // End of paintComponent(Graphics g) method.
}// End of private class;
/** This class allows actions to be added to the buttons and text fields;*/
private class Listener implements ActionListener{
public void actionPerformed(ActionEvent event){
int lengthVal, widthVal, yVal, xVal;
JButton button = (JButton) event.getSource () ;
String textX = x.getText();
String textY = y.getText();
String textLength = length.getText();
String textWidth = width.getText();
xVal = Integer.parseInt(textX);
yVal = Integer.parseInt(textY);
lengthVal = Integer.parseInt(textLength);
widthVal = Integer.parseInt(textWidth);
if(button.getText().equals("Add a shape")){
if(count<shapeArray.length){
shapeArray[count] = new MapShapes(lengthVal, widthVal, xVal, yVal);
count++;
} // end of nested if block;
} // End of if block;
repaint();
}// end of method;
}// end of private class;
}// end of class;
My second class.
/** This class makes the rectangles for the Map program. ;
* #author: James ;
*/
import java.util.*; // So that we can use the Random class.
import java.awt.*; // So that we can use the Color class and the Graphics class.
/** This class makes rectangles.*/
public class MapShapes{
private int x;
private int y;
private int length;
private int width;
private Color colour;
public MapShapes(int length, int width, int x, int y){
this.length = length;
this.width = width;
this.x = x;
this.y = y;
this.colour = new Color(randInt(0,254), randInt(0,254), randInt(0,254));
}
/** This randInt(int lowest, int highest) method:
* Returns a random value within particular limits to instantiate the colour data field.
* */
public int randInt( int lowest, int highest){
Random generator = new Random();
int randomNum = generator.nextInt(highest - lowest) + lowest;
return randomNum;
}
public void display(Graphics j){
j.setColor(colour);
j.fillRect(x, y, length, width);
}
}// end of class;
You need to add a ActionListener to your addButton, which when triggered, gathers the information required from your other fields and adds them shapeArray and calls repaint on the instance of your DrawingPanel which is visible on the screen.
See How to Write an Action Listeners and How to Use Buttons, Check Boxes, and Radio Buttons for more details

JFrame and ActionListener; Waiting for user input

I am expanding Image editing application in Java. I want to make a class that would adjust contrast of the image. Main class calls apply method and passes image that has to be modified. I managed to create JFrame and algorithm for calculation, but I have problems with Action Listener because I don't know how to make my apply method wait for the users input and only then calculate and edit image. Here is the code for contrast class:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
lic class ContrastFilter extends Filter implements ActionListener {
private JFrame contFr;
private JButton ok;
private JTextField textF;
private String s;
private int contV;
private int factor;
public ContrastFilter(String name){
super(name);
}
public void makeFrame(){
contFr = new JFrame("contrast window");
Container contentPane = contFr.getContentPane();
contentPane.setLayout(new FlowLayout());
JLabel label = new JLabel("Enter contrast");
contentPane.add(label, BorderLayout.PAGE_START);
textF = new JTextField(5);
contentPane.add(textF, BorderLayout.PAGE_START);
ok = new JButton("OK");
ok.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event)
{
if (event.getSource() == ok){
s = textF.getText();
contV = Integer.parseInt(s);
factor = Math.round((259*(contV+255))/(255*(259 - contV)));
}}
});
contentPane.add(ok, BorderLayout.PAGE_START);
contFr.pack();
contFr.setVisible(true);
}
public void apply(OFImage image) {
makeFrame();
int height = image.getHeight();
int width = image.getWidth();
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
Color pix = image.getPixel(x, y);
image.setPixel(x, y, new Color(trunC(factor*(pix.getRed()-128)+128),
trunC(factor*(pix.getGreen()-128)+128),
trunC(factor*(pix.getBlue()-128)+128)));
} } }
public int trunC(int a){
if (a>255){
return 255;
}
return a;
}
}
If you want your apply() method to work after the button "OK" was clicked (user inputs something, then clicks OK), then you need to put an apply() invocation into you ActionListener's actionPerformed() method body.

dragging a jlabel around the screen

So I am trying to click and drag a JLabel around a JFrame. The following code allows a JLabel to be moved around the screen when the mouse is pressed / dragged at any point on the screen, but I am not sure how to add a second ActionListener to check if the mouse is clicking on the label, assuming that is the solution.
I would like to have multiple JLabels on the screen so that the only label being moved is the one that the mouse has clicked and is now dragging.
Thanks.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class test extends JFrame implements MouseMotionListener {
private JPanel panel = new JPanel(null);
private JLabel dragLabel = new JLabel("drag test");
private int mouseX = 200;
private int mouseY = 200;
public test() {
this.add(panel);
panel.setBackground(Color.WHITE);
panel.add(dragLabel);
dragLabel.setForeground(Color.RED);
dragLabel.setBounds(mouseX, mouseY, 100, 50);
panel.addMouseMotionListener(this);
}
#Override
public void mouseDragged(MouseEvent e) {
mouseX = e.getX();
mouseY = e.getY();
dragLabel.setBounds(mouseX, mouseY, 100, 50);
}
#Override
public void mouseMoved(MouseEvent e) {}
public static void main(String[] args) {
test frame = new test();
frame.setVisible(true);
frame.setSize(600, 400);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Another way to do this is to add the JLabel to a JLayeredPane or to a JPanel held by a JLayeredPane and add a MouseAdapter as the JLayeredPane's MouseListener and MouseMotionListener. Then when clicking on the label, move it to the JLayeredPane's JLayeredPane.DRAG_LAYER so it moves on top of everything else, then place the JLabel on whichever is the most appropriate level on mouse release. I've found this to work well when moving chess pieces on a chess board, for instance, and you want to make sure that the piece you're moving is displayed above all the other pieces when dragging.
Addition: You've probably left this thread, but if you come back, or for the benefit of others, I wanted to clarify what I meant by using a JLayeredPane by posting an example.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DragLabelOnLayeredPane extends JLayeredPane {
public static final int WIDTH = 680;
public static final int HEIGHT = 480;
private static final int GRID_ROWS = 8;
private static final int GRID_COLS = 6;
private static final int GAP = 3;
private static final Dimension LAYERED_PANE_SIZE = new Dimension(WIDTH, HEIGHT);
private static final Dimension LABEL_SIZE = new Dimension(60, 40);
private GridLayout gridlayout = new GridLayout(GRID_ROWS, GRID_COLS, GAP, GAP);
private JPanel backingPanel = new JPanel(gridlayout);
private JPanel[][] panelGrid = new JPanel[GRID_ROWS][GRID_COLS];
private JLabel redLabel = new JLabel("Red", SwingConstants.CENTER);
private JLabel blueLabel = new JLabel("Blue", SwingConstants.CENTER);
public DragLabelOnLayeredPane() {
backingPanel.setSize(LAYERED_PANE_SIZE);
backingPanel.setLocation(2 * GAP, 2 * GAP);
backingPanel.setBackground(Color.black);
for (int row = 0; row < GRID_ROWS; row++) {
for (int col = 0; col < GRID_COLS; col++) {
panelGrid[row][col] = new JPanel(new GridBagLayout());
backingPanel.add(panelGrid[row][col]);
}
}
redLabel.setOpaque(true);
redLabel.setBackground(Color.red.brighter().brighter());
redLabel.setPreferredSize(LABEL_SIZE);
panelGrid[4][3].add(redLabel);
blueLabel.setOpaque(true);
blueLabel.setBackground(Color.blue.brighter().brighter());
blueLabel.setPreferredSize(LABEL_SIZE);
panelGrid[1][1].add(blueLabel);
backingPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
setPreferredSize(LAYERED_PANE_SIZE);
add(backingPanel, JLayeredPane.DEFAULT_LAYER);
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
}
private class MyMouseAdapter extends MouseAdapter {
private JLabel dragLabel = null;
private int dragLabelWidthDiv2;
private int dragLabelHeightDiv2;
private JPanel clickedPanel = null;
#Override
public void mousePressed(MouseEvent me) {
clickedPanel = (JPanel) backingPanel.getComponentAt(me.getPoint());
Component[] components = clickedPanel.getComponents();
if (components.length == 0) {
return;
}
// if we click on jpanel that holds a jlabel
if (components[0] instanceof JLabel) {
// remove label from panel
dragLabel = (JLabel) components[0];
clickedPanel.remove(dragLabel);
clickedPanel.revalidate();
clickedPanel.repaint();
dragLabelWidthDiv2 = dragLabel.getWidth() / 2;
dragLabelHeightDiv2 = dragLabel.getHeight() / 2;
int x = me.getPoint().x - dragLabelWidthDiv2;
int y = me.getPoint().y - dragLabelHeightDiv2;
dragLabel.setLocation(x, y);
add(dragLabel, JLayeredPane.DRAG_LAYER);
repaint();
}
}
#Override
public void mouseDragged(MouseEvent me) {
if (dragLabel == null) {
return;
}
int x = me.getPoint().x - dragLabelWidthDiv2;
int y = me.getPoint().y - dragLabelHeightDiv2;
dragLabel.setLocation(x, y);
repaint();
}
#Override
public void mouseReleased(MouseEvent me) {
if (dragLabel == null) {
return;
}
remove(dragLabel); // remove dragLabel for drag layer of JLayeredPane
JPanel droppedPanel = (JPanel) backingPanel.getComponentAt(me.getPoint());
if (droppedPanel == null) {
// if off the grid, return label to home
clickedPanel.add(dragLabel);
clickedPanel.revalidate();
} else {
int r = -1;
int c = -1;
searchPanelGrid: for (int row = 0; row < panelGrid.length; row++) {
for (int col = 0; col < panelGrid[row].length; col++) {
if (panelGrid[row][col] == droppedPanel) {
r = row;
c = col;
break searchPanelGrid;
}
}
}
if (r == -1 || c == -1) {
// if off the grid, return label to home
clickedPanel.add(dragLabel);
clickedPanel.revalidate();
} else {
droppedPanel.add(dragLabel);
droppedPanel.revalidate();
}
}
repaint();
dragLabel = null;
}
}
private static void createAndShowUI() {
JFrame frame = new JFrame("DragLabelOnLayeredPane");
frame.getContentPane().add(new DragLabelOnLayeredPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
Please feel free to post any questions, need for clarification, or corrections.
Inspired by your code and user compilex's answer, follows demonstration:
Full code:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
/**
* A demonstration of moving around labels in a panel.
* <p>
* Some labels show up layed out in a grid. Then the
* user can drag any label anywhere on the panel.
* </p>
*/
public class LabelDragger {
public static void main(final String[] args) {
final int labelRows = 5, //How many rows of labels.
labelColumns = 5, //How many columns of labels.
labelWidth = 55, //Width for each label.
labelHeight = 20; //Height for each label.
//Border colors for labels:
final Color[] colors = new Color[]{Color.BLUE, Color.GREEN, Color.BLACK, Color.GRAY};
final Random prng = new Random(); //For selecting border color for each label.
final JPanel dragP = new JPanel(null); //Nicely set to null! :D Did not know that trick.
//Creating the listener for the panel:
final MouseAdapter ma = new MouseAdapter() {
private JLabel selectedLabel = null; //Clicked label.
private Point selectedLabelLocation = null; //Location of label in panel when it was clicked.
private Point panelClickPoint = null; //Panel's click point.
//Selection of label occurs upon pressing on the panel:
#Override
public void mousePressed(final MouseEvent e) {
//Find which label is at the press point:
final Component pressedComp = dragP.findComponentAt(e.getX(), e.getY());
//If a label is pressed, store it as selected:
if (pressedComp != null && pressedComp instanceof JLabel) {
selectedLabel = (JLabel) pressedComp;
selectedLabelLocation = selectedLabel.getLocation();
panelClickPoint = e.getPoint();
//Added the following 2 lines in order to make selectedLabel
//paint over all others while it is pressed and dragged:
dragP.setComponentZOrder(selectedLabel, 0);
selectedLabel.repaint();
}
else {
selectedLabel = null;
selectedLabelLocation = null;
panelClickPoint = null;
}
}
//Moving of selected label occurs upon dragging in the panel:
#Override
public void mouseDragged(final MouseEvent e) {
if (selectedLabel != null
&& selectedLabelLocation != null
&& panelClickPoint != null) {
final Point newPanelClickPoint = e.getPoint();
//The new location is the press-location plus the length of the drag for each axis:
final int newX = selectedLabelLocation.x + (newPanelClickPoint.x - panelClickPoint.x),
newY = selectedLabelLocation.y + (newPanelClickPoint.y - panelClickPoint.y);
selectedLabel.setLocation(newX, newY);
}
}
};
dragP.addMouseMotionListener(ma); //For mouseDragged().
dragP.addMouseListener(ma); //For mousePressed().
//Filling the panel with labels:
for (int row = 0; row < labelRows; ++row)
for (int col = 0; col < labelColumns; ++col) {
//Create label for (row, col):
final JLabel lbl = new JLabel("Label" + (row * labelColumns + col));
lbl.setHorizontalAlignment(JLabel.CENTER);
//lbl.setVerticalAlignment(JLabel.CENTER);
lbl.setBounds(col * labelWidth, row * labelHeight, labelWidth, labelHeight); //Grid-like positioning.
lbl.setBorder(new LineBorder(colors[prng.nextInt(colors.length)], 2)); //Set a border for clarity.
//Add label to panel:
dragP.add(lbl);
}
//Creating and showing the main frame:
final JFrame frame = new JFrame(LabelDragger.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//The size of the content pane adds some extra room for moving the labels:
final Dimension paneSize = new Dimension((int)(1.5 * labelWidth * labelColumns),
(int)(1.5 * labelHeight * labelRows));
frame.getContentPane().setPreferredSize(paneSize);
frame.getContentPane().add(dragP);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Explanations are added as comments.
Tips:
Take a look at the documentation on Container.findComponentAt(int x, int y), if you are going to add Components on the dragP Container, other than "draggable" labels.
Also, you can instead use Container.getComponentAt(int x, int y), in this case. I suggest you read their (small) documentation first.
Add a mouse listener to the label instead of the panel. (You might still need a mouse listener on the panel for the dragging but at least the one on the label can tell you if it was selected).
Create two global variables:
int x_pressed = 0;
int y_pressed = 0;
then create two events (mousePressed and mouseDragged over JLabel):
lbl_banner.addMouseListener(new MouseAdapter()
{
#Override
public void mousePressed(MouseEvent e) {
//catching the current values for x,y coordinates on screen
x_pressed = e.getX();
y_pressed = e.getY();
}
});
lbl_banner.addMouseMotionListener(new MouseMotionAdapter(){
#Override
public void mouseDragged(MouseEvent e){
//and when the Jlabel is dragged
setLocation(e.getXOnScreen() - x_pressed, e.getYOnScreen() - y_pressed);
}
});

Categories