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();
}
Related
i have a problem with adding a specific number of buttons from my for-loop to my JPanel, i know how to add all oof them, but i want to add only 1-10 (i havent decided yet, lets go with 10).'
this is my class where i just declare what objects i want to have.
private static int cID;
private static Deck[] card;
static ArrayList<JButton> buttonList = new ArrayList<JButton>();
private JFrame f;
private JPanel p1;
private JButton button;
public boolean isEmpty() {
return cID == 0;
}
public static void main(String[] args) {
CustomDecks c = new CustomDecks();
c.deckCreator();
}```
this is my for-loop where i create 420 buttons and give them names "card" + i where i is 0 - 419, yet when i try to add card0 to my panel, it fails, why?
private void deckCreator() {
card = new Deck[25];
new ArrayList<Cards> (cSet.cards);
for(int i = 0; i < 420; i++) {
button = new JButton();
buttonList.add(button);
button.setName("card" + i);
f.add(button);
p1.add(card0);
}
f.add(p1);
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.setVisible(true);
f.setExtendedState(Frame.MAXIMIZED_BOTH);
f.setUndecorated(true);
}
}
}
I'm not sure you can create a JPanel large enough to hold 420 JButtons.
Here's an example of a JButton GUI.
[
Generally, you create an application model and view separately. The model is made up of one or more plain Java classes. The view reads from the application model but doesn't update the model.
Your controller classes (ActionListener classes) update the application model and update / repaint the view.
This pattern is called the model / view / controller (MVC) pattern.
You can see in the example code below that the model is created in the view class constructor. Generally, you create the application model first, then you create the application view.
And here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
public class JButtonScrollGUI {
private JFrame frame;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new JButtonScrollGUI();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private String[] greekAlphabet;
public JButtonScrollGUI() {
this.greekAlphabet = new String[] { "alpha", "beta", "gamma", "epsilon", "zeta" };
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setTitle("Application");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createScrollPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createScrollPanel() {
JPanel panel = new JPanel(new BorderLayout());
JPanel innerPanel = createButtonPanel();
Dimension d = innerPanel.getPreferredSize();
d.width += 50;
d.height /= 2;
panel.setPreferredSize(d);
JScrollPane scrollPane = new JScrollPane(innerPanel);
panel.add(scrollPane, BorderLayout.CENTER);
return panel;
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel(new GridLayout(0, 3, 10, 10));
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
for (int i = 0; i < 20; i++) {
JButton button1 = new JButton("Previous " + i);
panel.add(button1);
JComboBox<String> selectorBox = new JComboBox<>(greekAlphabet);
panel.add(selectorBox);
JButton button2 = new JButton("Next " + i);
button2.setPreferredSize(button1.getPreferredSize());
panel.add(button2);
}
return panel;
}
}
I am trying to get the class i added to JPanel and run a function within the class.
I created MyButton class that extends JButton, This class i added to JPanel but after i added this class i want to run getText() on this objects.
I tried this but it does not recognize the function:
panel.getComponent(1).getText();
Main
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel(new GridLayout(2, 5));
for (int i = 0; i < 10; i++) {
panel.add(new MyButton());
}
frame.add(panel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
MyButton
public class MyButton extends JButton {
private String text;
public MyButton()
{
this.text="Hello";
setText("test");
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
panel.getComponent(1).getText();
This returns a Component, which has no getText() method. It needs to be cast back to a JButton in order to use that method.
import java.awt.*;
import javax.swing.*;
public class ButtonText {
public static void main(String[] args) {
Runnable r = () -> {
JFrame frame = new JFrame();
JPanel panel = new JPanel(new GridLayout(2, 5));
for (int i = 0; i < 10; i++) {
panel.add(new JButton("Text " + (i+1)));
}
frame.add(panel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
Component[] components = panel.getComponents();
for (Component component : components) {
JButton b = (JButton) component;
System.out.println(b.getText());
}
};
EventQueue.invokeLater(r);
}
}
BTW - having to trawl back though a panel to get the components seems like a poor hack. See What is the XY problem? Whatever the actual goal is here (& what is that goal?) is likely better served by storing the buttons in an array or list structure, when created.
I know this problem has probably already been solved before but I don't really know how to describe the problem well, so I have a hard time finding it.
The problem I have is that I have a canvas that is attached to a panel and that panel is attached to a main panel and that to the frame. When I run the code the canvas does nothing. However if I dont add the button panel it works.
this is my code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ColorFrame extends JFrame {
private static final int FRAMEWIDTH = 400;
private static final int FRAMEHEIGHT = 400;
private int aORec = 4;
private Canvas canvas;
private JPanel mainPanel;
private JPanel panel;
private JPanel buttonPanel;
private JButton lessButton;
private JButton moreButton;
public ColorFrame() {
mainPanel = new JPanel();
panel = new JPanel();
canvas = new painter();
panel.add(canvas);
mainPanel.add(panel, BorderLayout.CENTER);
createComponents();
add(mainPanel);
setSize(FRAMEWIDTH,FRAMEHEIGHT);
setDefaultCloseOperation(3);
}
private void createComponents() {
buttonPanel = new JPanel();
lessButton = new JButton("Less");
moreButton = new JButton("More");
ActionListener bL = new ButtonListener();
lessButton.addActionListener(bL);
moreButton.addActionListener(bL);
buttonPanel.add(moreButton);
buttonPanel.add(lessButton);
mainPanel.add(buttonPanel, BorderLayout.NORTH);
}
class painter extends Canvas {
#Override
public void paint(Graphics g) {
for (int i = 0; i < aORec; i++) {
int tempWidth = (int)(Math.random() * (FRAMEWIDTH-0));
int tempHeight = (int)(Math.random() * (FRAMEHEIGHT -0));
g.drawRect(tempWidth,tempHeight,20,20);
}
}
}
class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == moreButton) {
aORec =+ aORec;
canvas.repaint();
} else {
if (aORec != 1) {
aORec -= (aORec*0.5);
canvas.repaint();
} else {
System.out.println("There are not enough rectangles to be drawn.");
}
}
}
}
}
Main panel is created by
mainPanel = new JPanel();
Components are being added to the main panel as
mainPanel.add(panel, BorderLayout.CENTER);
mainPanel.add(buttonPanel, BorderLayout.NORTH);
but no LayoutManager was set, so the default FlowLayout is used, not BorderLayout. Create the panel by
mainPanel = new JPanel(new BorderLayout());
or add the statement
mainPanel.setLayout(new BorderLayout());
This is also valid for panel (otherwise it will not be resized, that is, stay with size zero)
(BorderLayout is the default for JFrame(
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...
I want to add multiple jpanels to jpanel.So i added a root panel to jscrollpane.and then added all individual jpanels to this root panel.I made jscrollpane's scrolling policy as needed.i.e HORIZONTAL_SCROLLBAR_AS_NEEDED,VERTICAL_SCROLLBAR_AS_NEEDED.
But the problem is all individual panels are not shown inside root panel.
Code:
JScrollPane scPanel=new JScrollPane();
JPanel rootPanel=new JPanel();
rootPanel.setLayout(new FlowLayout());
JPanel indPanel = new JPanel();
rootPanel.add(indPanel);
JPanel indPanel2 = new JPanel();
rootPanel.add(indPanel2);
//.....like this added indPanals to rootPanel.
scPanel.setViewPortView(rootPanel);
//scPanel.setHorizontalScrollPolicy(HORIZONTAL_SCROLLBAR_AS_NEEDED);
And one more thing is, as i scroll the scrollbar the panels are going out of jscrollpane area.
I am not able to see all individual panels,
Please suggest me.
Edit: code snippet from double post:
MosaicFilesStatusBean mosaicFilesStatusBean = new MosaicFilesStatusBean();
DefaultTableModel tableModel = null;
tableModel = mosaicFilesStatusBean.getFilesStatusBetweenDates(startDate, endDate);
if (tableModel != null) {
rootPanel.removeAll();
rootPanel.setLayout(new BoxLayout(rootPanel, BoxLayout.PAGE_AXIS));
for (int tempRow = 0; tempRow < tableModel.getRowCount(); tempRow++) {
int fileIdTemp = Integer.parseInt(tableModel.getValueAt(tempRow, 0).toString());
String dateFromTemp = tableModel.getValueAt(tempRow, 3).toString();
String dateToTemp = tableModel.getValueAt(tempRow, 4).toString();
int processIdTemp = Integer.parseInt(tableModel.getValueAt(tempRow, 5).toString());
int statusIdTemp = Integer.parseInt(tableModel.getValueAt(tempRow, 6).toString());
String operatingDateTemp = tableModel.getValueAt(tempRow, 7).toString();
MosaicPanel tempPanel =
new MosaicPanel(fileIdTemp, dateFromTemp, dateToTemp, processIdTemp, statusIdTemp, operatingDateTemp);
rootPanel.add(tempPanel);
}
rootPanel.revalidate();
}
The main reason, why you couldn't see your JPanel is that you are using FlowLayout as the LayoutManager for the rootPanel. And since your JPanel added to this rootPanel has nothing inside it, hence it will take it's size as 0, 0, for width and height respectively. Though using GridLayout such situation shouldn't come. Have a look at this code example attached :
import java.awt.*;
import javax.swing.*;
public class PanelAddition
{
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("Panel Addition Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setLayout(new GridLayout(0, 1));
JScrollPane scroller = new JScrollPane();
CustomPanel panel = new CustomPanel(1);
contentPane.add(panel);
scroller.setViewportView(contentPane);
frame.getContentPane().add(scroller, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
for (int i = 2; i < 20; i++)
{
CustomPanel pane = new CustomPanel(i);
contentPane.add(pane);
contentPane.revalidate();
contentPane.repaint();
}
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new PanelAddition().createAndDisplayGUI();
}
});
}
}
class CustomPanel extends JPanel
{
public CustomPanel(int num)
{
JLabel label = new JLabel("" + num);
add(label);
}
#Override
public Dimension getPreferredSize()
{
return (new Dimension(200, 50));
}
}
Don't use FlowLayout for the rootPanel. Instead consider using BoxLayout:
JPanel rootPanel=new JPanel();
// if you want to stack JPanels vertically:
rootPanel.setLayout(new BoxLayout(rootPanel, BoxLayout.PAGE_AXIS));
Edit 1
Here's an SSCCE that's loosely based on your latest code posted:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.util.Random;
import javax.swing.*;
#SuppressWarnings("serial")
public class PanelsEg extends JPanel {
private static final int MAX_ROW_COUNT = 100;
private Random random = new Random();
private JPanel rootPanel = new JPanel();
public PanelsEg() {
rootPanel.setLayout(new BoxLayout(rootPanel, BoxLayout.PAGE_AXIS));
JScrollPane scrollPane = new JScrollPane(rootPanel);
scrollPane.setPreferredSize(new Dimension(400, 400)); // sorry kleopatra
add(scrollPane);
add(new JButton(new AbstractAction("Foo") {
#Override
public void actionPerformed(ActionEvent arg0) {
foo();
}
}));
}
public void foo() {
rootPanel.removeAll();
// rootPanel.setLayout(new BoxLayout(rootPanel, BoxLayout.PAGE_AXIS)); // only need to set layout once
int rowCount = random.nextInt(MAX_ROW_COUNT);
for (int tempRow = 0; tempRow < rowCount ; tempRow++) {
int fileIdTemp = tempRow;
String data = "Data " + (tempRow + 1);
MosaicPanel tempPanel =
new MosaicPanel(fileIdTemp, data);
rootPanel.add(tempPanel);
}
rootPanel.revalidate();
rootPanel.repaint(); // don't forget to repaint if removing
}
private class MosaicPanel extends JPanel {
public MosaicPanel(int fileIdTemp, String data) {
add(new JLabel(data));
}
}
private static void createAndShowGui() {
PanelsEg mainPanel = new PanelsEg();
JFrame frame = new JFrame("PanelsEg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
This SSCCE works, in that it easily shows removing and adding JPanels to another JPanel that is held by a JScrollPane. If you're still having a problem, you should modify this SSCCE so that it shows your problem.