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.
Related
Is there a way to achieve pixel perfect graphics in Swing/AWT components?
I am implementing a custom border for a button by extending AbstractBorder. For demonstration purpose thickness is always equal to 3 and each line is painted using different color.
import javax.swing.*;
import javax.swing.border.AbstractBorder;
import javax.swing.border.Border;
import javax.swing.plaf.basic.BasicLookAndFeel;
import java.awt.*;
public class ExampleFrame extends JFrame {
public ExampleFrame() {
init();
}
public static void main(String[] args) throws UnsupportedLookAndFeelException
{
UIManager.setLookAndFeel(new CustomLookAndFeel());
ExampleFrame frame = new ExampleFrame();
frame.setVisible(true);
}
private void init() {
setLayout(new BorderLayout());
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
getContentPane().add(panel, BorderLayout.NORTH);
GridBagConstraints constraints = new GridBagConstraints();
JButton button1 = new JButton("aaa");
button1.setVerticalTextPosition(JButton.BOTTOM);
button1.setHorizontalTextPosition(JButton.CENTER);
button1.setFocusable(false);
constraints.insets = new Insets(2, 2, 2, 2);
constraints.gridx = 0;
constraints.gridy = 0;
constraints.gridwidth = 1;
constraints.gridheight = 3;
constraints.fill = GridBagConstraints.BOTH;
constraints.anchor = GridBagConstraints.LINE_START;
panel.add(button1, constraints);
JButton button2 = new JButton("bbb");
button2.setHorizontalAlignment(JButton.CENTER);
button2.setFocusable(false);
constraints.gridx = 1;
constraints.gridy = 0;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.fill = GridBagConstraints.BOTH;
constraints.anchor = GridBagConstraints.LINE_START;
panel.add(button2, constraints);
JButton button3 = new JButton("eee");
button3.setHorizontalAlignment(JButton.CENTER);
button3.setFocusable(false);
constraints.gridx = 1;
constraints.gridy = 1;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.anchor = GridBagConstraints.LINE_START;
panel.add(button3, constraints);
JButton button4 = new JButton("ddd");
button4.setHorizontalAlignment(JButton.CENTER);
button4.setFocusable(false);
constraints.gridx = 1;
constraints.gridy = 2;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.anchor = GridBagConstraints.LINE_START;
panel.add(button4, constraints);
pack();
}
private static final class CustomBorder extends AbstractBorder {
private final int thickness;
public CustomBorder() {
this(1);
}
public CustomBorder(int thickness) {
this.thickness = thickness;
}
#Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
// ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
((Graphics2D) g).setStroke(new BasicStroke(1.0f));
for (int i = 0; i < thickness; i++) {
switch (i) {
case 0: {
g.setColor(Color.RED);
}
break;
case 1: {
g.setColor(Color.GREEN);
}
break;
case 2: {
g.setColor(Color.BLUE);
}
break;
}
// top-left -> top-right
g.drawLine(x, y + i, x + width, y + i);
// top-left > bottom-left
g.drawLine(x + i, y, x + i, y + height);
}
}
#Override
public Insets getBorderInsets(Component c, Insets insets) {
insets.top = thickness;
insets.bottom = thickness;
insets.left = thickness;
insets.right = thickness;
return insets;
}
}
private static final class CustomLookAndFeel extends BasicLookAndFeel {
#Override
protected void initComponentDefaults(UIDefaults table) {
super.initComponentDefaults(table);
// button
Border buttonBorder = new CustomBorder(3);
table.put("Button.border", buttonBorder);
table.put("Button.background", new Color(150, 150, 182));
table.put("Button.foreground", Color.BLACK);
}
#Override
public String getName() {
return "custom";
}
#Override
public String getID() {
return "custom";
}
#Override
public String getDescription() {
return "custom";
}
#Override
public boolean isNativeLookAndFeel() {
return false;
}
#Override
public boolean isSupportedLookAndFeel() {
return true;
}
}
}
Even though all 3 buttons have the same border parameters I get different border width and colors displayed.
VALUE_STROKE_PURE and VALUE_STROKE_NORMALIZE hints give different results, but none of them is pixel accurate.
Buttons "bbb", "eee" and "ddd" on the right side have the same width and height, but still the colors and total width of the border is different. Additionally, the default stroke that is being used has width of 1.0f.
I assume this happens, because Java 2D geometry operates on floating point numbers. Is there any way to overcome this limitation?
I tried different routines e.g. drawRect and different anti-aliasing hints, but no luck.
So I am in the process of creating a game similar to Plants vs Zombies, however I've run into a slight problem: before I can apply the finishing touches such as levels, I need to prevent more than one JLabel being added to a JPanel. The placing of the JLabel works fine, though I think that I may have gone a roundabout route. The problem as stated above is that another JLabel can currently be added below a pre-existing JLabel. How do I set a JPanel to accept no more than the original component (the initial JLabel)? Any assistance would be greatly appreciated.
private final JFrame FRAME;
private final JPanel squares[][] = new JPanel[8][11];
private final Color DGY = Color.DARK_GRAY;
private final Color GRN = Color.GREEN;
private final Color BLK = Color.BLACK;
private final Color LGY = Color.LIGHT_GRAY;
private final Color GRY = Color.GRAY;
private final Color BLU = Color.BLUE;
private final Font F1 = new Font("Tahoma", 1, 36);
private String icon = "";
private int lvl = 10;
private void squareGen(int i, int j, Color col, boolean border)
{
squares[i][j].setBackground(col);
if (border)
{
squares[i][j].setBorder(BorderFactory.createLineBorder(BLK, 1));
}
FRAME.add(squares[i][j]);
}
public GameGUI()
{
FRAME = new JFrame("ESKOM VS SA");
FRAME.setSize(1600, 900);
FRAME.setLayout(new GridLayout(8, 11));
for (int x = 0; x < 8; x++)
{
if (x > 1 && x < 7)
{
squares[x][0] = new JPanel();
squareGen(x, 0, GRN, true);
} else if (x == 1 || x == 7)
{
squares[x][0] = new JPanel();
squareGen(x, 0, DGY, true);
} else
{
squares[x][0] = new JPanel();
squareGen(x, 0, BLU, false);
}
for (int y = 1; y < 11; y++)
{
squares[x][y] = new JPanel();
if (x == 0)
{
squareGen(x, y, BLU, false);
} else if (y == 10 || x == 1 || x == 7)
{
squareGen(x, y, DGY, true);
} else
{
squareGen(x, y, LGY, true);
addDToPanel(x, y);
}
}
}
JButton btnPause = new JButton();
btnPause.setText("||");
btnPause.setFont(F1);
btnPause.addActionListener(new java.awt.event.ActionListener()
{
#Override
public void actionPerformed(java.awt.event.ActionEvent evt)
{
btnPauseActionPerformed(evt);
}
});
squares[7][10].add(btnPause);
addButtons(8);
FRAME.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
FRAME.setLocationRelativeTo(null);
}
public void restart()
{
FRAME.dispose();
GameGUI ggui = new GameGUI();
ggui.setVisible(true);
}
public void mainMenu()
{
FRAME.dispose();
new StartUpUI().setVisible(true);
}
private void btnPauseActionPerformed(java.awt.event.ActionEvent evt)
{
new PauseGUI(this).setVisible(true);
}
private void btnAddDefenseActionPerformed(java.awt.event.ActionEvent evt)
{
JButton btn = (JButton) evt.getSource();
icon = btn.getActionCommand();
}
private void addButtons(int x)
{
JButton[] btn = new JButton[x];
for (int j = 1; j <= x; j++)
{
btn[j - 1] = new JButton();
ImageIcon ii = new ImageIcon(this.getClass().getResource("" + j + ".png"));
btn[j - 1].setIcon(ii);
btn[j - 1].setActionCommand("" + j);
btn[j - 1].setText("");
btn[j - 1].setForeground(btn[j - 1].getBackground());
squares[0][j].add(btn[j - 1]);
btn[j - 1].addActionListener(new java.awt.event.ActionListener()
{
#Override
public void actionPerformed(java.awt.event.ActionEvent evt)
{
btnAddDefenseActionPerformed(evt);
}
});
}
}
private void addDToPanel(int x, int y)
{
squares[x][y].addMouseListener(new MouseAdapter()
{
#Override
public void mousePressed(MouseEvent me)
{
JPanel panel = (JPanel) me.getSource();
int j = (int) (panel.getX() / 145.45454545) + 1;
int i = (int) (panel.getY() / 112.5) + 1;
addDefense(i, j, icon);
icon = "";
FRAME.revalidate();
FRAME.repaint();
}
});
}
private void addDefense(int i, int j, String imageName)
{
try
{
JLabel jlbl = new JLabel();
ImageIcon ii = new ImageIcon(this.getClass().getResource(imageName + ".png"));
jlbl.setIcon(ii);
squares[i][j].add(jlbl, java.awt.BorderLayout.CENTER);
} catch (Exception e)
{
}
}
public void setLvl(int lvl)
{
this.lvl = lvl;
}
public void setVisible(boolean b)
{
FRAME.setVisible(b);
}
This is not my main class, this class is instantiated in the main class and setVisible() = true;
Again thanks in advance!
How do I set a JPanel to accept no more than the original
You can use the Container.getComponentCount() method to check how many components have been added to the panel.
Only add your component when the count is 0.
I have created a matrix on java and I need to add two JButton "cancel" and "submit" below the matrix
This is my code but it miss the two JButton , need your help please .
public class matrice2 extends JFrame{
private static final long serialVersionUID = 1L;
private final int width;
private final int height;
private final JLabel[] horizon;
private final JLabel[] vertical;
private final JButton[][] centre;
//private final JButton[] VC;
private final ImageIcon ZERO = new ImageIcon("0.jpg");
private final ImageIcon ONE = new ImageIcon("1.jpg");
public matrice2(int width, int height) {
this.width = width;
this.height = height;
horizon = new JLabel[width];
vertical = new JLabel[height];
centre = new JButton[width][height];
initFrame();
fillContent();
this.setVisible(true);
}
private void initFrame() {
this.setSize(700, 700);
this.setTitle("Matrice du graphe");
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private JLabel createColumnHeader(int x) {
horizon[x] = new JLabel("H" + (x + 1));
return horizon[x];
}
private JLabel createRowHeader(int y) {
vertical[y] = new JLabel("V" + (y + 1));
return vertical[y];
}
private JButton createCell(int x, int y) {
centre[x][y] = new JButton();
centre[x][y].addActionListener(new MatriceListener(this,x,y));
return centre[x][y];
}
public void fillContent() {
this.setLayout(new GridLayout(width+2, height+2));
this.add(new JLabel());
for (int x = 0; x < width; x++)
this.add(createColumnHeader(x));
for (int y = 0; y < height; y++) {
this.add(createRowHeader(y));
for (int x=0; x<width; x++)
this.add(createCell(x,y));
}
}
public void setIcon(int x, int y) {
centre[x][y].setIcon(ONE);
}
Change the fillContent() method:
public void fillContent() {
JPanel content = new JPanel();
content.setLayout(new GridLayout(width + 2, height + 2));
content.add(new JLabel());
for (int x = 0; x < width; x++) {
content.add(createColumnHeader(x));
}
for (int y = 0; y < height; y++) {
content.add(createRowHeader(y));
for (int x = 0; x < width; x++) {
content.add(createCell(x, y));
}
}
add(content, BorderLayout.CENTER);
JPanel buttons = new JPanel();
buttons.add(new JButton("Submit"));
buttons.add(new JButton("Cancel"));
add(buttons, BorderLayout.SOUTH);
}
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.
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.