Get click position in grid. Java Swing - java

I got this code witch creates a clickable grid that shows the mouse position, altough i am not able to get the position in the grid in where the mouse is clicked, trying to be both X and Y position. Any ideas? This is how the grid looks:
Code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
import javax.swing.border.MatteBorder;
public class TestGrid02 {
public TestGrid02() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private static final int ROWS = 20;
private static final int COLUMNS = 20;
private static GridBagConstraints gbc;
public TestPane() {
setLayout(new GridBagLayout());
gbc = new GridBagConstraints();
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLUMNS; col++) {
gbc.gridx = col;
gbc.gridy = row;
CellPane cellPane = new CellPane();
Border border = null;
if (row < ROWS-1) {
if (col < COLUMNS-1) {
border = new MatteBorder(1, 1, 0, 0, Color.GRAY);
} else {
border = new MatteBorder(1, 1, 0, 1, Color.GRAY);
}
} else {
border = new MatteBorder(1, 1, 1, 0, Color.GRAY);
}
cellPane.setBorder(border);
add(cellPane, gbc);
}
}
}
}
public class CellPane extends JPanel {
private Color defaultBackground;
public CellPane() {
addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
defaultBackground = getBackground();
setBackground(Color.RED);
}
#Override
public void mouseExited(MouseEvent e) {
setBackground(defaultBackground);
}
#Override
public void mouseClicked(MouseEvent e){
//Here is where it is supposed to be
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(30, 30);
}
}
}
In the CellPane class, witch is intended to be the one that listens to the mouse it is supposed to be the function that i need, at the mouseClicked listener, however i have tried with e.getX() or e.getLocationOnScreen() and these values were changing everytime i click in the same grid.

Well, that looks familiar 🤣
So, the basic idea would be to pass in the cell it's coordinates (ie, row/column) value via the constructor, for example...
public class CellPane extends JPanel {
private Color defaultBackground;
private Point cellCoordinate;
public CellPane(Point cellCoordinate) {
this.cellCoordinate = cellCoordinate;
addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
defaultBackground = getBackground();
setBackground(Color.RED);
}
#Override
public void mouseExited(MouseEvent e) {
setBackground(defaultBackground);
}
#Override
public void mouseClicked(MouseEvent e) {
//Here is where it is supposed to be
System.out.println("Did click cell # " + getCellCoordinate().x + "x" + getCellCoordinate().y);
}
});
}
public Point getCellCoordinate() {
return cellCoordinate;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(30, 30);
}
}
The cell itself doesn't really care, not does it have any reasonable information available to it to determine how it's been laid out, so your best bet is to "tell" it the information you want it to represent.
For me, I'd just pass in the GridBagLayout row/col information, for example...
gbc.gridx = col;
gbc.gridy = row;
CellPane cellPane = new CellPane(new Point(col, row));
This way you remove all concept (and the issues associated with it) of how the cell is laid out

This approach (using buttons and action listeners) is better IMO. It uses the getButtonRowCol method to return a string indicating the button's location in an array (the buttonArray).
Use b.setBorderPainted(false); (uncomment that code line) to get rid of the borders around each button. Look to the values passed to the constructor of the GridLayout to remove the space between buttons.
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
public class GameGridLayout {
int size = 40;
int iconSize = 10;
JButton[][] buttonArray = new JButton[size][size];
ActionListener actionListener;
JLabel output = new JLabel("Click somewhere on the GUI");
GameGridLayout() {
JPanel gui = new JPanel(new BorderLayout(2,2));
gui.setBorder(new EmptyBorder(4,4,4,4));
gui.add(output,BorderLayout.PAGE_END);
JPanel gameContainer = new JPanel(new GridLayout(0,size,2,2));
gui.add(gameContainer);
actionListener = e -> output.setText(getButtonRowCol((JButton)e.getSource()));
for (int ii=0; ii<size*size; ii++) {
JButton b = getButton();
gameContainer.add(b);
buttonArray[ii%size][ii/size] = b;
}
JFrame f = new JFrame("GameGridLayout");
f.add(gui);
f.pack();
f.setMinimumSize(f.getSize());
f.setLocationByPlatform(true);
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setVisible(true);
}
private String getButtonRowCol(JButton button) {
StringBuilder sb = new StringBuilder();
for (int xx=0; xx<size; xx++) {
for (int yy=0; yy<size; yy++) {
if (button.equals(buttonArray[xx][yy])) {
sb.append("User selected button at: ");
sb.append(xx+1);
sb.append(",");
sb.append(yy+1);
break;
}
}
}
return sb.toString();
}
private JButton getButton() {
JButton b = new JButton();
b.setIcon(new ImageIcon(
new BufferedImage(iconSize,iconSize,BufferedImage.TYPE_INT_ARGB)));
b.setRolloverIcon(new ImageIcon(
new BufferedImage(iconSize,iconSize,BufferedImage.TYPE_INT_RGB)));
b.setMargin(new Insets(0,0,0,0));
//b.setBorderPainted(false);
b.setContentAreaFilled(false);
b.addActionListener(actionListener);
return b;
}
public static void main(String[] args) {
Runnable r = () -> new GameGridLayout();
SwingUtilities.invokeLater(r);
}
}

