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.
Related
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
}
}
}
}
}
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.
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 create a Java game with a 10 x 10 grid made up of cells.
The Grid looks liks this:
public class Grid extends JPanel implements MouseListener {
public static final int GRID_SIZE = 10;
public Grid() {
setPreferredSize(new Dimension(300, 300));
setLayout(new GridLayout(GRID_SIZE, GRID_SIZE));
for (int x = 0; x < GRID_SIZE; x++)
for (int y = 0; y < GRID_SIZE; y++)
add(new Cell(x, y));
addMouseListener(this);
}
// All Mouse Listener methods are in here.
The Cell class looks like this:
public class Cell extends JPanel {
public static final int CELL_SIZE = 1;
private int xPos;
private int yPos;
public Cell (int x, int y) {
xPos = x;
yPos = y;
setOpaque(true);
setBorder(BorderFactory.createBevelBorder(CELL_SIZE));
setBackground(new Color(105, 120, 105));
setPreferredSize(new Dimension(CELL_SIZE, CELL_SIZE));
}
// Getter methods for x and y.
My issue is that I am now trying to implement the MouseListeners in the Grid class. What I have realised is that whilst I can return the X and Y coordinates of the Grid, I can't seem to manipulate the cells themselves.
I am assuming this is because when I created them in Grid, I am creating 100 random Cells with no identifiers and so I have no way to directly access them.
Could anybody give me advice on this? Do I need to overhaul my code and the way I am creating the cells? Am I being terribly stupid and missing an obvious way of accessing them?
Thanks
You could use an adapter pattern, as shown below. That way, you can add the listener to each grid cell individually, but still handle the events from Grid.
Note that Grid no longer implements MouseListener, this is handled by the cells now.
public class Grid extends JPanel {
public static final int GRID_SIZE = 10;
public Grid() {
setPreferredSize(new Dimension(300, 300));
setLayout(new GridLayout(GRID_SIZE, GRID_SIZE));
for (int x = 0; x < GRID_SIZE; x++) {
for (int y = 0; y < GRID_SIZE; y++) {
final Cell cell = new Cell(x, y);
add(cell);
cell.addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent e) {
click(e, cell);
}
// other mouse listener functions
});
}
}
}
public void click(MouseEvent e, Cell cell) {
// handle the event, for instance
cell.setBackground(Color.blue);
}
// handlers for the other mouse events
}
A subclass could override this as:
public class EnemyGrid extends Grid {
public void click(MouseEvent e, Cell cell) {
cell.setBackground(Color.red);
}
}
use put/getClientProperty
you can to multiple this method, with other additional parameters
example about How to determine clicked JButton in a grid, the same logics for JPanel and Mouse(Xxx)Listener
override getPreferredSize(new Dimension(x, y)) for JPanel instead of setPreferredSize(new Dimension(CELL_SIZE, CELL_SIZE));
The most obvious way would be to move your MouseListener on the Cell class itself.
Second option I can think of is to use java.awt.Container.getComponentAt(int, int).
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);
}
});