问题描述
我正在尝试制作一个简单的动画,其中一个矩形从屏幕开始(在屏幕右边缘的右侧)并向左移动.因此,在这种情况下,我的框架的宽度为 1000,而墙从 x 值为 1100 开始.显然,起初,矩形不应该是对我们可见.但是随着矩形向左移动,它最终应该变得可见.然而,这个动画并没有这样做.即使墙的 x 值在屏幕范围内,它也不会被渲染.
我尝试在墙的paintComponent()
方法中放入println()
语句,发现paintComponent()
没有被框架的 repaint()
方法调用.我认为当墙第一次被添加到框架时,Swing 决定因为它不在屏幕上,所以不需要渲染,所以即使墙最终出现在屏幕上,Swing 认为它不需要得到渲染.
我尝试重新验证和使框架和组件无效,但没有任何效果.请帮我解决这个问题.代码如下:
package graphics.simpleAnimation;公共类 Simple_Animation 实现 Runnable {私人用户界面 ui;//用户界面(框架)私人墙墙;//在屏幕上移动的墙对象私人 Simple_Animation() {//初始化墙对象(故意给定一个大于框架宽度的 x 值)墙 = 新墙(1100, 400, 200, 400);//初始化UI(宽度只有1000)ui = new UI(1000, 600, "几何破折号");//将墙添加到 ui(框架)ui.add(墙);}公共无效运行(){//设置框架可见ui.setVisible(true);//重新绘制框架并移动墙壁而(真){ui.repaint();wall.moveWall(-2, 0);尝试 {线程睡眠(16);} catch (InterruptedException IE) {System.out.println(IE);}}}//在新线程中启动程序公共静态无效主(字符串 [] args){Simple_Animation simpleAnimation = new Simple_Animation();新线程(简单动画).开始();}}包 graphics.simpleAnimation;导入 javax.swing.*;导入 java.awt.*;公共类 UI 扩展 JFrame {//存储内容窗格(正在呈现组件的位置)的宽度和高度的变量公共 int content_pane_width;公共 int content_pane_height;公共用户界面(int frameW,int frameH,String frameTitle){setTitle(frameTitle);setSize(frameW, frameH);setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);设置布局(空);content_pane_width = getContentPane().getWidth();content_pane_height = getContentPane().getHeight();}@覆盖公共无效油漆(图形g){super.paint(g);}}包 graphics.simpleAnimation;导入 java.awt.*;导入 javax.swing.*;公共类墙扩展 JComponent {private int wallX;private int wallY;private int wallW;private int wallH;墙(int x,int y,int sizeX,int sizeY){墙X = x;墙Y = y;墙W = 尺寸X;墙H = 大小Y;setSize(getPreferredSize());}公共无效移动墙(int moveX,int moveY){wallX += moveX;wallY += moveY;}@覆盖公共维度 getPreferredSize() {返回新维度(wallW,wallH);}@覆盖公共无效paintComponent(图形g){Graphics2D g2d = (Graphics2D) g;设置位置(wallX,wallY);g2d.fillRect(0, 0, wallW, wallH);}}
我可以在你的程序中找到几个错误
(Probably not in this case, as per @MadProgrammer's comment below), this is just another approach
while (true) {
this line might block the Event Dispatch Thread (EDT) along with this line:Thread.sleep(16);
, See Lesson: Concurrency in Swing to learn more about and How to use Swing Timers. You should also place your program on the EDT which can be done:public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { //Your constructor here } }); }
You're not calling
super.paintComponent()
on yourpaintComponent()
method of theWall
class which could break the paint chain, always call it first.You're extending
JComponent
, it would be better to extendJPanel
and do custom painting over it using the Shapes API
With all of the above in mind, you can then have a code like this one:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class SingleAnimation {
private JFrame frame;
private Timer timer;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new SingleAnimation().createAndShowGui();
}
});
}
public void createAndShowGui() {
frame = new JFrame(getClass().getSimpleName());
Wall wall = new Wall(300, 0);
timer = new Timer(16, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
wall.moveWall(-2, 0);
}
});
timer.setInitialDelay(0);
timer.start();
frame.add(wall);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
class Wall extends JPanel {
private int xCoord;
private int yCoord;
public int getxCoord() {
return xCoord;
}
public void setxCoord(int xCoord) {
this.xCoord = xCoord;
}
public int getyCoord() {
return yCoord;
}
public void setyCoord(int yCoord) {
this.yCoord = yCoord;
}
public Wall(int x, int y) {
this.xCoord = x;
this.yCoord = y;
}
public void moveWall(int xUnits, int yUnits) {
xCoord += xUnits;
yCoord += yUnits;
repaint();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLUE);
g2d.fill(new Rectangle2D.Double(xCoord, yCoord, 100, 20));
}
}
Which will produce a similar output like this one:
这篇关于一旦 JComponent 离开屏幕,它就会停止渲染的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!