I want to thank Andrew Thompson for helping me get this far in the code.
How do I access each individual button's actionPerformed listener?
The code is supposed to move the "ball" on the screen based on the button you press.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Lab2a extends JFrame {
Lab2a(){
setTitle("Lab 1b - Application #2");
Lab2Panel p = new Lab2Panel();
add(p);
}
public static void main(String[] args){
Lab2 frame = new Lab2();
frame.setTitle("Lab2 Application # 1");
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);
frame.setVisible(true);
}
}
class Lab2Panel extends JPanel{
Lab2Button canvas = new Lab2Button();
JPanel panel = new JPanel();
Lab2Panel () {
setLayout(new BorderLayout());
JButton leftButton = new JButton("left");
JButton rightButton = new JButton("right");
JButton upButton = new JButton("up");
JButton downButton = new JButton("down");
panel.add(leftButton);
panel.add(rightButton);
panel.add(upButton);
panel.add(downButton);
this.add(canvas, BorderLayout.CENTER);
this.add(panel, BorderLayout.SOUTH);
leftButton.addActionListener(new Lab2MoveBallListener(canvas));
rightButton.addActionListener(new Lab2MoveBallListener(canvas));
}
}
class Lab2Button extends JPanel {
int radius = 5;
int x = -1;
int y = -1;
protected void paintComponent(Graphics g){
if (x<0 || y<0) {
x = getWidth() / 2 - radius;
y = getHeight() / 2 - radius;
}
super.paintComponent(g);
g.drawOval(x,y, 2 * radius, 2 * radius);
}
public void moveLeft(){
x -= 5;
this.repaint();
}
public void moveRight(){
x += 5;
this.repaint();
}
public void moveUp(){
y += 5;
this.repaint();
}
public void moveDown(){
y -= 5;
this.repaint();
}
}
class Lab2MoveBallListener implements ActionListener{
private Lab2Button canvas;
Lab2MoveBallListener(Lab2Button canvas) {
this.canvas = canvas;
}
public void actionPerformed(ActionEvent e){
canvas.moveLeft();
}
}
Since you are using 1 action listener class with 2 buttons you will have to have a way to tell which button was pressed. You can try something like this in the actionPerformed method:
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().matches("left"))
System.out.print("left button pressed");
else if(e.getActionCommand().matches("right"))
System.out.print("right button pressed");
}
another way would be to do this is to create an anonymous class by doing this:
buttonLeft.addActionListener(new ActionListener(){
public void actionPerformed(){
//left button code
}
});
buttonRight.addActionListener(new ActionListener(){
public void actionPerformed(){
//right button code
}
});
In the ActionListener's actionPerformed(...) method, you can get the text of the button that's been pressed via the ActionEvent's getActionCommand() method.
Just test it to see the results:
public void actionPerformed(ActionEvent e){
String actionCommand = e.getActionCommand();
System.out.println("actionCommand is: " + actionCommand);
}
Now you can use this information inside of this method to do more than just write to the standard out, but I'll let you figure out the rest.
Related
Whenever I try to move the array lifegrid, the complier gives errors and something goes wrong with the window. Not sure what the array has to do with that as I am not yet using it to change the displayed information.
I want to be able to call my code in the class LifeRunningCode but because my array is defined in MyPanel it is not visible in CreateAndShowGUI. I need it to be visible to both methods. Can I place it just before the MAIN method?
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SwingPaintDemo3 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
static void createAndShowGUI() {
System.out.println("Created GUI on EDT? " + SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Swing Paint Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MyPanel());
f.pack();
JPanel subPanel = new JPanel();
JButton seed = new JButton("SEED");
subPanel.add(seed);
seed.setPreferredSize(new Dimension(70, 50));
seed.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
System.out.println("Seed");
}
});
JButton start = new JButton("START");
subPanel.add(start);
start.setPreferredSize(new Dimension(70, 50));
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae1) {
System.out.println("Start");
//lifegrid = LifeRunningCode.changeValues(lifegrid);
}
});
start.setPreferredSize(new Dimension(70, 50));
JButton stop = new JButton("STOP");
subPanel.add(stop);
stop.setPreferredSize(new Dimension(70, 50));
JButton reset = new JButton("RESET");
subPanel.add(reset);
reset.setPreferredSize(new Dimension(70, 50));
f.add(subPanel, BorderLayout.EAST);
f.setVisible(true);
}
}
class MyPanel extends JPanel {
int lifegrid[][][] = new int[62][42][2];
int squareX = 1280;
int squareY = 800;
int gridX = 0;
int gridY = 0;
public MyPanel() {
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
squareX = e.getX();
squareY = e.getY();
if ((squareX > 20 & squareX < 920) & (squareY > 50 & squareY < 650)) {
gridX = (squareX - 20) / 15 + 1;
gridY = (squareY - 50) / 15 + 1;
squareX = (squareX - 20) / 15 * 15 + 20;
squareY = (squareY - 50) / 15 * 15 + 50;
lifegrid[gridX][gridY][0] = 1;
System.out.println(gridX + " " + gridY);
repaint(squareX, squareY, 15, 15);
}
else {}
}
});
}
public Dimension getPreferredSize() {
return new Dimension(1280, 800);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(squareX, squareY, 13, 13);
g.setColor(Color.BLACK);
g.drawRect(squareX, squareY, 13, 13);
}
}
All the UI objects are localized in createAndShowGUI method.
If you need to access the array inside an instance of MyPanel class you should:
create a getter for this array in MyPanel
store an instance of MyPanel inside main class SwingPaintDemo3 and refer it as necessary:
// MyPanel
class MyPanel extends JPanel {
// ...
public int[][][] getLifegrid() {
return lifegrid;
}
}
// SwingPaintDemo3
public class SwingPaintDemo3 {
static MyPanel myPanel = new MyPanel();
static void createAndShowGUI() {
System.out.println("Created GUI on EDT? " + SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Swing Paint Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(myPanel);
// ...
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae1) {
System.out.println("Start");
LifeRunningCode.changeValues(myPanel.getLifegrid());
}
});
// ...
}
}
I am trying to add a Rectangle in the panel by button press and remove it with another one. It should work but it doesn't render anything, and I absolutely don't know why.
Can someone explain what I am doing wrong and give me some nice tips what I can improve with my code?
public class GUI extends JPanel {
public static boolean isRecVisible = false;
public static void main(String[] args) {
createGui();
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
super.paintComponent(g);
g2d.drawRect(10, 10, 200, 200);
}
public static void createGui() {
int frameWidth = 550;
int frameHeight = 400;
int buttonWidth1 = 250;
int buttonHeight1 = 30;
int buttonWidth2 = 500;
int buttonHeight2 = 30;
int displayWidth = frameWidth - 20;
int displayHeight = frameHeight - 105;
GUI drawRec = new GUI();
JFrame f = new JFrame("Rectangle");
JPanel p = new JPanel();
JPanel display = new JPanel();
JButton addRec = new JButton("Add Rectangle");
JButton removeRec = new JButton("Remove Rectangle");
JButton colorRec = new JButton("Color Rectangle");
f.add(p);
p.add(addRec);
p.add(removeRec);
p.add(colorRec);
p.add(display);
display.setBackground(Color.LIGHT_GRAY);
f.setSize(frameWidth, frameHeight);
f.setLocationRelativeTo(null);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
display.setBounds(frameWidth / 2 - displayWidth / 2, 10, displayWidth, displayHeight);
addRec.setBounds(frameWidth / 2 - buttonWidth1 / 2 - 250 / 2, frameHeight - 85, buttonWidth1, buttonHeight1);
removeRec.setBounds(frameWidth / 2 - buttonWidth1 / 2 + 250 / 2, frameHeight - 85, buttonWidth1, buttonHeight1);
colorRec.setBounds(frameWidth / 2 - buttonWidth2 / 2, frameHeight - 60, buttonWidth2, buttonHeight2);
addRec.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (isRecVisible == false) {
isRecVisible = true;
display.add(drawRec);
display.repaint();
System.out.println("Rectangle has been drawn!");
} else {
System.out.println("Rectangle has already been drawn!");
return;
}
}
});
removeRec.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (isRecVisible == true) {
isRecVisible = false;
System.out.println("Rectangle has been removed!");
} else {
System.out.println("Rectangle has already been removed");
return;
}
}
});
}
}
display.add(drawRec);
display.repaint();
When you add (or remove) components to a visible frame then the basic logic is:
display.add(...);
display.revalidate();
display.repaint(); // sometimes needed
The revalidate() is the key method because it invokes the layout manager so the size/location of the component can be set.
However, that still won't fix the problem because your custom panel doesn't have a preferred size, so there is nothing to paint for your component.
You need to override the getPreferredSize() method of your custom panel to return the preferred size of your custom component. So in your case you might set the preferred size to be (220, 220) so the rectangle is centered in the panel.
Read the section from the Swing tutorial on Custom Painting for more information and complete working examples.
Note: the tutorial example will also show you how to better structure your code to make sure the GUI is created on the Event Dispatch Thread.
Rather than adding or removing components, it would make more sense here to add the custom painted panel on construction, and use the isRecVisible boolean as a flag to test for drawing the rectangle.
Something like shown here:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GUI extends JPanel {
public static boolean isRecVisible = false;
public static void main(String[] args) {
createGui();
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
super.paintComponent(g);
if (isRecVisible) {
g2d.drawRect(10, 10, 200, 200);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(600,400);
}
public static void createGui() {
int frameWidth = 550;
int frameHeight = 400;
GUI drawRec = new GUI();
drawRec.setBackground(Color.LIGHT_GRAY);
JFrame f = new JFrame("Rectangle");
JPanel p = new JPanel();
JButton addRec = new JButton("Add Rectangle");
JButton removeRec = new JButton("Remove Rectangle");
JButton colorRec = new JButton("Color Rectangle");
f.add(p, BorderLayout.PAGE_START);
p.add(addRec);
p.add(removeRec);
p.add(colorRec);
f.add(drawRec);
f.setSize(frameWidth, frameHeight);
f.setLocationRelativeTo(null);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
addRec.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
isRecVisible = true;
drawRec.repaint();
}
});
removeRec.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
isRecVisible = false;
drawRec.repaint();
}
});
}
}
I have a circle randomly painted with 3 different colors (BLUE, RED and GREEN) and 3 Buttons with this same colors(BLUE, RED and GREEN) and if the Circle is RED and I press the RED Button I need to show up in the Label YOU WON if you choose wrong color YOU LOSE. It's very simple but i can't call in the ActionPerformed the variable (that is the color to match with the button) from paintComponent. Sry for my language too.
Here is the CODE with 2 Classes:
PaintPanel.class
public class PaintPanel extends JPanel implements ActionListener {
int x = 200, y = 250;
private JButton b1 = new JButton("BLUE");
private JButton b2 = new JButton("RED");
private JButton b3 = new JButton("GREEN");
JLabel label = new JLabel("Choose the right Color");
JPanel subPanel = new JPanel();
private Color[] colors;
public PaintPanel() {
setLayout(new BorderLayout());
setPreferredSize(new Dimension(440, 440));
add(label, BorderLayout.NORTH);
b1.addActionListener(this);
b2.addActionListener(this);
b3.addActionListener(this);
subPanel.add(b1);
b1.setForeground(Color.BLUE);
subPanel.add(b2);
b2.setForeground(Color.RED);
subPanel.add(b3);
b3.setForeground(Color.GREEN);
add(subPanel, BorderLayout.SOUTH);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Color[] colors = new Color[3];
colors[0] = Color.BLUE;
colors[1] = Color.RED;
colors[2] = Color.GREEN;
Color c1 = colors[randInt(colors.length)];
g.setColor(c1);
/* this.colors.equals(c1); !!!! HERE I TRIED !!!*/
g.fillOval(x, y, 30, 30);
}
private int randInt(int length) {
// TODO Auto-generated method stub
Random rand = new Random();
int randomColor = rand.nextInt(length);
return randomColor;
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == b1) {
if (Color.BLUE.equals(colors)) {
label.setText("You WIN");
}
}else {
label.setText("You LOSE");
}
if (e.getSource() == b2) {
}
if (e.getSource() == b3) {
}
}
}
Another one - DrawCircle.class -
public class DrawCircle extends JFrame {
private JPanel painted;
public DrawCircle() {
painted = new PaintPanel();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new FlowLayout());
setBounds(0, 0, 800, 540);
add(painted);
setVisible(true);
}
public static void main(String[] args) {
new DrawCircle();
}
}
Just a couple notes: You cannot access a non-static method from a static context. Consider Placing your DrawCircle() method in a separate class. Create an instance of that class and call DrawCircle() from that instance.
Regarding PaintPanel.class please note that paintComponent() is called very frequently, and is not just called on initialization. The Colors you generate need to be saved in a place accessible by actionPerformed(). Consider creating a Color tmp member in your class structure and reference your correct answer from there. In addition, you appear to be missing a call to UpdateUI(). This code is not perfect, but it works well. Personally, I'd find a different way to generate new colors apart from overriding paintComponent(), but if you need it there, this example should prove helpful. Comment below with improvements:
package com.company;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
public class PaintPanel extends JPanel implements ActionListener
{
int x = 200, y = 250;
private JButton b1 = new JButton("BLUE");
private JButton b2 = new JButton("RED");
private JButton b3 = new JButton("GREEN");
JLabel label = new JLabel("Choose the right Color");
JPanel subPanel = new JPanel();
private Color[] colors;
Color tmp = null;
public PaintPanel()
{
setLayout(new BorderLayout());
setPreferredSize(new Dimension(440, 440));
add(label, BorderLayout.NORTH);
b1.addActionListener(this);
b2.addActionListener(this);
b3.addActionListener(this);
subPanel.add(b1);
b1.setForeground(Color.BLUE);
subPanel.add(b2);
b2.setForeground(Color.RED);
subPanel.add(b3);
b3.setForeground(Color.GREEN);
add(subPanel, BorderLayout.SOUTH);
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
colors = new Color[3]; //Referencing Class member colors instead of local variable
colors[0] = Color.BLUE;
colors[1] = Color.RED;
colors[2] = Color.GREEN;
tmp = colors[randInt(colors.length)]; //Read into a class member instead of a local variable
g.setColor(tmp);
System.out.println("Paint Triggered. New Color is: " + tmp.toString()); //todo remove this debugging line
g.fillOval(x, y, 30, 30);
}
private int randInt(int length)
{
// TODO Auto-generated method stub
Random rand = new Random();
int randomColor = rand.nextInt(length);
return randomColor;
}
#Override
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == b1) {
if (Color.BLUE.equals(tmp)) {
label.setText("You WIN");
} else {
label.setText("You Loose");
}
} else if (e.getSource() == b2) {
if (Color.RED.equals(tmp)) {
label.setText("You WIN");
} else {
label.setText("You Loose");
}
} else if (e.getSource() == b3) {
if (Color.GREEN.equals(tmp)) {
label.setText("You WIN");
} else {
label.setText("You Loose");
}
}
updateUI(); //<---------------IMPORTANT To Sync What you see with each button press.
}
}
I think you've simply messed up your braces (and your indentation). Please use an auto-indent or auto-format tool in an IDE, it will locate these problems quickly.
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == b1) {
if (Color.BLUE.equals(colors)) {
label.setText("You WIN");
}
// v Problem is this extra brace
}else {
label.setText("You LOSE");
}
Change to
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == b1) {
if (Color.BLUE.equals(colors)) {
label.setText("You WIN");
}
else {
label.setText("You LOSE");
}
} else if( //...
Your colors array should not be created in the paintComponent() method. It should be declared as a PaintPanel instance variable, and should be created in the PaintPanel constructor.
Here is a possibility (you do not need a separate class; I added a main to PaintPanel):
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class PaintPanel extends JPanel implements ActionListener {
int x = 200, y = 250;
private JButton b1 = new JButton("BLUE");
private JButton b2 = new JButton("RED");
private JButton b3 = new JButton("GREEN");
JLabel label = new JLabel("Choose the right Color");
JPanel subPanel = new JPanel();
private Color circleColor;
public PaintPanel() {
setLayout(new BorderLayout());
setPreferredSize(new Dimension(440, 440));
add(label, BorderLayout.NORTH);
b1.addActionListener(this);
b2.addActionListener(this);
b3.addActionListener(this);
subPanel.add(b1);
b1.setForeground(Color.BLUE);
subPanel.add(b2);
b2.setForeground(Color.RED);
subPanel.add(b3);
b3.setForeground(Color.GREEN);
add(subPanel, BorderLayout.SOUTH);
Random rand = new Random();
int rc = rand.nextInt(3);
switch (rc) {
case 1:
circleColor = Color.RED;
break;
case 2:
circleColor = Color.GREEN;
break;
default:
circleColor = Color.BLUE;
break;
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(circleColor);
g.fillOval(x, y, 30, 30);
}
#Override
public void actionPerformed(ActionEvent e) {
JButton b = (JButton) e.getSource();
if (b.getForeground().equals(circleColor)) {
label.setText("You WIN");
} else {
label.setText("You LOSE");
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// create the main frame
JFrame frame = new JFrame();
// create the component to display in the frame
PaintPanel comp = new PaintPanel();
frame.add(comp, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent arg0) {
System.exit(0);
}
});
}
});
}
}
I am trying to set a new text into a button when you press on it. However it does not seem to work, I am doing something wrong, and I do not know what...
EDIT -----I attach the code for easier comprehension of what I mean
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GrowAndShrinkSquareGUItest {
JFrame frame;
SquareDrawPanel bigGreen;
SquareDrawPanel smallGreen;
JButton button;
growAndShrinkListener listener;
public class SquareDrawPanel extends JPanel {
int width;
int height;
SquareDrawPanel(int w, int h) {
width = w;
height = h;
}
public void paintComponent(Graphics g) {
g.setColor(Color.green);
g.fillRect(frame.getWidth() / 2 - (width / 2), frame.getHeight()
/ 2 - (height / 2) - 15, width, height);
}
}
public class growAndShrinkListener implements ActionListener {
// JButton button;
growAndShrinkListener(JButton button) {
button = new JButton("Click me to grow the Square");
frame.add(button, BorderLayout.NORTH);
button.addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
button.setText("Unselect all");
}
}
public static void main(String[] args) {
GrowAndShrinkSquareGUItest test = new GrowAndShrinkSquareGUItest();
test.go();
}
private void createPanels() {
bigGreen = new SquareDrawPanel(400, 400);
smallGreen = new SquareDrawPanel(100, 100);
}
private void drawPanel(JPanel panel) {
frame.add(panel);
panel.setVisible(true);
frame.add(panel, BorderLayout.CENTER);
}
private void createListenerButton() {
listener = new growAndShrinkListener(button);
}
private void loop(){}
public void go() {
frame = new JFrame();
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
createPanels();
drawPanel(smallGreen);
createListenerButton();
frame.setVisible(true);
}
}
It is because you use the button variable that is not defined in the scope of actionPerformed method. Java variables have scope and they are available inside curly braces where they're defined. The actionPerformed method is out of the curly braces of growAndShrinkListener method. The fixed code:
public class growAndShrinkListener implements ActionListener {
growAndShrinkListener(JButton button) {
button = new JButton("Click me to grow the Square");
frame.add(button, BorderLayout.NORTH);
button.addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if(source instanceof JButton) {
button = (JButton) source;
button.setText("Click to shrink square");
}
}
}
Alternatively, you can use a private variable:
public class growAndShrinkListener implements ActionListener {
private JButton button;
growAndShrinkListener() {
button = new JButton("Click me to grow the Square");
frame.add(button, BorderLayout.NORTH);
button.addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
button.setText("Click to shrink square");
}
}
Note: You should not overwrite the content of the argument in the constructor. The argument that you got is not a "pointer" to the callee's variable, but just a simple reference to that. If you overwrite, then the content will be lost for you and calle will not know that.
change like this..
public class YourSuperClass{
private JButton button;
public YourSuperClass(){
// your logics
button = new JButton();
button.addActionListener(new GrowAndShrinkListener(button));
frame.add(button, BorderLayout.NORTH);
}
class GrowAndShrinkListener implements ActionListener {
GrowAndShrinkListener(JButton button) {
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button){
button.setText("Click to shrink square");
}
}
}
}
Try This :
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class frame extends JFrame
{
JButton b;
public frame()
{
setLayout(new BorderLayout());
b=new JButton("Press");
add(b,BorderLayout.SOUTH);
b.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
b.setText("Clicked");
}
});
}
public static void main (String[] args) {
frame f=new frame();
f.setExtendedState(MAXIMIZED_BOTH);
f.setVisible(true);
}
}
I've hit a wall (in my brain) trying to update my board on button presses. Am I right in thinking that the GameBoard class is the one that needs to be repaint()ed?
GameBoard.java
public class GameBoard extends Panel {
static Compass compass = new Compass();
private static final long serialVersionUID = 1;
Graphics2D g2d;
static final Dimension WINDOW_SIZE = new Dimension(1150, 800);
public void boardMaker() throws Exception {
JFrame frame = new JFrame("Display image");
JPanel panel = new JPanel();
/* unimportant stuff
.....
*/
//
DieRoll roll = new DieRoll("Roll Dies");
roll.setC(compass);
roll.setG2D(g2d);
//
Button button = new Button("new");
button.setGameBoard(this);
JPanel buttonPanel = new JPanel();
buttonPanel.add(button);
buttonPanel.add(roll);
buttonPanel.setPreferredSize(new Dimension(200,100));
frame.getContentPane().add(buttonPanel, BorderLayout.NORTH);
//
frame.getContentPane().add(panel);
frame.setVisible(true);
}
public void paint(Graphics g) {
// not important I think
}
}
Button.java
public class Button extends JButton implements ActionListener {
private static final long serialVersionUID = 1L;
JPanel panel = new JPanel();
JFrame frame = new JFrame();
Compass c = new Compass();
GameBoard gb = new GameBoard();
Button(String text) {
this.setText(text);
this.addActionListener(this);
}
void setGameBoard(GameBoard gb) {
this.gb = gb;
}
#Override
public void actionPerformed(ActionEvent e) {
gb.g2d.setColor(Color.black);
gb.g2d.fillRect(100, 100, 100, 200);
gb.repaint();
}
}
This gives a null pointer exception. So any idea how to repaint my GameBoard? I'm not mad if I've to rewrite everything because of stupidity! ;)
Thanks
You have the wrong idea about how to draw in Java. Components like Panels draw themselves, and all drawing takes place on the UI thread.
Check out this tutorial: docs.oracle.com/javase/tutorial/2d/index.html
The article Painting in AWT and Swing may offer some perspective on application-triggered painting. The example below illustrates the principle. Note that setForeground() calls repaint() automatically because the foreground color is a bound property, but you can always call it yourself.
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
public class SwingPaint {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame();
final GamePanel gp = new GamePanel();
f.add(gp);
f.add(new JButton(new AbstractAction("Update") {
#Override
public void actionPerformed(ActionEvent e) {
gp.update();
}
}), BorderLayout.SOUTH);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
private static class GamePanel extends JPanel {
private static final Random r = new Random();
public GamePanel() {
this.setForeground(new Color(r.nextInt()));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(320, 240);
}
public void update() {
this.setForeground(new Color(r.nextInt()));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Dimension size = this.getSize();
int d = Math.min(size.width, size.height) - 10;
int x = (size.width - d) / 2;
int y = (size.height - d) / 2;
g.fillOval(x, y, d, d);
g.setColor(Color.blue);
g.drawOval(x, y, d, d);
}
}
}