好的,首先我知道关于这个问题有很多其他线程,但他们只是说尝试使用invalidate()和validate()对我没用。
我的问题是 - 因为标题很明显 - JPanel的repaint()方法不会重绘。我在paintComponent()方法中添加了一些调试消息,这里是控制台输出:
Debug
-10 421 010 441
repainted
Moved mouse
Moved mouse
Moved mouse
Moved mouse
Moved mouse
Moved mouse
Moved mouse
Moved mouse
Moved mouse
Moved mouse
Moved mouse
Moved mouse
Moved mouse
Moved mouse
Moved mouse
Moved mouse
请注意,您只能在程序开头看到debug
,(co-ordinates)
和repainted
一次,但我会调用repaint();每次移动鼠标。
我将我的五个类添加到一个中,因为我认为它最适合用于调试目的:
package com.trtld.spacewar;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class GroupClass {
private static Content content = new Content();
public static void main(String[] args) {
JFrame window = new JFrame("Spacewar!");
content.setVisible(true);
window.setContentPane(content);
MouseInput listener = new MouseInput();
content.addMouseMotionListener(listener);
content.addMouseListener(listener);
window.setSize(600, 480);
window.setLocation(100, 100);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
//window.setResizable(false);
System.out.println("Debug");
}
}
class Target {
private int x1, y1;
private int x2, y2;
public Target(int x1, int y1, int x2, int y2){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
public int getX1(){
return x1;
}
public int getX2(){
return x2;
}
public int getY1(){
return y1;
}
public int getY2(){
return y2;
}
}
class Content extends JPanel{
private static Content instance;
private Target[] targets = new Target[9];
private Bullet[] bullets = new Bullet[999];//assuming no more than 1000 bullets are on the screen at
//once (they'd have to have a really fancy-nice auto-clicker ha ha)
int spaceShipX = (getWidth()/2);
public Content (){
int yLevel = (((int)Math.random())*(getHeight() / 4));
int xPos = ((int)Math.random())*getWidth();
for(int i = 0;!(i == 9); i++){ //Create the randomly located targets
targets[i] = new Target(xPos, yLevel, xPos-15, yLevel-10);
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.RED);
System.out.println(spaceShipX-10 + " " + (getHeight()-20) + " " + spaceShipX+10 + " " + getHeight());
System.out.println("repainted");
g.fillRect(spaceShipX+50, getHeight()-20 ,spaceShipX+100 , getHeight());
/** //commented out for simplicity + needs to be fixed:
for(Target t : this.targets){ //paint targets
g.drawRect(t.getX1(), t.getY1(), t.getX2(), t.getY2());
}
for(Bullet b : this.bullets){ //paint bullets and remove invalid ones plus check for hits
if(b != null){
g.drawRect(b.getX1(), b.getY1(), b.getX2(), b.getY2());
if(!(b.checkTargetPresence() == null)){
for(Target target : targets){
if(b.checkTargetPresence() == target){
target = null;
}
}
}
if(b.isValid() == false){
b = null;
}
}
}*/
}
public static Content getInstance(){
if(instance == null) {
instance = new Content(); //TODO: Singletons are out-dated and not preferred; fix this
}
return instance;
}
//Getters and setters:
public Bullet[] getBullets(){
return bullets;
}
public Target[] getTargets(){
return targets;
}
public void setTarget(Target t, int loc){
this.targets[loc] = t;
}
public void setBullet(Bullet b){
int location = -1;
if(bullets[0] == null){
this.bullets[0] = b;
return;
}
for(Bullet bullet: bullets){
location++;
if(bullets[location] == null){ //TODO: Messy, clean this up
bullets[location] = b;
return;
}
}
}
public int getSpaceShipX(){
return spaceShipX;
}
public void setSpaceShipX(int x){
spaceShipX = x-10;
repaint();
}
}
class Bullet implements ActionListener{
int x1, x2;
int y1 = 10, y2 = 5;
Timer timer = new Timer(250, this);
public Bullet(int x1, int x2){
this.x1 = x1;
this.x2 = x2;
timer.start();
}
public void actionPerformed(ActionEvent evt) {
y1 = y1 + 2;
y2 += 2;
Content.getInstance().repaint();
}
public Target checkTargetPresence(){
for(Target t : Content.getInstance().getTargets()){
if(x1 <= t.getX1() && x1 >= t.getX2()){
if(y1 <= t.getY1() && y1 >= t.getY2()){
//HIT!
return t;
}
}
}
return null; //TODO
}
public boolean isValid(){//Checks if the bullet is still on the screen
if(y1 >= Content.getInstance().getHeight() || y2 >= Content.getInstance().getHeight()){
return false;
}else{
return true;
}
}
public int getX1(){
return x1;
}
public int getX2(){
return x2;
}
public int getY1(){
return y1;
}
public int getY2(){
return y2;
}
}
class MouseInput implements MouseListener, MouseMotionListener {
public void mouseDragged(MouseEvent arg0) {
}
public void mouseMoved(MouseEvent evt) {
Content.getInstance().setSpaceShipX(evt.getX());
Content.getInstance().repaint(); // I try to repaint here and in the Content class, but nothing happens.
System.out.println("Moved mouse");
}
public void mouseClicked(MouseEvent arg0) {
}
public void mouseEntered(MouseEvent arg0) {
}
public void mouseExited(MouseEvent arg0) {
}
public void mousePressed(MouseEvent evt) {
Content.getInstance().setBullet(new Bullet(evt.getX()-2, evt.getX()+2));
System.out.println("clicked");
}
public void mouseReleased(MouseEvent arg0) {
}
}
我非常感谢任何帮助,如果我需要以不同的方式格式化,请告诉我。 请注意,这是我的第一个GUI程序。
答案 0 :(得分:2)
我认为问题在于您创建了一个Content类,然后将其添加到框架中。
但是,在MouseListener代码中,您调用Content类的getInstance()
方法,并且“instance”变量为null,因此创建了一个新的Content实例(但从未添加到框架中,因此它永远不会被绘制)。
所以这个基本逻辑是错误的,你不想创建一个新实例。
而是在Content类的构造函数中执行:
instance = this;
然后getInstance()方法将返回变量,因为它总是有一个值。
此外,MouseListeners应该是Content类的内部类。那就是你应该创建并向你的类添加监听器。当你这样做时,你甚至不需要静态getInstance()方法,因为你可以直接访问实例变量。
但他们只是说尝试使用invalidate()和validate()这对我没有任何影响。
您不应该使用这些方法。这些用于AWT。在Swing中你可以使用:
revalidate();
repaint();
在GUI可见或更改自定义类中的属性后向GUI添加组件时。 revalidate()将调用布局管理器。 repaint()将绘制组件。在你的课堂上,你不会改变任何东西的大小,所以你只需要在你的setter方法中重绘()。
编辑:
介意分享您添加的代码?
我添加了一行代码:
public Content (){
int yLevel = (((int)Math.random())*(getHeight() / 4));
int xPos = ((int)Math.random())*getWidth();
for(int i = 0;!(i == 9); i++) {
//Create the randomly located targets
targets[i] = new Target(xPos, yLevel, xPos-15, yLevel-10);
}
instance = this; // added
}
一次更改一次。一旦您通过添加单行代码验证我的假设是有效的。然后你可以整理课程的其余部分。如果您一次进行多项更改,则无法知道哪一项导致了问题。