我有一个java jpanel的例子:
import java.awt.*;
import javax.swing.*;
public class JavaGame extends JFrame {
public JavaGame() {
setTitle("Game");
setSize(500,500);
setResizable(false);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void paint(Graphics g) {
g.drawString("Hello World!",75,75);
}
public static void main(String[] args) {
new JavaGame();
}
}
因此,我们只定义方法paint
,然后创建新的JavaGame对象,它只调用paint
。我没有得到两件事:
- new JavaGame() - 我们不应该分配像obj = new JavaGame()这样的对象名吗?
- 我们不应该像obj.paint()一样调用方法paint吗?
醇>
我对OOP有基本的了解,但是这段代码让我很困惑。有人可以向我解释一下吗?
答案 0 :(得分:4)
new JavaGame() - 我们不应该分配像obj = new JavaGame()这样的对象名吗?
这得到了对象和引用变量之间的重要区别。这里最重要的是创建一个JavaGame对象,您可以通过new JavaGame()
来完成。由于此对象在其构造函数中显示JFrame,因此只需创建对象即可创建显示,而无需将对象分配给任何变量。
请注意,对象没有名称,而是有一些变量。例如,如果您创建了一个Foo对象,并将其分配给一个条形变量:
Foo bar = new Foo();
然后将同一个对象分配给一个baz变量:
Foo baz = bar;
bar和baz都指向完全相同的Foo对象。那个对象的名字是什么?同样,对象名称不存在且毫无意义。
我们不应该像obj.paint()一样调用方法paint吗?
正如MightyPork所指出的那样(他是1+),paint方法被JVM称为 ,不应该直接调用。您可以建议通过调用repaint()
来调用它,但您几乎不应该直接调用它或paintComponent(...)
方法。
其他问题:
修改您问:
所以,当使用API时,我们只是用代码“填充”类中的方法,而JVM将知道何时调用这些方法?
大多数情况下,Swing图形是“被动的”。这意味着您将组件设置为以某种方式绘制,但您不会自己主动绘制它。而是JVM(Java虚拟机 - 运行Java程序的代码)为您绘制图纸。如果你想做动画,通常你会改变一些位置变量,例如xPosition和yPosition int变量,然后在你的JPanel的paintComponent(Graphics g)
方法中使用这些变量。因此,如果在Swing Timer中更改这些变量所持有的值,然后在值更改后调用repaint()
,JVM将(通常)使用新值重新绘制组件。
一个更复杂的示例,显示了JPanel中的绘图,并显示了一个非常简单的动画:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
// draw in a JPanel, not a JFrame
public class SimpleAnimation extends JPanel {
private static final int OVAL_WIDTH = 40;
private static final int TIMER_DELAY = 50;
private static final int PREF_W = 800;
private static final int PREF_H = PREF_W;
private int xPosition = 0;
private int yPosition = 0;
public SimpleAnimation() {
// start my timer here
new Timer(TIMER_DELAY, new TimerListener()).start();
}
@Override
protected void paintComponent(Graphics g) {
// call the super method so that the JPanel
// can do its own house-keeping graphics first
super.paintComponent(g);
// I do this to so that my graphics are smooth
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.red);
// use xPosition and yPosition to place my oval
g2.fillOval(xPosition, yPosition, OVAL_WIDTH, OVAL_WIDTH);
}
// so our GUI will be big enough to see
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
// class used by the Swing Timer to drive animation
private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
// change xPosition and yPosition
xPosition++;
yPosition++;
// and call repaint
repaint();
}
}
// a method to be called in our Runnable
private static void createAndShowGui() {
SimpleAnimation mainPanel = new SimpleAnimation();
JFrame frame = new JFrame("SimpleAnimation");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
// this is used to make sure that all Swing code
// is started on the Swing event thread.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
答案 1 :(得分:0)
您创建对象new JavaGame()
而不将其分配给任何变量,就是这样。
Swing渲染和事件线程启动并处理应用程序生命周期的其余部分。
我不确定垃圾收集器为什么不接收它并结束它,但我已经这样做了很长时间并且它工作正常。
答案 2 :(得分:0)
new
时,将调用构造函数,从而创建框架。