2013-12-15 9 views
6

Próbuję zmienić scenę w etapie javafx na podstawie kliknięcia menuItem. Oto moja sample.fxml:Nie można uzyskać sceny z MenuItem w JavaFX

<?xml version="1.0" encoding="UTF-8"?> 

<?import java.lang.*?> 
<?import java.net.*?> 
<?import javafx.geometry.Insets?> 
<?import javafx.scene.control.*?> 
<?import javafx.scene.control.Button?> 
<?import javafx.scene.control.Label?> 
<?import javafx.scene.image.*?> 
<?import javafx.scene.layout.*?> 
<?import javafx.scene.layout.GridPane?> 

<AnchorPane prefHeight="-1.0" prefWidth="560.0" styleClass="background" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="sample.Controller"> 
    <children> 
    <MenuBar layoutY="0.0" maxWidth="1.7976931348623157E308" prefWidth="300.0" useSystemMenuBar="false" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="2.0"> 
     <menus> 
     <Menu id="manageAccountsMenu" mnemonicParsing="false" onAction="#onManageAccountsMenuActionPerformed" text="Accounts" fx:id="manageAccountsMenu"> 
      <items> 
      <MenuItem mnemonicParsing="false" onAction="#onTweetsMenuActionPerformed" text="Manage" fx:id="manageAccountsSubmenuItem" /> 
      </items> 
     </Menu> 
     <Menu mnemonicParsing="false" onAction="#onTweetsMenuActionPerformed" text="Tweets" fx:id="tweetsMenuItem" /> 
     <Menu mnemonicParsing="false" text="Retweets" /> 
     </menus> 
    </MenuBar> 
    <VBox id="VBox" alignment="CENTER" layoutY="24.0" spacing="5.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"> 
     <children> 
     <ScrollPane id="ScrollPane" fitToHeight="true" fitToWidth="true" prefViewportHeight="400.0" prefViewportWidth="300.0"> 
      <content> 
      <TableView prefHeight="-1.0" prefWidth="-1.0" tableMenuButtonVisible="true"> 
       <columns> 
       <TableColumn editable="false" prefWidth="75.0" text="SNO" /> 
       <TableColumn prefWidth="200.0" text="Account" /> 
       <TableColumn prefWidth="200.0" text="Status" /> 
       <TableColumn prefWidth="75.0" text="Actions" /> 
       </columns> 
      </TableView> 
      </content> 
     </ScrollPane> 
     <Button mnemonicParsing="false" text="Add Account" textAlignment="CENTER"> 
      <graphic> 
      <ImageView fitHeight="150.0" fitWidth="200.0" mouseTransparent="true" pickOnBounds="true" preserveRatio="true"> 
       <image> 
       <Image url="@addAccount.png" /> 
       </image> 
      </ImageView> 
      </graphic> 
     </Button> 
     </children> 
    </VBox> 
    </children> 
    <stylesheets> 
    <URL value="@darkTheme.css" /> 
    </stylesheets> 
</AnchorPane> 

Oto moja Controller.java:

package sample; 

import javafx.event.ActionEvent; 
import javafx.fxml.FXML; 
import javafx.fxml.Initializable; 
import javafx.scene.Node; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.scene.control.MenuItem; 
import javafx.stage.Stage; 

import java.net.URL; 
import java.util.ResourceBundle; 

public class Controller implements Initializable { 
    @FXML 
    protected void onManageAccountsMenuActionPerformed(ActionEvent event) { 
     System.out.println("Manage Accbtnclick"); 
//  Node node=(Node) event.getSource(); 
//  Stage stage=(Stage) node.getScene().getWindow(); 
// 
//  Scene scene = new Scene(root); 
//  stage.setScene(scene); 
//  stage.show(); 
    } 
    @FXML 
    protected void onTweetsMenuActionPerformed(ActionEvent event) { 
     System.out.println("Manage Accbtnclick"); 
    Node node= (Node)event.getSource(); 
    Stage stage=(Stage) node.getScene().getWindow(); 
    Scene scene = Main.screens.get("tweet"); 
    stage.setScene(scene); 
    stage.show(); 
    } 

    @Override 
    public void initialize(URL url, ResourceBundle resourceBundle) { 
     //To change body of implemented methods use File | Settings | File Templates. 
    } 
} 

Oto moja Main.java:

package sample; 

import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.geometry.Pos; 
import javafx.scene.Group; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.scene.control.Label; 
import javafx.scene.control.ProgressBar; 
import javafx.scene.control.ProgressIndicator; 
import javafx.scene.layout.HBox; 
import javafx.scene.layout.VBox; 
import javafx.stage.Stage; 

