Im trying to use SwingWorker to update my gui.
The part of my gui that I'm trying to update is a JPanel (gridPanel) with a GridLayout [50][50].
Each grid in the GridLayout has a custom GridGraphic JComponent.
In the doInBackground() of my SwingWorker, I update each GridGraphic which represents some color. Then, I publish it to a List that the process() uses to update the gui. Though, the gui isn't updating.
Is there a way to do this without calling repaint().
How do I fix my SwingWorker so the gui is responsive. What do I want to return in order for the gridPanel, which is a [50][50] GridLayout of GridGraphic components responsive to changes
The SwingWorker is executed in the stepButton.addActionListener(new ActionListener()...............in SlimeGui
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
public class SlimeGui extends JFrame{
private JPanel buttonPanel, populationPanel, velocityPanel;
private JPanel gridPanel = new JPanel(new GridLayout(50, 50));
private JButton setupButton, stepButton, goButton;
private JLabel populationNameLabel, velocityNameLabel, populationSliderValueLabel, velocitySliderValueLabel;
private JSlider populationSlider, velocitySlider;
private GridGraphic [] [] gridGraphic;
private GridGraphic test;
private int agents = 125;
private int velocity = 500;
private boolean resetGrid;
public SlimeGui() {
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
//Set up JButtons
buttonPanel = new JPanel();
setupButton = new JButton("Setup");
stepButton = new JButton("Step");
goButton = new JButton("Go");
buttonPanel.add(setupButton);
buttonPanel.add(stepButton);
buttonPanel.add(goButton);
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 3;
add(buttonPanel, c);
//Set up population JSlider
populationPanel = new JPanel();
populationNameLabel = new JLabel(" Population");
populationSliderValueLabel = new JLabel(Integer.toString(agents));
populationSlider = new JSlider(JSlider.HORIZONTAL,0, 1000, 125);
populationSlider.setMajorTickSpacing(125);
populationSlider.setPaintTicks(true);
populationSlider.addChangeListener(new PopulationSliderListener());
populationPanel.add(populationNameLabel);
populationPanel.add(populationSlider);
populationPanel.add(populationSliderValueLabel);
c.gridx = 0;
c.gridy = 2;
add(populationPanel, c);
//Set up veolicty JSlider
velocityPanel = new JPanel();
velocityNameLabel = new JLabel(" Velocity");
velocitySliderValueLabel = new JLabel(Integer.toString(velocity));
velocitySlider = new JSlider(JSlider.HORIZONTAL,0, 1000, 500);
velocitySlider.setMajorTickSpacing(125);
velocitySlider.setPaintTicks(true);
velocitySlider.addChangeListener(new VelocitySliderListener());
velocityPanel.add(velocityNameLabel);
velocityPanel.add(velocitySlider);
velocityPanel.add(velocitySliderValueLabel);
c.gridx = 0;
c.gridy = 3;
add(velocityPanel, c);
//Set up grid with GridGraphic objects
gridGraphic = new GridGraphic[50][50];
for(int i = 0; i < 50; i++){
for(int j = 0; j < 50; j++){
gridGraphic[i][j] = new GridGraphic();
gridPanel.add(gridGraphic[i][j]);
}
}
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 3;
add(gridPanel, c);
//Set up ActionListener for the 'Setup' JButton
setupButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
int n1=0;
int n2=0;
//resets the grid so there are no agents
if(resetGrid){
for(int i = 0; i < 50; i++){
for(int j = 0; j < 50; j++){
gridGraphic[i][j].setDefault();
}
}
}
//sets a random number of positions for GridGraphics
for (int numOfAgenets = 0; numOfAgenets < agents; numOfAgenets++){
int lowerB = 0;
int upperB = 50;
n1 = (lowerB + (int)(Math.random()*(upperB-lowerB))); //random number 1
n2 = (lowerB + (int)(Math.random()*(upperB-lowerB))); //random number 2
System.out.println("Choosing random agent "+(numOfAgenets+1)+": "+n1 +" "+n2);
//sets the GridGraphic to an agent if it's available
if (gridGraphic[n1][n2].getIntensity() == 0)
gridGraphic[n1][n2].setAgent();
//if the GridGraphic is already an agent, it continues to search
else if(gridGraphic[n1][n2].getIntensity() == 5){
while(gridGraphic[n1][n2].getIntensity() == 5){
n1 = (lowerB + (int)(Math.random()*(upperB-lowerB)));
n2 = (lowerB + (int)(Math.random()*(upperB-lowerB)));
}
gridGraphic[n1][n2].setAgent();
}
}
repaint();
resetGrid = true;
}
});
//Set up ActionListener for the 'Step' JButton
stepButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
StepManager step = new StepManager(SlimeGui.this);
step.execute();
//repaint();
}
});
}
class PopulationSliderListener implements ChangeListener{
public void stateChanged(ChangeEvent e){
agents = ((JSlider)e.getSource()).getValue();
populationSliderValueLabel.setText(Integer.toString(agents));
System.out.println("Population of agents: " + agents);
}
}
class VelocitySliderListener implements ChangeListener{
public void stateChanged(ChangeEvent e){
velocity = ((JSlider)e.getSource()).getValue();
velocitySliderValueLabel.setText(Integer.toString(velocity));
System.out.println("Velocity(ms) of agents: " + velocity);
}
}
public Integer getVelocity(){
return velocity;
}
public GridGraphic getGridGraphic(int n1, int n2){
return gridGraphic[n1][n2];
}
public GridGraphic [][] getGridGraphic(){
return gridGraphic;
}
public void setGridGraphicArray(GridGraphic xxx, int n1, int n2 ){
gridGraphic[n1][n2] = xxx;
}
public void setGridPanel(GridGraphic[][] xxx){
for(int i = 0; i < 50; i++){
for(int j = 0; j < 50; j++){
gridPanel.add(xxx[i][j]);
}
}
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
SlimeGui slime = new SlimeGui();
slime.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Display the window.
slime.pack();
slime.setVisible(true);
slime.setResizable(false);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
My SwingWorker
import java.util.List;
import java.awt.*;
import javax.swing.*;
import java.util.concurrent.ExecutionException;
public class StepManager extends SwingWorker<Void, GridGraphic>{
private SlimeGui gui;
public StepManager(SlimeGui sg){
gui=sg;
}
#Override
protected Void doInBackground() throws Exception{
for(int i = 0; i < 50; i++){
for(int j = 0; j < 50; j++){
if(gui.getGridGraphic(i,j).getIntensity()==5){
if (i==0){
gui.getGridGraphic(i,j).setDefault();
gui.getGridGraphic(49,j).setAgent();
}
else{
gui.getGridGraphic(i,j).setDefault();
gui.getGridGraphic(i-1,j).setAgent();
}
}
publish(gui.getGridGraphic(i,j));
}
}
return null;
}
#Override
protected void process(List <GridGraphic> gg){
int k=0;
for ( int i = 0; i < 50; i++ ){
for(int j = 0; j < 50; j++){
gui.setGridGraphicArray(gg.get(k),i,j);
k++;
}
}
gui.setGridPanel(gui.getGridGraphicArray());
System.out.println("process has completed");
}
#Override
protected void done(){
System.out.println("doInBackground has completed");
}
}
My GridGraphic
import java.awt.*;
import javax.swing.*;
public class GridGraphic extends JComponent {
private int intensity = 0;
public GridGraphic() {
//setBorder(BorderFactory.createLineBorder(Color.BLUE));
}
public void paintComponent(Graphics g) {
//paints the GridGraphic black
if (intensity == 0){
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
}
//paints the GridGraphic black with a yellow dot
else if (intensity == 5){
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.YELLOW);
g.fillOval(3, 3, getWidth()/2, getHeight()/2);
}
//paints the GridGraphic dark yellow (pheromone)
if (intensity == 2){
super.paintComponent(g);
g.setColor(Color.BLACK.brighter());
g.fillRect(0, 0, getWidth(), getHeight());
}
}
public Dimension getPreferredSize() {
return new Dimension(10, 10);
}
public void setAgent(){
intensity = 5;
}
public void setPheromone1(){
intensity = 2;
}
public void setDefault(){
intensity = 0;
}
public int getIntensity(){
return intensity;
}
}
The line number in the stack trace indicates where the exception occurs. Your gui attribute in StepManager is null. It's never initialized.
Related
I'm having an issue with a JPanel and I don't get what's going on. So I have a JFrame with a init function, that create a custom JPanel called GamePanel, and the strange thing is it never goes in the paintComponents function, even if I use repaint on the object.
Here is my code when I initialize the JPanel (in a JFrame):
this.gamePanel = new GamePanel(this.grid, this);
this.panel.add(this.gamePanel, constraints);
And the JPanel itself:
public class GamePanel extends JPanel {
private final int SQUARE_SIZE = 50;
private Grid grid;
private final GameView gameView;
public GamePanel(Grid grid, GameView gameView) {
this.gameView = gameView;
this.setPreferredSize(new Dimension(200, 200));
}
public void setGrid(Grid grid) {
this.grid = grid;
this.setPreferredSize(new Dimension(grid.getSizeX() * SQUARE_SIZE, grid.getSizeY() * SQUARE_SIZE));
}
#Override
public void paintComponents(Graphics g) {
System.out.println("test");
if (this.grid != null) {
Graphics2D g2 = (Graphics2D) g;
double thickness = 3;
g2.setStroke(new BasicStroke((float) thickness));
g2.setColor(Color.BLACK);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
int x = SQUARE_SIZE * i;
int y = SQUARE_SIZE * j;
g2.drawRect(x, y, SQUARE_SIZE, SQUARE_SIZE);
if(this.grid.getSquareState(x, y) != 0) {
char[] tmp = ("" + this.grid.getSquareState(x, y)).toCharArray();
g2.drawChars(tmp, 0, 1, x, y);
}
}
}
}
}
}
EDIT: (the whole JFrame)
public class GameView extends JFrame {
private CustomSocket socket;
private JPanel panel;
private GamePanel gamePanel;
private JLabel listPlayers;
private JLabel playerPlaying;
private Grid grid;
public GameView(CustomSocket socket) {
this.socket = socket;
this.setTitle("TicTacToe - Client");
this.setSize(600, 480);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.init();
this.pack();
this.setVisible(true);
this.play();
}
private void init() {
this.panel = new JPanel();
this.panel.setLayout(new GridBagLayout());
GridBagConstraints constraints =new GridBagConstraints();
constraints.fill = GridBagConstraints.CENTER;
constraints.gridx = 0;
constraints.gridy = 0;
constraints.gridwidth = 1;
// Grid
this.gamePanel = new GamePanel(this.grid, this);
this.panel.add(this.gamePanel, constraints);
// Labels
constraints.gridy += 1;
this.listPlayers = new JLabel();
this.panel.add(this.listPlayers, constraints);
constraints.gridy += 1;
this.playerPlaying = new JLabel();
this.panel.add(this.playerPlaying, constraints);
this.setContentPane(this.panel);
}
private void play() {
String[] tmp = this.socket.getData().split(";");
this.grid = new Grid(Integer.parseInt(tmp[0]), Integer.parseInt(tmp[1]));
String players = "";
for(int i = 2; i < tmp.length; i++) {
players += tmp[i] + " ";
}
this.listPlayers.setText(players);
boolean notFinished = true;
while(notFinished) {
String[] gridData = this.socket.getData().split(";");
for(int i = 1; i < gridData.length; i++) {
String[] gridRow = gridData[i].replace("(", "").replace(")", "").split(",");
for(int j = 0; j < gridRow.length; j++) {
this.grid.setSquareState(i - 1, j, Integer.parseInt(gridRow[j]));
}
}
this.gamePanel.repaint();
String playerPlaying = this.socket.getData().split(";")[0];
if(playerPlaying != this.socket.getUsername()) {
}
notFinished = true;
}
}
}
Thank you in advance.
this.panel.add(this.gamePanel, constraints);
You add the component to a panel, but the panel doesn't have a preferred size. Since its size is (0, 0) there is nothing to paint so the method is never called.
All Swing components are responsible for determining their own preferred size. Override the getPreferredSize() method of your custom component. Then the layout manager can set the proper size/location of the component.
And paintComponent(...) is the proper method to override and don't forget the super.paintComponent(...) as the first statement to make sure the background gets cleared.
Currently I'm working on an assignment about creating a version of "Game of Life". However my cells won't appear.
This is my Cell Class:
class Cell{
boolean alive; //true if cell is alive, false if cell is dead
int numNeighbors; //number of alive neightboring cells
//change alive/dead state of the cell
void setAlive(boolean state){
alive = state;
}
//return alive/dead state of the cell
boolean isAlive(){
return alive;
}
//set numNeightbors of the cell to n
void setNumNeighbors(int n){
numNeighbors = n;
}
//take the cell to the next generation
void update(){
if(numNeighbors <2 || numNeighbors >3){
alive = false;
} else if((numNeighbors == 2 || numNeighbors == 3) && alive == true){
alive = true;
} else if(numNeighbors == 3 && alive == false){
alive = true;
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor( Color.blue );
g.setOpaque(true);
for(int i = 0; i < row; i++){
for(int j = 0; j < col; j++){
if(grid[i][j].isAlive()){
g.setColor( Color.BLACK);
} else {
g.setColor ( Color.WHITE);
g.fillRect(50, 50, 50*i, 50*j);
}
}
}
}
And this is my GameOfLife Class
<pre>import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import java.io.*;
public class GameOfLife implements MouseListener{
Cell[][] grid; //contain grid of cells
String birthFilename = "birth.txt"; //text file where initial generation is stored
int row; //number of rows
int col; //number of columns
ActionListener actionListener = new ActionListener(){
javax.swing.Timer timer = new javax.swing.Timer(500, this); //new timer
#Override
public void actionPerformed(ActionEvent event){
}
};
public void buildIt() {
int width = 600;
int height = 600;
JFrame frame = new JFrame("Game of Life");
readInitial();
//adds button interface
JPanel buttonbar = new JPanel();
frame.add(buttonbar, BorderLayout.SOUTH);
JButton start = new JButton("Start");
JButton stop = new JButton("Stop");
JButton nextg = new JButton("Next Generation");
buttonbar.add(nextg);
buttonbar.add(start);
buttonbar.add(stop);
JPanel panel = new JPanel();
frame.add(panel);
panel.setPreferredSize(new Dimension(width, height));
panel.setLayout(new GridLayout(row, col, 4, 4));
frame.pack();
frame.setBackground(Color.WHITE);
frame.setVisible(true);
}
public void mousePressed( MouseEvent e) {
//add code to update x and y
}
public void mouseReleased( MouseEvent e) { }
public void mouseClicked( MouseEvent e) { }
public void mouseEntered( MouseEvent e) { }
public void mouseExited( MouseEvent e) { }
//calculate number of living neightbors of each cell and sets numNeighbors
//Does not update dead/live state of cells
void calculateNumNeighbors(){
int numNeighbors = 0;
for(int i = 1; i < row + 1; i++){
for(int j = 1; j < col + 1; j++){
for(int k = -1; k < 2; k++){
for(int m = -1; m < 2; m++){
if(grid[i+k][j+m].isAlive() && !(k == 0 && m == 0)){
numNeighbors++;
}
}
}
grid[i][j].setNumNeighbors(numNeighbors);
}
}
}
//create grid and read initial generation from file
void readInitial(){
try{
grid = new Cell[row + 2][col + 2]; //empty neighbors at corners, so + 2
File file = new File(birthFilename);
Scanner scanner = new Scanner( file );
row = scanner.nextInt();
col = scanner.nextInt();
for(int i = 0; i < row + 2; i++){
for (int j = 0; j < col + 2; j++){
grid[i][j] = new Cell();
}
}
for(int i = 1; i < row + 1; i++){
for (int j = 1; j < col + 1; j++){
if(scanner.next().equals(".")){
grid[i][j].setAlive(false);
} else if(scanner.next().equals("*")){
grid[i][j].setAlive(true);
}
}
}
for(int i = 0; i < row + 2; i++){
grid[0][i].setAlive(false);
grid[row+2][i].setAlive(false);
}
for(int j = 0; j < col + 2; j++){
grid[j][0].setAlive(false);
grid[j][col+2].setAlive(false);
}
} catch(FileNotFoundException e) {
grid = new Cell[12][12];
row = 10;
col = 10;
for(int i = 0; i < 12; i++){
for (int j = 0; j < 12; j++){
grid[i][j] = new Cell();
grid[i][j].setAlive(false);
}
}
}
}
//update grid to the next generation, using the values of numNeightbors in the cells
void nextGeneration(){
for(int i = 1; i < row + 1; i++){
for (int j = 1; j < col + 1; j++){
grid[i][j].update();
}
}
}
public static void main(String[] arg) {
(new GameOfLife()).buildIt();
}
I hope anyone can help me out to make this program work.
I don't see why anything should draw. You've got a Cell class that yes has a paintComponent method, but this method is meaningless since it's not part of a Swing component. Your JPanel, where you should do drawing -- does nothing. You've other problems with the Cell class too in that it appears to be trying to draw the whole grid and not just a single cell.
Get rid of Cell's paintComponent method
Instead give it a public void draw(Graphics g) method that allows it to draw itself.
Create a JPanel that holds a grid of cells
Have this JPanel do the drawing in its paintComponent override. It will call the draw(g) method of all the Cells that it holds within a for loop.
Always place an #Override annotation above any overridden method. If you had done this, above your paintComponent, the compiler would have warned you that something was wrong.
For example: here's a small program that does not do the Game of Life, but shows an example of a JPanel holding and displaying a grid of non-component cells. By "non-component" the SimpleCell class does not extend from a Swing component, does not have any Swing methods, but as suggested above, does have a draw(...) method and can use this to draw itself. It also has a public boolean contains(Point p) method that the main program can use in its MouseListener to decide if it's been clicked:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class SimpleCellGrid extends JPanel {
private static final int ROWS = 40;
private static final int COLS = 40;
private static final int CELL_WIDTH = 10;
private static final int PREF_W = CELL_WIDTH * COLS;
private static final int PREF_H = CELL_WIDTH * ROWS;
private SimpleCell[][] cellGrid = new SimpleCell[ROWS][COLS];
public SimpleCellGrid() {
MyMouse myMouse = new MyMouse();
addMouseListener(myMouse);
for (int row = 0; row < cellGrid.length; row++) {
for (int col = 0; col < cellGrid[row].length; col++) {
int x = col * CELL_WIDTH;
int y = row * CELL_WIDTH;
cellGrid[row][col] = new SimpleCell(x, y, CELL_WIDTH);
}
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for (SimpleCell[] cellRow : cellGrid) {
for (SimpleCell simpleCell : cellRow) {
simpleCell.draw(g2);
}
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class MyMouse extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
for (SimpleCell[] cellRow : cellGrid) {
for (SimpleCell simpleCell : cellRow) {
if (simpleCell.contains(e.getPoint())) {
simpleCell.setAlive(!simpleCell.isAlive());
}
}
}
repaint();
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("SimpleCellGrid");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new SimpleCellGrid());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
public class SimpleCell {
private static final Color CELL_COLOR = Color.RED;
private boolean alive = false;
private int x;
private int y;
private int width;
private Rectangle rectangle;
public SimpleCell(int x, int y, int width) {
this.x = x;
this.y = y;
this.width = width;
rectangle = new Rectangle(x, y, width, width);
}
public boolean isAlive() {
return alive;
}
public void setAlive(boolean alive) {
this.alive = alive;
}
public void draw(Graphics2D g2) {
if (alive) {
g2.setColor(CELL_COLOR);
g2.fill(rectangle);
}
}
public boolean contains(Point p) {
return rectangle.contains(p);
}
#Override
public String toString() {
return "SimpleCell [alive=" + alive + ", x=" + x + ", y=" + y + ", width=" + width + ", rectangle=" + rectangle
+ "]";
}
}
I'm sorry if you've been annoyed by the recent posts. I usually can figure things if I Google them or use the API, but this project may have been over my head. I am using Swing to create a simple calculator that displays in a LED format in the IDE BlueJ (which offers no macros).
I'm sorry that the code is long but here is the JFrame I am displaying it with.
//Swing classes
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import javax.swing.Box;
import javax.swing.JTextField;
import javax.swing.JButton;
//Graphics classes
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.geom.AffineTransform;
import java.awt.Dimension;
import java.awt.event.*;
import java.awt.FlowLayout;
//Array, and math classes
import java.util.Arrays;
import java.util.ArrayList;
import java.lang.Math;
public class MCVE
{
public static void main(String[] args)
{
SwingUtilities.invokeLater( new Runnable() {
public void run() {
//frame width and height
final int FRAME_WIDTH = 317;
final int FRAME_HEIGHT = 415;
final JFrame myFrame = new JFrame();
myFrame.setSize(FRAME_WIDTH,FRAME_HEIGHT);
final JPanel myPanel = new JPanel();
myPanel.setLayout(null);
final JFrame ledFrame = new JFrame();
ledFrame.setLayout(new FlowLayout());
final MLED[] ledDisplay = new MLED[8];
for(int i = 0; i < ledDisplay.length; i++)
{
ledDisplay[i] = new MLED();
}
for(int i = 0; i < ledDisplay.length; i++)
{
ledFrame.add(ledDisplay[i]);
}
//Buttons on Simple Calculator
final JButton zeroButton = new JButton("0");
zeroButton.setSize(50,50);
zeroButton.setLocation(62,206);
final JButton endButton = new JButton("End");
endButton.setSize(102,50);
endButton.setLocation(186,275);
ledFrame.pack();
ledFrame.setSize(480,170);
ledFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
ledFrame.setLocationRelativeTo( null );
ledFrame.setVisible( true );
myFrame.add(myPanel);
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setVisible(true);
myPanel.add(zeroButton);
myPanel.add(endButton);
ledFrame.pack();
ledFrame.setSize(480,170);
ledFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
ledFrame.setLocationRelativeTo( null );
ledFrame.setVisible( true );
class CalculatorListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
//The entry
int x=0;
//final answer
int finalAnswer = 0;
//the variable count has two uses: to give an index to store into the array storage and to signal to the program that the operation has been completed and that it is time to move into a new operation.
int count = 0;
int count2 = 6;
String tempString;
ArrayList<Character> toLedArray = new ArrayList<Character>();
if(e.getSource() == zeroButton)
{
if(count>1)
{
x = 0;
count = 0;
}
else
{
if(x!=0)
{
x*=10;
x+=0;
}
else
{
x = 0;
}
}
tempString = String.valueOf(x);
for (char c : tempString.toCharArray()) {
toLedArray.add(c);
}
count = toLedArray.size();
if(count <= 8)
{
for(int i = 0; i < count ; i++)
{
tempString += toLedArray.get(i);
System.out.println("Calculator: 0 Button: Count = " + count2);
ledDisplay[count2].display(toLedArray.get(i));
count2--;
}
}
}
else if(e.getSource() == endButton)
{
myFrame.dispose();
}
}
}
//buttons are given life
CalculatorListener myListener = new CalculatorListener();
zeroButton.addActionListener(myListener);
endButton.addActionListener(myListener);
}
});
}
}
This class creates a JFrame that holds 2 buttons, one with the number zero on it and one that says "end". The zero button when pressed is supposed to light up the right most 7 segment display into the shape of a zero. Unfortunately, this is not the case. I suspect that there may be some threading issues in coming from the Swing operations.
I was hoping that you could take a look at it and point out my logic errors in the code.
Here are the two classes for the custom JPanel and JButton
public class MLED extends JPanel
{
// instance variables - replace the example below with your own
private static Bar[] bars = new Bar[7];
private GridBagConstraints c = new GridBagConstraints();
private final Dimension SIZE = new Dimension(60, 140);
/**
* Constructor for objects of class LED
*/
public MLED()
{
bars[0] = new MBar(30, 10);
bars[1] = new MBar(10, 30);
bars[2] = new MBar(10, 30);
bars[3] = new MBar(30, 10);
bars[4] = new MBar(10, 30);
bars[5] = new MBar(10, 30);
bars[6] = new Bar(30, 10);
this.setLayout(new GridBagLayout());
System.out.println("The LED class is being accessed");
}
public void display(char str)
{
if(str == '0')
{
System.out.println("LED: The zero has been pressed");
bars[0].lightUp();
bars[1].lightUp();
bars[2].lightUp();
bars[4].lightUp();
bars[5].lightUp();
bars[6].lightUp();
}
repaint();
}
public void clear()
{
bars[0].dim();
bars[1].dim();
bars[2].dim();
bars[3].dim();
bars[4].dim();
bars[5].dim();
bars[6].dim();
bars[7].dim();
repaint();
}
#Override public void paintComponent(Graphics g)
{
super.paintComponent(g);
for(int i = 0; i < bars.length; i++)
{
switch(i)
{
case 0:
c.gridx = 1;
c.gridy = 0;
break;
case 1:
c.gridx = 0;
c.gridy = 1;
break;
case 2:
c.gridx = 2;
c.gridy = 1;
break;
case 3:
c.gridx = 1;
c.gridy = 2;
break;
case 4:
c.gridx = 0;
c.gridy = 3;
break;
case 5:
c.gridx = 2;
c.gridy = 3;
break;
case 6:
c.gridx = 1;
c.gridy = 4;
break;
}
this.add(bars[i], c);
}
}
#Override public Dimension getPreferredSize()
{
return SIZE;
}
}
And the custom JComponent:
public class MBar extends JComponent
{
// instance variables - replace the example below with your own
private boolean litUp = false;
private boolean vertical = false;
private boolean rotated = false;
private boolean rotClockwise = false;
private int positionX;
private int positionY;
private final Dimension SIZE;
public MBar(int sizeX, int sizeY)
{
litUp = false;
//vertical = vert;
SIZE = new Dimension(sizeX, sizeY);
//positionX = posX;
//positionY = posY;
repaint();
}
public void lightUp()
{
litUp = true;
repaint();
}
public void dim()
{
litUp = false;
repaint();
}
public void setDirection(boolean vert)
{
vertical = vert;
repaint();
}
public void rotate(boolean rot, boolean dir)
{
rotated = rot;
rotClockwise = dir;
repaint();
}
public void moveRight()
{
positionX = positionX + 11;
repaint();
}
public void moveLeft()
{
positionX = positionX - 11;
repaint();
}
#Override public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2D = (Graphics2D)g;
System.out.println("BAR: Paint Component");
Color color;
int sizeX;
int sizeY;
// if(vertical == true)
// {
// sizeX = 10;
// sizeY = 30;
if(rotated == true)
{
if(rotClockwise == true)
{
g2D.rotate(0.3398);
}
else
{
g2D.rotate(-0.3398);
}
}
if(litUp == true)
{
color = Color.red;
}
else
{
color = Color.black;
}
// else{
// sizeX = 30;
// sizeY = 10;
// if(litUp == true)
// {
// color = Color.red;
// }
// else
// {
// color = Color.black;
// }
// }
g2D.setColor(color);
g2D.fillRect(0 , 0, SIZE.width, SIZE.height);
}
#Override public Dimension getPreferredSize(){
return SIZE;
}
}
The problem is private static Bar[] bars = new Bar[7];.
Every instance of MLED you create re-initialises this with their own values, meaning that each instance of MLED actually gets the SAME reference, instead of there own, which they should have.
When I make it private Bar[] bars = new Bar[7]; it produces...
I am currently writing code for a program that, when it works, opens an external window that has a building and a scrolling banner on it. If you input a phrase into a textbox above the building, that phrase will scroll across the banner.
DisplayWindow
import javax.swing.*;
import java.awt.*;
public class DisplayWindow extends JFrame {
private Container c;
public DisplayWindow() {
super("Display");
c = this.getContentPane();
}
public void addPanel(JPanel p) {
c.add(p);
}
public void showFrame() {
this.pack();
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
MovingSignPanel
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class MovingSignPanel extends JPanel implements ActionListener{
JMenuBar b;
JButton start = new JButton("Start");
JButton stop = new JButton("Stop");
JButton quit = new JButton("Quit");
JTextField phrase = new JTextField(20);
private int lVar = 200;
private int rVar = 600;
private int hVar = 200;
private int ground = 400;
private Timer scroll = new Timer(40,this);
private int xVel = 2;
private int xVal = lVar;
private int yVal = 150;
private String input = " ";
private int inputWidth = 0;
private Boolean scrolling = false;
public MovingSignPanel(JMenuBar b){
setPreferredSize(new Dimension(1000, 1000));
setBackground(Color.white);
this.add(phrase);
phrase.addActionListener(this);
this.add(start);
start.addActionListener(this);
this.add(stop);
stop.addActionListener(this);
this.add(quit);
quit.addActionListener(this);
}
public void drawBanner(Graphics g){
clearBanner(g);
drawBuilding(g);
int position = xVal;
while(position < rVar){
g.drawString(input,position,yVal);
position += inputWidth;
}
position = xVal - inputWidth;
while(position > lVar - inputWidth){
g.drawString(input,position,yVal);
position -= inputWidth;
}
if(xVal > rVar)
xVal -= inputWidth;
xVal += xVel;
drawBuilding(g);
}
public void drawBuilding(Graphics g){
super.paintComponent(g);
g.setColor(Color.white);
g.fillRect(0,0,1000,1000);
g.setColor(Color.gray);
g.fillRect(lVar,200,rVar-lVar,hVar);
g.fillRect(lVar,100,rVar-lVar,hVar-800);
g.setColor(Color.lightGray);
g.fillRect(0, ground, 700, 400 - ground);
g.setColor(Color.blue);
for(int n = lVar + 20; n < rVar - 10; n += 40){
for(int m = 60; m < 150; m += 30){
g.fillRect(n,m,20,20);
}
}
for(int n = lVar + 20; n < rVar - 10; n += 40){
for(int m = 210; m < 350; m += 30){
g.fillRect(n,m,20,20);
}
}
g.setColor(Color.darkGray);
g.fillRect(0,0,lVar,ground);
g.fillRect(rVar,0,lVar,ground);
}
public void inputMsg(){
input = phrase.getText();
inputWidth = phrase.getText().length();
}
public void resetTimer(){
scroll.stop();
scrolling = false;
}
public void startMsg(){
inputMsg();
if(!scrolling){
scroll.start();
scrolling = true;
}
}
public void clearBanner(Graphics g){
g.clearRect(0,0,1000,1000);
}
public void actionPerformed(ActionEvent e){
if (e.getSource() == quit)
System.exit(0);
if (e.getSource() == start)
repaint();
startMsg();
if (e.getSource() == stop)
resetTimer();
}
}
SignDriver
import javax.swing.*;
public class SignDriver {
public static void main(String[] args) {
DisplayWindow d = new DisplayWindow();
JMenuBar menuBar = new JMenuBar();
d.setJMenuBar(menuBar);
MovingSignPanel p = new MovingSignPanel(menuBar);
d.addPanel(p);
d.showFrame();
}
}
I can organize this better if needed. I know the buttons don't work yet, but right now I'm more concerned with why nothing is being drawn when the program is run. The error occurs whenever I try to run the program and looks like this:
java.lang.NoSuchMethodError: MovingSignPanel.<init>(Ljavax/swing/JMenuBar;)V
at SignDriver.main(SignDriver.java:9)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at edu.rice.cs.drjava.model.compiler.JavacCompiler.runCommand(JavacCompiler.java:272)
Seems your SignDriver class at runtime has an old version of the class MovingSignPanel, a version that does not have this constructor MovingSignPanel(javax.swing.JMenuBar). Just try to clean and rebuild, and this error should disappear.
I am designing a grid-based game which uses the Java swing framework. I have a JFrame with two JPanel within it, but one of them appears in two places. Here is a screenshot:
The panel that says "Turn 1" and has the buttons is only supposed to appear to the right of the grid, but it strangely also appears in the upper-left hand corner. Here is my code:
public class ArenaPanel extends JPanel {
private final GridPanel gp;
private final InfoPanel ip;
private GameManager gm;
private int w, h;
private int cw, ch;
private double tw, th;
private Point p2;
private Point p1;
private int shotWidth;
private Color shotColor;
public ArenaPanel(int w, int h) {
Images.load();
setLayout(new GridBagLayout());
this.w = w;
this.h = h;
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 1;
c.weightx = 0;
c.weighty = 1;
gp = new GridPanel();
gp.setPreferredSize(new Dimension(700, 700));
this.add(gp, c);
c.gridx = 1;
c.weightx = c.weighty = 0;
ip = new InfoPanel();
add(ip, c);
}
public void setGameManager(GameManager g) {
gm = g;
}
public void start() {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
gm.start();
}
});
t.start();
}
public void step() {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
gm.doTurn();
}
});
t.start();
}
public void paint(Graphics g) {
g.setColor(Color.black);
int val = Math.min(getWidth() - 200, getHeight());
gp.setPreferredSize(new Dimension(val, val));
gp.revalidate();
g.fillRect(0, 0, getWidth(), getHeight());
paintComponents(g);
}
private class GridPanel extends JPanel {
public void paint(Graphics g) {
cw = getWidth();
ch = getHeight();
g.setColor(Color.gray);
g.fillRect(0, 0, cw, ch);
tw = (double) cw / w;
th = (double) ch / h;
g.setColor(Color.black);
for (int i = 0; i < w; i++) {
g.drawLine((int) (i * tw), 0, (int) (i * tw), ch);
}
for (int i = 0; i < h; i++) {
g.drawLine(0, (int) (i * th), cw, (int) (i * th));
}
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
Robot t = gm.getGrid()[i][j];
if (t != null) {
Point p = expand(i, j);
g.drawImage(t.getImage(), p.x + t.getOffsetX(),
p.y + t.getOffsetY(), (int) tw, (int) th, null);
}
}
}
if (p1 != null) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(shotColor);
g2.setStroke(new BasicStroke(shotWidth));
g2.drawLine(p1.x, p1.y, p2.x, p2.y);
p1 = null;
p2 = null;
}
}
}
private class InfoPanel extends JPanel implements ActionListener {
private JButton start, stop, step;
private JLabel turns;
private int numTurns = 0;
private GridBagConstraints gbc;
private ArrayList<TeamPanel> tpanels;
public InfoPanel() {
JPanel buttons = new JPanel();
setLayout(new GridBagLayout());
buttons.setLayout(new GridBagLayout());
gbc = new GridBagConstraints();
start = new JButton("Start");
gbc.gridy = 0;
gbc.gridx = 1;
turns = new JLabel("Turn 1");
buttons.add(turns, gbc);
start.addActionListener(this);
gbc.gridy = 1;
gbc.gridx = 0;
buttons.add(start, gbc);
step = new JButton("Step");
step.addActionListener(this);
gbc.gridx++;
buttons.add(step, gbc);
stop = new JButton("Stop");
stop.addActionListener(this);
gbc.gridx++;
buttons.add(stop, gbc);
gbc.gridx = 0;
gbc.gridy = 0;
add(buttons, gbc);
tpanels = new ArrayList<TeamPanel>();
}
#Override
public void actionPerformed(ActionEvent actionEvent) {
if (actionEvent.getSource() == start) {
start();
} else if (actionEvent.getSource() == stop) {
gm.stop();
} else if (actionEvent.getSource() == step) {
step();
}
}
public void incrementTurn() {
numTurns++;
turns.setText("Turn " + numTurns);
}
public void initializeTeams(Map<String, TeamInfo> m) {
Set<String> k = m.keySet();
for (TeamPanel tp : tpanels) {
this.remove(tp);
}
tpanels.clear();
gbc.gridy = 1;
for (String s : k) {
TeamPanel tp = new TeamPanel(m.get(s));
add(tp, gbc);
gbc.gridy++;
tpanels.add(tp);
}
this.revalidate();
}
}
private class TeamPanel extends JPanel {
private Color col;
private int score;
private JLabel scoreLabel;
private TeamInfo inf;
public TeamPanel(TeamInfo inf) {
this.inf = inf;
col = getColor(inf.c);
super.setLayout(new FlowLayout());
BufferedImage ico = new BufferedImage(20, 20, BufferedImage.TYPE_3BYTE_BGR);
Graphics g = ico.getGraphics();
g.setColor(col);
g.fillRect(0, 0, 20, 20);
add(new JLabel(new ImageIcon(ico)));
this.add(new JLabel(inf.team));
scoreLabel = new JLabel("" + inf.score);
add(scoreLabel);
}
public void paint(Graphics g) {
//g.setColor(col);
//g.fillRect(-5, 0, 10, 10);
scoreLabel.setText("Score: " + inf.score);
this.paintComponents(g);
}
}
public void initializeTeams(Map<String, TeamInfo> m) {
ip.initializeTeams(m);
}
}
I have looked on google and StackOverflow for a similar problem, but I was unable to find one. Any help would be greatly appreciated.
Thanks!
Don't override the paint(...) method
Override the JPanel's paintComponent(...) method instead.
Don't forget to call the super paintComponent(...) method within your override.
And never call the super's paintComponents(...) (note the trailing "s") from within either the paint or paintComponent method. This smells like it could be the cause of your problem.