我正在制作一款游戏,而我正试图摆脱代码中的所有冗余。我的所有面板(PlayPanel
,HighScore
,Quit
,..)都有很多共同属性,因此我在所有面板中都进行了IPanel
类扩展。它看起来像这样:
package menu;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class IPanel extends JPanel implements ActionListener{
public Image achtergrond;
public Tanks mainVenster;
public String backgroundPath;
public IPanel(String backgroundPath, Tanks mainVenster)
{
super();
this.mainVenster = mainVenster;
this.setLayout(null);
this.backgroundPath = backgroundPath;
achtergrond = new //achtergrond is dutch for background
ImageIcon(getClass().getResource(backgroundPath)).getImage();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(achtergrond, 0, 0, this.getWidth(), this.getHeight(),
this);
}
public void actionPerformed(ActionEvent ae)
{
mainVenster.switchPanel();
}
public void switchPanel(Tanks toActivate)
{
remove(mainVenster);
mainVenster = toActivate;
add(mainVenster); //this is wrong, no idea what to do actually
validate();
repaint();
}
}
我可以在其他类中使用构造函数,但我不知道如何使用
其他类中的paintComponent
和actionPerformed
方法。我在所有面板中使用这两种方法,所以我认为没有必要为所有这些面板重新编写方法。
我的某个面板的示例是QuitPanel
:
package menu;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
@SuppressWarnings("serial")
public class QuitPanel extends JPanel implements ActionListener
{
public Button yesKnop, noKnop;
public JLabel label;
public Tanks mainVenster;
public QuitPanel quitPanel;
public IPanel quit;
public QuitPanel(Tanks mainVenster)
{
quit = new IPanel("/achtergronden/menu.jpg", mainVenster);
int x = 95, width = 200, height = 50;
label = new JLabel("ARE YOU SURE?");
Font font = new Font("Courier", Font.BOLD, 25);
label.setFont(font);
label.setBounds(x+20, 400, width, height);
yesKnop = new Button("/buttons/YES.png",x, 450, this);
noKnop = new Button("/buttons/NO.png",x, 525, this);
this.add(quit);
this.add(label);
this.add(noKnop);
this.add(yesKnop);
}
public void actionPerformed(ActionEvent ae)
{
if(ae.getSource() == noKnop)
quit.switchPanel(mainVenster); //this is wrong
else if(ae.getSource() == yesKnop)
System.exit(0);
}
}
正如您所看到的,我使用JPanel
扩展了课程,因为当我尝试扩展IPanel
时,我在public HTPPanel(Tanks mainVenster)
处遇到错误
当我打开我的quitPanel时,我得到了这个:
所以我知道必须有一部分代码正确,唯一的问题是我的后台无法加载
- > (public void paintComponent(Graphics g)
方法)
另外, noButton 无效(yesButton工作正常)
- > (public void actionPerformed(ActionEvent ae)
方法)
- >也是因为public void switchPanel(Tanks toActivate)
我猜
非常感谢你!
答案 0 :(得分:3)
是的,你可以,并且有两种普遍的方法,构成和相互作用。
使用组合,您可以通过创建并保存代码保存类的实例,将代码推送到当前解决方案所使用的新类中。
使用继承,您可以创建当前解决方案扩展的类,并将代码放在该父类的方法中。然后你有“其他”类扩展包含所需代码的类。
通常,组合比继承更容易处理;但是,随着时间的推移,你会发现继承是更好的解决方案,因为它能够利用多态性。
答案 1 :(得分:1)
错误是因为当你扩展IPanel
时,你应该使用至少一个super
的构造函数。在这种情况下,有一个,所以你必须使用:
public IPanel(String backgroundPath, Tanks mainVenster)
CORRECTION
不一定你需要(对我来说似乎很理想),但在构造函数中,需要使用{{1}调用superclass's
构造函数之一}。
意思是,如果我的课程super(...)
有构造函数:
A
和班级public class A {
public A(String name) {
}
}
,我可以做一些事情:
B extends A
无论如何,最后,如果您的public class B {
// Option 1: Superclass's Constructor
public B(String name) {
super(name);
}
// Option 2: Pass static value
public B() {
super("something here");
}
// Option 3: Use null
public B() {
super(null);
}
}
仅包含superclass
constructors
,则每个parameters
子类都需要调用constructor
到其中一个super(...)
。
如果您在superclass's constructors
中添加了默认constructor
例如:public A() {}
,则无需在其中任何一个上调用superclass
。
答案 2 :(得分:0)
你应该将没有参数的默认构造函数添加到IPanel类中, e.g。
public IPanel() { }
然后您可以使用父类IPanel进行扩展。
答案 3 :(得分:0)
如果指定构造函数,编译器不会为您创建没有参数的构造函数(您在IPanel类中执行了此操作)。
public class A {
public A(String str) {
//Compiler will not create a constructor without parameters.
}
}
反过来,如果你没有指定构造函数,编译器将为你创建一个没有参数的构造函数(你在HTPPanel类中这样做了。)
public class A {
//Compiler will create a constructor without parameters.
}
现在的问题是,在扩展其他类的类中,默认构造函数将调用它的超类构造函数而不带参数。
public class A {
public A(String str) {}
}
public class B extends A {}
public class C {
public static void main(String[] args) {
B b = new B(); //Compile error
}
}
但是如果你在类B中指定构造函数,但是没有添加对它的超类构造函数的调用,编译器将自动调用超类构造函数而不带参数。
public class A {
public A(String str) {}
}
public class B extends A {
public B(int i) {}
}
public class C {
public static void main(String[] args) {
B b = new B(); //Compile error
}
}
换句话说,你应该在你的IPanel类中添加一个没有参数的构造函数,(或者用适当的参数添加对超级构造函数的调用),但我相信这不是你想要做的。
现在,至于你的其他问题,可能是由于多种原因,如果没有完整的代码,它总是一个猜测。还要考虑一下,当您要使用某个Panel类扩展IPanel类时,如果您想要覆盖此面板中的paintComponent
方法并仍然绘制背景,则应调用super.paintComponent(g);
,试着找出为什么。