Почему исчезает содержимое JavaFX на моем TopComponent?

У меня проблема, которая может быть вызвана отсутствием понимания в некоторых принципах платформы Netbeans Platform (7.1.2) или JavaFX 2. Я хотел добавить JFXPanel с помощью очень простого Scene к Swing JPanel, который является дочерним элементом TopComponent. Я достиг этого следующим кодом:

 public accexTopComponent() {
    initComponents();
    setName(Bundle.CTL_accexTopComponent());
    setToolTipText(Bundle.HINT_accexTopComponent());
    putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);



    //Begin of my code
    myFX = new JFXPanel(); //myFX is a static JFXPanel
    Platform.runLater(new Runnable() {

        @Override
        public void run() {

            myFX.setScene(new Scene(ButtonBuilder.create().minHeight(40.0).minWidth(40.0).build()));

        }
    });

      jPanel1.add(myFX);



}

Это компилируется без проблем, и JavaFX Button отображается, когда я показываю TopComponent в первый раз. Но как только компонент скрыт и отображается снова, JavaFX Button исчезает, пока другие дети все еще видны.

Почему содержимое JavaFX исчезает?

Edit:

Теперь я включаю источник всего TopComponent. Я предполагаю, что все, что вам нужно, проверить для себя. Я не изменил ни одного другого файла.

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.jeed.nbgan.accexplorer;

import java.awt.Color;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.control.ButtonBuilder;
import javafx.scene.text.TextBuilder;
import javafx.scene.web.WebView;
import javafx.scene.web.WebViewBuilder;
import org.netbeans.api.settings.ConvertAsProperties;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.windows.TopComponent;
import org.openide.util.NbBundle.Messages;

/**
 * Top component which displays something.
 */
@ConvertAsProperties(dtd = "-//de.jeed.nbgan.accexplorer//accex//EN",
autostore = false)
@TopComponent.Description(preferredID = "accexTopComponent",
//iconBase="SET/PATH/TO/ICON/HERE", 
persistenceType = TopComponent.PERSISTENCE_ALWAYS)
@TopComponent.Registration(mode = "explorer", openAtStartup = true)
@ActionID(category = "Window", id = "de.jeed.nbgan.accexplorer.accexTopComponent")
@ActionReference(path = "Menu/Window" /*
 * , position = 333
 */)
@TopComponent.OpenActionRegistration(displayName = "#CTL_accexAction",
preferredID = "accexTopComponent")
@Messages({
    "CTL_accexAction=accex",
    "CTL_accexTopComponent=Konten-Explorer",
    "HINT_accexTopComponent=Durchsuchen von Abteilungen und Konten"
})
public final class accexTopComponent extends TopComponent {

    static JFXPanel myFX;

    public accexTopComponent() {
        initComponents();
        setName(Bundle.CTL_accexTopComponent());
        setToolTipText(Bundle.HINT_accexTopComponent());
        putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
        myFX = new JFXPanel();
        Platform.runLater(new Runnable() {

            @Override
            public void run() {

                myFX.setScene(new                            Scene(ButtonBuilder.create().minHeight(40.0).minWidth(40.0).build()));

        }
    });

      jPanel1.add(myFX);


}

/**
 * This method is called from within the constructor to initialize the form.
 * WARNING: Do NOT modify this code. The content of this method is always
 * regenerated by the Form Editor.
 */
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

    jPanel1 = new javax.swing.JPanel();

    jPanel1.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));
    jPanel1.setLayout(new java.awt.GridBagLayout());

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
    this.setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addGap(54, 54, 54)
            .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 193, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addContainerGap(153, Short.MAX_VALUE))
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addGap(33, 33, 33)
            .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 193, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addContainerGap(74, Short.MAX_VALUE))
    );
}// </editor-fold>                        
// Variables declaration - do not modify                     
private javax.swing.JPanel jPanel1;
// End of variables declaration                   

@Override
public void componentOpened() {
    // TODO add custom code on component opening
}

@Override
public void componentClosed() {
    // TODO add custom code on component closing
}

void writeProperties(java.util.Properties p) {
    // better to version settings since initial version as advocated at
    // http://wiki.apidesign.org/wiki/PropertyFiles
    p.setProperty("version", "1.0");
    // TODO store your settings
}

void readProperties(java.util.Properties p) {
    String version = p.getProperty("version");
    // TODO read your settings according to their version
}
}

В моем случае этот TopComponent является частью Компонента, называемого AccountExplorer, который ссылается на JavaFX и ссылается на обычное приложение платформы NB.

Ответ 1

Попробуйте следующее:

Platform.setImplicitExit(false);

Ответ 2

Мы испытываем ту же проблему. Основываясь на следующих потоках, мы предполагаем, что, как только панель перестанет быть видимой, платформа JavaFX автоматически выйдет из-за того, что все элементы gui JavaFX больше не видны.

Это предположение основано на информации от:
https://forums.oracle.com/forums/thread.jspa?messageID=10287328 и
https://forums.oracle.com/forums/thread.jspa?threadID=2390971

Первая попытка в нашей среде - добавить фиктивный JFXPanel где-нибудь в коде и оставить его там, пока ваши выходы из программы, похоже, не сработают.

Вторая попытка вашего кода также работает:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package de.jeed.nbgan.accexplorer;

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.geometry.Rectangle2D;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ButtonBuilder;
import javafx.scene.paint.Color;
import javafx.stage.Modality;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import org.netbeans.api.settings.ConvertAsProperties;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.windows.TopComponent;
import org.openide.util.NbBundle.Messages;

