I'm trying to create a method myMethod in JAVA that can fill a user defined jPanel with buttons according to the panels size. It works if I change "Object j" to "jFrameScreen j" , remove Component p and change variable p to j. jPanel2 in myMethod.
But that's not what I want, I want the user to be able to determine what jFrame and jPanel the buttons will be created on when calling myMethod.
When I run the code as shown here it gives me these errors:
p.add(btn[b]); //JButton cannot be converted to PopupMenu
j.setVisible(true); //Cannot find symbol, method setVisible(boolean)
My work is as follows:
public class Main {
public static void main(String[] args) {
jFrameScreen j = new jFrameScreen();
myMethod(j, j.jPanel2, 10, 10, 600, 400);
}
public static void myMethod(Object j, Component p, int col, int row, int myWidth, int myHeight) {
int bWidth = myWidth / col;
int bHeight = myHeight / row;
int numberOfButtons = (myWidth / bWidth) * (myHeight / bHeight);
JButton btn[] = new JButton[numberOfButtons];
for (int k = 0, x = 0, b = 0; k < myWidth / bWidth; k++, x += bWidth) {
for (int i = 0, y = 0; i < myHeight / bHeight; i++, y += bHeight, b++) {
btn[b] = new JButton();
btn[b].setBounds(2 + x, 3 + y, bWidth, bHeight);
btn[b].setText(Integer.toString(b));
btn[b].setVisible(true);
p.add(btn[b]); //JButton cannot be converted to PopupMenu
}
}
p.setVisible(true);
j.setVisible(true); //Cannot find symbol, method setVisible(boolean)
}
}
A variable declared with the Object type doesn't have a setVisible() method.
And Component.add() accepts only instances of the PopupMenu class :
public void add(PopupMenu popup) {
But that's not what I want, I want the user to be able to determine
what jFrame and jPanel the buttons will be created on when calling
"myMethod".
You try to provide a generic method but you don't rely on suitable base classes according to your requirements.
Object and Component are too generic to represent respectively a JFrame and a JPanel.
If these two parameters have to represent instances of these types, just use them : replace Object j by JFrame j and Component p by JPanel p.
Besides, their naming is really not good. frame and panel are better :
public static void myMethod(JFrame frame, JPanel panel, int col, int row, int myWidth, int myHeight) {
Related
I am having challenges calling my graphics method in my main method so that it can paint a triangle using points from an array. When I don't use an array and just use regular numbers the painting works just fine, but the idea of the program is that the user enters values into the array to be used. Any suggestions on how to make the triangle paint? Here's the code: (I have all the proper imports)
public class Summative extends JFrame{
static int[] inpoot() {
Scanner input = new Scanner(System.in);
int[] numbers = new int[6];
System.out.println("Please enter 3 sets of coordinates:");
for (int i = 0; i < 6; i++) {
numbers[i] = input.nextInt();
}
return numbers;
}
static void outpoot(int [] numbers) {
double A = Math.sqrt (Math.pow ((numbers[4] - numbers[2]), 2) + Math.pow ((numbers[5] - numbers[3]), 2));
double B = Math.sqrt (Math.pow ((numbers[4] - numbers[0]), 2) + Math.pow ((numbers[5] - numbers[1]), 2));
double C = Math.sqrt (Math.pow ((numbers[2] - numbers[0]), 2) + Math.pow ((numbers[3] - numbers[1]), 2));
double s = (A + B + C) / 2;
double area = (Math.sqrt (s * (s - A) * (s - B) * (s - C)));
System.out.println ("The area of the triangle entered is : " + area + " units squared.");
}
public static void main(String[] args) {
int[] numbers = inpoot();
outpoot(numbers);
JFrame frame = new JFrame("Triangle");
frame.setVisible(true);
frame.setSize(new Dimension(500, 500));
JPanel panel = new myPanel();
frame.add(panel);
frame.validate();
frame.repaint();
}
}
And this is the graphics class:
public class myPanel extends JPanel{
public void paint (int [] numbers, Graphics g) {
super.paint (g);
g.setColor (Color.BLACK);
int[] xTri = {numbers[0], numbers[2], numbers[4]};
int[] yTri = {500 - numbers[1], 500 - numbers[3], 500 - numbers[5]};
g.fillPolygon (xTri, yTri, 3);
}
}
You need to supply some means to pass the information from you main method to your myPanel class. In your case, you could simply supply a custom constructor, something like...
public class myPanel extends JPanel{
private int[] xTri;
private int[] yTri;
public myPanel(int[] xTri, int[] yTri) {
this.xTri = xTri;
this.yTri = yTri;
}
public void paint (int [] numbers, Graphics g) {
super.paint (g);
g.setColor (Color.BLACK);
g.fillPolygon (xTri, yTri, xTri.length);
}
}
Observations...
Don't extend from JFrame, you're creating a new instance anyway which is just confusing the issue
Because of the way that Swing works, you need to make sure that you start you UI within the context of the Event Dispatching Thread. So, in your main method, you should use...
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
// Your UI code here
}
});
and build your UI within the run method
I've been trying to create a maze using swing.
For now, I just want to create a 10x10 grid using lines, which would be all around my cells (a 40x40 square, from the "w"). I'm trying to create each lines of my square depending of my boolean[] walls tab ( walls[0] is top, walls[1] is right, walls[2] is bottom and walls[3] is left).
If the value is true, then we have a wall, if not, the passage is opened and no line on this side.
I'm using an ArrayList<Cell> for collecting the differents cells of my grid.
All of this is working (it seems) but I've came across a problem.
Indeed I would like to use my object's (Cell) attributes in paintComponent(Graphics g) for doing custom dimensions of cells.
But, I don't know really how to do this. I've tried to separate my Cell class and do another class for my graphic interface but it didn't worked out as well.
public class Cell {
int i,j;
int w = 40;
ArrayList<Cell> grid = new ArrayList<Cell>();
boolean[] walls = new boolean[4];
boolean visited;
public Cell () {
this.setup();
}
public Cell(int i, int j) {
this.i = i;
this.j = j;
this.walls[0] = true;
this.walls[1] = true;
this.walls[2] = true;
this.walls[3] = true;
this.visited = false;
}
public int getI() {
return i;
}
public int getJ() {
return j;
}
public void setup() {
JFrame f = new JFrame("Maze");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(400, 400);
f.setVisible(true);
JPanel panel = new JPanel();
f.getContentPane().add(panel);
int cols = (int) f.getWidth()/w;
int rows = (int) f.getHeight()/w;
for (int j = 0; j < rows; j++)
{
for (int i = 0; i < cols; i++)
{
Cell cell = new Cell(i,j);
grid.add(cell);
}
}
}
public void paintComponent(Graphics g) {
int x = i*w;
int y = j*w;
g.setColor(Color.black);
if (this.walls[0])
g.drawLine(x , y , x + w, y );
if (this.walls[1])
g.drawLine(x + w, y , x + w, y + w);
if (this.walls[2])
g.drawLine(x + w, y + w, x , y + w);
if (this.walls[3])
g.drawLine(x , y + w, x , y );
}
public static void main(String[] args) {
new Cell();
}
}
You can't just add a paintComponent(...) method to a class and expect that method to be invoked.
To do custom painting you override the paintComponent() method of a JPanel. So you need a custom panel. The panel would contain the ArrayList of Cell objects and in the paintComponent() method you iterate through each Cell object and paint it.
So first you need to start by reading the section from the Swing tutorial on Custom Painting to learn the basics of painting a single object.
Once you understand that you can check out Custom Painting Approaches which shows how to paint from a List of objects.
I have a Board 14x14 which has JButtons and every Jbutton has a different color. When you click one of those buttons, it checks the neighbors with the same color and removes them. When it removes them, theres a blank space between the board so the above buttons, should move down to fill the blank space. I tried with GridLayout but I don't know how to move the above buttons.
This actually is a case where you can hardly use a layout manager at all.
A LayoutManager is supposed to compute the layout of all components at once. It is triggered by certain events (e.g. when the parent component is resized). Then it computes the layout and arranges the child components accordingly.
In your case, the situation is quite different. There is no layout manager that can sensibly represent the "intermediate" state that appears while the upper buttons are falling down. While the components are animated, they cannot be part of a proper layout.
The animation itself may also be a bit tricky, but can fortunately be solved generically. But you still have to keep track of the information about where each component (i.e. each button) is currently located in the grid. When one button is removed, you have to compute the buttons that are affected by that (namely, the ones directly above it). These have to be animated. After the animation, you have to assign the new grid coordinates to these buttons.
The following is a MCVE that shows one basic approach. It simply removes the button that was clicked, but it should be easy to generalize it to remove other buttons, based on other conditions.
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class FallingButtons
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
int rows = 8;
int cols = 8;
GridPanel gridPanel = new GridPanel(rows, cols);
for (int r=0; r<rows; r++)
{
for (int c=0; c<cols; c++)
{
JButton button = new JButton(r+","+c);
gridPanel.addComponentInGrid(r, c, button);
button.addActionListener(e ->
{
Point coordinates = gridPanel.getCoordinatesInGrid(button);
if (coordinates != null)
{
gridPanel.removeComponentInGrid(
coordinates.x, coordinates.y);
}
});
}
}
f.getContentPane().add(gridPanel);
f.setSize(500, 500);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class GridPanel extends JPanel
{
private final int rows;
private final int cols;
private final JComponent components[][];
GridPanel(int rows, int cols)
{
super(null);
this.rows = rows;
this.cols = cols;
this.components = new JComponent[rows][cols];
addComponentListener(new ComponentAdapter()
{
#Override
public void componentResized(ComponentEvent e)
{
layoutGrid();
}
});
}
private void layoutGrid()
{
int cellWidth = getWidth() / cols;
int cellHeight = getHeight() / rows;
for (int r=0; r<rows; r++)
{
for (int c=0; c<cols; c++)
{
JComponent component = components[r][c];
if (component != null)
{
component.setBounds(
c * cellWidth, r * cellHeight, cellWidth, cellHeight);
}
}
}
}
Point getCoordinatesInGrid(JComponent component)
{
for (int r=0; r<rows; r++)
{
for (int c=0; c<cols; c++)
{
if (components[r][c] == component)
{
return new Point(r, c);
}
}
}
return null;
}
void addComponentInGrid(int row, int col, JComponent component)
{
add(component);
components[row][col] = component;
layoutGrid();
}
JComponent getComponentInGrid(int row, int col)
{
return components[row][col];
}
void removeComponentInGrid(int row, int col)
{
remove(components[row][col]);
components[row][col] = null;
List<Runnable> animations = new ArrayList<Runnable>();
for (int r=row-1; r>=0; r--)
{
JComponent component = components[r][col];
if (component != null)
{
Runnable animation =
createAnimation(component, r, col, r + 1, col);
animations.add(animation);
}
}
for (Runnable animation : animations)
{
Thread t = new Thread(animation);
t.setDaemon(true);
t.start();
}
repaint();
}
private Runnable createAnimation(JComponent component,
int sourceRow, int sourceCol, int targetRow, int targetCol)
{
int cellWidth = getWidth() / cols;
int cellHeight = getHeight() / rows;
Rectangle sourceBounds = new Rectangle(
sourceCol * cellWidth, sourceRow * cellHeight,
cellWidth, cellHeight);
Rectangle targetBounds = new Rectangle(
targetCol * cellWidth, targetRow * cellHeight,
cellWidth, cellHeight);
Runnable movement = createAnimation(
component, sourceBounds, targetBounds);
return () ->
{
components[sourceRow][sourceCol] = null;
movement.run();
components[targetRow][targetCol] = component;
repaint();
};
}
private static Runnable createAnimation(JComponent component,
Rectangle sourceBounds, Rectangle targetBounds)
{
int delayMs = 10;
int steps = 20;
Runnable r = () ->
{
int x0 = sourceBounds.x;
int y0 = sourceBounds.y;
int w0 = sourceBounds.width;
int h0 = sourceBounds.height;
int x1 = targetBounds.x;
int y1 = targetBounds.y;
int w1 = targetBounds.width;
int h1 = targetBounds.height;
int dx = x1 - x0;
int dy = y1 - y0;
int dw = w1 - w0;
int dh = h1 - h0;
for (int i=0; i<steps; i++)
{
double alpha = (double)i / (steps - 1);
int x = (int)(x0 + dx * alpha);
int y = (int)(y0 + dy * alpha);
int w = (int)(w0 + dw * alpha);
int h = (int)(h0 + dh * alpha);
SwingUtilities.invokeLater(() ->
{
component.setBounds(x, y, w, h);
});
try
{
Thread.sleep(delayMs);
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
return;
}
}
SwingUtilities.invokeLater(() ->
{
component.setBounds(x1, y1, w1, h1);
});
};
return r;
}
}
You could try using a 2-dimensional array of JButtons
JButton[][] buttons = new JButton[14][14];
for (int i=0; i < buttons.length; i++) {
for (int j=0; j < buttons[i].length; j++) {
buttons[i][j] = new JButton("Button [" + i + "][" + j + "]");
}
}
// Then do whatever,remove,change color,check next element in array
// and compare colors etc
buttons[2][3].setText("changed text");
If you want the above buttons to take more space to fill the empty space when you remove a component well, this is not possible using GridLayout, but you can add some empty components like JLabels to fill the space.
You can add a component in a container at a specific index for this purpose, by using Container's add (Component comp, int index) method.
This code snippet will replace a button at a specified index (45, just for example) with a blank component in a panel which has a GridLayout set:
JPanel boardPanel = new JPanel (new GridLayout (14, 14));
// ... add your buttons ...
// This code could be invoked inside an ActionListener ...
boardPanel.remove (45);
boardPanel.add (new JLabel (""), 45);
boardPanel.revalidate ();
boardPanel.repaint ();
This way, the rest of the components will not move, and you will just see a blank space replacing your button.
You can achieve more: if you add the empty label at index = 0, all the buttons will move to the right (remember that the number of components should not change, else the components will resize and you could obtain bad behaviour), and so on, you can "move" a single component by simply removing it and adding it at a different index.
Another way to go would be to store a 2-dimensional array of objects representing your model logic (you can store color and all the stuff you need), and painting them on your own by overriding paintComponent method.
For an example of a custom painting approach, take a look at this MadProgrammer's answer, where he shows how to highlight a specific cell in a grid (in this case he uses a List to store objects, but a 2d array will work as well).
I am writing a GUI with Swing. I'm using a GridBagLayout to display multiple JLabels in a grid (basically like a chess board). As soon as I use a self made label class derived from JLabel instead of JLabel, the GridBagLayout stacks every label on the top left corner of the JPanel.
Either my subclass TileLabel is incorrect or I don't use the layout and constraints the right way. I think the last one because I can't see what would be a problem in such a minimal subclass.
This is how it looks using JLabel (L represents a label):
(MenuBar)
L L L L L L L L L
L L L L L L L L L
L L L L L L L L L
This is how it looks using TileLabel (S represents all the labels stacked):
(MenuBar)
S
This is my simple subclass from JLabel:
import javax.swing.JLabel;
public class TileLabel extends JLabel {
private static final long serialVersionUID = 6718776819945522562L;
private int x;
private int y;
public TileLabel(int x, int y) {
super();
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
And this is the GUI class. I Marked the three lines where I used my custom label which lead to the layout problem.
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainGUI extends JPanel {
private static final long serialVersionUID = -8750891542665009043L;
private JFrame frame;
private MainMenuBar menuBar;
private TileLabel[][] labelGrid; // <-- LINE 1
private GridBagConstraints constraints;
private int gridWidth;
private int gridHeight;
// Basic constructor.
public MainGUI(int frameWidth, int frameHeight) {
super(new GridBagLayout());
constraints = new GridBagConstraints();
buildFrame(frameWidth, frameHeight);
buildLabelGrid(frameWidth, frameHeight);
}
// Builds the frame.
private void buildFrame(int frameWidth, int frameHeight) {
menuBar = new MainMenuBar();
frame = new JFrame("Carcasonne");
frame.getContentPane().add(this);
frame.setJMenuBar(menuBar);
frame.setResizable(false);
frame.setVisible(true);
frame.setSize(frameWidth, frameHeight);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBackground(new Color(165, 200, 245));
}
// Creates the grid of labels.
private void buildLabelGrid(int frameWidth, int frameHeight) {
gridWidth = frameWidth / 100;
gridHeight = frameHeight / 100;
labelGrid = new TileLabel[gridWidth][gridHeight]; // <-- LINE 2
for (int x = 0; x < gridWidth; x++) {
for (int y = 0; y < gridHeight; y++) {
labelGrid[x][y] = new TileLabel(x, y); // <-- LINE 3
constraints.gridx = x;
constraints.gridy = y;
add(labelGrid[x][y], constraints); // add label with constraints
}
}
}
// sets the icon of a specific label
public void paint(Tile tile, int x, int y) {
if (x >= 0 && x < gridWidth && y >= 0 && y < gridHeight) {
labelGrid[x][y].setIcon(tile.getImage());
} else {
throw new IllegalArgumentException("Invalid label grid position (" + x + ", " + y + ")");
}
}
// Just to test this GUI:
public static void main(String[] args) {
MainGUI gui = new MainGUI(1280, 768);
Tile tile = TileFactory.createTile(TileType.Road);
for (int x = 0; x < 12; x++) {
for (int y = 0; y < 7; y++) {
gui.paint(tile, x, x);
}
}
}
}
Where is the problem?
There are quite a few things to fix in your code, but your problem originates from 3 things:
Your method definitions in your custom label:
public class TileLabel extends JLabel {
// #Override !!!!
public int getX() {
return x;
}
// #Override !!!!
public int getY() {
return y;
}
}
You are overriding JComponent's getX() and getY(), which are responsible for returning their coordinates. This messes up the layout completely.
Be careful with your paint method, a method with the same name exists in a superclass, though you are saved in this case since the arguments are different.
You have a typo at your loop: gui.paint(tile, x, x) should be gui.paint(tile, x, y).
The order in which you call your methods is wrong. First, you create the frame and display it, then you change its contents by adding the panel with the labels to it, then you change the text in the labels. You should do this the other way around.
My recommendations:
Make your paint method be made a member of your TileLabel class. It makes more sense.
Set the icons during creation of the labels, unless they are not known. If you can't, you might need to recalculate the space requirements.
Never make your layout dependent on the size of the screen or its resolution. It makes for a fragile GUI (as noted in the comments). Use pack() for the frame to calculate the correct size.
You have accidentally overridden JComponent#getX() and JComponent#getY(). The values returned by this method are not consistent with the values that the layout may set internally (via calls to setBounds or so). This messes up the layout.
(Admittedly, I did not really check whether this is the reason, but it likely is, and it is a problem in general!)
I posted this question a bit earlier and was told to make it SSCCE so here goes (if I can make any improvements feel free to let me know):
I'm wondering why when my button "confirm" is clicked the old squares disappear and the redrawn squares do not appear on my GUI (made with swing). The Squares class draws 200 spaced out squares with an ID (0, 1, 2, or 3 as String) inside obtained from a different class (for the purpose of this question, let's assume it is always 0 and not include that class). For clarification: Squares draws everything perfectly the first time (also retrieves the correct IDs), but I want it to redraw everything once the button is clicked with new IDs.
Code for Squares:
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.util.ArrayList;
public class Squares extends JPanel{
private ArrayList<Rectangle> squares = new ArrayList<Rectangle>();
private String stringID = "0";
public void addSquare(int x, int y, int width, int height, int ID) {
Rectangle rect = new Rectangle(x, y, width, height);
squares.add(rect);
stringID = Integer.toString(ID);
if(ID == 0){
stringID = "";
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
FontMetrics fm = g2.getFontMetrics();
int fontAscent = fm.getAscent();
g2.setClip(new Rectangle(0,0,Integer.MAX_VALUE,Integer.MAX_VALUE));
for (Rectangle rect : squares) {
g2.drawString(stringID, rect.x + 7, rect.y + 2 + fontAscent);
g2.draw(rect);
}
}
}
Code for GUI:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GUIReserver extends JFrame implements Runnable{
private int myID;
private JButton confirm = new JButton("Check Availability and Confirm Reservation");
private JFrame GUI = new JFrame();
private Squares square;
public GUIReserver(int i) {
this.myID = i;
}
#Override
public void run() {
int rows = 50;
int seatsInRow = 4;
confirm.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
GUI.getContentPane().remove(square);
square = new Squares();
int spaceNum = 0;
int rowNum = 0;
int offsetX = 200;
int offsetY = 0;
for(int i = 0; i < rows * seatsInRow; i++){
square.addSquare(rowNum * 31 + offsetX,spaceNum * 21 + 50 + offsetY,20,20, 0); //normally the 4th parameter here would retrieve the ID from the main class
rowNum++;
if(rowNum == 10){
rowNum = 0;
spaceNum++;
}
if(spaceNum == 2){
spaceNum = 3;
rowNum = 0;
}
if(spaceNum == 5){
spaceNum = 0;
offsetY += 140;
}
}
GUI.getContentPane().add(square); //this does not show up at all (could be that it wasn't drawn, could be that it is out of view etc...)
GUI.repaint(); //the line in question
}
});
GUI.setLayout(new FlowLayout());
GUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GUI.setLocation(0,0);
GUI.setExtendedState(JFrame.MAXIMIZED_BOTH);
square = new Squares();
int spaceNum = 0;
int rowNum = 0;
int offsetX = 200;
int offsetY = 0;
for(int i = 0; i < rows * seatsInRow; i++){
square.addSquare(rowNum * 31 + offsetX,spaceNum * 21 + 50 + offsetY,20,20, 0); //normally the 4th parameter here would retrieve the ID from the main class
rowNum++;
if(rowNum == 10){
rowNum = 0;
spaceNum++;
}
if(spaceNum == 2){
spaceNum = 3;
rowNum = 0;
}
if(spaceNum == 5){
spaceNum = 0;
offsetY += 140;
}
}
GUI.getContentPane().add(square); //this shows up the way I wish
GUI.add(confirm);
GUI.pack();
GUI.setVisible(true);
}
}
Code for main:
public class AircraftSeatReservation {
static AircraftSeatReservation me = new AircraftSeatReservation();
private final int rows = 50;
private final int seatsInRow = 4;
private int seatsAvailable = rows * seatsInRow;
private Thread t3;
public static void main(String[] args) {
GUIReserver GR1 = new GUIReserver(3);
me.t3 = new Thread(GR1);
me.t3.start();
}
}
One major problem: Your Squares JPanels preferred size is only 20 by 20, and will likely actually be that size since it seems to be added to a FlowLayout-using container. Next you seem to be drawing at locations that are well beyond the bounds of this component, and so the drawings likely will never be seen. Consider allowing your Squares objects to be larger, and make sure to only draw within the bounds of this component.
Note also there is code that doesn't make sense, including:
private int myID;
private JTextField row, column, instru draft saved // ???
package question2;ction1, instruction2, seatLabel, rowLabel; // ???
I'm guessing that it's
private int myID;
private JTextField row, column, instruction1, instruction2, seatLabel, rowLabel;
And this won't compile for us:
int rows = AircraftSeatReservation.getRows();
int seatsInRow = AircraftSeatReservation.getSeatsInRow(); // and shouldn't this take an int row parameter?
since we don't have your AircraftSeatReservation class (hopefully you don't really have static methods in that class).
And we can't compile or run your current code. We don't want to see your whole program, but rather you should condense your code into the smallest bit that still compiles, has no extra code that's not relevant to your problem, but still demonstrates your problem. So as Andrew Thompson recommends, for better help, please create and post your Minimal, Complete, and Verifiable example or Short, Self Contained, Correct Example.
I would try to OOP-ify your problem as much as possible, to allow you to divide and conquer. This could involve:
Creating a SeatClass enum, one with possibly two elements, FIRST and COACH.
Creating a non-GUI Seat class, one with several fields including possibly: int row, char seat ( such as A, B, C, D, E, F), a SeatClass field to see if it is a first class seat or coach, and a boolean reserved field that is only true if the seat is reserved.
This class would also have a getId() method that returns a String concatenation of the row number and the seat char.
Creating a non-GUI Airplane class, one that holds two arrays of Seats, one for SeatClass.FIRST or first-class seats, and one for SeatClass.COACH.
It would also have a row count field and a seat count (column count) field.
After creating all these, then work on your GUI classes.
I'd create a GUI class for Seats, perhaps GuiSeat, have it contain a Seat object, perhaps have it extend JPanel, allow it to display its own id String that it gets from its contained Seat object, have it override getBackground(...) so that it's color will depend on whether the seat is reserved or not.
etc.....