首先它会再长一点,因为我想展示我迄今为止所做的所有代码,所以请原谅..
这是我第一次参加java。
我正在尝试建造一个用鱼和水母绘制和使用线程的水族馆。
当我尝试添加动物时我想画它但没有成功,我构建了PaintComponent
方法但是当我尝试使用重绘时我无法绘制..
我错过了什么?
看起来就是这样,当我点击Add Animal窗口打开时,我选择了值,然后点击OK后,需要绘制动物
我希望我所做的其余事情还可以。非常感谢你的帮助!
paintComponent
和repaint
位于AquaPanel
等级。
public class AquaFrame extends JFrame {
private AquaPanel mPanel;
private JLabel label1;
private ImageIcon icon;
private BufferedImage imag;
public AquaFrame() {
super("my Aquarium");
setLayout(new BorderLayout());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(700, 600);
setResizable(false);
setVisible(true);
setLocationRelativeTo(null);
mPanel = new AquaPanel(getGraphics());
add(mPanel);
}
public void buildFrame(){
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu file = new JMenu("File");
menuBar.add(file);
JMenuItem exItem = new JMenuItem("Exit");
file.add(exItem);
exItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
JMenu background = new JMenu("Background");
menuBar.add(background);
JMenuItem blue = new JMenuItem("Blue");
blue.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mPanel.setBackground(Color.BLUE);
}
});
JMenuItem none = new JMenuItem("None");
none.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mPanel.setBackground(null);
}
});
JMenuItem image = new JMenuItem("Image");
image.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
imag = ImageIO.read(new File("aquarium_background.jpg"));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
background.add(image);
background.add(blue);
background.add(none);
JMenu help = new JMenu("Help");
JMenuItem helpItem = new JMenuItem("help");
helpItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null,"GUI @ Threads");
}
});
menuBar.add(help);
help.add(helpItem);
setVisible(true);
}
public void paint(Graphics g){
g.drawImage(imag, 0, 0, null);
}
public static void main(String[] args) {
AquaFrame mFrame = new AquaFrame();
mFrame.buildFrame();
}
}
/******************************************/
public class AquaPanel extends JPanel {
private JFrame infoTableFrame;
private JTable infoTable;
private Set<Swimmable > swimmables = new HashSet<Swimmable>();
private AddAnimalDialog animalDialog;
private int totalEatCounter;
private Graphics g;
public AquaPanel(Graphics g) {
this.g = g;
totalEatCounter = 0;
infoTableFrame = new JFrame();
infoTableFrame.setVisible(false);
setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.PAGE_END;
constraints.weighty = 1;
JButton btAdd = new JButton("Add Animal");
btAdd.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (swimmables.size() >= 5)
{
JOptionPane.showMessageDialog(null, "You can't have more than 5 animals at the same time.");
}
else
{
animalDialog = new AddAnimalDialog(AquaPanel.this);
animalDialog.setVisible(true);
}
}
});
JButton btSleep = new JButton("Sleep");
btSleep.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for (Swimmable swimmable : swimmables)
{
swimmable.setSuspend();
}
}
});
JButton btWakeup = new JButton("Wake Up");
btWakeup.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for (Swimmable swimmable : swimmables)
{
swimmable.setResume();
}
}
});
JButton btRst = new JButton("Reset");
btRst.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for (Swimmable swimmable : swimmables)
{
swimmable.kill();
}
swimmables.clear();
}
});
JButton btFood = new JButton("Food");
btFood.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (swimmables.size() > 0)
{
CyclicBarrier barrier = new CyclicBarrier(swimmables.size());
for (Swimmable swimmable : swimmables)
{
swimmable.setBarrier(barrier);
swimmable.setFood(true);
}
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(3));
g2.setColor(Color.red);
g2.drawArc(getWidth() / 2, getHeight() / 2 - 5, 10, 10, 30, 210);
g2.drawArc(getWidth()/2, getHeight()/2+5, 10, 10, 180, 270);
g2.setStroke(new BasicStroke(1));
}
}
});
JButton btInfo = new JButton("Info");
btInfo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
showInfoTable();
}
});
JButton btExit = new JButton("Exit");
btExit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
add(btAdd,constraints);
add(btSleep,constraints);
add(btWakeup,constraints);
add(btRst,constraints);
add(btFood,constraints);
add(btInfo,constraints);
add(btExit,constraints);
}
public void showInfoTable(){
if (infoTableFrame.isVisible())
{
infoTableFrame.remove(infoTable);
infoTableFrame.setVisible(false);
}
else
{
String[] col = {"Animal","Color","Size","Hor.speed","Ver.speed","Eat counter"};
String[][] data = new String[swimmables.size()][col.length];
int i=0;
for (Swimmable swimmable : swimmables)
{
data[i][0] = swimmable.getAnimalName();
data[i][1] = swimmable.getColor();
data[i][2] = "" + swimmable.getSize();
data[i][3] = "" + swimmable.getHorSpeed();
data[i][4] = "" + swimmable.getVerSpeed();
data[i][5] = "" + swimmable.getEatCount();
++i;
}
infoTable = new JTable(data, col);
//TODO - not overriding values
JScrollPane jPane = new JScrollPane(infoTable);
infoTableFrame.add(jPane, BorderLayout.CENTER);
infoTableFrame.setSize(300, 150);
infoTableFrame.setVisible(true);
}
}
public void addAnimal(Swimmable animal)
{
animal.setAquaPanel(this);
swimmables.add(animal);
animal.run();
//myrepaint();
/**********************************/
repaint();
/**********************************/
}
public void onEatFood(Swimmable eater)
{
eater.eatInc();
++totalEatCounter;
for (Swimmable swimmable : swimmables)
{
swimmable.setFood(false);
}
}
/*public void myrepaint()
{
for (Swimmable swimmable : swimmables)
{
swimmable.drawAnimal(g);
}
}*/
/************************************************/
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Swimmable swimmable : swimmables)
{
swimmable.drawAnimal(g);
}
}
/*********************************************/
}
public abstract class Swimmable extends Thread {
protected AquaPanel aquaPanel;
protected boolean isFood;
protected boolean isSuspended;
protected int horSpeed;
protected int verSpeed;
protected int x_dir, y_dir;
protected int eatCount;
protected CyclicBarrier barrier;
protected int x0, y0;
protected boolean isAlive;
public Swimmable() {
horSpeed = 0;
verSpeed = 0;
x_dir = 1;
y_dir = 1;
eatCount = 0;
}
public Swimmable(int hor, int ver) {
horSpeed = hor;
verSpeed = ver;
x_dir = 1;
y_dir = 1;
eatCount = 0;
}
@Override
public void run() {
isAlive = true;
while (isAlive) {
try {
sleep(10);
if (isSuspended)
{
wait();
}
else
{
if (isFood)
{
barrier.await();
updateFrontsTowardsFood();
if (isNearFood())
{
aquaPanel.onEatFood(this);
}
}
else
{
updateFronts();
}
//aquaPanel.myrepaint();
aquaPanel.repaint();
}
}
catch (Exception e)
{
//TODO - handle exception
}
}
}
public void kill()
{
isAlive = false;
}
public int getHorSpeed() {
return horSpeed;
}
public int getVerSpeed() {
return verSpeed;
}
public void setHorSpeed(int hor) {
horSpeed = hor;
}
public void setVerSpeed(int ver) {
verSpeed = ver;
}
abstract public int getSize();
abstract public String getColor();
public void setSuspend()
{
isSuspended = true;
}
public void setResume()
{
isSuspended = false;
}
public void eatInc()
{
++eatCount;
}
public int getEatCount()
{
return eatCount;
}
public void setBarrier(CyclicBarrier b)
{
barrier = b;
}
public void setFood(boolean isFood)
{
this.isFood = isFood;
}
public void setAquaPanel(AquaPanel panel)
{
aquaPanel = panel;
x0 = aquaPanel.getWidth() / 2;
y0 = aquaPanel.getHeight() / 2;
}
abstract public String getAnimalName();
abstract public void drawAnimal(Graphics g);
abstract protected void updateFronts();
abstract protected void updateFrontsTowardsFood();
abstract protected boolean isNearFood();
}
public class Fish extends Swimmable {
protected int x_front , y_front;
private int size;
private Color color;
public Fish(Color col, int sz, int hor, int ver) {
super(hor, ver);
size = sz;
color = col;
x_front = 0;
y_front = 0;
}
public void drawAnimal(Graphics g) {
g.setColor(color);
if (x_dir == 1) // fish swims to right side
{
// Body of fish
g.fillOval(x_front - size, y_front - size / 4, size, size / 2);
// Tail of fish
int[] x_t = { x_front - size - size / 4, x_front - size - size / 4, x_front - size };
int[] y_t = { y_front - size / 4, y_front + size / 4, y_front };
Polygon t = new Polygon(x_t, y_t, 3);
g.fillPolygon(t);
// Eye of fish
Graphics2D g2 = (Graphics2D) g;
g2.setColor(new Color(255 - color.getRed(),255 - color.getGreen(),255- color .getBlue()));
g2.fillOval(x_front-size/5, y_front-size/10, size/10, size/10);
//Mouth of fish
if(size>70)
g2.setStroke(new BasicStroke(3));
else if(size>30)
g2.setStroke(new BasicStroke(2));
else
g2.setStroke(new BasicStroke(1));
g2.drawLine(x_front, y_front, x_front-size/10, y_front+size/10);
g2.setStroke(new BasicStroke(1));
}
else // fish swims to left side
{
// Body of fish
g.fillOval(x_front, y_front - size / 4, size, size / 2);
// Tail of fish
int[] x_t = { x_front + size + size / 4, x_front + size + size / 4, x_front + size };
int[] y_t = { y_front - size / 4, y_front + size / 4, y_front };
Polygon t = new Polygon(x_t, y_t, 3);
g.fillPolygon(t);
// Eye of fish
Graphics2D g2 = (Graphics2D) g;
g2.setColor(new Color(255 - color.getRed(), 255 - color.getGreen(), 255 - color.getBlue()));
g2.fillOval(x_front+size/10, y_front-size/10, size/10, size/10);
// Mouth of fish
if (size > 70)
g2.setStroke(new BasicStroke(3));
else if (size > 30)
g2.setStroke(new BasicStroke(2));
else
g2.setStroke(new BasicStroke(1));
g2.drawLine(x_front, y_front, x_front + size / 10, y_front + size / 10);
g2.setStroke(new BasicStroke(1));
}
}
public String getAnimalName() {
return "Fish";
}
public int getSize() {
return size;
}
public String getColor() {
if (color == Color.RED)
return "RED";
else if (color == Color.GREEN)
return "GREEN";
else if (color == Color.ORANGE)
return "ORANGE";
else
return "UNKNOWN";
}
protected void updateFronts()
{
x_front += x_dir * horSpeed;
y_front += y_dir * verSpeed;
if (x_front > x0*2 || x_front < 0)
x_dir *= -1;
if (y_front > y0*2 || y_front < 0)
y_dir *= -1;
}
protected void updateFrontsTowardsFood()
{
//TODO - copy from word
}
protected boolean isNearFood()
{
return ((Math.abs(x_front-x0) <= 5) && (Math.abs(y_front-y0) <= 5));
}
}
public class Jellyfish extends Swimmable {
private int x_front , y_front;
private int size;
private Color color;
public Jellyfish(Color col, int sz, int hor, int ver) {
super(hor, ver);
size = sz;
color = col;
x_front = 0;
y_front = 0;
}
public void drawAnimal(Graphics g) {
int numLegs;
if (size < 40)
numLegs = 5;
else if (size < 80)
numLegs = 9;
else
numLegs = 12;
g.setColor(color);
g.fillArc(x_front - size / 2, y_front - size / 4, size, size / 2, 0, 180);
for (int i = 0; i < numLegs; i++)
g.drawLine(x_front - size / 2 + size / numLegs + size * i / (numLegs + 1), y_front,
x_front - size / 2 + size / numLegs + size * i / (numLegs + 1), y_front + size / 3);
}
public String getAnimalName() {
return "Jellyfish";
}
public int getSize() {
return size;
}
public String getColor() {
if (color == Color.RED)
return "RED";
else if (color == Color.GREEN)
return "GREEN";
else if (color == Color.ORANGE)
return "ORANGE";
else
return "UNKNOWN";
}
public void updateFronts()
{
x_front += x_dir * horSpeed;
y_front += y_dir * verSpeed;
if (x_front > x0*2 || x_front < 0)
x_dir *= -1;
if (y_front > y0*2 || y_front < 0)
y_dir *= -1;
}
protected void updateFrontsTowardsFood()
{
//TODO - copy from word
}
protected boolean isNearFood()
{
return ((Math.abs(x_front-x0) <= 5) && (Math.abs(y_front-y0) <= 5));
}
}
public class AddAnimalDialog extends JDialog {
private JButton btOk, btCancel;
private JTextField tfSize, tfHspeed, tfVspeed;
private ButtonGroup groupType, groupColor;
private JRadioButton rbFish, rbJellyfish, rbRed, rbGreen, rbOrange;
JPanel panel;
public AddAnimalDialog(AquaPanel aquaPanel) {
this.setLayout(new FlowLayout());
panel = new JPanel();
panel.setLayout(new GridLayout(10, 20));
panel.add(new JLabel("Size(20-320): "));
panel.add(tfSize = new JTextField());
panel.add(new JLabel("Horizontal speed(1-10): "));
panel.add(tfHspeed = new JTextField());
panel.add(new JLabel("Vertical speed(1-10): "));
panel.add(tfVspeed = new JTextField());
panel.add(new JLabel("Type: "));
panel.add(new JLabel(" "));
panel.add(rbFish = new JRadioButton("fish"));
panel.add(rbJellyfish = new JRadioButton("jellyfish"));
panel.add(new JLabel("Color: "));
panel.add(new JLabel(" "));
panel.add(rbRed = new JRadioButton("Red"));
panel.add(rbGreen = new JRadioButton("Green"));
panel.add(rbOrange = new JRadioButton("Orange"));
// Group the radio buttons.
groupType = new ButtonGroup();
groupType.add(rbFish);
groupType.add(rbJellyfish);
rbFish.setSelected(true);
groupColor = new ButtonGroup();
groupColor.add(rbRed);
groupColor.add(rbGreen);
groupColor.add(rbOrange);
rbRed.setSelected(true);
panel.add(new JLabel(""));
panel.add(btOk = new JButton("OK"));
panel.add(btCancel = new JButton("Cancel"));
this.add(panel);
this.setLocationRelativeTo(null);
this.setResizable(false);
this.pack();
this.btOk.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
int size = Integer.parseInt(tfSize.getText());
int hSpeed = Integer.parseInt(tfHspeed.getText());
int vSpeed = Integer.parseInt(tfVspeed.getText());
if (checkValues(size, hSpeed, vSpeed)) {
Color clr = Color.RED;
if (rbRed.isSelected()) {
clr = Color.RED;
} else if (rbGreen.isSelected()) {
clr = Color.GREEN;
} else if (rbOrange.isSelected()) {
clr = Color.ORANGE;
} else {
JOptionPane.showMessageDialog(null, "You must choose a color!");
}
if (rbFish.isSelected()) {
setVisible(false);
aquaPanel.addAnimal(new Fish(clr, size, hSpeed, vSpeed));
} else if (rbJellyfish.isSelected()) {
setVisible(false);
aquaPanel.addAnimal(new Jellyfish(clr, size, hSpeed, vSpeed));
} else {
JOptionPane.showMessageDialog(null, "You must choose animal type!");
}
}
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, "One of the number values has wrong format, please check it");
}
}
});
this.btCancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
setVisible(false);
System.out.println("Click the Close button if you want to stop adding windows");
}
});
}
private boolean checkValues(int size, int hspeed, int vspeed) {
if ((size > 320 || size < 20) || (hspeed < 1 || hspeed > 10) || (vspeed < 1 || vspeed > 10)) {
JOptionPane.showMessageDialog(null, "One of the values is out of bounds, please follow the restrictions.");
return false;
}
return true;
}
}
答案 0 :(得分:1)
有许多基本问题......
主要问题在于您的Swimmable
run
方法,它阻止了事件调度线程,阻止它能够响应UI事件,包括重绘事件。有关详细信息,请参阅Concurrency in Java。
你永远不应该使用getGraphics
,除了能够返回null
之外,你绘制的任何东西都是在正常的绘画周期之外绘制的,并且会在下次重新绘制组件时绘制。有关详细信息,请参阅Painting in AWT and Swing和Performing Custom Painting。
您当前的方法不会很好地扩展,您添加的鱼越多,它们消耗的资源就越多,并且会影响程序跟上所有不同更改和重新绘制请求的能力。
更好的解决方案是进行单一的更新&#34;循环,它负责告诉每个Swimmable
它需要更新,然后在每个循环中安排一个repaint
。就个人而言,我从一个Swing Timer
开始,因为它&#34;滴答&#34;在EDT中,使得修改paintComponent
方法所需的对象状态更加安全。
有关详细信息,请参阅How to use Swing Timers
我建议您查看this,其中基本上描述了您尝试做的事情以及我建议您应该做的事情
答案 1 :(得分:0)
在调用addAnimal方法后尝试在JFrame类中调用repaint。这里也有revalidate()方法,它们的区别在于本文:Java Swing revalidate() vs repaint()