2012-07-07 100 views
3

我正在使用Jpype將java類用於python腳本。 java類涉及使用AWT庫:這似乎是問題所在。Jpype:「由於Java是在第一個線程上啓動的,因此無法啓動AWT。」

這個python腳本:

import jpype 
import os.path 
import threading 

jarpath = os.path.join(os.path.abspath('.'), 'build/jar') 
target=jpype.startJVM(jpype.getDefaultJVMPath(), "-Djava.ext.dirs=%s" % jarpath) 
Capture = jpype.JClass('Capture')   # Capture is the class, contained in ./ folder 
t = Capture(50,354,90,90,130,650,"num",36); # create the instance 
jpype.shutdownJVM() 

所以我只是想將類實例,只是退出。 這是java類。我只報告是導致錯誤的代碼:

class Capture { 

    public Capture(int x, int y, int width, int height, int mouseNextX, int mouseNextY, final String fnamestart, final int countmax) { 
      //... 
      images = new ArrayList<BufferedImage>(); 
      getImages(fnamestart,countmax); //THIS is the problem 
} 

    // reference to getImages() method: 
    public void getImages(String fname, int countmax) { 

     images.clear(); 
     for(int i=0; i<=countmax; i++) { 
      try { 
       BufferedImage img = ImageIO.read(new File(fname+i+".bmp")); 
       images.add(img); 
      } catch(IOException e) { 
       images.add(null); 
      } 
     } 
    } 
} 

此代碼,運行python腳本時,鼓舞了我以下錯誤:

jpype._jexception.VirtualMachineErrorPyRaisable: java.lang.InternalError: Can't start 
the AWT because Java was started on the first thread. Make sure StartOnFirstThread is 
not specified in your application's Info.plist or on the command line 

長話短說,這是一個已知的問題: Eclipse有「自己的版本」,然後解決。不幸的是,沒有人談到與jpype有關的這個問題。

我嘗試了這些解決方案,這並不工作:

  • 在python腳本,在開始之前JVM啓動一個線程。然後在另一個線程中啓動JVM。

  • 在Python腳本,啓動JVM與參數-XstartOnFirstThread

    target=jpype.startJVM(jpype.getDefaultJVMPath(), "-XStartOnFirstThread -Djava.ext.dirs=%s" % jarpath) 
    
  • 在Java代碼:使用AWT方法invokeLater,在構造:

    java.awt.EventQueue.invokeLater(new Runnable() { 
        public void run() { 
         images = new ArrayList<BufferedImage>(); 
         getImages(fnamestart,countmax); 
        } 
    }); 
    

我真的不知道該怎麼做,希望你能幫助我。 謝謝

喬瓦尼

回答

0

-XstartOnFirstThread究竟是你必須確保有在命令行上。在python中啓動線程沒有區別,問題在於JVM的線程。 invokeLater也不會有什麼區別 - AWT運行循環必須在第一個線程上執行。這是一個可可限制,所以我想你是在Mac上運行的。

現在,您應該查看確切的命令行來啓動JVM,然後嘗試追溯到根本原因 - 生成該命令行的代碼。 JVM正在通過您的直接控制之外的方法啓動。

+0

在我看來,這是一個Jpype問題:我讀它初始化JVM中的代碼,並把它傳遞給蟒蛇上課前運行的Java線程。這樣,當我初始化AWT時,它在第二個線程中完成。儘管我會在Linux機器上運行我的代碼,而不是像我從現在開始那樣在MAC OSX上運行代碼。希望這會解決問題!謝謝 – joker 2012-07-11 16:15:30

+0

據我所知,AWT事件循環的初始化在客戶端代碼的控制之外,並且使用AWT對象的線程並不重要。所以這個錯誤的唯一原因是RunOnFirstThread。這聽起來像是Jpype的問題。 – 2012-07-11 17:50:06

1

使用此參數:

jpype.startJVM(jpype.getDefaultJVMPath(), '-Djava.awt.headless=true')