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

У меня есть проблема, которая, возможно, вызвана непониманием некоторых принципов платформы Netbeans (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 исчезает?

Редактировать:

Теперь я включаю исходный код всего 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.


person dajood    schedule 16.05.2012    source источник
comment
Я попытался воспроизвести вашу проблему, используя netbeans 7.1 и JavaFX 2.1. Все компоненты снова появляются, как и ожидалось. Опубликуйте SSCCE, пожалуйста.   -  person pmoule    schedule 19.05.2012
comment
Спасибо за попытку. См. мой проект здесь   -  person dajood    schedule 19.05.2012
comment
Извините, пожалуйста, без ссылок на скачивание проекта. Чтобы привлечь других и сделать помощь более привлекательной, опубликуйте SSCCE.   -  person pmoule    schedule 19.05.2012
comment
Я надеюсь, что теперь прикрепленный источник + краткое объяснение - это то, что вы имеете в виду :)   -  person dajood    schedule 20.05.2012


Ответы (3)


Попробуй это:

Platform.setImplicitExit(false);
person Cedric    schedule 12.01.2013

Мы испытываем ту же проблему. Основываясь на следующих потоках, мы предполагаем, что когда панель больше не видна, платформа JavaFX автоматически завершает работу, поскольку все элементы графического интерфейса 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
    }
}
person Escay    schedule 25.05.2012
comment
У меня больше не было надежды. Большое спасибо, это действительно большая помощь для меня. - person dajood; 25.05.2012
comment
Реальное исправление должно быть в javaFX 2.2. См. javafx-jira.kenai.com/browse/RT. -15011 Следует использовать Platform.setImplicitExit(boolean implicitExit). - person Escay; 29.05.2012

Я застрял в той же проблеме: у меня проблема не только с верхним компонентом... но и с моими модальными диалоговыми окнами. В некоторых ОС они сначала работают (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, которая, надеюсь, будет исправлена ​​в следующей версии.

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

Инго

person Ingo    schedule 18.05.2014