Related

How to make all images in Grid Overlay flush?

I am trying to implement a GUI for a maze-based game I created that meets the following specific conditions:
The GUI itself has a set size and is not resizable (line 41) .
The master panel (line 57) that contains all the maze images is scrollable. All maze image components are flush with each other.
If maze is small enough, then entire maze will be visible in master panel.
If maze is very large, then user would need to scroll.
The master panel needs to be accessed by a mouse listener (line 130) that returns the component that is being clicked.
The following code seems to meet criteria 1 and 3, but fails criteria 2:
public class MazeGui extends JFrame implements DungeonView {
private final Board board;
public MazeGui(ReadOnlyModel m) {
//this.setSize(m.getNumRows()*100, m.getNumCols()*100);
this.setSize(600, 600);
this.setLocation(200, 200);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.board = new Board(m);
JScrollPane scroller = new JScrollPane(board);
this.add(scroller, BorderLayout.CENTER);
setTitle("Dungeon Escape");
}
private class Board extends JPanel {
private ReadOnlyModel m;
public Board(ReadOnlyModel m) {
this.m = m;
GridLayout layout = new GridLayout(m.getNumRows(),m.getNumCols(), 0, 0);
// layout.setHgap(-100);
// layout.setVgap(-100);
this.setLayout(layout);
this.setSize(m.getNumRows()*64,m.getNumCols()*64);
for (int i = 0; i < m.getNumRows() * m.getNumCols(); i++) {
try {
// load resource from the classpath instead of a specific file location
InputStream imageStream = getClass().getResourceAsStream(String.format("/images/%s.png", m.getRoomDirections(i + 1)));
// convert the input stream into an image
Image image = ImageIO.read(imageStream);
// add the image to a label
JLabel label = new JLabel(new ImageIcon(image));
label.setPreferredSize(new Dimension(64, 64));
JPanel panel = new JPanel();
panel.setSize(64, 64);
String name = String.format("%d", i);
panel.setName(name);
panel.add(label);
// add the label to the JFrame
//this.layout.addLayoutComponent(TOOL_TIP_TEXT_KEY, label);
this.add(panel);
} catch (IOException e) {
JOptionPane.showMessageDialog(this, e.getMessage());
e.printStackTrace();
}
}
}
}
#Override
public void addClickListener(DungeonController listener) {
Board board = this.board;
MouseListener mouseListener = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println(String.format("(%d,%d)", e.getX(), e.getY()));
JPanel panel = (JPanel) board.getComponentAt(e.getPoint());
System.out.println(panel.getName());
}
};
board.addMouseListener(mouseListener);
}
#Override
public void refresh() {
this.repaint();
}
#Override
public void makeVisible() {
this.setVisible(true);
}
}
Here is an image of what it produces:
First, I'd make use of a different layout manager, one which would try and expand to fit the size of the underlying container.
Then, I would let the components do their jobs. I don't know why you're adding the label to another panel, the panel doesn't seem to be adding additional functionality/features and is just adding to the complexity.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
List<Maze.Direction> directions = new ArrayList<>(32);
directions.add(Maze.Direction.EAST_SOUTH);
directions.add(Maze.Direction.EAST_SOUTH_WEST);
directions.add(Maze.Direction.EAST_SOUTH_WEST);
directions.add(Maze.Direction.EAST_SOUTH_WEST);
directions.add(Maze.Direction.EAST_SOUTH_WEST);
directions.add(Maze.Direction.SOUTH_WEST);
directions.add(Maze.Direction.NORTH_EAST_SOUTH);
directions.add(Maze.Direction.NORTH_EAST_SOUTH_WEST);
directions.add(Maze.Direction.NORTH_EAST_SOUTH_WEST);
directions.add(Maze.Direction.NORTH_EAST_SOUTH_WEST);
directions.add(Maze.Direction.NORTH_EAST_SOUTH_WEST);
directions.add(Maze.Direction.NORTH_SOUTH_WEST);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH);
directions.add(Maze.Direction.NORTH);
directions.add(Maze.Direction.NORTH);
directions.add(Maze.Direction.NORTH);
directions.add(Maze.Direction.NORTH);
directions.add(Maze.Direction.NORTH);
System.out.println(directions.size());
Maze maze = new DefaultMaze(5, 6, directions);
MazeGui frame = new MazeGui(maze);
frame.addClickListener(null);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface Maze {
enum Direction {
EAST_SOUTH("EastSouth.png"), EAST_SOUTH_WEST("EastSouthWest.png"), SOUTH_WEST("SouthWest.png"),
NORTH_EAST_SOUTH("NorthEastSouth.png"), NORTH_EAST_SOUTH_WEST("NorthEastSouthWest.png"),
NORTH_SOUTH_WEST("NorthSouthWest.png"), NORTH_SOUTH("NorthSouth.png"), NORTH("North.png");
private BufferedImage image;
private Direction(String name) {
try {
image = ImageIO.read(getClass().getResource("/images/" + name));
} catch (IOException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
public BufferedImage getImage() {
return image;
}
}
public int getRows();
public int getColumns();
public Direction getRoomDirections(int index);
}
public class DefaultMaze implements Maze {
int rows;
int columns;
private List<Direction> directions;
public DefaultMaze(int rows, int columns, List<Direction> directions) {
this.rows = rows;
this.columns = columns;
this.directions = directions;
}
public int getRows() {
return rows;
}
public int getColumns() {
return columns;
}
#Override
public Direction getRoomDirections(int index) {
return directions.get(index);
}
}
public class MazeGui extends JFrame {
// Missing code
public interface DungeonController {
}
private final Board board;
public MazeGui(Maze m) {
this.setSize(600, 600);
this.setResizable(false);
this.board = new Board(m);
JScrollPane scroller = new JScrollPane(board);
this.add(scroller, BorderLayout.CENTER);
setTitle("Dungeon Escape");
}
public Board getBoard() {
return board;
}
public void addClickListener(DungeonController listener) {
Board board = getBoard();
board.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
Component cell = board.getComponentAt(e.getPoint());
System.out.println(cell.getName());
board.highlight(cell.getBounds());
}
});
}
private class Board extends JPanel {
private Rectangle selectedCell;
private Maze maze;
public Board(Maze maze) {
this.maze = maze;
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
for (int index = 0; index < maze.getRows() * maze.getColumns(); index++) {
Maze.Direction direction = maze.getRoomDirections(index);
JLabel label = new JLabel(new ImageIcon(direction.getImage()));
label.setName(direction.name());
add(label, gbc);
gbc.gridx++;
if (gbc.gridx >= maze.getColumns()) {
gbc.gridx = 0;
gbc.gridy++;
}
}
// addMouseListener(new MouseAdapter() {
// #Override
// public void mouseClicked(MouseEvent e) {
// Component component = getComponentAt(e.getPoint());
// selectedCell = null;
// if (component != null) {
// selectedCell = component.getBounds();
// }
// repaint();
// }
// });
}
public void highlight(Rectangle bounds) {
selectedCell = bounds;
repaint();
}
#Override
public void paint(Graphics g) {
super.paint(g);
if (selectedCell != null) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(new Color(0, 0, 255, 128));
g2d.fill(selectedCell);
g2d.dispose();
}
}
}
}
}
The GUI itself has a set size and is not resizable
So the issue here is that you are forcing the "board" panel to have an arbitrary size.
this.setSize(600, 600);
The actual size of the panel should be 8 * 64 = 512. So extra space is being added to each grid.
Don't hardcode size values.
It is the job of the layout manager to determine the preferred size of each component.
So instead of using setSize(...) you should pack() the frame before making it visible:
this.pack();
this.setVisible(true);
When you do this you will see that the maze fits completely in the frame.
If you want extra space around the maze then you need to add a "border" to your board:
setBorder( new EmptyBorder(88, 88, 88, 88) );
GridLayout layout = new GridLayout(m.getNumRows(),m.getNumCols(), 0, 0);
Turns out I should have been using GridBagLayout!
There is no need to change layout managers, only use the layout managers more effectively.
If you really for some reason need to specify a fixed frame size then you can make the following change:
//this.add(scroller, BorderLayout.CENTER);
JPanel wrapper = new JPanel( new GridBagLayout() );
wrapper.add(scroller, new GridBagConstraints());
this.add(wrapper, BorderLayout.CENTER);
This will allow the "board" panel to be displayed at its preferred size and the "board" panel will be centered in its parent container.
Using these tips will help you effectively create more complicated layouts.

