问题描述
我正在尝试在Java Swing应用程序中编写一个简单的动画或物理示例.我已经打开并正在运行实际的Windows应用程序,但是我无法弄清楚如何实际绘制形状,以及如何格式化框架之间用于计算的代码,诸如此类.
I'm attempting to code a simple animation or physics example in a Java Swing application. I have the actual windows application open and working, but I can't figure out how to actually draw my shapes, and how I'd format the code for calculations between frames, that sort of stuff.
我已经阅读了一些有关使用绘画方法的内容,但是我不知道这意味着什么,而且我不相信我现在正在使用的代码中使用它.这是我的代码:
I've read some stuff about over riding a paint method, but I don't know what that means, and I don't believe I'm using it in the code I'm using right now. This is my code:
public class Physics extends JFrame{
public Physics() {
initUI();
}
private void initUI() {
JPanel panel = new JPanel();
getContentPane().add(panel);
panel.setLayout(null);
final JLabel label = new JLabel("Hi, press the button to do something");
label.setBounds(20, 0, 2000, 60);
final JButton submitButton = new JButton("Start");
submitButton.setBounds(20, 150, 80, 20);
submitButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//Put button code here later
}
});
panel.add(label);
panel.add(submitButton);
setTitle("Program");
setSize(300, 250);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Physics ex = new Physics();
ex.setVisible(true);
}
});
}
}
所以我在按钮上方有一些空白,我想在屏幕上画一个正方形或圆形作为开始,一旦发现这个空白,我就可以开始研究更高级的东西了.有关如何执行此操作的任何提示都可以使用:D
So I have some blank space above my button where I'd like to draw maybe a square or circle moving across the screen to start off with, once I get that down I can start getting into the more advanced stuff. Any hints on how to do that would be appriciated :D
谢谢!
推荐答案
因此,您已覆盖actionPerformed
,因此您知道@Override
是什么.正如您从ActionListener
中注意到的那样,您从不会实际上显式调用actionPerformed
,但是无论您放置在哪里,仍然会使用get.这是因为ActionListener
为您隐式调用它.
So you've overridden actionPerformed
, so you know what an @Override
is. As you'll notice from the ActionListener
, you never actually explicitly call actionPerformed
, but whatever you put in the there, still get's used. That's because the ActionListener
implicitly call it for you.
绘画也是如此.在Swing绘制过程中,Swing会使用一个绘制链来绘制组件.一路在某处调用paint
.因此,就像actionPerformed
一样,您可以覆盖paint
,它将为您隐式调用.
The same is true with painting. In the Swing painting process, there is a paint chain that Swing uses to paint components. Along the way paint
is called somewhere. So just like actionPerformed
, you can override paint
and it will get implicitly called for you.
@Override
public void paint(Graphics g) {
super.paint(g);
}
传递给该方法的Graphics
对象是Swing将用于绘画的图形上下文.您可以查看 Graphics API
查看您可以使用的方法.您可以使用 drawOval
画一个圆
The Graphics
object passed to the method is the graphics context that Swing will use for the painting. You can look at the Graphics API
to see the methods you can use. You can use drawOval
to draw a circle
@Override
public void paint(Graphics g) {
super.paint(g);
g.drawOval(x, y, width, height);
}
现在这是东西.您实际上并不想覆盖paint
.在上面链接的教程中,一些示例将使用applet并覆盖paint
,但您不应在JFrame
或JApplet
之类的顶级容器上绘画.而是在JPanel
或JComponent
上绘画,然后将其添加到JFrame
.当您在JPanel
或JComponent
上进行涂漆时,您将覆盖paintComponent
(也沿涂漆链调用),而不是paint
Now here's the thing. You don't actually want to override paint
. In the tutorials linked above, some of the examples will use applets and override paint
, but you shouldn'y paint on top level containers like JFrame
or JApplet
. Instead paint on a JPanel
or JComponent
and just add it the JFrame
. When you do paint on JPanel
or JComponent
, you'll instead override paintComponent
(which also gets called along the paint chain), instead of paint
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(x, y, width, height);
}
您会看到我如何在drawOval
方法中使用变量. x
是屏幕顶部的x位置,y
和y点. width
和height
是圆的宽度和高度.使用变量的好处是可以在运行时更改它们的值.
You see how I used variables for the drawOval
method. The x
is the x location from the top-let of the screen, and y
and the y point. width
and height
are width and height of the circle. The great thing about using variables is that their values can be changed at runtime.
那就是动画播放的地方.如所指出的,您使用 javax.swing.Timer
That's where the animation comes to play. As pointed out, you an use a javax.swing.Timer
基本结构是
public Timer(int delay, ActionListener listener) {
}
delay
是延迟每次调用侦听器的毫秒数.侦听器将使您的actionPerformed
回调每隔delay
毫秒执行一次内部操作.因此,您只需将drawOval
和repaint()
更改为x
,它就会进行动画处理.像
The delay
is the milliseconds to delay each call to the listener. The listener will have your actionPerformed
call back that will do what's inside, every delay
milliseconds. So what you can do, is just change the x
from the drawOval
and repaint()
, and it will animate. Something like
Timer timer = new Timer(40, new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
x += 5;
repaint();
}
});
timer.start();
您可以将计时器代码放入构造函数中.这可能是我能给出的最简单的解释.希望能帮助到你.
The timer code you can just put in the constructor. That's probably simplest explanation I can give. Hope it helps.
别忘了看到自定义绘画和 Grapics2D 有关图形的更多高级主题.另请参见此处和和此处和和此处
Don't forget the to see Custom Painting and Grapics2D for more advance topics on graphics. Also see some example of timers and animation here and here and here and here and here
还避免使用空布局.请参阅在容器内布置组件,以了解如何使用布局管理器,就像使用Swing应用程序一样.
Also avoid using null layouts. See Laying out Components Within a Container to learn how to use layout managers, as should be done with Swing apps.
这篇关于Java中的简单动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!