一旦JComponent离开屏幕,它就会停止渲染 [英] JComponent stops getting rendered once it goes off the screen
问题描述
我正在尝试制作一个简单的动画,其中矩形从屏幕开始(在屏幕右边缘的右侧)并向左移动。因此,在这种情况下,我的框架宽度为1000,墙壁的起始值为x值1100.显然,首先,矩形不应该是
对我们来说是可见的。但随着矩形向左移动,它最终应该变得可见。但是,这个动画不会这样做。即使墙的x值在屏幕的范围内,它也不会被渲染。
我试过放一个 println()墙上的
语句,我发现 paintComponent()
方法中的 paintComponent()
没有被框架的 repaint()
方法调用。我认为当墙首次添加到框架时,Swing决定,因为它不在屏幕上,所以即使墙壁最终进入屏幕,Swing认为它不需要渲染。得到渲染
我尝试重新验证并使框架和组件无效,但没有任何效果。请帮我解决这个问题。下面是代码:
package graphics.simpleAnimation;
公共类Simple_Animation实现Runnable {
private UI ui; // UI(框架)
私人墙; //在屏幕上移动的Wall对象
private Simple_Animation(){
//初始化wall对象(故意给出一个大于帧宽度的x值)
wall = new Wall(1100,400,200,400);
//初始化UI(宽度仅为1000)
ui =新UI(1000,600,Geometry Dash);
//将墙添加到ui(框架)
ui.add(墙);
}
public void run(){
//设置框架可见
ui.setVisible(true);
//重绘框架并移动墙
while(true){
ui.repaint();
wall.moveWall(-2,0);
try {
Thread.sleep(16);
} catch(InterruptedException IE){
System.out.println(IE);
}
}
}
//在新线程中启动程序
public static void main(String [] args){
Simple_Animation simpleAnimation = new Simple_Animation();
new Thread(simpleAnimation).start();
}
}
package graphics.simpleAnimation;
import javax.swing。*;
import java.awt。*;
公共类UI扩展JFrame {
//存储内容窗格的宽度和高度的变量(呈现组件的位置)
public int content_pane_width;
public int content_pane_height;
public UI(int frameW,int frameH,String frameTitle){
setTitle(frameTitle);
setSize(frameW,frameH);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setLayout(null);
content_pane_width = getContentPane()。getWidth();
content_pane_height = getContentPane()。getHeight();
}
@Override
public void paint(Graphics g){
super.paint(g);
}
}
package graphics.simpleAnimation;
import java.awt。*;
import javax.swing。*;
公共类Wall扩展JComponent {
private int wallX;
private int wallY;
private int wallW;
private int wallH;
Wall(int x,int y,int sizeX,int sizeY){
wallX = x;
wallY = y;
wallW = sizeX;
wallH = sizeY;
setSize(getPreferredSize());
}
public void moveWall(int moveX,int moveY){
wallX + = moveX;
wallY + = moveY;
}
@Override
public Dimension getPreferredSize(){
返回新维度(wallW,wallH);
}
@Override
public void paintComponent(Graphics g){
Graphics2D g2d =(Graphics2D)g;
setLocation(wallX,wallY);
g2d.fillRect(0,0,wallW,wallH);
}
}
那里我可以在你的程序中找到几个错误
-
你使用的是null layout
,请参阅I am trying to make a simple animation in which a rectangle starts off the screen (on the right side of the right edge of the screen) and moves towards the left. So, in this case, my frame has a width of 1000 and the wall starts off at an x-value of 1100. Obviously, at first, the rectangle is not supposed to be visible to us. But as the rectangle moves to the left, it should eventually become visible. However, this animation doesn't do that. Even when the wall's x-value is within the bounds of the screen, it isn't being rendered.
I tried putting a
println()
statement in thepaintComponent()
method of the wall, and I discovered that thepaintComponent()
wasn't getting called by the frame'srepaint()
method. I figured that when the wall was first added to the frame, Swing decided that since it was off the screen it doesn't need to get rendered, and so even when the wall eventually gets on the screen Swing thinks that it doesn't need to get rendered.I have tried revalidating and invalidating the frame and the component, but nothing has worked. Please help me to fix this. Below is the code:
package graphics.simpleAnimation; public class Simple_Animation implements Runnable { private UI ui; // The UI (frame) private Wall wall; // Wall object that moves across the screen private Simple_Animation() { // Initialize the wall object (intentionally given an x value that is greater than the frame's width) wall = new Wall(1100, 400, 200, 400); // Initialize the UI (width is only 1000) ui = new UI(1000, 600, "Geometry Dash"); // Add the wall to the ui (the frame) ui.add(wall); } public void run() { // Set the frame visible ui.setVisible(true); // Repaint the frame and move the wall while (true) { ui.repaint(); wall.moveWall(-2, 0); try { Thread.sleep(16); } catch (InterruptedException IE) { System.out.println(IE); } } } // Starts the program in a new thread public static void main(String[] args) { Simple_Animation simpleAnimation = new Simple_Animation(); new Thread(simpleAnimation).start(); } } package graphics.simpleAnimation; import javax.swing.*; import java.awt.*; public class UI extends JFrame { // Variables storing the width and height of the content pane (where the components are being rendered) public int content_pane_width; public int content_pane_height; public UI(int frameW, int frameH, String frameTitle) { setTitle(frameTitle); setSize(frameW, frameH); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout(null); content_pane_width = getContentPane().getWidth(); content_pane_height = getContentPane().getHeight(); } @Override public void paint(Graphics g) { super.paint(g); } } package graphics.simpleAnimation; import java.awt.*; import javax.swing.*; public class Wall extends JComponent { private int wallX; private int wallY; private int wallW; private int wallH; Wall(int x, int y, int sizeX, int sizeY) { wallX = x; wallY = y; wallW = sizeX; wallH = sizeY; setSize(getPreferredSize()); } public void moveWall(int moveX, int moveY) { wallX += moveX; wallY += moveY; } @Override public Dimension getPreferredSize() { return new Dimension(wallW, wallH); } @Override public void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D) g; setLocation(wallX, wallY); g2d.fillRect(0, 0, wallW, wallH); } }
解决方案There are a couple of errors I can find in your program
You're using a(Probably not in this case, as per @MadProgrammer's comment below), this is just another approachnull layout
, please see Null layout is evil and the answers in this question to see why you should avoid its use.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离开屏幕,它就会停止渲染的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!