How to add zooming and panning functions to a JPanel?

So I have a program in Java which uses a grid bag layout to create cells(like graph paper), and if a mouse is over one of the cell said cell will change its color. I would like to implement a zoom function, using mouse scroll wheel. Also I would like to add a function that, when your zoomed in, you can pan around by clicking and dragging the zoomed in canvas. To specify panning around, think of clicking and dragging to move around a zoomed in map, like google maps.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
import javax.swing.border.MatteBorder;
public class Testing {
public int RowI = 10;
public int ColI = 10;
public static void main(String[] args) {
new Testing();
}
public Testing() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
for (int row = 0; row < RowI; row++) {
for (int col = 0; col < ColI; col++) {
gbc.gridx = col;
gbc.gridy = row;
CellPane cellPane = new CellPane();
Border border = null;
if (row < 4) {
if (col < 4) {
border = new MatteBorder(1, 1, 0, 0, Color.GRAY);
} else {
border = new MatteBorder(1, 1, 0, 1, Color.GRAY);
}
} else {
if (col < 4) {
border = new MatteBorder(1, 1, 1, 0, Color.GRAY);
} else {
border = new MatteBorder(1, 1, 1, 1, Color.GRAY);
}
}
cellPane.setBorder(border);
add(cellPane, gbc);
}
}
}
}
public class CellPane extends JPanel { //The CellPane class changes the color of an individual cell based on whether or no the mouse I on a cell.
private Color defaultBackground; //This is a private color that is only used by the mouseListener.
public CellPane() {
addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) { //If mouse is on cell turn cell the given color(in this case green).
defaultBackground = getBackground();
setBackground(Color.GREEN);
}
#Override
public void mouseExited(MouseEvent e) { //If mouse is not on cell revert to default background.
setBackground(defaultBackground);
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(50, 50); //Cell size on x and y axis.
}
}
}
Maybe this question will answer what you're looking for.

