方法呼叫的模棱两可和不一致的顺序



我正在编写一个程序,该程序使用两种油漆方法根据以前的"油漆"方法产生的"绘画"产生输出。有两种方法:draw1和draw2,使用draw1给定的初始配置,然后使用draw2来生成下一行的输出。但是,当我执行代码时,我会遇到有关定义的方法的奇怪错误。我在我的代码中添加了几个print()语句,以尝试理解这一点,但这只会加剧问题,因为添加了print()语句似乎会影响方法调用的顺序。

这是代码(仍然是非常基本的版本) -

import java.awt.*;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import java.awt.image.BufferedImage;
public class Processor extends JFrame
{
static int x=1;
public Processor()
{
    setTitle("Automaton");
    setSize(1000,1000);
    setVisible(true);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    System.out.println("In constructor");
}
public void paint(Graphics g)
{
    if(x==1)
        draw(g);
    else if(x==2)    
        draw2(g);        
}
public void draw(Graphics g)
{
    g.setColor(Color.WHITE);
    g.fillRect(0,0,1000,1000);
    System.out.println("In Draw");
}//This is the initial setting.
public void draw2(Graphics g)
{
    g.setColor(Color.BLACK);
    g.fillRect(500,22,50,50);
    System.out.println("In Draw2");
}
public static BufferedImage toBufferedImage(Component component) 
{
    BufferedImage image = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_RGB);
    Graphics g = image.getGraphics();
    component.paint(g);
    return image;
}
public static void main(String[]args)
{
    System.out.println("Start");
    BufferedImage image;
    Processor t=new Processor();
    System.out.println("Middle");
    image=toBufferedImage(t);
    System.out.println("End");
    //Color myColor=new Color(image.getRGB(500,500));
    x=2;
    image=toBufferedImage(t);
}
}

运行此代码时,我将获得以下输出以及空的白色屏幕 -

Start
In Draw
In constructor
Middle
In Draw
In Draw
End
In Draw2

我想到的两个问题

1)为什么执行

image=toBufferedImage(t);

导致draw()被称为两次?

2)从" draw2"行中证明,该程序已输入draw2()。那我为什么要获得空白和白屏?(没有正方形)。

此外,当我尝试添加另一个print()语句时,方法的顺序会自我更改。由于问题的长度过长,我尚未在代码和输出中添加输出,但是我想知道是否有一些解释。

P.S我正在使用BlueJ环境来运行我的代码。

如果您想知道从何处调用了一种方法,这是一个简单的技巧。更改您的paint方法:

public void paint(Graphics g)
{
    System.out.println("paint called from " + Thread.currentThread().getName());
    new Exception().printStackTrace(System.out);
    if(x==1)
        draw(g);
    else if(x==2)    
        draw2(g);        
}

输出将告诉您呼叫不是来自toBufferedImage,而是来自称为AWT-EventQueue-0的线程:

这是我的执行之一的输出:

Start
In constructor
Middle
paint called from AWT-EventQueue-0
java.lang.Exception
    at Processor.paint(Processor.java:22)
    at javax.swing.RepaintManager$3.run(RepaintManager.java:822)
    at javax.swing.RepaintManager$3.run(RepaintManager.java:794)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:794)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:769)
    at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:718)
    at javax.swing.RepaintManager.access$1100(RepaintManager.java:62)
    at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1680)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744)
    at java.awt.EventQueue.access$400(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:697)
    at java.awt.EventQueue$3.run(EventQueue.java:691)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:714)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
In Draw
paint called from main
java.lang.Exception
    at Processor.paint(Processor.java:22)
    at Processor.toBufferedImage(Processor.java:47)
    at Processor.main(Processor.java:57)
In Draw
End
paint called from main
paint called from AWT-EventQueue-0
java.lang.Exception
    at Processor.paint(Processor.java:22)
    at Processor.toBufferedImage(Processor.java:47)
    at Processor.main(Processor.java:62)
In Draw2
java.lang.Exception
    at Processor.paint(Processor.java:22)
    at javax.swing.RepaintManager$3.run(RepaintManager.java:822)
    at javax.swing.RepaintManager$3.run(RepaintManager.java:794)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:794)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:769)
    at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:718)
    at javax.swing.RepaintManager.access$1100(RepaintManager.java:62)
    at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1680)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744)
    at java.awt.EventQueue.access$400(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:697)
    at java.awt.EventQueue$3.run(EventQueue.java:691)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:714)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
In Draw2
paint called from AWT-EventQueue-0
java.lang.Exception
    at Processor.paint(Processor.java:22)
    at javax.swing.RepaintManager$3.run(RepaintManager.java:822)
    at javax.swing.RepaintManager$3.run(RepaintManager.java:794)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:794)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:769)
    at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:718)
    at javax.swing.RepaintManager.access$1100(RepaintManager.java:62)
    at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1680)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744)
    at java.awt.EventQueue.access$400(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:697)
    at java.awt.EventQueue$3.run(EventQueue.java:691)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:714)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
In Draw2

btw:我可以看到您错过的广场。

您是从两个线程执行draw方法:EventDispatchThreadmain线程。

要避免这种情况,请勿从构造函数中调用setVisible(true)-稍后从main()致电。

您的绘画代码是错误的。

  1. 不要覆盖jframe的油漆()。但是,如果您这样做,那么至少您需要一个super.paint()来确保绘画做得正确。

  2. 绘画是通过jpanel上的paintcomponent(...)完成的。然后将面板添加到框架中。

  3. 不要直接调用油漆(...)。秋千将创建图形对象,并将其传递到Paint()方法。取而代

所以我无法回答您关于正在发生的事情的任何问题,除了说这幅画是错误的。绘画也是如此,我确定不一致会消失。