import java.io.IOException; 
import java.util.HashMap; 

public class Main extends Application { 

    public static HashMap<String,Scene> screens=new HashMap<String,Scene>(); 

    @Override 
    public void start(Stage stage) { 
     try { 
      Parent accountScreen= FXMLLoader.load(getClass().getResource("sample.fxml")); 
      Parent tweetScreen=FXMLLoader.load(getClass().getResource("tweetform.fxml")); 
      //Parent retweetScreen=FXMLLoader.load(getClass().getResource("retweetform.fxml")); 
      screens.put("account",new Scene(accountScreen)); 
      screens.put("tweet",new Scene(tweetScreen)); 
      //screens.put("retweet",new Scene(retweetScreen)); 
      stage.setTitle("Manage Accounts"); 
      stage.setScene(screens.get("account")); 
      stage.show(); 
     } catch (IOException e) { 
      e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. 
     } 

    } 
    public static void main(String[] args) { 
     launch(args); 
    } 
} 

Kiedy klikam na MENUITEM Zarządzaj pod Menu Konta, otrzymuję następujący wyjątek:

"C:\Program Files\Java\jdk1.7.0_17\bin\java" -Didea.launcher.port=7541 "-Didea.launcher.bin.path=C:\Program Files (x86)\JetBrains\IntelliJ IDEA 12.1.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_17\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\rt.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\ext\zipfs.jar;C:\Users\rahulserver\IdeaProjects\DrawingText\out\production\DrawingText;C:\Program Files (x86)\JetBrains\IntelliJ IDEA 12.1.4\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain sample.Main 
Manage Accbtnclick 
Manage Accbtnclick 
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException 
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1440) 
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:69) 
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217) 
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92) 
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53) 
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:28) 
    at javafx.event.Event.fireEvent(Event.java:171) 
    at javafx.scene.control.MenuItem.fire(MenuItem.java:456) 
    at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1188) 
    at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer$6.handle(ContextMenuContent.java:1139) 
    at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer$6.handle(ContextMenuContent.java:1137) 
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:69) 
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217) 
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170) 
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92) 
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53) 
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:33) 
    at javafx.event.Event.fireEvent(Event.java:171) 
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3328) 
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3168) 
    at javafx.scene.Scene$MouseHandler.access$1900(Scene.java:3123) 
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1563) 
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2265) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:250) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:173) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:292) 
    at com.sun.glass.ui.View.handleMouseEvent(View.java:528) 
    at com.sun.glass.ui.View.notifyMouse(View.java:922) 
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) 
    at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29) 
    at com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:73) 
    at java.lang.Thread.run(Thread.java:722) 
Caused by: java.lang.reflect.InvocationTargetException 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:601) 
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:55) 
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:601) 
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:269) 
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1435) 
    ... 40 more 
Caused by: java.lang.ClassCastException: javafx.scene.control.MenuItem cannot be cast to javafx.scene.Node 
    at sample.Controller.onTweetsMenuActionPerformed(Controller.java:29) 
    ... 50 more 

Jak mogę uzyskać etap/scenę zawierającą z menu Element kliknął obsługę zdarzeń?

EDIT Linia

Node node= (Node)event.getSource(); 

w controller.java jest linia numer 29, który powoduje problemy.

+0

* 'java.lang.NullPointerException na sample.Controller.onTweetsMenuActionPerformed (Controller.java:30)' * => gdzie znajduje się wiersz 30 klasy Controller.java? – assylias

+0

@assylias Stage stage = (Stage) node.getScene(). GetWindow(); – rahulserver

+0

Domyślam się, że 'węzeł' nie jest widoczny, dlatego nie ma okna. Możesz spróbować debugować kod, aby sprawdzić zmienne w tym punkcie. – assylias

Odpowiedz

12

Twój błąd jest wyświetlany w przedostatniej linii śladu stosu:

Caused by: java.lang.ClassCastException: javafx.scene.control.MenuItem cannot be cast to javafx.scene.Node 
    at sample.Controller.onTweetsMenuActionPerformed(Controller.java:29) 

Ten błąd odnosi się do następnej linii od kontrolera:

Node node= (Node)event.getSource(); 

Patrząc na JavaFX Dokumenty API, ani MenuItem, ani Menu to podklasy Węzła. http://docs.oracle.com/javafx/2/api/javafx/scene/control/MenuItem.html

Proponuję pobrać źródło jako obiekt, a następnie sprawdzić jego typ przed kontynuowaniem. Ponadto napotkałem problemy przy użyciu metody getSource(); metoda getTarget() działała lepiej dla mnie. Tak czy inaczej, nadal potrzebujesz sposobu na wejście na scenę.