/**
 * Top component which displays something.
 */
@ConvertAsProperties(dtd = "-//de.jeed.nbgan.accexplorer//accex//EN",
autostore = false)
@TopComponent.Description(preferredID = "accexTopComponent",
//iconBase="SET/PATH/TO/ICON/HERE", 
persistenceType = TopComponent.PERSISTENCE_ALWAYS)
@TopComponent.Registration(mode = "explorer", openAtStartup = true)
@ActionID(category = "Window", id = "de.jeed.nbgan.accexplorer.accexTopComponent")
@ActionReference(path = "Menu/Window" /*
 * , position = 333
 */)
@TopComponent.OpenActionRegistration(displayName = "#CTL_accexAction",
preferredID = "accexTopComponent")
@Messages({
    "CTL_accexAction=accex",
    "CTL_accexTopComponent=Konten-Explorer",
    "HINT_accexTopComponent=Durchsuchen von Abteilungen und Konten"
})
public final class accexTopComponent extends TopComponent {

    static JFXPanel myFX;
    static JFXPanel myDummyFXtoKeepJavaFxRunning;

    public accexTopComponent() {
        initComponents();
        setName(Bundle.CTL_accexTopComponent());
        setToolTipText(Bundle.HINT_accexTopComponent());
        putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
        myFX = new JFXPanel();
        myDummyFXtoKeepJavaFxRunning = new JFXPanel();
        Platform.runLater(new Runnable() {

            @Override
            public void run() {
                // Actual FX code that will be hidden/shown
                myFX.setScene(new Scene(ButtonBuilder.create().minHeight(40.0).minWidth(40.0).build()));

                // Workaround
                Stage dummyPopup = new Stage();
                dummyPopup.initModality(Modality.NONE);
                // set as utility so no iconification occurs
                dummyPopup.initStyle(StageStyle.UTILITY);
                // set opacity so the window cannot be seen
                dummyPopup.setOpacity(0d);
                // not necessary, but this will move the dummy stage off the screen
                final Screen screen = Screen.getPrimary();
                final Rectangle2D bounds = screen.getVisualBounds();
                dummyPopup.setX(bounds.getMaxX());
                dummyPopup.setY(bounds.getMaxY());
                // create/add a transparent scene
                final Group root = new Group();
                dummyPopup.setScene(new Scene(root, 1d, 1d, Color.TRANSPARENT));
                // show the dummy stage
                dummyPopup.show();

                // size back to scene size
                dummyPopup.sizeToScene();   

                // if you centered it before hiding
                //dummyPopup.centerOnScreen();      
            }
        });

        jPanel1.add(myFX);
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();

        jPanel1.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));
        jPanel1.setLayout(new java.awt.GridBagLayout());

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(54, 54, 54)
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 193, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(153, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(33, 33, 33)
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 193, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(74, Short.MAX_VALUE))
        );
    }// </editor-fold>                        
    // Variables declaration - do not modify                     
    private javax.swing.JPanel jPanel1;
    // End of variables declaration                   

    @Override
    public void componentOpened() {
        // TODO add custom code on component opening
    }

    @Override
    public void componentClosed() {
        // TODO add custom code on component closing
    }

    void writeProperties(java.util.Properties p) {
        // better to version settings since initial version as advocated at
        // http://wiki.apidesign.org/wiki/PropertyFiles
        p.setProperty("version", "1.0");
        // TODO store your settings
    }

    void readProperties(java.util.Properties p) {
        String version = p.getProperty("version");
        // TODO read your settings according to their version
    }
}

Ответ 3

Я столкнулся с одной и той же проблемой: У меня есть проблема не только с верхним компонентом... но и с моими модальными диалоговыми окнами. На некоторых ОС они, похоже, работают сначала (Windows), а другие запускаются как черные, пустые поля (linux). В некоторых диалоговых окнах (под Windows) при работе с диалогом (обычно после нажатия кнопок) диалоговое окно также становится пустым (обычно после шестого щелчка или так?). При перемещении мыши (без щелчка) над кнопками они снова появляются (но не остальные)

У меня также есть эффект (по крайней мере, под окнами), что минимизация и восстановление главного окна приводит к пустому окну.

Но: (!!!!!) Я узнал, что изменение размера главного окна или диалогов с помощью мыши возвращает содержимое!!!! Поэтому я предполагаю, что ваше предположение с досрочной смертью не может быть причиной (почему это должно произойти тогда).

В диалоговом окне я нашел решение: Сделайте сцену окна членом класса, чтобы вы могли получить к ней доступ позже в следующем методе repaint():

  /**
   * force repaint by re-setting the scene
   * This solves a repainting bug in JavaFx 1.8.05
   */
  private void repaint(){
    setScene(null);
    Platform.runLater(new Runnable() {
      @Override
      public void run() {
        setScene(scene);
      }
    });
  }

В диалоговом окне я использую repaint() непосредственно перед showModal() и в конце каждого события кнопки → отлично работает:-) Но я не нашел событие, где я могу вызвать repaint() после минимизации для главного окна. Теперь новое мистическое, но решение: Если я помещаю repaint() непосредственно перед show() для MainWindow, все работает отлично. Я понятия не имею, почему...

Но я определенно все думаю об ошибке в JavaFX, которая, надеюсь, будет исправлена ​​в следующей версии.

С наилучшими пожеланиями

Инго