2017-01-03 1 views
-1

Просто быстрый вопрос, который находится на моем уме прямо сейчас:JavaFX InstanceOf ScrollPaneSkin терпит неудачу

У меня есть приложение JavaFX, который содержит (среди прочих) ScrollPane и мне нужно, чтобы захватить событие MouseClicked этого ScrollPane. На самом деле это не проблема, за исключением того, что мне нужно обработать событие только в том случае, если целью события является экземпляр Rectangle, ToggleButton или ScrollPaneSkin. На самом деле это тоже довольно легко, я знаю. Прямо сейчас, у меня есть следующий код:

@FXML 
void scrollPaneOnMouseClicked(MouseEvent event) { 
    System.out.println(event.getTarget().getClass().getName()); 
    System.out.println(event.getTarget() instanceof ScrollPaneSkin); 
    if (event.getTarget() instanceof RoomRectangle || event.getTarget() instanceof ToggleButton || event.getTarget() instanceof ScrollPaneSkin) { 
     // handle 
    } 
} 

за исключением того, что event.getTarget() instanceof ScrollPaneSkin говорит ложь, даже если System.out.println(event.getTarget().getClass().getName()); выходы com.sun.javafx.scene.control.skin.ScrollPaneSkin$4 (и отладчик подтверждает, что).

Я также пробовал event.getTarget() instanceof ScrollPaneSkin$4, который привел к тому, что символ «не может найти символ» -error.

Что я пропустил здесь?

+0

Почему вы (думаете) вам это нужны? Что ты пытаешься сделать? –

ответ

1

Хорошо, я исправил его сам. Проблема была довольно простой, и причина была $4. Как я только что узнал, $4 указывает на анонимный внутренний класс ScrollPaneSkin, который, очевидно, не может быть доступен извне. Это означает, что цель действительно не является экземпляром ScrollPaneSkin, а скорее экземпляром этого внутреннего класса. Единственным обходным решением является использование event.getTarget.getClass().getName() и сравнение строк. (Решение взято с here)

1

ScrollPaneSkin$4 скорее всего является экземпляром name mangling для анонимного внутреннего класса, созданного внутри ScrollPaneSkin. Вероятно, поэтому ваш код event.getTarget() instanceof ScrollPaneSkin не работает (потому что цель на самом деле является экземпляром анонимного внутреннего класса, а не самого скина).

Объем анонимных классов ограничивается их родительского класса, так что компилятор должен произвести «квалифицированное» общественное имя внутреннего класса, чтобы избежать конфликта, где существуют другие классы с таким же именем (внутренний или нет) в том же пространстве имен. Точно так же анонимные классы должны иметь «поддельные» публичные имена, созданные для них (поскольку концепция анонимных классов существует только в компиляторе, а не во время выполнения). Таким образом, составление следующей программы Java

public class foo { 
    class bar { 
     public int x; 
    } 

    public void zark() { 
     Object f = new Object() { 
      public String toString() { 
       return "hello"; 
      } 
     }; 
    } 
} 

будет производить три .class файлы:

  • foo.class, содержащие основной (внешний) класс Foo
  • foo$bar.class, содержащие названный внутренний foo.bar класса
  • foo$1.class, содержащий анонимный внутренний класс (местный к методу foo.zark)

является com.sun, который не поддерживается общедоступным API, написание написанного на нем кода, вероятно, не является хорошей идеей, поскольку оно может быть хрупким и подверженным ошибкам из-за внутренней реализации ScrollPaneSkin, которая может изменяться с Java на версия для версии. У меня нет другого предложения о том, как вы должны выполнить то, что хотите.

+0

Да, я знаю, что на самом деле это не очень хорошая идея для кодирования скинов, но у меня нет большого выбора.У меня есть конкретный случай использования, когда цель оказывается в том, что 'ScrollPaneSkin $ 4'-thing и цель события - это единственное, что я могу использовать, чтобы отличать, когда обрабатывать событие и когда нет (я тоже смотрел на другие вещи). Я, наконец, закончил выполнение строкового сравнения имени класса (см. Мой собственный ответ ниже). Спасибо, в любом случае :) – vatbub