问题
Title says it all... My friend and I are doing this and we have no idea why Ball.java isn't actually making the balls in the gamePanel and then making the GUI. This is 8-ball pool, by the way. Here is the code:
Driver or Final2
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.*;
import java.awt.event.*;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
public class Final2 implements ActionListener {
JPanel titlePanel, gamePanel, buttonPanel;
JLabel titleLabel, turnLabel, oneTypeLabel, twoTypeLabel;
JButton newGameButton;
int turn;
String oneType,twoType;
public JPanel createContentPane() {
turn = 0;
oneType = "";
twoType = "";
JPanel totalGUI = new JPanel();
totalGUI.setLayout(null);
titlePanel = new JPanel();
titlePanel.setLayout(null);
titlePanel.setLocation(10,0);
titlePanel.setSize(500,100);
totalGUI.add(titlePanel);
titleLabel = new JLabel("8-ball Pool");
titleLabel.setLocation(25,10);
titleLabel.setSize(100,20);
titleLabel.setHorizontalAlignment(0);
titleLabel.setForeground(Color.red);
titlePanel.add(titleLabel);
gamePanel = new gamePanel();
gamePanel.setLayout(null);
gamePanel.setLocation(200,250);
gamePanel.setSize(864,432); //this needs to be turned into 864x432 later
gamePanel.setBorder(BorderFactory.createLineBorder(Color.black));
totalGUI.add(gamePanel);
buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout());
buttonPanel.setLocation(900,40);
buttonPanel.setSize(200,40);
totalGUI.add(buttonPanel);
turnLabel = new JLabel("" + turn);
turnLabel.setHorizontalAlignment(0);
titlePanel.add(turnLabel);
oneTypeLabel = new JLabel(oneType);
oneTypeLabel.setHorizontalAlignment(0);
oneTypeLabel.setForeground(Color.red);
buttonPanel.add(oneTypeLabel);
twoTypeLabel = new JLabel(twoType);
twoTypeLabel.setHorizontalAlignment(0);
twoTypeLabel.setForeground(Color.blue);
buttonPanel.add(twoTypeLabel);
newGameButton = new JButton("New Game");
newGameButton.addActionListener(this);
buttonPanel.add(newGameButton);
return totalGUI;
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == newGameButton) {
}
}
public static void createAndShowGUI() {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("8-ball Pool!");
//Create and set up the content pane.
Final gui = new Final();
frame.setContentPane(gui.createContentPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000, 1500);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
} }
gamePanel
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.*;
import java.awt.event.*;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
public class gamePanel extends JPanel {
private boolean setup = true;
public gamePanel() { setOpaque(true); setBackground(Color.GREEN);
}
public void paintComponent(Graphics g) { /* Graphics2D g2 = (Graphics2D) g; Ellipse2D circle = new Ellipse2D.Double(100 - 18,100
-18,18,18); g2.setColor(Color.BLUE); g2.draw(circle); Rectangle2D rect = new Rectangle2D.Double(100 - 18,100 -5,18,5);
g2.setColor(Color.WHITE); g2.draw(rect); */
super.paintComponent(g); //column 1 //1 /*
g.setColor(Color.BLACK); g.drawOval(624,206,20,20);
g.setColor(Color.YELLOW); g.fillOval(625,207,18,18);
//column 2 //14 g.setColor(Color.BLACK);
g.drawOval(644,196,20,20); g.setColor(Color.GREEN);
g.fillOval(645,197,18,18);
//4 g.setColor(Color.BLACK); g.drawOval(644,216,20,20);
g.setColor(Color.MAGENTA); g.fillOval(645,217,18,18);
g.setColor(Color.WHITE); g.fillRect(645 + 7,217,5,18);
//column 3 //5 g.setColor(Color.BLACK); g.drawOval(664,186,20,20);
g.setColor(Color.ORANGE.darker()); g.fillOval(665,187,18,18);
g.setColor(Color.WHITE); g.fillRect(665 + 7,187,5,18);
//8 g.setColor(Color.BLACK); g.drawOval(664,206,20,20);
g.setColor(Color.BLACK); g.fillOval(665,207,18,18);
//13 g.setColor(Color.BLACK); g.drawOval(664,226,20,20);
g.setColor(Color.ORANGE.darker()); g.fillOval(665,227,18,18);
//column 4 //11 g.setColor(Color.BLACK);
g.drawOval(684,176,20,20); g.setColor(Color.RED);
g.fillOval(685,177,18,18); g.setColor(Color.WHITE); g.fillRect(685
+ 7,177,5,18);
//2 g.setColor(Color.BLACK); g.drawOval(684,196,20,20);
g.setColor(Color.BLUE); g.fillOval(685,197,18,18);
//12 g.setColor(Color.BLACK); g.drawOval(684,216,20,20);
g.setColor(Color.MAGENTA); g.fillOval(685,217,18,18);
//9 (looks suspiciously like solid yellow) g.setColor(Color.BLACK);
g.drawOval(684,236,20,20); g.setColor(Color.YELLOW);
g.fillOval(685,237,18,18); g.setColor(Color.WHITE); g.fillRect(685
+ 7,237,5,18);
//column 5 //7 g.setColor(Color.BLACK);
g.drawOval(704,166,20,20);
g.setColor(Color.ORANGE.darker().darker().darker().darker());
g.fillOval(705,167,18,18);
//10 g.setColor(Color.BLACK); g.drawOval(704,186,20,20);
g.setColor(Color.BLUE); g.fillOval(705,187,18,18);
g.setColor(Color.WHITE); g.fillRect(705 + 7,187,5,18);
//15 g.setColor(Color.BLACK); g.drawOval(704,206,20,20);
g.setColor(Color.ORANGE.darker().darker().darker().darker());
g.fillOval(705,207,18,18); g.setColor(Color.WHITE); g.fillRect(705
+ 7,207,5,18);
//3 g.setColor(Color.BLACK); g.drawOval(704,226,20,20);
g.setColor(Color.RED); g.fillOval(705,227,18,18);
//6 g.setColor(Color.BLACK); g.drawOval(704,246,20,20);
g.setColor(Color.GREEN); g.fillOval(705,247,18,18);
g.setColor(Color.WHITE); g.fillRect(705 + 7,247,5,18);
//the almighty cue ball g.setColor(Color.BLACK);
g.drawOval(304,206,20,20); g.setColor(Color.WHITE);
g.fillOval(305,207,18,18); */ if (setup) {
setup = false;
//column 1
//1
Ball ball1 = new Ball(1,624,206);
this.add(ball1);
this.update(this.getGraphics()); //this breaks everything yay
//column 2
//6
Ball ball6 = new Ball(6,644,196);
//12
Ball ball12 = new Ball(12,644,216);
//column 3
//13
Ball ball13 = new Ball(13,664,186);
//8
Ball ball8 = new Ball(8,664,206);
//5
Ball ball5 = new Ball(5,664,226);
//column 4
//11
Ball ball11 = new Ball(11,684,176);
//2
Ball ball2 = new Ball(2,684,196);
//4
Ball ball4 = new Ball(4,684,216); }
} }
Ball
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.*;
import java.awt.event.*;
import java.awt.Color;
public class Ball extends gamePanel {
private int xcor,ycor;
private int rxcor,rycor,radius;
private int num;
public Ball(int n,int x,int y) {
num = n;
xcor = x;
ycor = y;
radius = 9;
this.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
boolean isStriped = (num 8);
int color = num%8;
if (color == 0) {
if (isStriped) {
//8ball
g.setColor(Color.BLACK);
g.drawOval(xcor,ycor,20,20);
g.setColor(Color.BLACK);
g.fillOval(xcor+1,ycor+1,18,18);
}
else {
//cue ball is 16
g.setColor(Color.BLACK);
g.drawOval(xcor,ycor,20,20);
g.setColor(Color.WHITE);
g.fillOval(xcor+1,ycor+1,18,18);
}
}
else {
if (color == 1) {
if (isStriped) {
//9ball
g.setColor(Color.BLACK);
g.drawOval(xcor,ycor,20,20);
g.setColor(Color.WHITE);
g.fillOval(xcor+1,ycor+1,18,18);
g.setColor(Color.YELLOW);
g.fillOval(xcor+8,ycor+1,5,18);
}
else {
//1ball
g.setColor(Color.BLACK);
g.drawOval(xcor,ycor,20,20);
g.setColor(Color.YELLOW);
g.fillOval(xcor+1,ycor+1,18,18);
}
}
else {
if (color == 2) {
if (isStriped) {
//10ball
g.setColor(Color.BLACK);
g.drawOval(xcor,ycor,20,20);
g.setColor(Color.WHITE);
g.fillOval(xcor+1,ycor+1,18,18);
g.setColor(Color.BLUE);
g.fillOval(xcor+8,ycor+1,5,18);
}
else {
//2ball
g.setColor(Color.BLACK);
g.drawOval(xcor,ycor,20,20);
g.setColor(Color.BLUE);
g.fillOval(xcor+1,ycor+1,18,18);
}
}
else {
if (color == 3) {
if (isStriped) {
//11ball
g.setColor(Color.BLACK);
g.drawOval(xcor,ycor,20,20);
g.setColor(Color.WHITE);
g.fillOval(xcor+1,ycor+1,18,18);
g.setColor(Color.RED);
g.fillOval(xcor+8,ycor+1,5,18);
}
else {
//3ball
g.setColor(Color.BLACK);
g.drawOval(xcor,ycor,20,20);
g.setColor(Color.RED);
g.fillOval(xcor+1,ycor+1,18,18);
}
}
else{
if (color == 4) {
if (isStriped) {
//12ball
g.setColor(Color.BLACK);
g.drawOval(xcor,ycor,20,20);
g.setColor(Color.WHITE);
g.fillOval(xcor+1,ycor+1,18,18);
g.setColor(Color.MAGENTA);
g.fillRect(xcor+8,ycor+1,5,18);
}
else {
//4ball
g.setColor(Color.BLACK);
g.drawOval(xcor,ycor,20,20);
g.setColor(Color.MAGENTA);
g.fillRect(xcor+1,ycor+1,18,18);
}
}
else {
if (color == 5) {
if (isStriped) {
//13ball
g.setColor(Color.BLACK);
g.drawOval(xcor,ycor,20,20);
g.setColor(Color.WHITE);
g.fillOval(xcor+1,ycor+1,18,18);
g.setColor(Color.ORANGE.darker());
g.fillRect(xcor+8,ycor+1,5,18);
}
else {
//5ball
g.setColor(Color.BLACK);
g.drawOval(xcor,ycor,20,20);
g.setColor(Color.ORANGE.darker());
g.fillOval(xcor+1,ycor+1,18,18);
}
}
else {
if (color == 6) {
if (isStriped) {
//14ball
g.setColor(Color.BLACK);
g.drawOval(xcor,ycor,20,20);
g.setColor(Color.WHITE);
g.fillOval(xcor+1,ycor+1,18,18);
g.setColor(Color.GREEN);
g.fillOval(xcor+8,ycor+1,5,18);
}
else {
//6ball
g.setColor(Color.BLACK);
g.drawOval(xcor,ycor,20,20);
g.setColor(Color.GREEN);
g.fillOval(xcor+1,ycor+1,18,18);
}
}
else {
if (color == 7) {
if (isStriped) {
//15ball
g.setColor(Color.BLACK);
g.drawOval(xcor,ycor,20,20);
g.setColor(Color.WHITE);
g.fillOval(xcor+1,ycor+1,18,18);
g.setColor(Color.ORANGE.darker().darker().darker().darker());
g.fillOval(xcor+8,ycor+1,5,18);
}
else {
//7ball
g.setColor(Color.BLACK);
g.drawOval(xcor,ycor,20,20);
g.setColor(Color.ORANGE.darker().darker().darker().darker());
g.fillOval(xcor+1,ycor+1,18,18);
}
}
}
}
}
}
}
}
}
}
}
回答1:
Here's the thing. You don't want a bunch of JPanel
s as balls. You should just have one JPanel
to paint on and use only that one paintComponent
method for all the Balls. So you Ball
class doesn't need to extend anything at all. The Ball
class should only be a model to hold data, such ass the RGB color. You should also a draw method in the ball class that take a Graphics
object as an argument, and draws the ball
public class Ball {
int R, G, B;
boolean striped;
int x, y;
public Ball(int R, int G, int B, boolean striped) {
this.R = R:
this.G = G;
this.B = B;
this.striped = striped;
}
public void drawBall(Graphics g) {
if (isStriped) {
// draw the ball with the values from this class
}
else {
// draw the ball with the values from this class
}
}
}
Then in the class that you're doing the actual drawing with, you want to have a list of Ball
objects
public class TablePanel extends JPanel {
List<Ball> balls = new ArrayList<Ball>();
public TablePanel(){
makeBalls();
}
public void makeBalls(){
balls.add(new Ball(213, 2, 255, true);
// add more balls
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Ball ball : balls) {
ball.drawBall(g);
}
}
}
You can see all I did was use the method ball.drawBall(g);
. The ball will appear. But you will also need to specify the x
and y
location of the ball too. Then when you need to animate the balls, just change their x
and y
fields.
Here's an example
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class SorryPoolTable extends JPanel{
List<ABall> balls = new ArrayList<ABall>();
public SorryPoolTable(){
makeBalls();
}
public void makeBalls(){
balls.add(new ABall(213, 2, 255, true, 125, 25));
balls.add(new ABall(65, 34, 25, true, 150, 135));
balls.add(new ABall(124, 211, 45, true, 160, 180));
balls.add(new ABall(35, 123, 255, true, 200, 200));
balls.add(new ABall(45, 222, 255, true, 50, 200));
balls.add(new ABall(65, 92, 155, true, 125, 175));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (ABall ball : balls) {
ball.drawBall(g);
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 300);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
JFrame frame = new JFrame("Sorry Pool Table");
frame.add(new SorryPoolTable());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
class ABall {
int R, G, B;
boolean striped;
int x, y;
public ABall(int R, int G, int B, boolean striped, int x, int y) {
this.R = R;
this.G = G;
this.B = B;
this.striped = striped;
this.x = x;
this.y = y;
}
public void drawBall(Graphics g) {
g.setColor(new Color(R, G, B));
g.fillOval(x, y, 20, 20);
}
}

UPDATE
Example of MouseMotionListener
. This is a very simple example. The stick doesn't rotate or anthing. Take a look at Graphics2D tutorial for more complex details about how you can accomplish this
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class PoolStick extends JPanel{
int x = 100;
int y = 100;
public PoolStick() {
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
Point p = e.getPoint();
x = (int)p.getX();
y = (int)p.getY();
repaint();
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillRect(x, y, 5, 200);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 300);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
JFrame frame = new JFrame("Sorry Pool Table");
frame.add(new PoolStick());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
回答2:
I think you have two problems here:
You don't override paintComponent() properly. This is a
protected
method, notpublic
. If you add@Override
annotation on this method then the compiler will complain. This is a really good reason for adding this annotation every time you need to override some method.Ball
class extends fromgamePanel
so when you callsuper.paintComponent(g)
in the first class it will callpaintComponent(g)
on its ancestor. If you add balls insidegamePanel
then you'll get an endless loop that will probably cause a stack overflow.
Off-topic
Always follow Java Code Conventions.
来源:https://stackoverflow.com/questions/21336141/how-to-gui-using-paintcomponent-to-initialize-a-gui-and-then-to-add-gui-base