I'm using the following code in order to create a grid of JButtons and change their color on click. The next step I want to do is be able to compare this grid with other grids like it. I have been trying to get the coordinates of the JButton when clicked, (x, y), but have been unable to find a way to do so. Thanks for any help in advance!
public class ButtonGrid {
JFrame frame = new JFrame(); //creates frame
JButton[][] grid; //names the grid of buttons
HashMap<JButton, String> state;
static int WIDTH = 8;
static int LENGTH = 8;
public ButtonGrid(int width, int length) { //constructor
frame.setLayout(new GridLayout(width,length)); //set layout
grid = new JButton[width][length]; //allocate the size of grid
state = new HashMap<JButton, String>();
for(int y = 0; y < length; y++) {
for(int x = 0; x < width; x++) {
final JButton nb = new JButton();//new ButtonColor; //creates a button
nb.setPreferredSize(new Dimension(50, 50));
grid[x][y] = nb;
state.put(grid[x][y], "blank");
nb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(state.get(nb).equals("blank"))
mapButtonToColor(nb, "red");
else if(state.get(nb).equals("red"))
mapButtonToColor(nb, "blank");
setButtonColors();
}
});
frame.add(grid[x][y]); //adds new button to grid
}
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack(); //sets appropriate size for frame
frame.setVisible(true); //makes frame visible
}
public static void main(String[] args) {
new ButtonGrid(WIDTH, LENGTH);
}
public void mapButtonToColor(JButton b, String c) {
state.put(b, c);
}
public void setButtonColors() {
for(JButton b : state.keySet()) {
Color c = state.get(b).equals("red") ? Color.black : Color.white;
b.setBackground(c);
}
}
}
Can you not just implement a MouseListener?
yourButton.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
int x=e.getX();
int y=e.getY();
System.out.println(x+","+y);
}
});
This should do what you need as far as getting coordinates whenever your button is clicked. Also you could set the listener on your JFrame component to find the coordinate for every click (if that is needed).
maybe this will help you:
when a button is pressed in the said grid, simple iterate it to find the button that was clicked, then return the coordinates, something like this:
private class ButtonHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
Object source = e.getSource();
for(int i = 0;i< grid.length; i++){
for(int j = 0;j < grid.length;j++){
if(source == grid[i][j]){
JButton clicked == grid[i][j];
// do something with this
}
}
}
}
}
Related
I'm doing a Coursework assignment for the Uni, the assignment is to create a RectanglesGUI with JPanel, but I have a problem with the buttons I have created.
The buttonSOUTH supposed to do the following:
When the user clicks on the JButton in the SOUTH region, the
rectangles filled with color1 should all change to a random Color,
while the rectangles filled with color2 should not change. A second
click on the JButton should make the rectangles filled with color2 all
change to a random Color, while the rectangles filled with a random
Color by the first click should stay the same Color. The user should be
able to continue clicking on the button indefinitely, and with each click
one set of rectangles will be filled with a random Color.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class RectanglesGUI {
JFrame frame;
RectangleDrawPanel drawPanel;
Color color1 = Color.orange;
Color color2 = Color.blue;
public static void main (String[] args) {
RectanglesGUI gui = new RectanglesGUI();
gui.go();
}
//this method sets up the JFrame
public void go() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
drawPanel = new RectangleDrawPanel();
frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
frame.getContentPane().setBackground(Color.black);
frame.setSize(600,600);
frame.setVisible(true);
CreateButton newButton = new CreateButton();
newButton.CreateButton();
frame.repaint();
}
// To Create a new Button
public class CreateButton {
JButton buttonSOUTH;
JButton buttonNORTH;
public void CreateButton () {
buttonSOUTH = new JButton("Change Colors");
buttonSOUTH.setPreferredSize(new Dimension(100, 50));
buttonSOUTH.setVisible(true);
frame.add(buttonSOUTH, BorderLayout.SOUTH);
buttonSOUTH.addActionListener(new RandomColorListener());
buttonNORTH = new JButton("Reset Colors");
buttonNORTH.setPreferredSize(new Dimension(100, 50));
buttonNORTH.setVisible(true);
frame.add(buttonNORTH, BorderLayout.NORTH);
buttonNORTH.addActionListener(new ResetListener());
}
// ActionListener for buttonSOUTH
private class ResetListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
color1 = Color.orange;
color2 = Color.blue;
frame.repaint();
}
}
// ActionListener for buttonNORTH
private class RandomColorListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
ChangeColor c = new ChangeColor();
for (int i = 0; i < 100; i++){
if (i % 2 == 0) {
color1 = c.getColor1();
frame.repaint();
} else {
color2 = c.getColor2();
frame.repaint();
}
}
}
}
// Change Color Class
private class ChangeColor {
private Color getColor1(){
Random fill1 = new Random();
color1 = new Color (fill1.nextInt(256), fill1.nextInt(256),
fill1.nextInt(256));
return color1;
}
private Color getColor2(){
Random fill2 = new Random();
color2 = new Color (fill2.nextInt(256), fill2.nextInt(256),
fill2.nextInt(256));
return color2;
}
}
}
class RectangleDrawPanel extends JPanel {
public void paintComponent (Graphics g){
super.paintComponent(g);
Graphics2D g2=(Graphics2D)g;
int width = getWidth();
int height = getHeight();
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
int x = (getWidth() / 5) * i;
int y = (getHeight() / 5) * j;
if ((i % 2) == (j % 2)) {
g2.setColor(color1);
} else
g2.setColor(color2);
g2.fill3DRect(x,y,width,height,true);
}
}
}
}
}
But I don't know how to set this to be infinite
for (int i = 0; i < 100; i++){
if (i % 2 == 0) {
color1 = c.getColor1();
frame.repaint();
}
else {
color2 = c.getColor2();
frame.repaint();
}
}
this part for (int i = 0; i < 100; i++)
is not useful for checking.
both part inside condition checking will always executed. that mean both color2 and color1 will change. since i%2 will return 0 and 1
add this property to RectangleGui class boolean status=false;
then change code inside method actionPerformed in class RandomColorListener to:
if (status) {
color1 = c.getColor1();
frame.repaint();
} else {
color2 = c.getColor2();
frame.repaint();
}
status=!status;
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.
I'm trying to make a chess game, but I can't figure out how to smoothly redraw my cells. I want them to be redrawn every time a Piece moves. I tried to just keep adding Jframes, but it makes it glitch back to old frames. Is there a simple way to just update some part of the GUI?
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class GUI {
public static JFrame frame; //global variable for drawn frame
public static ChessBoardPane tiles;
public GUI(final Piece[][] board) { //GUI for Board and Pieces
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
frame = new JFrame("Chess"); //initialize frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //closes on exit
drawFrame(board); //draw frame
}
});
}
public void drawFrame(final Piece[][] board){ //updates gui with a new frame
try{
tiles=new ChessBoardPane(board);
frame.add(tiles); //add chess board to frame
frame.pack(); //resizes frame to fit chess grid
frame.setLocationRelativeTo(null); //window in middle of screen
frame.setVisible(true); //visible
} catch(Exception ex){
}
}
public class ChessBoardPane extends JPanel{ //creates a grid of jButtons
public ChessBoardPane(Piece board[][]) {
int index = 0;
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
for (int row = 0; row < Board.width; row++) {
for (int col = 0; col < Board.height; col++) {
Color color = index % 2 == 0 ? Color.LIGHT_GRAY : Color.DARK_GRAY; //cells are dark and light gray
gbc.gridx = col;
gbc.gridy = row;
String symbol;
if(board[col][Board.height-row-1]!=null){
symbol=board[col][Board.height-row-1].symbol; //chooses the correct picture for a piece
}
else
symbol=null;
Cell tile = new Cell(color,symbol);
tile.addActionListener(new ButtonActionListener(col, Board.height-row-1));
add(tile, gbc); //add cell to gui
index++;
}
index++;
}
}
private class ButtonActionListener implements ActionListener{ //used to get x and y coordinates for button presses and call methods
private int x;
private int y;
public ButtonActionListener(int x, int y){
this.x=x;
this.y=y;
}
public void actionPerformed(ActionEvent e){ //runs commands when a tile is pressed
Game.attemptMove(x,y);
}
}
}
public class Cell extends JButton { //sets up cell behavior
int x;
int y;
public Cell(Color background, String symbol) {
setContentAreaFilled(false);
if(symbol!=null){
ImageIcon img = new ImageIcon(symbol); //puts picture in cell
setIcon(img);
}
setBorderPainted(false);
setBackground(background); //sets cell color
setOpaque(true);
}
#Override
public Dimension getPreferredSize() { //sets size of cell
return new Dimension(75, 75);
}
}
}
I'm struggling with this code, I want to click on one of the cells of the grid, made by JPanel objects, and in that cell make appear a label with the index of that cell. I made a method to add final vars and return the JPanel with that label. It's not working. How can I do this?
public MyTest01(int width, int length) { //constructor
frame.setLayout(new GridLayout(width, length)); //set layout
JPanel temp = null;
JLabel l;
for (int y = 0; y < length; y++) {
for (int x = 0; x < width; x++) {
temp = new JPanel();
temp.setBorder(new LineBorder(Color.black, 1));
temp=doStuff(temp,x,y);
frame.add(temp);
}
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack(); //sets appropriate size for frame
frame.setVisible(true); //makes frame visible
}
public static JPanel doStuff( final JPanel temp,final int x, final int y) {
MouseListener mouseListener = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent mouseEvent) {
JLabel l = new JLabel("("+x+" - "+y+")");
temp.add(l);
}
};
return temp;
}
You never add the listener to the JPanel.
You need to revalidate and repaint the JPanel after adding a component (JLabel);
MouseListener mouseListener = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent mouseEvent) {
JLabel l = new JLabel("(" + x + " - " + y + ")");
temp.add(l);
temp.revalidate();; <-------- revalidate
temp.repaint(); <-------- repaint
}
};
temp.addMouseListener(mouseListener); <-------- add listener
return temp;
Here is the working code
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
public class MyTest {
JFrame frame = new JFrame();
public MyTest(int width, int length) { //constructor
frame.setLayout(new GridLayout(width, length)); //set layout
JPanel temp = null;
JLabel l;
for (int y = 0; y < length; y++) {
for (int x = 0; x < width; x++) {
temp = new JPanel();
temp.setBorder(new LineBorder(Color.black, 1));
temp = doStuff(temp, x, y);
frame.add(temp);
}
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack(); //sets appropriate size for frame
frame.setVisible(true); //makes frame visible
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new MyTest(3, 3);
}
});
}
public static JPanel doStuff(final JPanel temp, final int x, final int y) {
MouseListener mouseListener = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent mouseEvent) {
JLabel l = new JLabel("(" + x + " - " + y + ")");
temp.add(l);
temp.revalidate();;
temp.repaint();
}
};
temp.addMouseListener(mouseListener);
return temp;
}
}
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);
}
});