instalar - Cambiar entre paneles en JavaFX
javafx tutorial netbeans (3)
Así es como lo hago: (en este ejemplo, he creado dos documentos FXML con sus controladores correspondientes. Se llaman FXMLLogin.fxml y Home.fxml, respectivamente).
Entonces, para pasar de FXMLLogin a Inicio,
En este ejemplo, creé un método dentro de FXMLLoginController que responde al botón "iniciar sesión" en ese formulario que se está presionando:
@FXML
private void login(javafx.event.ActionEvent event) throws IOException
{
if(pwf1.getText().equals("alphabetathetagamma"))
{
Parent blah = FXMLLoader.load(getClass().getResource("Home.fxml"));
Scene scene = new Scene(blah);
Stage appStage = (Stage) ((Node) event.getSource()).getScene().getWindow();
appStage.setScene(scene);
appStage.show();
}
else
{
label1.setText("Password is incorrect. Please Try Again");
}
}
Tenga en cuenta que @FXML es extremadamente importante.
Si entendí tu pregunta correctamente, entonces esto debería ser el truco.
Cambiar entre paneles no es del todo obvio, y no se describe claramente en ningún tutorial en la web que he encontrado. Tuve que buscar mucho en Google antes de darme cuenta por primera vez. Afortunadamente, en realidad es bastante simple una vez que lo dominas.
Espero no haber entendido mal tu pregunta? Avísame si esto es lo que necesitas :)
Estoy tratando de hacer un programa Java en JavaFX usando FXML. Sin embargo, tengo problemas con la administración del diseño. Quiero cambiar entre paneles, tal como estoy acostumbrado con CardLayout en swing, pero parece que no puedo conseguirlo.
Busqué en Google y no encontré ninguna respuesta.
¿Hay algún CardLayout equivalente en JavaFX? y si es así, ¿puedes darme un ejemplo? ¡Eso ayudaría mucho a mi noche!
Aquí está mi código FXML
<AnchorPane id="anchorPane" prefHeight="324.0" prefWidth="530.0" xmlns:fx="http://javafx.com/fxml" fx:controller="javafxapplication2.SampleController">
<children>
<Pane fx:id="mainScreen" layoutX="6.0" prefHeight="324.0" prefWidth="518.0">
<children>
<Button layoutX="254.0" layoutY="37.0" mnemonicParsing="false" text="Button" />
</children>
</Pane>
<Pane fx:id="loginScreen" prefHeight="324.0" prefWidth="530.0">
<children>
<TextField id="password" fx:id="username" layoutX="142.0" layoutY="106.0" prefWidth="200.0" />
<TextField fx:id="password" layoutX="142.0" layoutY="140.0" prefWidth="200.0" />
<Label fx:id="label" layoutX="126.0" layoutY="120.0" minHeight="16.0" minWidth="69.0" />
<Button fx:id="button" layoutX="213.0" layoutY="196.0" onAction="#handleButtonAction" onKeyPressed="#handleButtonAction" text="Login" />
</children>
</Pane>
</children>
</AnchorPane>
JRebirth Application Framework proporciona un ''CardLayout'' personalizado utilizando su patrón dedicado wB-CSMvc.
La clase StackModel hará el trabajo (proporcionado por org.jrebirth.af:component artefact), puede encontrar 2 usos aquí y aquí .
Se puede llamar a cada modelo de ''tarjeta'' utilizando un identificador de enum | modelKey, y cada pila tiene un nombre único.
La primera muestra se usa para la aplicación de demostración JRebirth , es una aplicación bastante simple que permitirá visualizar otras aplicaciones de escaparate JRebirth cargadas dinámicamente como módulo JRebirth (desde un contenedor separado e independiente).
public final class JRebirthDemo extends DefaultApplication<StackPane> {
public static void main(final String... args) {
Application.launch(JRebirthDemo.class, args);
}
@Override
public Class<? extends Model> firstModelClass() {
return MainModel.class;
}
@Override
protected String applicationTitle() {
return "JRebirth Demo Application";
}
@Override
protected void customizeScene(final Scene scene) {
super.customizeScene(scene);
addCSS(scene, DemoStyles.DEFAULT);
addCSS(scene, WorkbenchStyles.DEFAULT);
}
@Override
protected void customizeStage(final Stage stage) {
// Center the stage
stage.centerOnScreen();
}
@Override
protected List<? extends ResourceItem<?, ?, ?>> getResourceToPreload() {
return Collections.emptyList();
}
}
Esta aplicación cargará su primer modelo (MainModel) y colocará su nodo raíz en el nodo raíz de la escena (StakPane, construido automáticamente).
MainModel enumerará todos los submódulos de la aplicación para agregar entradas de botones en su menú izquierdo y un StackModel que mostrará el contenido de cada módulo. StackModel se carga utilizando una anotación especial con su única clave String.
public final class MainModel extends DefaultModel<MainModel, MainView> {
private final List<ModuleModel> modules = new ArrayList<>();
@Link("DemoStack")
private StackModel stackModel;
@Override
protected void initModel() {
for (final ModuleModel mm : getModels(ModuleModel.class)) {
this.modules.add(mm);
}
}
@Override
protected void showView() {
view().node().setCenter(this.stackModel.node());
}
@Override
protected void hideView() {
// Nothing to do yet
}
List<ModuleModel> getModules() {
return this.modules;
}
}
MainView se encargará de crear el menú del módulo:
public final class MainView extends DefaultView<MainModel, BorderPane, MainController> {
private final List<Button> buttonList = new ArrayList<>();
public MainView(final MainModel model) throws CoreException {
super(model);
}
@Override
protected void initView() {
node().setPrefSize(800, 600);
node().setLeft(createMenu());
}
@Override
public void start() {
this.buttonList.stream().findFirst().ifPresent(button -> button.fire());
}
private Node createMenu() {
final VBox box = new VBox();
for (final ModuleModel mm : model().getModules()) {
final Node n = createModuleButton(mm);
VBox.setMargin(n, new Insets(4, 4, 4, 4));
box.getChildren().add(n);
}
return box;
}
private Node createModuleButton(final ModuleModel mm) {
final Button b = new Button(mm.moduleName());
b.getStyleClass().add("menuButton");
b.setPrefSize(100, 50);
b.setOnAction(controller()::onButtonFired);
b.setUserData(Key.create(mm.getClass()));
this.buttonList.add(b);
return b;
}
}
Y MainController cargará el contenido del Módulo cuando se active cualquier botón de menú:
public final class MainController extends DefaultController<MainModel, MainView> implements ActionAdapter {
public MainController(final MainView view) throws CoreException {
super(view);
}
public void onButtonFired(final ActionEvent event) {
final Button b = (Button) event.getSource();
final UniqueKey<? extends Model> data = (UniqueKey<? extends Model>) b.getUserData();
model().sendWave(StackWaves.SHOW_PAGE_MODEL,
WBuilder.waveData(StackWaves.PAGE_MODEL_KEY, data),
WBuilder.waveData(StackWaves.STACK_NAME, "DemoStack"));
}
}
El segundo ejemplo cargará el StackModel como un innerComponent y cada tarjeta se identificará mediante una entrada enum (almacenada en FXMLPage), veamos FXMLShowCaseModel:
final InnerComponent<StackModel> stack = CBuilder.innerComponent(StackModel.class, FXMLPage.class);
this.stackModel = findInnerComponent(stack);
La enumeración que vincula la entrada enum con el Modelo:
public enum FXMLPage implements PageEnum {
StandaloneFxml,
IncludedFxml,
ViewEmbeddedFxml,
HybridFxml;
@Override
public UniqueKey<? extends Model> getModelKey() {
UniqueKey<? extends Model> modelKey;
switch (this) {
default:
case ViewEmbeddedFxml:
modelKey = Key.create(EmbeddedModel.class);
break;
case StandaloneFxml:
modelKey = Key.create(StandaloneModel.class);
break;
case HybridFxml:
modelKey = Key.create(HybridModel.class, FXMLModel.KEYPART_FXML_PREFIX + "org.jrebirth.af.showcase.fxml.ui.hybrid.Hybrid");
break;
case IncludedFxml:
modelKey = Key.create(IncludedModel.class, new LoremIpsum());
break;
}
return modelKey;
}
}
Como se conoce la lista de tarjetas, el elemento de la barra de herramientas se crea estáticamente en FXMLShowCaseView y el manejo de eventos también se define de forma estática en FXMLShowCaseController utilizando otra técnica:
public final class FXMLShowCaseController extends DefaultController<FXMLShowCaseModel, FXMLShowCaseView> {
private static final Logger LOGGER = LoggerFactory.getLogger(FXMLShowCaseController.class);
public FXMLShowCaseController(final FXMLShowCaseView view) throws CoreException {
super(view);
}
@Override
protected void initEventAdapters() throws CoreException {
// WaveData<Class<? extends PageEnum>> stackName = Builders.waveData(StackWaves.STACK_PAGES, FXMLShowCaseModel.STACK_PAGES);
// Manage Ui Command Button
linkWave(view().getShowIncluded(), ActionEvent.ACTION, StackWaves.SHOW_PAGE_ENUM,
WBuilder.waveData(StackWaves.PAGE_ENUM, FXMLPage.IncludedFxml));
linkWave(view().getShowEmbedded(), ActionEvent.ACTION, StackWaves.SHOW_PAGE_ENUM,
WBuilder.waveData(StackWaves.PAGE_ENUM, FXMLPage.ViewEmbeddedFxml));
linkWave(view().getShowStandalone(), ActionEvent.ACTION, StackWaves.SHOW_PAGE_ENUM,
WBuilder.waveData(StackWaves.PAGE_ENUM, FXMLPage.StandaloneFxml));
linkWave(view().getShowHybrid(), ActionEvent.ACTION, StackWaves.SHOW_PAGE_ENUM,
WBuilder.waveData(StackWaves.PAGE_ENUM, FXMLPage.HybridFxml));
}
}
Avísame si tienes alguna pregunta
Transiciones no animadas
Si no necesita transiciones animadas entre sus paneles, puede:
- Reemplace toda la escena creando una nueva escena y establezca esa escena en su escenario O
- Reemplace solo un panel específico en un diseño principal, eliminando el panel anterior de su elemento primario y agregando su nuevo panel (manipulando la lista de elementos secundarios del padre) O
- Coloque todos sus paneles en un
StackPane
y mueva el panel que desea mostrar a la parte superior de la lista secundaria de la pila .
Transiciones animadas
Si desea realizar transiciones animadas entre sus paneles, consulte la serie de dos partes de Angela Caicedo sobre la administración de pantallas múltiples en JavaFX:
La solución de Angela es usar un StackPane con una clase de ScreenController personalizada separada para administrar Transiciones o animaciones entre paneles en la pila.
Frameworks
Los marcos como JFXFlow y WebFX también pueden proporcionar una interfaz de estilo de navegador para su aplicación, lo que permite a los usuarios cambiar de una pantalla a otra usando los botones para avanzar y retroceder y una lista de historial.
Actualización 2017
Creo que el desarrollo en los dos marcos de referencia anteriores ahora está desaparecido. Otros marcos que están en desarrollo son:
Y muchos otros (no proporcionaré una lista completa aquí).
Relacionado