Просто потратьте два часа на отладку этого, я думаю, что знаю причину проблемы, но я не понимаю, как она может давать такие результаты.
У меня есть приложение на основе Swing, в котором я переопределяю JPanel.paint(Graphics 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)
Более интересные вещи, если я соответствующим образом перемещаю вывод/вычисления отладки, чтобы углубиться в это, проблема исчезает.
Это происходит только с JRE из jdk1.8.0_25.jdk (в Mac OS X 10.8.5), а не с Java 1.6 или 1.6.
Хорошо, я думаю, что настоящий виновник в том, что JPanel не был создан в потоке отправки событий, как только я сделал это, исключение никогда не выбрасывается, несоответствий нет.
Совершенно очевидно, что проблема, связанная с потоком, зависит от времени, но мне любопытно, как это может произойти с «правилами» Java JVM, все задействованные переменные являются локальными для метода, а матричные методы из AffineTransform не должны иметь побочных эффектов, так что добрый трудно понять, как проблемы с потоками могут вызвать что-то подобное…
Для моего разума я хотел бы понять, что здесь происходит.
В качестве побочного эффекта этот вопрос может помочь какой-нибудь бедняге, борющейся с подобными проблемами.
Также я не возражаю, если кому-то удастся указать такой очевидный недостаток в коде/отладке/выводах, поскольку я уже часами смотрю на эти строки….
g2
, из которого вы копируете начальное преобразование? -- Хм. Вероятно, нет, учитывая, что вы используете один и тот жеmc
для вывода отладки. - person JimmyB   schedule 04.11.2014