Javafx: переход к страницам

Я пытаюсь использовать приложение JavaFX2.0 в отношении образца Ensemble. Как и Ensemble, я также хочу показывать разные страницы, но на основе кликов, сделанных на центральной странице. У меня нет дерева, панели инструментов и т. д. Просто хочу, чтобы набор страниц отображался на основе определенного выбора. Пример: моя главная страница может иметь 6 кнопок, при нажатии кнопки 1 я хочу, чтобы страница 1, страница 2 щелкала кнопку 2 и так далее. На странице 1 у меня снова будет несколько кнопок и кнопка «Возврат», чтобы вернуться на предыдущую страницу. В обычной Java мы могли бы легко добиться этого с помощью CardLayout. Добавить все страницы в карты и показать нужную страницу.

Глядя на проект Enemble, я увидел, что все образцы страниц, такие как AnchorLayout, ColorButton и т. д., расширяют Sample. И в классе Pages есть члены AllPagesPage, SamplesPage, DocPage и т. д., и все они отображаются в TreeView слева.

Я добавил Sample, который расширяет панель, создайте еще один класс DataPane, который расширяет Sample. Третий класс, который имеет ссылку на все панели:

public class AllPagesPage {
HashMap<String, Sample> pages = null; 
private static String DATAPANE = "DATAPANE";

public AllPagesPage() {
    pages = new HashMap<String, Sample>();
    addPages();
}

private void addPages() {
    pages.put(DATAPANE, (Sample)new DataPane());
}

public Sample getPage(String page) {
    if (pages.containsKey(page))
        return (Sample) pages.get(page);

    return null;

}

}

Чтобы сохранить ссылку на основе имени, я использовал HashMap. Теперь в моем классе приложений, как мне настроить страницу как DataPane?

    @Override
public void start(Stage primaryStage) {
    primaryStage.setTitle("Hello World");
    Group root = new Group();
    Scene scene = new Scene(root, 300, 250);
    /*
    Button btn = new Button();
    btn.setLayoutX(100);
    btn.setLayoutY(80);
    btn.setText("Hello World");
    btn.setOnAction(new EventHandler<ActionEvent>() {

        public void handle(ActionEvent event) {
            System.out.println("Hello World");
        }
    });
    root.getChildren().add(btn);
    * 
    */

    primaryStage.setScene(scene);
    primaryStage.show();
}

// Should be called as gotoPage(AllPagesPage.DATAPANE), 
// on this command everythign else should be removed and contents of DataPane should come up.      
public void goToPage(String page) {

}

DataPane просто содержит код из AnchorPaneSample в конструкторе. Ничего лишнего или никаких других функций - ТОЛЬКО конструктор.

Как мне получить сцену и установить страницы при вызове метода gotoPage(String page)???


person Tvd    schedule 03.12.2011    source источник


Ответы (1)


Просто создайте область, в которой вы хотите видеть свои панели, и измените их:

public class Main extends Application {

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

    private Pane pagesArea;
    private AllPagesPage pages = new AllPagesPage();

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Hello World");
        VBox root = new VBox();
        Scene scene = new Scene(root, 300, 250);

        Button btn = new Button();
        btn.setText("Open DataPane");
        btn.setOnAction(new EventHandler<ActionEvent>() {

            public void handle(ActionEvent event) {
                goToPage(AllPagesPage.DATAPANE);
            }
        });
        root.getChildren().addAll(btn, pagesArea = new StackPane());
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public void goToPage(String page) {
        Pane pane = pages.getPage(page);
        if (pane != null) {
            pagesArea.getChildren().clear();
            pagesArea.getChildren().add(pane);
        }
    }
}

Вы можете обновить свой класс AllPagesPage:

  • проверка в getPage() избыточна, HashMap сделает это за вас
  • вместо статических строк вы можете использовать enum для большей гибкости (это позволит итерацию, простое сравнение, более простой рефакторинг и другое)
person Sergey Grinev    schedule 03.12.2011
comment
Спасибо за начало. Если HashMap не подходит, то должен ли я использовать ArrayList или что с перечислением? ТАКЖЕ, в DatePane я хочу установить другую страницу, скажем, MainPane. Я должен вызвать goToPage для этого из события DataPane btn. Так что либо нужно сделать gotoPane статическим (что неправильно), либо передать ссылку obj приложения на все другие страницы. Как вы думаете, что должно получиться? - person Tvd; 03.12.2011
comment
Хэшмап в порядке. Я имел в виду, что для этого вам не нужен дополнительный класс. Просто добавьте карту в основной класс. Что касается вашего второго вопроса: вы можете передать ссылку на основной класс приложениям, это правильный подход. Или вы можете сделать класс Main одноэлементным и со статическим геттером, и ваш вызов будет выглядеть как Main.getInstance().toToPage(page.MainPage); - person Sergey Grinev; 03.12.2011
comment
Спасибо Сергей. Если реализуете enum, то почему бы не использовать EnumMap вместо HashMap. Я попробовал этот код, но получил ошибку в строке инициализации EnumMap: public enum Pages {DATAPANE(DATAPANE); приватное строковое значение; частные страницы (строка s) { значение = s; } }; EnumMap pagesMap‹Pages, Sample› = new EnumMap‹Pages, Sample›(Pages.class); Вместо Sample я также пытался использовать String, но также получал ошибки только в этой единственной строке. Пробовал удалить Paes.class, тоже не помогло. Какую глупую ошибку я здесь совершаю, не могу найти. Можете ли вы указать. - person Tvd; 06.12.2011
comment
Добро пожаловать. Вы правы в использовании EnumMap. В вашей строке инициализации у вас неправильное расположение общих параметров. Вот правильный вариант: EnumMap‹Pages, Sample› pagesMap = new EnumMap‹Pages, Sample›(Pages.class); - person Sergey Grinev; 06.12.2011