Add and remove button dynamically in Swing frame

I'm developing a swing application. In that I've a JFrame which add JTextfield and JButton dynamically on the button click.and remove the created components if the user clicks the same button.
In the below screen image , when user clicks ADD button new row was added, and text was changed to REMOVE like in 2nd image.
New Row added and previous button text changed to REMOVE.
Now, if I click the REMOVE button, then the newly added row has to dispose and then button has to change the text again to ADD.
I've tried till adding the components, but I stuck up with removing the newly added row.
Anyone please guide me to achieve this.
Below is my code.
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ButtonAddDynamic implements ActionListener {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ButtonAddDynamic().createAndShowGUI();
}
});
}
private JFrame frame;
private JPanel panel = new JPanel(new GridBagLayout());
private GridBagConstraints constraints = new GridBagConstraints();
private List fields = new ArrayList();
private List fieldButton = new ArrayList();
private List fieldFile = new ArrayList();
private static int countReport = 0;
String files = null;
int y = 2;
protected void createAndShowGUI() {
try {
UIManager
.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
} catch (InstantiationException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
String[] labels = { "VALIDATION FORM" };
for (String label : labels)
addColumn(label);
frame = new JFrame("Add Button Dynamically");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(panel));
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
// Set the default button to button1, so that when return is hit, it
// will hit the button1
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
}
private void addColumn(String labelText) {
constraints.gridx = fields.size();
constraints.gridy = 1;
panel.add(new JLabel(labelText), constraints);
constraints.gridy = 2;
final JTextField field = new JTextField(40);
field.setEditable(false);
panel.add(field, constraints);
fields.add(field);
// constraints.gridy=3;
constraints.gridx = fields.size() + fieldButton.size();
final JButton button = new JButton("ADD");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (button.getText().equals("ADD")) {
button.setText("REMOVE");
addRowBelow();
frame.pack();
} else if (button.getText().equals("REMOVE")) {
button.setText("ADD");
frame.pack();
}
}
});
panel.add(button, constraints);
fieldButton.add(button);
panel.revalidate(); // redo layout for extra column
}
private void addRowBelow() {
y++;
constraints.gridy = y;
// System.out.println(fields.size());
for (int x = 0; x < fields.size(); x++) {
constraints.gridx = x;
final JTextField field = new JTextField(40);
field.setEditable(false);
panel.add(field, constraints);
constraints.gridx = x + 1;
final JButton button = new JButton("ADD");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (button.getText().equals("ADD")) {
button.setText("REMOVE");
addRowBelow();
frame.pack();
} else if (button.getText().equals("REMOVE")) {
button.setText("ADD");
frame.pack();
}
}
});
panel.add(button, constraints);
}
}
public void actionPerformed(ActionEvent ae) {
if ("Add Another TextField and Button".equals(ae.getActionCommand())) {
addRowBelow();
frame.pack();
frame.setLocationRelativeTo(null);
}
}
}
Trying to use GridBagLayout is making this very complicated for you. A nested layout scheme is much easier to work with when you are doing this type of thing.
See this MCVE:
I'm not sure I understood your intended functionality 100% correct but I don't think it's as important as the layouts.
My layout scheme is as follows:
This is nice because BoxLayout will handle the vertical listing without much hullabaloo. Instead of having to wrangle with GridBagConstraints, the text field and button are contained together by a panel.
import javax.swing.*;
import java.awt.event.*;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Insets;
public class FieldList implements Runnable, ActionListener {
public static void main(String... args) {
SwingUtilities.invokeLater(new FieldList());
}
final int maxFields = 2;
JFrame frame;
JPanel listing;
#Override
public void run() {
frame = new JFrame("Text Field Listing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel content = new JPanel(new BorderLayout());
content.add(new JLabel("Input Form", JLabel.CENTER), BorderLayout.NORTH);
listing = new JPanel();
listing.setLayout(new BoxLayout(listing, BoxLayout.Y_AXIS));
content.add(listing, BorderLayout.CENTER);
frame.setContentPane(content);
addNewField();
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
void addNewField() {
FieldButtonPair field = new FieldButtonPair();
field.button.addActionListener(this);
listing.add(field);
frame.pack();
}
void removeLastField() {
listing.remove(listing.getComponentCount() - 1);
frame.pack();
}
#Override
public void actionPerformed(ActionEvent ae) {
AddRemoveButton source = (AddRemoveButton)ae.getSource();
if(source.state == AddRemoveButton.State.ADD) {
if(listing.getComponentCount() < maxFields) {
addNewField();
source.setState(AddRemoveButton.State.REMOVE);
}
} else if(source.state == AddRemoveButton.State.REMOVE) {
removeLastField();
source.setState(AddRemoveButton.State.ADD);
}
}
}
class FieldButtonPair extends JPanel {
JTextField field;
AddRemoveButton button;
FieldButtonPair() {
super(new BorderLayout());
field = new JTextField();
add(field, BorderLayout.CENTER);
button = new AddRemoveButton();
add(button, BorderLayout.EAST);
}
#Override
public Dimension getPreferredSize() {
Dimension pref = super.getPreferredSize();
pref.width = Math.max(480, pref.width);
return pref;
}
}
class AddRemoveButton extends JButton {
enum State { ADD, REMOVE }
State state = State.ADD;
AddRemoveButton() {
setText(state.name());
}
void setState(State state) {
setText(state.name());
this.state = state;
}
#Override
public Dimension getPreferredSize() {
Dimension pref = super.getPreferredSize();
Font f = getFont();
FontMetrics fm = getFontMetrics(f);
int w = fm.stringWidth(State.REMOVE.name());
Insets ins = getInsets();
pref.width = (ins.left + w + ins.right);
return pref;
}
}

Trying To Delay the Appearance of JLabels in a JDialog

Hi I've there a little problem: What I want is to delay the appearance of JLabels in a JDialog-Window, in terms of that the first line of JLabels shoud come out and then two seconds later the second line of Jlabels etc.
I've tried something with Windowlistener,the doClick()-Method etc., bu every time the Jdialog revalidates all of its panels AT ONCE and shows them without any delaying!
Please help me(Just copy the code below and try out)!
package footballQuestioner;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
public class attempter {
public static void main(String[] args) throws InterruptedException {
JDialog dialog = new Punkte();
}
}
class Punkte extends JDialog {
private JPanel screenPanel = new JPanel(new GridLayout(4, 1));
private JButton button = new JButton();
private int i = 1;
private class WindowHandler implements WindowListener {
#Override
public void windowActivated(WindowEvent e) {
}
#Override
public void windowClosed(WindowEvent e) {
}
#Override
public void windowClosing(WindowEvent e) {
}
#Override
public void windowDeactivated(WindowEvent e) {
}
#Override
public void windowDeiconified(WindowEvent e) {
}
#Override
public void windowIconified(WindowEvent e) {
}
#Override
public void windowOpened(WindowEvent e) {
button.doClick(1000);
button.doClick(1000);
button.doClick(1000);
button.doClick(); // here im trying to delay the appearance of the
// JLabels....
}
}
private class ButtonHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
switch (i) {
case 1:
settingUpPanel(getPanelFromScreenPanel(i), "Right", new Color(
102, 205, 0));
settingUpPanel(getPanelFromScreenPanel(i), "Wrong", Color.RED);
break;
case 2:
settingUpPanel(getPanelFromScreenPanel(i), "Trefferquote",
Color.YELLOW);
break;
case 3:
settingUpPanel(getPanelFromScreenPanel(i), "Ausgezeichnet",
Color.BLUE);
break;
}
System.out.println(i);
i++;
}
}
public Punkte() {
button.addActionListener(new ButtonHandler());
addWindowListener(new WindowHandler());
setModal(true);
setResizable(true);
setLayout(new BorderLayout());
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
settingUpScreenPanel();
add(screenPanel);
setSize(1200, 1000);
centeringWindow();
setVisible(true);
}
private void settingUpScreenPanel() {
JPanel titlePanel = new JPanel(new GridBagLayout());
JPanel rightWrongCountPanel = new JPanel(new GridLayout(1, 2));
JPanel shareOfRightQuestions = new JPanel(new GridBagLayout());
JPanel grade = new JPanel(new GridBagLayout());
settingUpPanel(titlePanel, "Result", Color.BLACK);
// settingUpPanel(rightWrongCountPanel,
// "Right: "+numberOfRightAnsers+"/6",new Color(102,205,0));
// settingUpPanel(rightWrongCountPanel,
// "Wrong: "+(6-numberOfRightAnsers)+"/6", Color.RED);
// settingUpPanel(shareOfRightQuestions,
// "Trefferquote: "+(numberOfRightAnsers*100/6)+"%",Color.YELLOW);
// settingUpPanel(summaSummarum,
// getBufferedImage("footballQuestioner/Strich.png"));
// settingUpPanel(grade,"Aushezeichnet", Color.BLUE);
borderingJPanel(screenPanel, null, null);
titlePanel.setOpaque(false);
rightWrongCountPanel.setOpaque(false);
shareOfRightQuestions.setOpaque(false);
grade.setOpaque(false);
screenPanel.add(titlePanel);
screenPanel.add(rightWrongCountPanel);
screenPanel.add(shareOfRightQuestions);
screenPanel.add(grade);
}
private void settingUpPanel(JComponent panel, String string, Color color) {
Font font = new Font("Rockwell Extra Bold", Font.PLAIN, 65);
JPanel innerPanel = new JPanel(new GridBagLayout());
JLabel label = new JLabel(string);
label.setForeground(color);
label.setFont(font);
innerPanel.add(label);
innerPanel.setOpaque(false);
panel.add(innerPanel);
panel.validate();
panel.repaint();
}
public JPanel getPanelFromScreenPanel(int numberOfPanel) {
JPanel screenPanel = (JPanel) getContentPane().getComponent(0);
JPanel labelPanel = (JPanel) screenPanel.getComponent(numberOfPanel);
return labelPanel;
}
public void centeringWindow() {
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int x;
int y;
x = (int) (dimension.getWidth() - getWidth()) / 2;
y = (int) (dimension.getHeight() - getHeight()) / 2;
setLocation(x, y);
}
public void borderingJPanel(JComponent panel, String jPanelname,
String fontStyle) {
Font font = new Font(fontStyle, Font.BOLD + Font.ITALIC, 12);
if (jPanelname != null) {
panel.setBorder(BorderFactory.createTitledBorder(BorderFactory
.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY,
Color.WHITE), jPanelname,
TitledBorder.DEFAULT_JUSTIFICATION,
TitledBorder.DEFAULT_POSITION, font));
} else if (jPanelname == null || fontStyle == null) {
panel.setBorder(BorderFactory.createTitledBorder(BorderFactory
.createEtchedBorder(EtchedBorder.LOWERED, Color.BLACK,
Color.WHITE)));
}
panel.setOpaque(false);
}
}
This is a really good use case for javax.swing.Timer...
This will allow you to schedule a callback, at a regular interval with which you can perform an action, safely on the UI.
private class WindowHandler extends WindowAdapter {
#Override
public void windowOpened(WindowEvent e) {
System.out.println("...");
Timer timer = new Timer(2000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JPanel panel = getPanelFromScreenPanel(1);
panel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
for (int index = 0; index < 100; index++) {
panel.add(new JLabel(Integer.toString(index)), gbc);
}
panel.revalidate();
}
});
timer.start();
timer.setRepeats(false);
}
}
Now, if you wanted to do a series of actions, separated by the interval, you could use a counter to determine the number of "ticks" that have occurred and take appropriate action...
private class WindowHandler extends WindowAdapter {
#Override
public void windowOpened(WindowEvent e) {
System.out.println("...");
Timer timer = new Timer(2000, new ActionListener() {
private int counter = 0;
private int maxActions = 10;
#Override
public void actionPerformed(ActionEvent e) {
switch (counter) {
case 0:
// Action for case 0...
break;
case 1:
// Action for case 1...
break;
.
.
.
}
counter++;
if (counter >= maxActions) {
((Timer)e.getSource()).stop();
}
}
});
timer.start();
}
}
Take a look at How to use Swing Timers for more details

