I know that the same question has been asked many times, but I really don't seem to find the error in my code that hinders the object of type JPanel to be displayed in the JFrame. Here is the constructor of the class that extends JFrame:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Game extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private Board board;
public Game() {
super("Game");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBackground(Color.WHITE);
board = new Board();
add(board, BorderLayout.CENTER);
JButton button = new JButton("Start new game");
button.setFocusPainted(false);
button.addActionListener(this);
JPanel control = new JPanel();
control.setBackground(Color.WHITE);
control.add(button);
add(control, BorderLayout.SOUTH);
pack();
setResizable(false);
setVisible(true);
}
And this one is the constructor of the class that extends JPanel:
public class Board extends JPanel implements ActionListener {
public Board() {
setBackground(Color.WHITE);
setLayout(new GridLayout(NUMBER_OF_ROWS, NUMBER_OF_COLUMNS));
setBorder(BorderFactory.createEmptyBorder(20, 20, 0, 20));
board = new Cell[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS];
for (int row = 0; row < NUMBER_OF_ROWS; row++) {
for (int column = 0; column < NUMBER_OF_COLUMNS; column++) {
board[row][column] = new Cell(this, row, column);
add(board[row][column]);
}
}
}
When I run the main method (which I didn't show here), it shows only the frame and the button. If someone could give a hint on this, I would be very thankful.
It seems to show up just fine in this close variant of the code that is runnable (a MCTaRE).
Note that I put some space in the GridLayout and changed the colors to make panel boundaries more clear.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Game extends JFrame {
private static final long serialVersionUID = 1L;
private Board board;
public Game() {
super("Game");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBackground(Color.WHITE);
board = new Board();
add(board, BorderLayout.CENTER);
JButton button = new JButton("Start new game");
button.setFocusPainted(false);
JPanel control = new JPanel();
control.setBackground(Color.GREEN);
control.add(button);
add(control, BorderLayout.SOUTH);
pack();
setResizable(false);
setVisible(true);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new Game();
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency
SwingUtilities.invokeLater(r);
}
}
/** A pseudo Cell */
class Cell extends JButton {
Cell(JComponent parent, int row, int column) {
super(row + " " + column);
}
}
/** And this one is the constructor of the class that extends JPanel */
class Board extends JPanel {
int NUMBER_OF_ROWS=3;
int NUMBER_OF_COLUMNS=4;
Cell[][] board;
public Board() {
setBackground(Color.RED);
setLayout(new GridLayout(NUMBER_OF_ROWS, NUMBER_OF_COLUMNS, 5, 5));
setBorder(BorderFactory.createEmptyBorder(20, 20, 0, 20));
board = new Cell[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS];
for (int row = 0; row < NUMBER_OF_ROWS; row++) {
for (int column = 0; column < NUMBER_OF_COLUMNS; column++) {
board[row][column] = new Cell(this, row, column);
add(board[row][column]);
}
}
}
}
Related
I am trying to create a 2D array of buttons but the buttons I created are all in the same line. I can change lines in 2D arrays of int and float by using System.out.println(). What should I so for buttons? (line 67 to 75)
As well, I don't know how to create actionListeners for buttons in a loop. Should I create a method for acctionLisener? Do they share the same action listener?
import java.awt.*;
import javax.swing.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JInternalFrame;
public class Hanoi {
private JFrame frame;
JButton[][] buttons= new JButton[3][3];
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Hanoi window = new Hanoi();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Hanoi() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 901, 696);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panelone = new JPanel();
frame.getContentPane().add(panelone, BorderLayout.CENTER);
panelone.setBackground(Color.WHITE);
GridBagLayout gbl_panelone = new GridBagLayout();
gbl_panelone.columnWidths = new int[]{0};
gbl_panelone.rowHeights = new int[]{0};
gbl_panelone.columnWeights = new double[]{Double.MIN_VALUE};
gbl_panelone.rowWeights = new double[]{Double.MIN_VALUE};
panelone.setLayout(gbl_panelone);
JPanel paneltwo = new JPanel();
frame.getContentPane().add(paneltwo, BorderLayout.NORTH);
paneltwo.setBackground(Color.WHITE);
JLabel lblFunHanoiTower = new JLabel("Fun Hanoi Tower");
lblFunHanoiTower.setForeground(Color.BLACK);
lblFunHanoiTower.setBackground(SystemColor.activeCaption);
lblFunHanoiTower.setFont(new Font("Viner Hand ITC", Font.PLAIN, 36));
paneltwo.add(lblFunHanoiTower);
//JButton[][] buttons = new JButton[3][3];
for(int row = 0; row < buttons.length ; row++) {
for(int col= 0; col < buttons[0].length ;col++) {
buttons[row][col] = new JButton(String.valueOf((row+3)+(col*3)));
buttons[row][col].setFont(new Font("Tempus Sans ITC", Font.BOLD, 16));
buttons[row][col].setBackground(SystemColor.controlHighlight);
buttons[row][col].setSize(66, 66);
panelone.add(buttons[row][col]);
}
}
}
}
Rather than modify your code, I have provided an example of GridLayout.
GridLayout divides the area of the JPanel into a grid, i.e. a table of rows and columns, where each "cell" in the grid can contain one component and each cell has the same size. Here is a complete, compilable and runnable example.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public class Hanoi implements Runnable {
#Override // java.lang.Runnable
public void run() {
showGui();
}
private JPanel createGridPanel() {
// Number of rows will be calculated depending on total number
// of components added but each row will contain no more than
// three components.
GridLayout gridLayout = new GridLayout(0, 3);
JPanel gridPanel = new JPanel(gridLayout);
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
int number = (row + 3) + (col * 3);
String text = String.valueOf(number);
JButton button = new JButton(text);
gridPanel.add(button);
}
}
return gridPanel;
}
private void showGui() {
JFrame frame = new JFrame("Hanoi");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(createGridPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
Hanoi instance = new Hanoi();
EventQueue.invokeLater(instance);
}
}
And here is a screen capture of the running application.
(Note that I am using JDK 12 on Windows 10.)
You can use a grid layout, i change your original code (as you can see below). I recommend to use some designer for the gui, it more easy and clean. Net beans have a nice grafic interface builder.
public class Hanoi {
private JFrame frame;
JButton[][] buttons= new JButton[3][3];
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Hanoi window = new Hanoi();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Hanoi() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 901, 696);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panelone = new JPanel();
panelone.setLayout(new GridLayout(3,3));
frame.getContentPane().add(panelone);
panelone.setBackground(Color.WHITE);
/*GridBagLayout gbl_panelone = new GridBagLayout();
gbl_panelone.columnWidths = new int[]{0};
gbl_panelone.rowHeights = new int[]{0};
gbl_panelone.columnWeights = new double[]{Double.MIN_VALUE};
gbl_panelone.rowWeights = new double[]{Double.MIN_VALUE};*/
// panelone.setLayout(gbl_panelone);
JPanel paneltwo = new JPanel();
frame.getContentPane().add(paneltwo, BorderLayout.NORTH);
paneltwo.setBackground(Color.WHITE);
JLabel lblFunHanoiTower = new JLabel("Fun Hanoi Tower");
lblFunHanoiTower.setForeground(Color.BLACK);
lblFunHanoiTower.setBackground(SystemColor.activeCaption);
lblFunHanoiTower.setFont(new Font("Viner Hand ITC", Font.PLAIN, 36));
paneltwo.add(lblFunHanoiTower);
//JButton[][] buttons = new JButton[3][3];
for(int row = 0; row < buttons.length ; row++) {
for(int col= 0; col < buttons[0].length ;col++) {
buttons[row][col] = new JButton(String.valueOf((row+3)+(col*3)));
buttons[row][col].setFont(new Font("Tempus Sans ITC", Font.BOLD, 16));
buttons[row][col].setBackground(SystemColor.controlHighlight);
buttons[row][col].setSize(66, 66);
panelone.add(buttons[row][col]);
}
}
}
}
I am trying to add and actionListener to a JPanel it's self but keep getting the error"cannot find symbol". I was just wondering if it is possible to do this as I want to be able to click on the panel and make the colour change. Any help would be appreciated.
Here is what i have so far.
import java.awt.*;
import javax.swing.*;
import javax.swing.JPanel.*;
import java.awt.Color.*;
import java.awt.event.*;
/**
* Write a description of class SimpleFrame here.
*
* #author OFJ2
* #version
*/
public class Game extends JFrame
implements ActionListener
{
private final int ROWS = 5;
private final int COLUMS = 2;
private final int GAP = 2;
private final int SIZE = ROWS * COLUMS;
private int x;
private JPanel leftPanel = new JPanel(new GridLayout(ROWS,COLUMS, GAP,GAP));
private JPanel [] gridPanel = new JPanel[SIZE];
private JPanel middlePanel = new JPanel();
private JPanel rightPanel = new JPanel();
private Color col1 = Color.GREEN;
private Color col2 = Color.YELLOW;
private Color tempColor;
public Game()
{
super("Chasing Bombs OFJ2");
setSize(200,200);
setVisible(true);
makeFrame();
}
public void makeFrame()
{
Container contentPane = getContentPane();
contentPane.setLayout(new GridLayout());
leftPanel.setLayout(new GridLayout(ROWS, COLUMS));
//JLabel label2 = new JLabel("Pocahontas");
JButton playButton = new JButton("Play Game");
JButton exitButton = new JButton("Exit");
JButton easyButton = new JButton("Easy");
JButton mediumButton = new JButton("Medium");
JButton hardButton = new JButton("Hard");
add(leftPanel);
add(middlePanel, new FlowLayout());
add(rightPanel);
setGrid();
middlePanel.add(playButton);
middlePanel.add(exitButton);
rightPanel.add(easyButton);
rightPanel.add(mediumButton);
rightPanel.add(hardButton);
leftPanel.setBackground(Color.PINK);
middlePanel.setBackground(Color.RED);
easyButton.addActionListener(this);
mediumButton.addActionListener(this);
hardButton.addActionListener(this);
playButton.addActionListener(this);
exitButton.addActionListener(this);
}
public void setGrid()
{
for(int x = 0; x < SIZE; x++) {
gridPanel[x] = new JPanel();
gridPanel[x].setBorder(BorderFactory.createLineBorder(Color.BLACK));
leftPanel.add(gridPanel[x]);
gridPanel[x].setBackground(Color.GREEN);
gridPanel[x].addActionListener(this);
}
}
#Override
public void actionPerformed(ActionEvent e)
{
Object source = e.getSource();
if (source == gridPanel[0]){
gridPanel[x].setBackground(Color.BLACK);
}
}
}
I have tried to find if there is any other method that is needed to do this but cant find anything. Is it possible that I will have to add a button to fill each of the panels to make this work?
Thanks!
It defaults to no addActionListener, and the code below is a reference suggestion.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
class GPanel extends JPanel {
private List<ActionListener> listenerList = new ArrayList<>();
public GPanel() {
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
var event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "GPanel");
for (var i : listenerList) {
i.actionPerformed(event);
}
}
});
}
public void addActionListener(ActionListener listener) {
listenerList.add(listener);
}
}
public class ActionListenerTest extends JFrame {
public static void main(String[] args) {
new ActionListenerTest();
}
public ActionListenerTest() {
GPanel test = new GPanel();
test.setBackground(Color.BLUE);
add(test);
test.addActionListener(e-> {
System.out.println("Click: " + e.getActionCommand());
});
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
}
I'm having trouble with the functionality of dispose for my checkerboard (called Checkers) . For each checkerboard that I have, i want to be able to remove it by using dispose before calling another instance of my interface. Here is my progress so far:
Checkers class:
import java.awt.*;
import javax.swing.*;
import java.awt.Color.*;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.util.Random;
public class Checkers extends JFrame
{
Random random = new Random();
private final int ROWS = 2;
private final int COLS = 5;
private final int GAP = 2;
private final int NUM = ROWS * COLS;
private int i;
public int score;
private JPanel pane = new JPanel(new GridLayout(ROWS,COLS, GAP,GAP));
private JPanel pane2 = new JPanel();
private JPanel pane3 = new JPanel();
private JButton btn1 = new JButton("Play A Game");
private JButton btn2 = new JButton("Exit");
private JButton btn3 = new JButton("Easy");
private JButton btn4 = new JButton("Intermediate");
private JButton btn5 = new JButton("Difficult");
private JLabel lbl1 = new JLabel ("score: " + score);
private JLabel gameLost = new JLabel("You lose! You got: " + score + " points");
private MyPanel [] panel = new MyPanel[NUM];
private Color col1 = Color.RED;
private Color col2 = Color.WHITE;
private Color col3 = Color.GREEN;
private Color tempColor;
public Checkers()
{
super("Checkers");
setSize(600,600);
setVisible(true);
setBackground(Color.BLACK);
setBoard();
}
public void setBoard()
// roates colors on the checkbaord
{
for (int i = 0; i < panel.length; i++) {
panel[i] = new MyPanel(this);
pane.add(panel[i]);
if (i % COLS == 0) {
tempColor = col1;
col1 = col2;
col2 = tempColor;}
if (i % 2 == 0) {
panel[i].setBackground(col1);}
else {
panel[i].setBackground(col2);}
}
//pane background colour and the size of this pane.
pane.setBackground(Color.BLACK);
pane.setPreferredSize(new Dimension(300,300));
//pane background colour and size of this pane.
pane2.setBackground(Color.white);
pane2.setPreferredSize(new Dimension(300,300));
//directions on the board where these panes appear.
add(pane, BorderLayout.WEST);
add(pane2, BorderLayout.EAST);
pane2.add(lbl1);
pane2.setLayout(new BoxLayout(pane2, BoxLayout.PAGE_AXIS));
}
public void incrementScore(){
score++;
lbl1.setText("Score: " + Integer.toString(score));
}
//This is the method for resetting via dispose - only works once.
public void restartBoard(){
this.dispose();
new Checkers();
}
}
And also the MyPanel class
public class MyPanel extends JPanel implements MouseListener {
private final Checkers checkers;
public MyPanel(Checkers checkers) {
this.checkers = checkers;
addMouseListener(this);
}
#Override
public void mouseClicked(MouseEvent e) {
setBackground(Color.BLACK);
checkers.incrementScore();
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
EXPECTED RESULT - What i'd like to do is be able to close the current version of interface by using the dispose method, and then opening a new instance of said interface.
ACTUAL RESULT - When opening an interface, then calling dispose method, it will work once. once you try to remove the 2nd interface when creating a 3rd interface, dispose will not function, and I cant see why this is.
Any help is welcome.
For what it's worth, this is an MCVE that shows your likely problem:
import java.awt.Dimension;
import javax.swing.*;
public class CheckersTest {
private static void createAndShowGui() {
Checkers checkers = new Checkers();
JButton restartButton = new JButton("Restart");
restartButton.addActionListener(event -> checkers.restartBoard());
JPanel restartPanel = new JPanel();
restartPanel.setPreferredSize(new Dimension(400, 400));
restartPanel.add(restartButton);
JFrame frame = new JFrame("Checkers Test");
frame.add(restartPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class Checkers extends JFrame {
public Checkers() {
setPreferredSize(new Dimension(200, 200));
pack();
setLocationByPlatform(true);
setVisible(true);
}
public void restartBoard(){
this.dispose();
new Checkers();
}
}
The restart button refers to the original Checkers instance and so will not close any new instances created. The solution would be to get the restart method out of Checkers, create a Checkers field, and make sure the restart method refers to the visible Checkers instance:
import java.awt.Dimension;
import javax.swing.*;
public class CheckersTest {
private static Checkers checkers = new Checkers(); // holds reference
private static void restartBoard() {
if (checkers != null) {
checkers.dispose();
checkers = new Checkers(); // assign to reference field
}
}
private static void createAndShowGui() {
// !! Checkers checkers = new Checkers();
JButton restartButton = new JButton("Restart");
// !! restartButton.addActionListener(event -> checkers.restartBoard());
restartButton.addActionListener(event -> restartBoard());
JPanel restartPanel = new JPanel();
restartPanel.setPreferredSize(new Dimension(400, 400));
restartPanel.add(restartButton);
JFrame frame = new JFrame("Checkers Test");
frame.add(restartPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class Checkers extends JFrame {
public Checkers() {
setPreferredSize(new Dimension(200, 200));
pack();
setLocationByPlatform(true);
setVisible(true);
}
}
Notes:
Again a much better design is not to swap JFrames but rather JPanel views
Note that the MCVE has code that reproduces the problem but avoids code not related to the problem. So it shows the restartBoard method, it compiles, but avoids game code since this is not relevant to the problem.
I've intended to create a simple gui that would draw an oval in the top third of the window, display a name in the middle third, and draw a rectangle in the bottom third(to be done later)
So far, the only parts I've been able to create and make visible are four buttons that are eventually meant to toggle the visibility of the objects and label.
The problem I'm having is that I cannot get the label or the oval to appear, and I'm not sure what I'm missing preventing either to be visble
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.io.*;
public class Gui extends JFrame
implements ActionListener
{
private JButton bottomLeftButton;
private JButton bottomMiddleLeftButton;
private JButton bottomRightButton;
private JButton bottomMiddleRightButton;
private OtherPanel mypanel;
private JLabel name;
private JPanel panelOne;
private boolean visible;
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == bottomLeftButton)
{
visible = name.isVisible();
name.setVisible(visible);
}
else if(e.getSource() == bottomMiddleLeftButton)
{
}
else if (e.getSource() == bottomMiddleRightButton)
{
}
else if (e.getSource() == bottomRightButton)
{
}
repaint();
}
public Gui()
{
setTitle("First GUI");
setSize(800,800);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane = this.getContentPane();
contentPane.setLayout(new BorderLayout());
JPanel BottomPanel = new JPanel(new GridLayout(1,4));
contentPane.add(BottomPanel, BorderLayout.SOUTH);
bottomLeftButton = new JButton("Name");
bottomLeftButton.addActionListener(this);
BottomPanel.add(bottomLeftButton);
bottomMiddleLeftButton = new JButton("Oval");
bottomMiddleLeftButton.addActionListener(this);
BottomPanel.add(bottomMiddleLeftButton);
bottomMiddleRightButton = new JButton("Square");
bottomMiddleRightButton.addActionListener(this);
BottomPanel.add(bottomMiddleRightButton);
bottomRightButton = new JButton("Special");
bottomRightButton.addActionListener(this);
BottomPanel.add(bottomRightButton);
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new GridLayout(3,1));
panelOne = new OtherPanel();
name = new JLabel("Name");
name.setHorizontalAlignment(SwingConstants.CENTER);
JLabel label3 = new JLabel("Label3");
centerPanel.add(panelOne);
centerPanel.add(name);
centerPanel.add(label3);
}
public static void main(String[] args)
{
Gui gui = new Gui();
gui.setVisible(true);
}
}
(meant to draw the oval)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class OtherPanel extends JPanel
{
public void paintComponent(Graphics g)
{
int x = 10;
int y = 10;
int width = getWidth(); //ten pixels of spaces
int height = getHeight();
g.fillOval(x, y, width, height);
}
}
was missing a line of code to add the objects to the contentPane
contentPane.add(centerPanel); goes at the end of the gui() method
I have a JFrame which contains 2 JPanel subclass and 2 JLabel in BorderLayout. One of the JPanel contains JButtons and the other is used for displaying graphics. The JLabels are in north and south, the button JPanel in the west and the display JPanel in center.
The display JPanel requires constant refresh, so i invoke its repaint() method via the action event generated by swing timer. I also override its paintComponent() method to do my drawings.
Instead of displaying what i have drawn, the "content of the JFrame" is being drawn onto the display JPanel. I am aware that i can simply "clear" the display JPanel by using g.fillRect() or super.paintComponent() before doing my drawings.
I am just curious why this happens.
i'm using jdk 1.6u27. below is my code:
package test;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class Main {
public static void main(String[] args) {
Simulation sim = new Simulation();
}
}
class Simulation extends JFrame {
public JLabel state;
private JLabel id;
private ButtonPanel control;
private Display display;
public Simulation() {
id = new JLabel("Test");
state = new JLabel("Test");
control = new ButtonPanel();
display = new Display(this);
this.setLayout(new BorderLayout());
this.add(id, BorderLayout.NORTH);
this.add(control, BorderLayout.WEST);
this.add(display, BorderLayout.CENTER);
this.add(state, BorderLayout.SOUTH);
this.setSize(500, 600);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public ButtonPanel getControl() {
return this.control;
}
}
class ButtonPanel extends JPanel implements ActionListener {
public JButton b[] = new JButton[8];
public boolean bp[] = new boolean[8];
public ButtonPanel() {
this.setLayout(new GridLayout(8, 1));
for (int i = 0; i < b.length; i++) {
b[i] = new JButton(""+i);
b[i].addActionListener(this);
bp[i] = false;
this.add(b[i]);
}
}
public void actionPerformed(ActionEvent e) {
//do something
}
}
class Display extends JPanel implements ActionListener {
private Timer tm;
private int yco;
private Simulation sim;
public Display(Simulation sim) {
tm = new Timer(100, this);
tm.start();
yco = 0;
this.sim = sim;
}
#Override
public void paintComponent(Graphics g) {
//draw something
g.drawLine(0, yco, 100, 100);
}
public void actionPerformed(ActionEvent e) {
yco ++;
this.repaint();
}
}
Without super.paintComponent(g), the result depends on your platform's default for the opacity property of the JPanel UI delegate, PanelUI. Mine happens to be true, but you can experiment on your platform, as suggested below.
Addendum: "If you do not honor the opaque property you will likely see visual artifacts."—paintComponent(). The artifact you observe will vary by platform, but it is not atypical. In effect, you are breaking the promise to draw every pixel, and you see whatever is left over in some buffer.
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class Main {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Simulation sim = new Simulation();
}
});
}
}
class Simulation extends JFrame {
public JCheckBox state;
private JLabel id;
private ButtonPanel control;
private Display display;
public Simulation() {
id = new JLabel("Test");
state = new JCheckBox("Opaque");
control = new ButtonPanel();
display = new Display(this);
this.setLayout(new BorderLayout());
this.add(id, BorderLayout.NORTH);
this.add(control, BorderLayout.WEST);
this.add(display, BorderLayout.CENTER);
this.add(state, BorderLayout.SOUTH);
state.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
display.setOpaque(e.getStateChange() == ItemEvent.SELECTED);
}
});
state.setSelected(true);
this.pack();
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public ButtonPanel getControl() {
return this.control;
}
}
class ButtonPanel extends JPanel {
private static final int N = 8;
private List<JToggleButton> list = new ArrayList<JToggleButton>(N);
public ButtonPanel() {
this.setLayout(new GridLayout(0, 1));
for (int i = 0; i < N; i++) {
final JToggleButton b = new JToggleButton(String.valueOf(i));
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//System.out.println(b.isSelected());
}
});
list.add(b);
this.add(b);
}
}
}
class Display extends JPanel {
private Simulation sim;
private Timer tm;
private int yco;
public Display(Simulation sim) {
this.setPreferredSize(new Dimension(320, 320));
this.setOpaque(true);
this.sim = sim;
tm = new Timer(100, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
yco++;
repaint();
}
});
tm.start();
}
#Override
public void paintComponent(Graphics g) {
//super.paintComponent(g);
g.drawLine(0, yco, getWidth() / 2, getHeight() / 2);
}
}