Aby to zrobić, możesz użyć tagu fx:id w FXML zamiast tagu id. Umożliwi to wstrzyknięcie elementów FXML bezpośrednio do kontrolera. Na przykład można pobrać Stage z MenuBar (który jest podklasą Node) poprzez wstrzyknięcie elementu MenuBar do kontrolera.

W FXML:

<MenuBar fx:id="myMenuBar" layoutY="0.0" maxWidth="1.7976931348623157E308" prefWidth="300.0" useSystemMenuBar="false" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="2.0"> 

W regulatorze:

public class Controller implements Initializable { 
    @FXML MenuBar myMenuBar; 
    ... 
    @FXML 
    protected void onTweetsMenuActionPerformed(ActionEvent event) { 
     System.out.println("Manage Accbtnclick"); 
     Stage stage = (Stage) myMenuBar.getScene().getWindow(); 
     Scene scene = Main.screens.get("tweet"); 
     stage.setScene(scene); 
     stage.show(); 
    } 
    ... 
} 

Być może trzeba zrobić trochę szczypanie tutaj, ale mam nadzieję, że to pomaga.

+0

Brzmi świetnie. +10 dla u. Ale wuld potwierdził to jako odpowiedź po spróbowaniu. – rahulserver

-1

Oto sposób na uzyskanie Scene i Window w oparciu o element menu, który jest klikany, bez wstawiania elementu FXML lub bez odwoływania się do niego, jeśli utworzono go z FXML. Innymi słowy, używając celu Event.

W moim problemem miałem MenuButton z rozwijanego menu (a ContextMenu jak się dowiedziałem, czego nie wiem, jak ja tworzę menu w FXML) zawierający MenuItems i chciałem otworzyć FileChooser, który potrzebuje Window jako argument, gdy kliknięto "Zapisz" MenuItem.

Zwykle poszedłbym w dół, aby zdobyć cel wydarzenia, następnie Rodzica, następnie następnego Rodzica itd., A na koniec Scenę, a następnie Okno. Jak Menu i MenuItem nie są Node s, a zatem nie mają Parent s W tym przypadku jednak zrobiłem następujące:

FileChooser fileChooser = new FileChooser(); 

MenuItem menuItem = (MenuItem)event.getTarget(); 
ContextMenu cm = menuItem.getParentPopup(); 
Scene scene = cm.getScene(); 
Window window = scene.getWindow(); 

fileChooser.showSaveDialog(window); 

Albo, przekształcając większość do argumentu jednym wierszu:

FileChooser fileChooser = new FileChooser(); 

fileChooser.showSaveDialog(((MenuItem)event.getTarget()).getParentPopup().getScene().getWindow()); 

Wystarczy dostosuj to w razie potrzeby na podstawie własnego wykresu sceny (tj. ilu rodziców musisz przejść w przypadku podmenu itp.) i co chcesz zrobić po uzyskaniu Window, ale gdy dojdziesz do ContextMenu (lista podręczna o MenuItems), możesz uzyskać Scene, a następnie uzyskać Window.




Tak na marginesie, tutaj jest FXML I wykorzystywane do tworzenia moich MenuButton, a więc dlaczego nie zdawał sobie sprawy, miałem dostać ContextMenu drodze zaproszenia do getParentPopup() bez jakiegoś procesu . i błędów:

<MenuButton fx:id="menu" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" prefHeight="34.0" prefWidth="35.0" style="-fx-background-color: #6600ff; -fx-border-width: 0; -fx-mark-color: white; -fx-padding: 5;" textAlignment="CENTER" textFill="WHITE" underline="true"> 
    <items> 
     <MenuItem fx:id="newSearch" mnemonicParsing="false" text="New Search" onAction="#clearSearch" /> 
     <SeparatorMenuItem /> 
     <MenuItem fx:id="saveSearch" mnemonicParsing="false" text="Save Search" onAction="#saveSearch" /> 
     <MenuItem fx:id="loadSearch" mnemonicParsing="false" text="Load Search" /> 
     <SeparatorMenuItem /> 
     <MenuItem fx:id="saveResults" mnemonicParsing="false" text="Save Results" /> 
     <MenuItem fx:id="loadResults" mnemonicParsing="false" text="Load Results" /> 
     <SeparatorMenuItem /> 
     <MenuItem fx:id="exportResults" mnemonicParsing="false" text="Export Results" /> 
    </items> 
    <font> 
     <Font name="Arial" size="12.0" /> 
    </font> 
</MenuButton> 
0

etapu etap = (stopień) ((Node) myMenuBar) .getScene() getWindow();

+2

proszę dodać wyjaśnienie do swojej odpowiedzi –

Powiązane problemy