modifying addMouseListener()

This is my button Code onclick i want my program to wait for the user to click one JPanel and as the user clicks the JPanel it should print its name on console.
This button code is not showing the output
JPopupMenu popupMenu_1 = new JPopupMenu();
JMenuItem mntmOneToOne = new JMenuItem("One to One");
mntmOneToOne.setIcon(new ImageIcon("C:\\Users\\Ashad\\Desktop\\oneToone.png"));
popupMenu_1.add(mntmOneToOne);
OneToOne.addMouseListener(new MouseAdapter()
{
#Override
public void mouseClicked(MouseEvent arg0)
{
MouseListener Listen= new MouseAdapter()
{
public void mousePressed(MouseEvent me)
{
String name=new String();
JPanel panel = (JPanel) me.getSource();
// name = panel.getName();
System.out.println(panel.getName());
}
};
}
});
for better help sooner post an SSCCE, short,
runnable, compilable,
because works in my SSCCE, and the answer to
This is my button Code onclick i want my program to wait for the user
to click one JPanel and as the user clicks the JPanel it should print
its name on console.
issue must be in rest of your code,
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class MyGridLayout {
public MyGridLayout() {
JPanel bPanel = new JPanel();
bPanel.setLayout(new GridLayout(10, 10, 2, 2));
for (int row = 0; row < 10; row++) {
for (int col = 0; col < 10; col++) {
JPanel b = new JPanel() {
private static final long serialVersionUID = 1L;
#Override
public Dimension getPreferredSize() {
return new Dimension(20, 20);
}
};
b.putClientProperty("column", row);
b.putClientProperty("row", col);
b.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
JPanel btn = (JPanel) e.getSource();
System.out.println("clicked column " + btn.getClientProperty("column")
+ ", row " + btn.getClientProperty("row"));
}
});
b.setBorder(new LineBorder(Color.blue, 1));
bPanel.add(b);
}
}
JFrame frame = new JFrame("PutClientProperty Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(bPanel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
MyGridLayout myGridLayout = new MyGridLayout();
}
});
}
}
You declared a MouseAdapter in your MouseListener mouseClicked method which just sits there and does exactly nothing because nothing is done with it. If you want to add a MouseListener to a panel do the following:
panel.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
JPanel panel = (JPanel) arg0.getSource();
System.out.println(panel.getName());
}
});

Categories

Resources