How to Get X and Y Index of Element Inside Gridlayout

How to get X and Y index of element inside GridLayout?

This example shows how to create a grid button that knows its location on the grid. The method getGridButton() shows how to obtain a button reference efficiently based on its grid coordinates, and the action listener shows that the clicked and found buttons are identical.

GridButtonPanel

package gui;

import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
* @see http://stackoverflow.com/questions/7702697
*/
public class GridButtonPanel {

private static final int N = 5;
private final List<JButton> list = new ArrayList<JButton>();

private JButton getGridButton(int r, int c) {
int index = r * N + c;
return list.get(index);
}

private JButton createGridButton(final int row, final int col) {
final JButton b = new JButton("r" + row + ",c" + col);
b.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent e) {
JButton gb = GridButtonPanel.this.getGridButton(row, col);
System.out.println("r" + row + ",c" + col
+ " " + (b == gb)
+ " " + (b.equals(gb)));
}
});
return b;
}

private JPanel createGridPanel() {
JPanel p = new JPanel(new GridLayout(N, N));
for (int i = 0; i < N * N; i++) {
int row = i / N;
int col = i % N;
JButton gb = createGridButton(row, col);
list.add(gb);
p.add(gb);
}
return p;
}

private void display() {
JFrame f = new JFrame("GridButton");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(createGridPanel());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {

@Override
public void run() {
new GridButtonPanel().display();
}
});
}
}

My way to get X and Y index of buttons inside GridLayout

The original version of this example used extension:

GridButton extends JButton

The updated version was predicated on the colloquy seen here. While extension may be appropriate in some contexts, a few alternatives are mentioned here; a client property is particularly convenient. Identifying a button from its grid coordinates is also easy:

private static final int N = 5;
List<JButton> list = new ArrayList<>();

private JButton getGridButton(int r, int c) {
int index = r * N + c;
return list.get(index);
}

How to get the gridlayout cell position of a JButton in Java?

It's not the easiest thing to do... Likely it would be more useful to hold your JButtons in a 2D array, or better hold a map of JButton to position.

If you really must discern the gridcell from the button, call

JPanel.getComponents() (or whatever the parent container is), and find your Button in there. Then do the math.

say you find it at index 6.

Then since your grid is x by y divide by x to get the row, and mod by x to get the column.

so say the grid ix 4x4

6/4 is 1, so you are in the row with index 1 (second row)

6 % 4 is 2, so you are in the column with index 2 (third column)

How to get components from a JFrame with a GridLayout?

This example compares two approaches:

  1. Maintain a List<JButton> and calculate the index algebraically.

  2. Extend JButton and allow each button to maintain its own grid location.

GridLayout coordinates

I didn't test it but try this out:

    for (int y = s-1; y >= 0; y--) {

for (int x = 0; x < v; x++) {

grid[x][y] = new JLabel((x)+","+(y));

world.add(grid[x][y]);

How should a JButton keep track of its position in a GridLayout?

You could simply create a class extending JButton and adding two fields for the position in the grid. Create a new constructor (or setters) that assign values to theses fields, and two simple getters that will return them.

Example :

class MyJButton extends JButton {

private int gridx;
private int gridy;

public MyJButton(String label, int gridx, int gridy) {
super(label);
this.gridx = gridx;
this.gridy = gridy;
}

public int getGridx() {
return gridx;
}

public int getGridy() {
return gridy;
}
}

You can assign these gridx,gridy values when you build the GUI. For example, the following creates 16 buttons, labelled with their position in the grid :

for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
MyJButton btn = new MyJButton(i + "," + j, i, j);
//Configure your button here...
panel.add(btn);
}
}

How to get the row/column location of a widget in a QGridLayout?

There are two notions of coordinates that you're mixing up. There is the position within the parent widget. That's available via QWidget::x(), QWidget::y() and QWidget::pos() methods. You don't need to implement anything here: it already works.

Then there's the notion of the row and column within the grid layout. This can be obtained without a need for any subclassing. The grid layout knows where its widgets are, you can simply ask it for the row/column location of any widget.

screenshot

#include <QtWidgets>

struct Pos { int row = -1, col = -1; };

Pos gridPosition(QWidget * widget) {
if (! widget->parentWidget()) return {};
auto layout = qobject_cast<QGridLayout*>(widget->parentWidget()->layout());
if (! layout) return {};
int index = layout->indexOf(widget);
Q_ASSERT(index >= 0);
int _;
Pos pos;
layout->getItemPosition(index, &pos.row, &pos.col, &_, &_);
return pos;
}

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
QGridLayout l(&w);
QLabel gridPos;
l.addWidget(&gridPos, 0, 0, 1, 4);
for (int i = 1; i < 4; ++ i)
for (int j = 0; j < 3; ++ j) {
auto b = new QPushButton(QString("%1,%2").arg(i).arg(j));
l.addWidget(b, i, j);
QObject::connect(b, &QPushButton::clicked, [&gridPos, b]{
auto p = gridPosition(b);
gridPos.setText(QString("Grid Pos: %1,%2")
.arg(p.row).arg(p.col));
});
}
w.show();
return a.exec();
}

JButtons inside JPanels with a GridLayout JFrame

Here try this code example:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class LayoutExample extends JFrame
{
private static final String INITIAL_TEXT = "Nothing Pressed";
private static final String ADDED_TEXT = " was Pressed";
private JLabel positionLabel;
private JButton resetButton;
private static int gridSize = 4;

public LayoutExample()
{
super("Layout Example");
}

private void createAndDisplayGUI()
{
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

JPanel contentPane = new JPanel();
contentPane.setLayout(new FlowLayout(FlowLayout.LEFT, 20, 20));
contentPane.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 2));

JPanel leftPanel = new JPanel();
leftPanel.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 2));
leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));
JPanel labelPanel = new JPanel();
positionLabel = new JLabel(INITIAL_TEXT, JLabel.CENTER);
JPanel buttonLeftPanel = new JPanel();
resetButton = new JButton("Reset");
resetButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
positionLabel.setText(INITIAL_TEXT);
}
});
labelPanel.add(positionLabel);
buttonLeftPanel.add(resetButton);
leftPanel.add(labelPanel);
leftPanel.add(buttonLeftPanel);

contentPane.add(leftPanel);

JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(gridSize, gridSize, 10, 10));
for (int i = 0; i < gridSize; i++)
{
for (int j = 0; j < gridSize; j++)
{
JButton button = new JButton("(" + i + ", " + j + ")");
button.setActionCommand("(" + i + ", " + j + ")");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
JButton but = (JButton) ae.getSource();
positionLabel.setText(
but.getActionCommand() + ADDED_TEXT);
}
});
buttonPanel.add(button);
}
}
contentPane.add(buttonPanel);

setContentPane(contentPane);
pack();
setLocationByPlatform(true);
setVisible(true);
}

public static void main(String[] args)
{
if (args.length > 0)
{
gridSize = Integer.parseInt(args[0]);
}
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new LayoutExample().createAndDisplayGUI();
}
});
}
}

OUTPUT :

Start
After Click



Related Topics



Leave a reply



Submit