在 for 循环结束之前不会重绘,只有两帧
Repaint won't happen until the for loop has escaped, with only two frames
我正在尝试做一些基本的 Java,我的框架中有一个形状。它使用 JComponent class 来绘制形状,通过点击顶部的按钮触发动画。
jpanel中添加的组件代码就是这个
public void paintComponent(Graphics g){
Dimension dim = getSize();
g.setColor(Color.GREEN);
g.fillOval(margin, 150, 100, 100);
super.paintComponent(g);
}
动画只是在 for 循环内完成,它只是编辑左边距,使圆圈向右移动;
int getMarg = cc.getMargin();
for(int i = 1;i < 20;i++){
getMarg = cc.getMargin();
cc.setMargin(getMarg + 1);
reValidate();
System.out.println(i);
但是好像直到循环结束才移动,每次移动20个像素。我以前有一个睡眠功能,但当它没有动画时它似乎毫无意义。
有什么见解吗?干杯。
所有感兴趣的人的完整代码,凌乱且主要是为了获得样式:
class Main extends JFrame{
public JPanel panel = new JPanel();
JButton button1 = new JButton("Move Right");
CreateComps cc = new CreateComps();
Main(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initUI();
}
void initUI(){
setSize(800,800);
setBackground(Color.GRAY);
setLayout(new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS));
JPanel topBar = new JPanel();
topBar.setPreferredSize(new Dimension(800,30));
topBar.setMaximumSize(new Dimension(800,30));
topBar.setLayout(new BorderLayout());
topBar.add(button1, BorderLayout.WEST);
topBar.setBackground(Color.GRAY);
JPanel container = new JPanel();
container.setLayout(new GridBagLayout());
container.setBackground(Color.DARK_GRAY);
panel.setPreferredSize(new Dimension(600,500));
panel.setMinimumSize(new Dimension(600,500));
panel.setBackground(Color.WHITE);
panel.setLayout(new BorderLayout());
panel.add(cc, BorderLayout.CENTER);
add(topBar);
add(container);
container.add(panel);
Listener listen = new Listener();
button1.addActionListener(listen);
setVisible(true);
}
public void reValidate(){
panel.revalidate();
panel.repaint();
}
public static void main (String[] args){
Main main = new Main();
}
class Listener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Listening..");
if(e.getSource().equals(button1)){
int getMarg = cc.getMargin();
for(int i = 1;i < 20;i++){
getMarg = cc.getMargin();
cc.setMargin(getMarg + 1);
reValidate();
System.out.println(i);
}
}
}
}
}
class CreateComps extends JComponent{
int margin = 10;
public void setMargin(int marg){
margin = marg;
}
public int getMargin(){
return margin;
}
@Override
public Dimension getPreferredSize(){
return new Dimension(new Dimension(200,200));
}
@Override
public Dimension getMaximumSize(){
return new Dimension(new Dimension(200,200));
}
@Override
public Dimension getMinimumSize(){
return new Dimension(new Dimension(200,200));
}
public void paintComponent(Graphics g){
Dimension dim = getSize();
g.setColor(Color.GREEN);
g.fillOval(margin, 150, 100, 100);
super.paintComponent(g);
}
}
如果没有停顿,您将堆叠对 revalidate
的调用,并且除了最后一次调用的结果之外什么也看不到。
您之前拥有的休眠功能可能是在 Event Dispatch Thread 上调用的,这一点都不好,因为您阻止了整个事件调度和 GUI 更新。
考虑使用 sleep
调用另一个 Thread
:
@Override
public void actionPerformed(final ActionEvent e) {
System.out.println("Listening..");
if (e.getSource().equals(button1)) {
new Thread() {
@Override
public void run() {
int getMarg = cc.getMargin();
for (int i = 1; i < 20; i++) {
getMarg = cc.getMargin();
cc.setMargin(getMarg + 1);
reValidate();
System.out.println(i);
try {
Thread.sleep(50);
} catch (Throwable e) {
}
}
}
}.start();
}
}
或者您也可以简单地使用 Timer,这对这项工作非常有用。
我正在尝试做一些基本的 Java,我的框架中有一个形状。它使用 JComponent class 来绘制形状,通过点击顶部的按钮触发动画。
jpanel中添加的组件代码就是这个
public void paintComponent(Graphics g){
Dimension dim = getSize();
g.setColor(Color.GREEN);
g.fillOval(margin, 150, 100, 100);
super.paintComponent(g);
}
动画只是在 for 循环内完成,它只是编辑左边距,使圆圈向右移动;
int getMarg = cc.getMargin();
for(int i = 1;i < 20;i++){
getMarg = cc.getMargin();
cc.setMargin(getMarg + 1);
reValidate();
System.out.println(i);
但是好像直到循环结束才移动,每次移动20个像素。我以前有一个睡眠功能,但当它没有动画时它似乎毫无意义。
有什么见解吗?干杯。
所有感兴趣的人的完整代码,凌乱且主要是为了获得样式:
class Main extends JFrame{
public JPanel panel = new JPanel();
JButton button1 = new JButton("Move Right");
CreateComps cc = new CreateComps();
Main(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initUI();
}
void initUI(){
setSize(800,800);
setBackground(Color.GRAY);
setLayout(new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS));
JPanel topBar = new JPanel();
topBar.setPreferredSize(new Dimension(800,30));
topBar.setMaximumSize(new Dimension(800,30));
topBar.setLayout(new BorderLayout());
topBar.add(button1, BorderLayout.WEST);
topBar.setBackground(Color.GRAY);
JPanel container = new JPanel();
container.setLayout(new GridBagLayout());
container.setBackground(Color.DARK_GRAY);
panel.setPreferredSize(new Dimension(600,500));
panel.setMinimumSize(new Dimension(600,500));
panel.setBackground(Color.WHITE);
panel.setLayout(new BorderLayout());
panel.add(cc, BorderLayout.CENTER);
add(topBar);
add(container);
container.add(panel);
Listener listen = new Listener();
button1.addActionListener(listen);
setVisible(true);
}
public void reValidate(){
panel.revalidate();
panel.repaint();
}
public static void main (String[] args){
Main main = new Main();
}
class Listener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Listening..");
if(e.getSource().equals(button1)){
int getMarg = cc.getMargin();
for(int i = 1;i < 20;i++){
getMarg = cc.getMargin();
cc.setMargin(getMarg + 1);
reValidate();
System.out.println(i);
}
}
}
}
}
class CreateComps extends JComponent{
int margin = 10;
public void setMargin(int marg){
margin = marg;
}
public int getMargin(){
return margin;
}
@Override
public Dimension getPreferredSize(){
return new Dimension(new Dimension(200,200));
}
@Override
public Dimension getMaximumSize(){
return new Dimension(new Dimension(200,200));
}
@Override
public Dimension getMinimumSize(){
return new Dimension(new Dimension(200,200));
}
public void paintComponent(Graphics g){
Dimension dim = getSize();
g.setColor(Color.GREEN);
g.fillOval(margin, 150, 100, 100);
super.paintComponent(g);
}
}
如果没有停顿,您将堆叠对 revalidate
的调用,并且除了最后一次调用的结果之外什么也看不到。
您之前拥有的休眠功能可能是在 Event Dispatch Thread 上调用的,这一点都不好,因为您阻止了整个事件调度和 GUI 更新。
考虑使用 sleep
调用另一个 Thread
:
@Override
public void actionPerformed(final ActionEvent e) {
System.out.println("Listening..");
if (e.getSource().equals(button1)) {
new Thread() {
@Override
public void run() {
int getMarg = cc.getMargin();
for (int i = 1; i < 20; i++) {
getMarg = cc.getMargin();
cc.setMargin(getMarg + 1);
reValidate();
System.out.println(i);
try {
Thread.sleep(50);
} catch (Throwable e) {
}
}
}
}.start();
}
}
或者您也可以简单地使用 Timer,这对这项工作非常有用。