I have 2 classes: GameOfLife() and PanelGrid. When a new object of panelgrid is created, the (overwritten) method paintComponent is not called. Putting "repaint()" in the constructor doesn't work either.
import java.util.Scanner;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
class GameOfLife {
JFrame frame = new JFrame("Game of life");
PanelGrid panelGrid;
void buildIt() {
frame.setSize(600, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(buttonStart, BorderLayout.SOUTH);
frame.add(buttonStop, BorderLayout.NORTH);
panelGrid = new PanelGrid();
panelGrid.setOpaque(true);
frame.add(panelGrid);
}
public static void main(String[] args) {
new GameOfLife().buildIt();
}
}
class PanelGrid extends JPanel implements ActionListener {
Timer timer;
int delay;
JLabel label;
int height; // get length from the file
int width; //get width of array from the file
//constructor
public PanelGrid() {
delay = 1000;
timer = new Timer(delay, this);
width = 4;
height = 5;
//if there exists a file with an initial configuration, initial[][], width and height are updated.
//if not, the default array is used
readInitial();
//repaint(); putting repaint() here din't make a difference.
}
#Override
public void paintComponent(Graphics g) {
System.out.println("if you read this, the method is called");
super.paintComponent(g); //erases panel content
this.setLayout(new GridLayout(width, height));
for (int r = 0; r < height; r++) {
for (int c = 0; c < width; c++) {
JPanel panel = new JPanel();
if (grid[r][c].isAlive() == true) {
panel.setBackground(Color.BLACK);
} else {
panel.setBackground(Color.WHITE);
}
this.add(panel);
}
}
//the rest of this class I have left out for clarity
}
}
I think you need to add your PanelGrid to theJFrame. If it's not in a visible top-level container paint() and therefore paintComponent() won't be called. Maybe. Worth a shot...
Related
This program just creates a UI1 and a Button. When I click on that button a new UI Appear which I coded so that it doesn't go outside the bounds of UI1. My main problem is that I'm trying to make the width and height of the button smaller so that it looks more like an app icon. But when I set the bounds on the button it doesn't change anything when I run the code.
//Start
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Objects;
import javax.imageio.ImageIO;
import javax.swing.*;
public class MainUI extends JFrame {//MainUI
private JButton button;
private JPanel panel;
public MainUI() {
//UI1
setSize(1000, 700);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
try {
//Here is the Button--
button = new JButton();
button.setBounds(200,200,70,70);
Image img = ImageIO.read(Objects.requireNonNull(getClass().getResource("icons8-messages-100.png")));
button.setIcon(new ImageIcon(img));
button.setFocusable(false);
panel = new JPanel();
panel.add(button);
add(panel);
button.addActionListener(e -> {
UI2 ui2 = new UI2();
ui2.setLocationRelativeTo(panel);
ui2.setVisible(true);
ui2.addComponentListener(new ComponentAdapter() {
public void componentMoved(ComponentEvent e) {
//This makes the ui2 not go outside the Main UI
int x = ui2.getX();
int y = ui2.getY();
int width1 = getWidth();
int height1 = getHeight();
int width2 = ui2.getWidth();
int height2 = ui2.getHeight();
if (x < getX()) {
ui2.setLocation(getX(), y);
}
if (y < getY()) {
ui2.setLocation(x, getY());
}
if (x + width2 > getX() + width1) {
ui2.setLocation(getX() + width1 - width2, y);
}
if (y + height2 > getY() + height1) {
ui2.setLocation(x, getY() + height1 - height2);
}//end of if statements
}//componentMoved
});//addComponentListener
});//addActionListener
} catch(Exception e) {
System.out.println("Something's Wrong");
}
}//End of MainUI
public static void main(String[] args) {
MainUI mainFrame = new MainUI();
mainFrame.setVisible(true);
}
}//Class MainUI
class UI2 extends JFrame {
public UI2() {
setBounds(getX() + 50, getY() + 50, 200, 200);
setResizable(false);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setLayout(new BorderLayout());
}
}//Class UI2
//End
UI2 should be a dialog and not another JFrame since Swing applications should usually only have a single, top-level container.
You also don't need to do all the hard work yourself of placing GUI components on the screen nor sizing them. You should use layout managers and other, relevant parts of the rich, API – in order to make the JButton look like an app icon.
More notes after the code.
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Objects;
import javax.imageio.ImageIO;
import javax.swing.*;
public class MainUI {
private JButton button;
private JFrame frame;
private JPanel panel;
private UI2 ui2;
public MainUI() {
frame = new JFrame();
frame.setSize(1000, 700);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
button = new JButton();
Image img = ImageIO.read(Objects.requireNonNull(getClass().getResource("icons8-messages-100.png")));
button.setIcon(new ImageIcon(img));
button.setFocusable(false);
button.setContentAreaFilled(false);
button.setBorderPainted(false);
panel = new JPanel();
panel.add(button);
frame.add(panel);
button.addActionListener(e -> {
if (ui2 == null) {
ui2 = new UI2(frame);
}
ui2.setVisible(true);
});// addActionListener
}
catch (Exception e) {
e.printStackTrace();
}
frame.setVisible(true);
}// End of MainUI
public static void main(String[] args) {
EventQueue.invokeLater(() -> new MainUI());
}
}// Class MainUI
#SuppressWarnings("serial")
class UI2 extends JDialog {
public UI2(JFrame owner) {
super(owner);
setSize(200, 200);
setResizable(false);
setLocationRelativeTo(owner);
addComponentListener(new ComponentAdapter() {
public void componentMoved(ComponentEvent e) {
// This makes the ui2 not go outside the Main UI
int x = getX();
int y = getY();
int width1 = owner.getWidth();
int height1 = owner.getHeight();
int width2 = getWidth();
int height2 = getHeight();
if (x < owner.getX()) {
setLocation(owner.getX(), y);
}
if (y < owner.getY()) {
setLocation(x, owner.getY());
}
if (x + width2 > owner.getX() + width1) {
setLocation(owner.getX() + width1 - width2, y);
}
if (y + height2 > owner.getY() + height1) {
setLocation(x, owner.getY() + height1 - height2);
} // end of if statements
}// componentMoved
});// addComponentListener
}
}// Class UI2
(Below notes are in no particular order.)
You don't need to create a new UI2 each time the user clicks the JButton (in UI1). Create it once and then just hide it when you close it and show it when you click the JButton. The default behavior is to hide the JDialog when it is closed.
A Swing application does not need to extend JFrame (or JPanel or any other JComponent). A Swing application can extend JComponent (or subclass thereof) but it does not have to.
The default layout for [the content pane of] JFrame is BorderLayout so no need to explicitly set this.
Printing a message, like Something's Wrong, in a catch block, might be user-friendly but it won't help you find the cause of the exception
. I nearly always print the stack trace in my catch blocks.
Screen capture of running app.
However, since you don't want UI2 to move outside of UI1, an alternative would be to use a JInternalFrame rather than a JDialog. Here is a demonstration.
(Again, there are notes after the code.)
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.util.Objects;
import javax.imageio.ImageIO;
import javax.swing.DefaultDesktopManager;
import javax.swing.DesktopManager;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
public class IframTst {
private JDesktopPane desktopPane;
private JInternalFrame iFrame;
public IframTst() throws IOException {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createButton(), BorderLayout.PAGE_START);
frame.add(createDesktopPane(), BorderLayout.CENTER);
frame.setSize(1000, 700);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createButton() throws IOException {
JPanel panel = new JPanel();
JButton button = new JButton();
Image img = ImageIO.read(Objects.requireNonNull(getClass().getResource("icons8-messages-100.png")));
button.setIcon(new ImageIcon(img));
button.setFocusable(false);
button.setContentAreaFilled(false);
button.setBorderPainted(false);
button.addActionListener(this::showIframe);
panel.add(button);
return panel;
}
private JDesktopPane createDesktopPane() {
desktopPane = new JDesktopPane();
DesktopManager manager = new DefaultDesktopManager() {
private static final long serialVersionUID = -4685522430190278205L;
#Override
public void dragFrame(JComponent f, int newX, int newY) {
setBoundsForFrame(f, newX, newY, f.getWidth(), f.getHeight());
}
#Override
public void setBoundsForFrame(JComponent f,
int newX,
int newY,
int newWidth,
int newHeight) {
Rectangle rect = desktopPane.getVisibleRect();
if (newX < 0) {
newX = 0;
}
if (newX + newWidth > rect.width) {
newX = rect.width - newWidth;
}
if (newY < 0) {
newY = 0;
}
if (newY + newHeight > rect.height) {
newY = rect.height - newHeight;
}
super.setBoundsForFrame(f, newX, newY, newWidth, newHeight);
}
};
desktopPane.setDesktopManager(manager);
return desktopPane;
}
private void showIframe(ActionEvent event) {
if (iFrame == null) {
iFrame = new JInternalFrame(null, false, true, false, false);
iFrame.setDefaultCloseOperation(JInternalFrame.HIDE_ON_CLOSE);
iFrame.setSize(200, 200);
desktopPane.add(iFrame);
}
iFrame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
try {
new IframTst();
}
catch (IOException xIo) {
xIo.printStackTrace();
}
});
}
}
The ActionListener is implemented using method references
The inspiration for keeping the JInternalFrame within the bounds of its parent JDesktopPane came from
Preventing JInternalFrame from being moved out of a JDesktopPane
(as well as looking at the source code for class DefaultDesktopManager)
You can also set the initial location of the JInternalFrame within the JDesktopPane. Refer to
How do I open a JInternalFrame centered in a JDesktopPane?
How it looks when I run it.
Hereunder is a minimal example of a bug I can't fix in a Java program.
The bug consists is that the lines are randomly shown in the JFrame: sometimes I see the board at runtime, sometimes not.
Any hint greatly appreciated.
import java.awt.Graphics;
import javax.swing.JFrame;
public class EssaiDrawLine extends JFrame{
public static void main(String[] args) {
EssaiDrawLine mafenetre = new EssaiDrawLine();
mafenetre.setVisible(true);
}
// constructeur
public EssaiDrawLine() {
setTitle("mon titre");
setSize(600, 500);
}
public void paint(Graphics g) {
super.paint(g);
for (int i = 0; i <= 8; i++) {
g.drawLine(50 * i + 10, 40, 50*i + 10, 440);
g.drawLine(10, 50 * i + 40, 410, 50 * i + 40);
}
g.drawString("Cliquer pour obtenir la prochaine solution", 20, 470);
}
}
Another option: don't draw the lines but instead create a grid of components, such as a 2-D array of JPanels held in another JPanel, one that uses GridLayout, and then give the JPanels a MouseListener so that they can respond to mouse events. For example, a simple version of this could look something like so (please read the comments in the code):
import java.awt.BorderLayout;
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.*;
#SuppressWarnings("serial") // get rid of warning
public class EssaiDrawLine3 extends JPanel {
private static final int SIDE = 8;
private static final int SQR_LENGTH = 50;
private static final int GAP = 5;
private static final Color CLICK_COLOR = Color.RED;
private static final Color SQR_COLOR = Color.LIGHT_GRAY;
private static final String CLICK_TEXT = "Cliquer pour obtenir la prochaine solution";
// our grid of JPanel
private JPanel[][] grid = new JPanel[SIDE][SIDE];
public EssaiDrawLine3() {
// JPanel to hold the grid
// give it an 8x8 GridLayout with 1 pixel gap for lines to show
JPanel gridHolder = new JPanel(new GridLayout(SIDE, SIDE, 1, 1));
// background color that shows through as lines in gaps in grid
gridHolder.setBackground(Color.BLACK);
gridHolder.setBorder(BorderFactory.createLineBorder(Color.black));
// mouse listener to add to each JPanel cell
MyMouse myMouse = new MyMouse();
// nested for loop to create our grid of JPanels
for (int row = 0; row < grid.length; row++) {
for (int col = 0; col < grid[row].length; col++) {
// create a single cell
JPanel cellPanel = new JPanel();
// size it 50x50 pixels
cellPanel.setPreferredSize(new Dimension(SQR_LENGTH, SQR_LENGTH));
// add the mouse listener to it
cellPanel.addMouseListener(myMouse);
// give it a default background color
cellPanel.setBackground(SQR_COLOR);
// place it into the 2-D array of JPanel
grid[row][col] = cellPanel;
// place it into the grid layout-using JPanel
gridHolder.add(cellPanel);
}
}
// display text at the bottom
JLabel label = new JLabel(CLICK_TEXT, SwingConstants.CENTER);
// allow gaps around the main JPanel
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
// give the main JPanel a BorderLayout
setLayout(new BorderLayout(GAP, GAP));
add(gridHolder); // add the grid to the CENTER position
// add the JLabel to the bottom position
add(label, BorderLayout.PAGE_END);
}
private class MyMouse extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
// get the JPanel cell that was clicked
JComponent comp = (JComponent) e.getSource();
// get its color and change it
Color color = comp.getBackground();
if (color.equals(CLICK_COLOR)) {
comp.setBackground(SQR_COLOR);
} else {
comp.setBackground(CLICK_COLOR);
}
}
}
private static void createAndShowGui() {
EssaiDrawLine3 mainPanel = new EssaiDrawLine3();
JFrame frame = new JFrame("Essai Draw Line3");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
Never draw directly in the JFrame but instead within a JPanel's paintComponent method, and then display that JPanel in your JFrame. This is all well explained in the standard tutorials: : Lesson: Performing Custom Painting
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.*;
#SuppressWarnings("serial")
public class EssaiDrawLine2 extends JPanel {
private static final int PS_WIDTH = 600;
private static final int PS_HEIGHT = 500;
public EssaiDrawLine2() {
setPreferredSize(new Dimension(PS_WIDTH, PS_HEIGHT));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i <= 8; i++) {
g.drawLine(50 * i + 10, 40, 50 * i + 10, 440);
g.drawLine(10, 50 * i + 40, 410, 50 * i + 40);
}
g.drawString("Cliquer pour obtenir la prochaine solution", 20, 470);
}
private static void createAndShowGui() {
EssaiDrawLine2 mainPanel = new EssaiDrawLine2();
JFrame frame = new JFrame("Essai Draw Line");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
I have the following problem, when i want to add 2JPanels to my JFrame only one is visible, depending on which I added to the frame last. I overrided the JPanels default paintComponent() method on both of the JPanels. How can i fix this?
Code snippet:
Border:
public class BorderDrawer extends JPanel{
private int _width,_height;
BorderDrawer(int width,int height)
{
setOpaque(false);
_width = width;
_height = height;
}
#Override
protected void paintComponent(Graphics g) {
final int BUTTON_WIDTH = 20,BUTTON_HEIGHT = 20;
int MINES_HORIZONTALLY = _width;
int MINES_VERTICALLY = _height;
super.paintComponent(g);
try{
BufferedImage topLeftCorner = ImageIO.read(this.getClass().getResource("topLeftCorner.png"));
g.drawImage(topLeftCorner, 0, 0, null);
....// drawing other border components
}
}
Clock:
public class GraphicTimer extends JPanel{
Timer _aktTimer = null;
int seconds;
int _width = 0;
GraphicTimer(int width)
{
setSize(52, 31);
setOpaque(false);
_width = width;
int delay = 1000; //milliseconds
_aktTimer = new Timer(delay, taskPerformer);
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
try
{
final int BUTTON_WIDTH = 20,BUTTON_HEIGHT = 20;
int MINES_HORIZONTALLY = _width;
int HORIZONTAL_ENDING = 15+BUTTON_WIDTH*MINES_HORIZONTALLY;
BufferedImage clock = ImageIO.read(this.getClass().getResource("clock.png"));
g.drawImage(clock,HORIZONTAL_ENDING-54,22, null);
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
....
}
JFrame:
public class DrawerField extends JFrame implements Serializable{
//...
public DrawerField()
{
super("MineSweeper");
_FIELD = new Field();
constructorInit();
}
public void constructorInit()
{
_buttons = new FieldButton[_height][_width];
_isMouseEventEnabled = true;
fieldPanel = new JPanel();
smilePanel = new JPanel();
//INITS
int fieldSizeWidth = (_width)*20;
int fieldSizeHeight = (_height)*20; // Magic size
fieldPanel.setSize(fieldSizeWidth,fieldSizeHeight); // 20x20
fieldPanel.setLocation(15, 70);
fieldPanel.setLayout(new GridLayout(_width,_height));
int fullWindowWidth = fieldSizeWidth+36;
int fullWindowHeight = fieldSizeHeight+142;
setSize(fullWindowWidth,fullWindowHeight);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
restartButton = new RestartButton(this);
smilePanel.setSize(34,34);
smilePanel.add(restartButton);
smilePanel.setLayout(new GridLayout(1,1));
smilePanel.setLocation((int)fullWindowWidth/2-(34/2)-1,20);
///INITIALS
for(int i = 0; i < _height; i++)
{
for(int j = 0; j < _width ; j++)
{
_buttons[i][j] = new FieldButton(_hidden[i][j],true,i,j,this);
fieldPanel.add(_buttons[i][j]);
}
}
add(smilePanel);
add(fieldPanel);
borderDrawer = new BorderDrawer(_width,_height);
_graphicTimer = new GraphicTimer(_width);
_graphicTimer.start();
add(_graphicTimer); // This is the two lines which change the result
add(borderDrawer);
MenuBar menuBar = new MenuBar(this);
setJMenuBar(menuBar);
setVisible(true);
}
//...
}
Easier and compilable example:
public class Main {
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setSize(500, 500);
MyPanel panel1 = new MyPanel(30,30);
frame.add(panel1);
MyPanel panel2 = new MyPanel(70,30);
frame.add(panel2);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.repaint();
frame.setVisible(true);
}
public static class MyPanel extends JPanel
{
int _x,_y;
MyPanel(int x, int y)
{
_x = x; _y = y;
}
#Override
public void paint(Graphics g) {
g.drawOval(_x,_y,20,20);
}
}
}
My main goal is to add 2 circles to the JFrame without using any Layout.( As you can see in the example above I already have a lot of things on my JFrame that's why I don'T want to use layouts). The problem is the same in this example, when i add the 2nd circle the first is disappearing.
Its simple. Adding a panel in a frame adds it to the content pane of the frame. This contentpane has a default layout of BorderLayout which means, every time you add a panel, it gets added to the center of the content pane and gets replaces the previous one. This is the reason why you see only the last one. Its always good to use a Jpanel set to the layout of your choice put everything that needs to be shown on the screen in that panel. If you don't want to do that, you may also call getContentPane() from the frame and play with the returned instance of JPanel.
Here is the example code for you:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Frame extends JFrame {
public Frame() {
setTitle("Two panels");
setSize(new Dimension(500,500));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Here goes your code
JPanel p= (JPanel) getContentPane();
p.setLayout(new GridLayout(1,2)); //set your own layout
p.add(new MyPanel(Color.BLUE)); //add panel with blue border
p.add(new MyPanel(Color.GREEN));//add panel with green border
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Frame f= new Frame();
f.setVisible(true);
}
});
}
}
class MyPanel extends JPanel {
public MyPanel(Color color) {
setBorder(BorderFactory.createLineBorder(color));
}
}
Run it and see... You should be able to see something like this:
Hello guys I am a rookie programmer so please excuse me if I am trying something stupid.
I started learning about GUI applications today, and I wanted to do a practice to check if I learned it properly. When I run the program, there is a dot on the screen, and I want it to move right when I click on the start button. I accomplished this, however I wanted it to be an animation, I wanted the dot to look as if it was moving slowly. But When I click to button, it just teleports.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Guila extends JFrame {
private JPanel panel;
private JButton myButton;
private final int WINDOW_WIDTH = 300;
private final int WINDOW_HEIGHT = 600;
private JPanel[] array = new JPanel[900];
private int i = 0;
int j = 0;
int m = 0;
int k = 0;
public Guila() {
setTitle("Simple Animation");
setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
panel.setLayout(new GridLayout(30, 30));
while(i < 900) {
array[i] = new JPanel();
if(i == 460) {
array[i].setBackground(Color.BLACK);
}
else {
array[i].setBackground(Color.WHITE);
}
panel.add(array[i]);
i++;
}
JPanel panel2 = new JPanel();
myButton = new JButton("Start");
myButton.addActionListener(new myActionListener());
setLayout(new GridLayout(2,1));
add(panel);
panel2.add(myButton);
add(panel2);
setVisible(true);
}
private class myActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
array[460+j].setBackground(Color.WHITE);
array[461+j].setBackground(Color.BLACK);
repeat();
}
}
public void repeat() {
if (j<11) {
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
j++;
myButton.doClick();
}
}
public static void main(String[] args) {
new Guila();
}
}
Don't use Thread.sleep() on code that executes on the Event Dispatch Thread.
Use a Swing Timer for animation. Every time the Timer fires you update a property of the component you want to change and then you invoke repaint() on the component.
I agree with using the Swing Timer for animation. Although it might be a challenge to create your desired slow motion effect.
Use the following code to help you get started, if needed:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Bullet extends JPanel implements ActionListener
{
private static final long serialVersionUID = 1L;
private static final int SCREEN_WIDTH = 500;
private static final int increments = 5;
int[] xPoints = new int[5];
public void paintComponent(Graphics g)
{
g.setColor(Color.WHITE);
g.fillRect(0,0,800,800);
g.setColor(Color.BLACK);
for (int i = 0; i < xPoints.length; i++)
{
g.fillRect(xPoints[i]+150, 210, 20, 20);
}
Timer timer = new Timer(100, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
for (int i = 0; i <= 1; i++)
{
if (xPoints[i] + increments < SCREEN_WIDTH)
{
xPoints[i] += increments;
} else {
xPoints[i] = 0;
}
}
repaint();
}
});
timer.start();
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setSize(500,500);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new Bullet());
frame.setVisible(true);
}
}
I'm dumbfounded here. I have a JPanel (defBoardPanel) that I'm adding to a parent JPanel (GamePanel) as follows:
public GamePanel(SetupBoard sb) {
this.setLayout(new BorderLayout());
// this.setBackground(Color.yellow);
JPanel defBoardPanel = new JPanel();
defBoardPanel.setBackground(Color.yellow);
for (int r = 0; r < sb.boardSize; r++){
for (int c = 0; c < sb.boardSize; c++){
Cell c = new Cell(r, c);
c.label.setOpaque(true);
if (sb.getCell(r, c).status == sb.getCell(r,c).status.occupied){
c.label.setBackground(Color.black);
System.out.println("LABEL IS OCCUPIED");
}
else {
c.label.setBackground(Color.white);
}
defBoardPanel.add(c.label);
}
}
defBoardPanel.revalidate();
defBoardPanel.setVisible(true);
this.add(defBoardPanel, BorderLayout.WEST);
this.revalidate();
this.setVisible(true);
This panel is to be added to a JFrame (MainFrame), which is shown below. When the application is launched, the JFrame displays a different type of Panel (SetupBoard), with which the user sets up their game board. When they click "accept", the StartGame() method of the MainFrame is called, which should show the JPanels above.
public MainFrame() {
this.setLayout(new BorderLayout());
this.setSize(500, 500);
SetupBoard sb = new SetupBoard(10, this);
this.setContentPane(sb);
}
void startGame(SetupBoard sb){
GamePanel gp = new GamePanel(sb);
this.setContentPane(gp);
this.revalidate();
}
My issue is that the child panel (defBoardPanel) is not displaying. The GamePanel itself displays (which I've verified using the setBackground(Color.yellow) method you see commented out), but not the panel I've added onto it.
What stupid mistake am I overlooking here?
EDIT: startGame() is being called from within the SetupBoard class:
void startGame(){
mf.startGame(this);
}
where mf is a reference to the MainFrame that created the SetupBoard instance. The fact that the GamePanel displays at all confirms that this is being called correctly.
Seems to work ok if I trim the code I don't have. Most likely the issue is coming from what you are not showing us. Therefore, producing an SSCCE would greatly benefit you. Meanwhile, you can always take advantage (to find the differences with your code) of the following one, which is highly originated from yours (I filled some gaps as I could):
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class GamePanel extends JPanel {
private static final int COLS = 10;
private static final int ROWS = 10;
public GamePanel() {
this.setLayout(new BorderLayout());
// this.setBackground(Color.yellow);
JPanel defBoardPanel = new JPanel(new GridLayout(ROWS, COLS));
defBoardPanel.setBackground(Color.yellow);
for (int r = 0; r < ROWS; r++) {
for (int c = 0; c < COLS; c++) {
JLabel label = new JLabel((r + 1) + " " + (c + 1));
label.setOpaque(true);
if (Math.random() > 0.5) {
label.setBackground(Color.black);
label.setForeground(Color.WHITE);
System.out.println("LABEL IS OCCUPIED");
} else {
label.setBackground(Color.white);
}
defBoardPanel.add(label);
}
}
this.add(defBoardPanel, BorderLayout.WEST);
}
public static class MainFrame extends JFrame {
public MainFrame() {
this.setLayout(new BorderLayout());
this.setSize(500, 500);
}
void startGame() {
GamePanel gp = new GamePanel();
this.setContentPane(gp);
pack();
setVisible(true);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
MainFrame mainFrame = new MainFrame();
mainFrame.startGame();
}
});
}
}
This code sequence replaces the GamePanel after it has been added to MainFrame
public MainFrame() {
this.setLayout(new BorderLayout());
this.setSize(500, 500);
SetupBoard sb = new SetupBoard(10, this); // invokes startGame
this.setContentPane(sb); <----- GamePanel replaced here
}
void startGame(SetupBoard sb) {
GamePanel gp = new GamePanel(sb);
this.setContentPane(gp);
this.revalidate();
}