只需花費兩個小時來調試這個問題,我想我知道問題的原因,但我不明白它怎麼能產生它所做的那種結果。同樣的計算結果如何產生不同的結果
我有一個基於Swing應用程序,我重寫JPanel.paint(圖形G)這樣
public void paint(Graphics g) {
<snipped code>
Insets is = getInsets();
Dimension sz = getSize();
g2.setClip(is.left + 1, is.top + 1, sz.width - is.right - is.left - 2, sz.height - is.top - is.bottom - 2);
int w = getWidth();
int h = getHeight();
double s = Math.min(sz.getWidth(), sz.getHeight());
AffineTransform mc = g2.getTransform();
AffineTransform m1 = new AffineTransform(mc);
m1.preConcatenate(AffineTransform.getTranslateInstance(-m_CenterX, -m_CenterY));
m1.preConcatenate(AffineTransform.getScaleInstance(m_ScaleX * s, -m_ScaleY * s));
m1.preConcatenate(AffineTransform.getTranslateInstance(w/2, h/2));
AffineTransform m2 = new AffineTransform(mc);
m2.preConcatenate(AffineTransform.getTranslateInstance(-m_CenterX, -m_CenterY));
m2.preConcatenate(AffineTransform.getScaleInstance(m_ScaleX * s, -m_ScaleY * s));
m2.preConcatenate(AffineTransform.getTranslateInstance(w/2, h/2));
try {
m_InverseViewTransform = m1.createInverse();
} catch (NoninvertibleTransformException e) {
AffineTransform m3 = new AffineTransform(mc);
m3.preConcatenate(AffineTransform.getTranslateInstance(-m_CenterX, -m_CenterY));
m3.preConcatenate(AffineTransform.getScaleInstance(m_ScaleX * s, -m_ScaleY * s));
m3.preConcatenate(AffineTransform.getTranslateInstance(w/2, h/2));
System.out.println("m1 = " + m1);
System.out.println("m2 = " + m2);
System.out.println("m3 = " + m3);
AffineTransform m4 = new AffineTransform(mc);
System.out.println("m4 = " + m4);
m4.preConcatenate(AffineTransform.getTranslateInstance(-m_CenterX, -m_CenterY));
System.out.println("m4 = " + m4);
m4.preConcatenate(AffineTransform.getScaleInstance(m_ScaleX * s, -m_ScaleY * s));
System.out.println("m4 = " + m4);
m4.preConcatenate(AffineTransform.getTranslateInstance(w/2, h/2));
System.out.println("m4 = " + m4);
System.out.println(w);
System.out.println(h);
System.out.println(s);
System.out.println(m_CenterX);
System.out.println(m_CenterY);
System.out.println(m_ScaleX);
System.out.println(m_ScaleY);
e.printStackTrace();
現在的奧祕,有時當我啓動應用程序,往往不是,說三次在四個中,引發NoninvertibleTransformException。
正如你所看到的調試,我輸出違規矩陣和三個其他相同計算的矩陣和用於形成這些矩陣的變量。
這就是它變得有趣的地方,請看下面的輸出,所有的矩陣都沒有相同的值!
m1 = AffineTransform[[0.0, 0.0, 400.0], [0.0, -0.0, 289.0]]
m2 = AffineTransform[[0.0, 0.0, 400.0], [0.0, -0.0, 289.0]]
m3 = AffineTransform[[0.0, 0.0, 400.0], [0.0, -0.0, 289.0]]
m4 = AffineTransform[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
m4 = AffineTransform[[1.0, 0.0, -49.5], [0.0, 1.0, -0.362762953421903]]
m4 = AffineTransform[[5.254545454545455, 0.0, -260.1], [0.0, -587.9922126928986, 213.3017916655554]]
m4 = AffineTransform[[5.254545454545455, 0.0, 139.89999999999998], [0.0, -587.9922126928986, 502.3017916655554]]
800
578
578.0
49.5
0.36276295342190257
0.009090909090909092
1.0172875652126274
java.awt.geom.NoninvertibleTransformException: Determinant is 0
at java.awt.geom.AffineTransform.createInverse(AffineTransform.java:2706)
更有趣的東西,如果我適當地移動調試輸出/計算周圍深入挖掘這個問題消失。
這種情況只發生在jdk1.8.0_25.jdk(Mac OS X 10.8.5)的JRE中,而不是Java 1.6或1.6。
好吧,我認爲真正的罪魁禍首是JPanel不是在Event Dispatched線程中創建的,一旦我這樣做了,那麼異常永遠不會拋出,沒有不一致。
所以很明顯是一個線程相關的時間依賴問題,但我很好奇在Java JVM的「規則」中如何發生這種情況?所涉及的所有變量都是本地方法,並且AffineTransform的矩陣方法不應該有副作用很難理解螺紋問題如何導致這樣的事情...
對於我的想法,我想了解這裏發生了什麼。
作爲一個副作用,這個問題可能會幫助一些可憐的靈魂在類似的問題上掙扎。
另外我不介意如果有人設法在代碼/調試/扣除中指出如此明顯的缺陷,因爲我現在已經盯着這些線路幾個小時......。
那麼,你的值(我看到像m_CenterX這樣的東西)在除了讀取它們的EDT之外的任何其他線程上更改(或初始化)?如果是這樣,那麼你知道你可能有一個多線程問題。 – NESPowerGlove 2014-11-04 16:29:42
難道是另一個線程正在與您從中複製初始轉換的'g2'同時'混淆'? - 嗯。可能不會,看到你正在爲你的調試輸出使用相同的'mc'。 – JimmyB 2014-11-04 16:36:02
感謝和公平點,m_CenterX等在MouseListener中更新。但是,這是運行在EDT ...也許當我在主線程(而不是EDT,因爲它應該是)創建JPanel時,paint()被調用錯誤的線程(至少一次)。嗯,我可以在出現問題時輸出線程名稱...。 – nyholku 2014-11-04 16:39:37