繁体   English   中英

方法调用的含糊不定顺序

[英]Ambiguous and inconstant order of method call

我正在编写一个程序,该程序使用两种绘制方法来根据以前的“绘制”方法产生的“绘制”产生输出。 有两种方法,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)从“ In draw2”行中可以看出,程序已进入draw2()。 那我为什么会出现黑屏和白屏? (没有广场)。

而且,当我尝试添加另一个print()语句时,方法调用本身的顺序也会更改。 由于问题的长度过长,我没有为此添加代码和输出,但是我想知道对此是否有一些解释。

PS我正在使用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

顺便说一句:我可以看到你错过的广场。

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

为避免这种情况,请勿从构造函数中调用setVisible(true) ,以后再从main()调用。

您的绘画代码错误。

  1. 不要重写JFrame的paint()。 但是,如果您这样做,那么至少需要一个super.paint()来确保绘画正确完成。

  2. 通过覆盖JPanel上的paintComponent(...)完成绘制。 然后将面板添加到框架。

  3. 不要直接调用paint(...)。 Swing将创建Graphics对象,并将其传递给paint()方法。 而是在组件上调用repaint()。

因此,除了说这幅画是错误的以外,我无法回答您有关正在发生的一切问题。 绘画也应如此,我敢肯定这种矛盾会消失。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM