从 Swing 转换为 JavaFX?

Posted

技术标签:

【中文标题】从 Swing 转换为 JavaFX?【英文标题】:Converting from Swing to JavaFX? (Migration Guide) 【发布时间】:2016-06-24 17:23:01 【问题描述】:

将 Swing 项目转换为 JavaFx 项目时,JavaFx 中的哪些类与 Swing 类匹配?

1-1 对决是最好的。

我不是在寻找与 Swing 的集成,而是彻底改造。

【问题讨论】:

【参考方案1】:

以下是一些基本类:

Swing -> JavaFx JFrame -> Application & Stage(如果您在主类中扩展 JFrame,Application.launch() 可用于启动扩展 Application)。 Stage 是明确的 JavaFx 并且是创建 Window 所必需的。您将需要使用它的实例,而不是 JFrame 的实例。 JPanel -> Scene & Pane(场景与 JPanel 匹配,但您的类应该扩展 Pane。然后从窗格构建场景。窗格是 JavaFX 中的布局) JButton -> 按钮 JLabel -> 标签 在许多情况下,删除 J 即可解决问题... JOptionPane -> 对话框(但并非总是如此) ActionListener -> EventHandler)(需要在 JavaFx 中为您需要的每个操作创建一个新方法/类,不像 Swing 的一个方法可以完成所有工作)

更新现在使用 Java 8+ 应该更容易使用事件处理程序,并增加了 JavaFX 现在支持的函数式接口功能。

示例 Swing(我制作的游戏的基本界面)

public class Interface extends JFrame 

public static void main(String[] args) 
    new Interface();


private CardLayout layout;
private JPanel manager;
private Introduction start;
private MainDisplay display;

public Interface() 
    super("Demo");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setMinimumSize(new Dimension(750, 500));
    this.setPreferredSize(new Dimension(750, 500));
    this.setMaximumSize(new Dimension(750, 500));

    setUp();

    this.pack();
    this.setVisible(true);


private void setUp() 
    layout = new CardLayout();
    manager = new JPanel(layout);
    this.add(manager);

    start = new Introduction();
    manager.add(start, INTRODUCTION);

    display = new MainDisplay();
    manager.add(display);

    layout.show(manager);


public class Introduction extends JPanel implements ActionListener 

    private static final int LOAD = 0;
    private static final int SAVE = 1;
    private JButton start;
    private JButton toGame;
    private JButton load;
    private JButton save;
    private JButton exit;

    public Introduction() 
        setUp();
    

    private void setUp() 
        SpringLayout manager = new SpringLayout();
        this.setLayout(manager);

        JLabel title = new JLabel("Demo");
        title.setFont(new Font(Font.SERIF, Font.BOLD, 60));
        manager.putConstraint(SpringLayout.HORIZONTAL_CENTER, title, 0,
                SpringLayout.HORIZONTAL_CENTER, this);
        manager.putConstraint(SpringLayout.NORTH, title, 10, SpringLayout.NORTH,
                this);
        this.add(title);

        start = new JButton("New Game");
        start.setFont(new Font(Font.SERIF, Font.PLAIN, 16));
        start.addActionListener(this);
        manager.putConstraint(SpringLayout.HORIZONTAL_CENTER, start, -250,
                SpringLayout.HORIZONTAL_CENTER, this);
        manager.putConstraint(SpringLayout.NORTH, start, 50, SpringLayout.SOUTH,
                title);
        this.add(start);

        toGame = new JButton("Continue");
        toGame.setFont(new Font(Font.SERIF, Font.PLAIN, 16));
        toGame.addActionListener(this);
        toGame.setEnabled(false);
        manager.putConstraint(SpringLayout.HORIZONTAL_CENTER, toGame, -250,
                SpringLayout.HORIZONTAL_CENTER, this);
        manager.putConstraint(SpringLayout.NORTH, toGame, 10, SpringLayout.SOUTH,
                start);
        this.add(toGame);

        load = new JButton("Load Game");
        load.setFont(new Font(Font.SERIF, Font.PLAIN, 16));
        load.addActionListener(this);
        manager.putConstraint(SpringLayout.HORIZONTAL_CENTER, load, -250,
                SpringLayout.HORIZONTAL_CENTER, this);
        manager.putConstraint(SpringLayout.NORTH, load, 10, SpringLayout.SOUTH,
                toGame);
        this.add(load);

        save = new JButton("Save Game");
        save.setFont(new Font(Font.SERIF, Font.PLAIN, 16));
        save.addActionListener(this);
        save.setEnabled(false);
        manager.putConstraint(SpringLayout.HORIZONTAL_CENTER, save, -250,
                SpringLayout.HORIZONTAL_CENTER, this);
        manager.putConstraint(SpringLayout.NORTH, save, 10, SpringLayout.SOUTH, load);
        this.add(save);

        exit = new JButton("Exit Game");
        exit.setFont(new Font(Font.SERIF, Font.PLAIN, 16));
        exit.setToolTipText("Saves the current game, and exits the program.");
        exit.addActionListener(this);
        manager.putConstraint(SpringLayout.HORIZONTAL_CENTER, exit, -250,
                SpringLayout.HORIZONTAL_CENTER, this);
        manager.putConstraint(SpringLayout.NORTH, exit, 10, SpringLayout.SOUTH, save);
        this.add(exit);
    

    private void perform(int option) 
        JFileChooser chooser = new JFileChooser();
        chooser.setFileFilter(new TextFileFilter());
        if (option == LOAD) 
            int choice = chooser.showDialog(this, "Load Game");
            if (choice == JFileChooser.APPROVE_OPTION)
                chooser.getSelectedFile();
         else if (option == SAVE) 
            int choice = chooser.showDialog(this, "Save Game");
            if (choice == JFileChooser.APPROVE_OPTION)
                chooser.getSelectedFile();
        
    

    @Override
    public void actionPerformed(ActionEvent e) 
        if (display.isRunning()) 
            if (e.getSource() == start || e.getSource() == load) 
                String verify = "A game is currently running.  Are you sure you want to start a new game?"
                        + "\r\nAny previous game data will be deleted.";
                int choice = JOptionPane.showConfirmDialog(this, verify,
                        "New Game - Warning", JOptionPane.YES_NO_OPTION,
                        JOptionPane.WARNING_MESSAGE);

                if (choice == JOptionPane.NO_OPTION)
                    return;
            
        

        if (e.getSource() == start) 
            display.start();
            layout.show(manager, MAIN_DISPLAY);
            toGame.setEnabled(true);
            save.setEnabled(true);
         else if (e.getSource() == toGame)
            layout.show(manager, MAIN_DISPLAY);
        else if (e.getSource() == load)
            perform(LOAD);
        else if (e.getSource() == save)
            perform(SAVE);
        else if (e.getSource() == exit) 
            perform(SAVE);
            Interface.this.setVisible(false);
            Interface.this.dispose();
        
    



public class MainDisplay extends JPanel implements ActionListener 

    private static final long serialVersionUID = 1L;
    private boolean running;
    private JButton overview;
    private JButton map;
    private JButton ranking;
    private JButton reports;
    private JButton home;

    public MainDisplay() 
        running = false;
        setUp();
    

    public boolean isRunning() 
        return running;
    

    private void setUp() 
        SpringLayout manager = new SpringLayout();
        this.setLayout(manager);

        ranking = new JButton("Ranking");
        ranking.setFont(new Font(Font.SERIF, Font.PLAIN, 10));
        ranking.addActionListener(this);
        manager.putConstraint(SpringLayout.HORIZONTAL_CENTER, ranking, 0,
                SpringLayout.HORIZONTAL_CENTER, this);
        manager.putConstraint(SpringLayout.NORTH, ranking, 10, SpringLayout.NORTH,
                this);
        this.add(ranking);

        map = new JButton("Map");
        map.setFont(new Font(Font.SERIF, Font.PLAIN, 10));
        map.addActionListener(this);
        manager.putConstraint(SpringLayout.EAST, map, -10, SpringLayout.WEST,
                ranking);
        manager.putConstraint(SpringLayout.NORTH, map, 10, SpringLayout.NORTH, this);
        this.add(map);

        overview = new JButton("Overview");
        overview.setFont(new Font(Font.SERIF, Font.PLAIN, 10));
        overview.addActionListener(this);
        manager.putConstraint(SpringLayout.EAST, overview, -10, SpringLayout.WEST,
                map);
        manager.putConstraint(SpringLayout.NORTH, overview, 10, SpringLayout.NORTH,
                this);
        this.add(overview);

        reports = new JButton("Reports");
        reports.setFont(new Font(Font.SERIF, Font.PLAIN, 10));
        reports.addActionListener(this);
        manager.putConstraint(SpringLayout.WEST, reports, 10, SpringLayout.EAST,
                ranking);
        manager.putConstraint(SpringLayout.NORTH, reports, 10, SpringLayout.NORTH,
                this);
        this.add(reports);

        home = new JButton("Home");
        home.setFont(new Font(Font.SERIF, Font.PLAIN, 10));
        home.addActionListener(this);
        manager.putConstraint(SpringLayout.WEST, home, 10, SpringLayout.EAST,
                reports);
        manager.putConstraint(SpringLayout.NORTH, home, 10, SpringLayout.NORTH, this);
        this.add(home);
    

    public void start() 
        running = true;
    

    public void actionPerformed(ActionEvent e) 
        if (e.getSource() == home) 
            layout.show(manager, INTRODUCTION);
        
    



public static final class TextFileFilter extends FileFilter 

    private static final String FILE_EXTENSION = "tra";

    @Override
    public boolean accept(File f) 
        if (f.isDirectory())
            return true;
        if (f.getName().toLowerCase().endsWith(FILE_EXTENSION))
            return true;
        return false;
    

    @Override
    public String getDescription() 
        return "Demo";
    



JavaFx 示例(JavaFx 中的示例几乎相同)

public class Interface extends Application 

public static void main(String[] args) 
    Application.launch(Interface.class, args);


private static final int WIDTH = 750;
private static final int HEIGHT = 500;
private static Stage stage;
private static Introduction start;
private static MainDisplay display;
private static Scene startScene;
private static Scene displayScene;

public Interface() 
    start = new Introduction();
    display = new MainDisplay();
    startScene = new Scene(start, WIDTH, HEIGHT);
    displayScene = new Scene(display, WIDTH, HEIGHT);


@Override
public void start(Stage primaryStage) throws Exception 
    Interface.stage = primaryStage;

    stage.setTitle(Constants.TITLE);
    stage.setResizable(false);
    stage.setWidth(WIDTH);
    stage.setHeight(HEIGHT);

    stage.setScene(startScene);
    stage.show();


public class Introduction extends BorderPane 

    private static final int LOAD = 0;
    private static final int SAVE = 1;
    private Button toGame;
    private Button save;
    public Introduction() 
        setUp();
    

    private void setUp() 

        this.setBackground(
                new Background(new BackgroundFill(Color.BLACK, null, null)));

        VBox menu = new VBox();
        menu.setSpacing(10);

        Label title = new Label(Constants.TITLE.toUpperCase());
        title.setFont(Font.font("Arial", FontWeight.THIN, 60));
        title.setTextFill(Color.RED);
        menu.getChildren().add(title);

        int btnWidth = 300;
        Background menuBkg = new Background(new BackgroundFill(null, null, null));
        Border menuBorder = new Border(new BorderStroke(Color.RED,
                BorderStrokeStyle.SOLID, new CornerRadii(10), null));

        Button start = new Button(Constants.START.toUpperCase());
        start.setFont(Font.font("Times New Roman", 16));
        start.setTextFill(Color.WHITE);
        start.setPrefWidth(btnWidth);
        start.setBackground(menuBkg);
        start.setBorder(menuBorder);
        start.setOnAction(new StartHandler());

        toGame = new Button(Constants.CONTINUE.toUpperCase());
        toGame.setFont(Font.font("Times New Roman", 16));
        toGame.setTextFill(Color.WHITE);
        toGame.setPrefWidth(btnWidth);
        toGame.setBackground(menuBkg);
        toGame.setBorder(menuBorder);
        toGame.setDisable(true);
        toGame.setOnAction(new ContinueHandler());

        Button load = new Button(Constants.LOAD.toUpperCase());
        load.setFont(Font.font("Times New Roman", 16));
        load.setTextFill(Color.WHITE);
        load.setPrefWidth(btnWidth);
        load.setBackground(menuBkg);
        load.setBorder(menuBorder);
        load.setOnAction(new LoadHandler());

        save = new Button(Constants.SAVE.toUpperCase());
        save.setFont(Font.font("Times New Roman", 16));
        save.setTextFill(Color.WHITE);
        save.setPrefWidth(btnWidth);
        save.setBackground(menuBkg);
        save.setBorder(menuBorder);
        save.setDisable(true);
        save.setOnAction(new SaveHandler());

        Button ranking = new Button(Constants.RANKING.toUpperCase());
        ranking.setFont(Font.font("Times New Roman", 16));
        ranking.setTextFill(Color.WHITE);
        ranking.setPrefWidth(btnWidth);
        ranking.setBackground(menuBkg);
        ranking.setBorder(menuBorder);
        ranking.setOnAction(new RankingHandler());

        Button exit = new Button(Constants.EXIT.toUpperCase());
        exit.setFont(Font.font("Times New Roman", 16));
        exit.setTextFill(Color.WHITE);
        exit.setPrefWidth(btnWidth);
        exit.setBackground(menuBkg);
        exit.setBorder(menuBorder);
        exit.setTooltip(new Tooltip(Constants.EXIT_TOOLTIP));
        exit.setOnAction(new ExitHandler());

        menu.getChildren().addAll(start, toGame, load, save, ranking, exit);
        menu.setAlignment(Pos.CENTER);
        this.setCenter(menu);
    

    private void performIO(int option) 
        FileChooser chooser = new FileChooser();
        ExtensionFilter ext = new ExtensionFilter(Constants.EXT_DESCRIPTION, ".pt");
        chooser.setSelectedExtensionFilter(ext);
        if (option == LOAD) 
            chooser.setTitle(Constants.LOAD);
            File choice = chooser.showOpenDialog(stage);
         else if (option == SAVE) 
            chooser.setTitle(Constants.SAVE);
            File choice = chooser.showSaveDialog(stage);
        
    

    private boolean verifyRestart() 
        Alert alert = new Alert(AlertType.WARNING, Constants.START_WARNING_MESSAGE,
                ButtonType.YES, ButtonType.NO);
        alert.setTitle(Constants.START_WARNING);
        alert.showAndWait();

        if (alert.getResult() == ButtonType.YES)
            return true;
        return false;
    

    private class StartHandler implements EventHandler<ActionEvent> 

        @Override
        public void handle(ActionEvent event) 
            if (display.isRunning()) 
                if (!verifyRestart())
                    return;
            

            display.start();
            stage.setScene(displayScene);
            toGame.setDisable(false);
            save.setDisable(false);
        

    

    private class ContinueHandler implements EventHandler<ActionEvent> 

        @Override
        public void handle(ActionEvent event) 
            stage.setScene(displayScene);
        

    

    private class LoadHandler implements EventHandler<ActionEvent> 

        @Override
        public void handle(ActionEvent event) 
            if (display.isRunning()) 
                if (!verifyRestart())
                    return;
            

            performIO(LOAD);
        

    

    private class SaveHandler implements EventHandler<ActionEvent> 

        @Override
        public void handle(ActionEvent event) 
            performIO(SAVE);
        

    

    private class RankingHandler implements EventHandler<ActionEvent> 

        @Override
        public void handle(ActionEvent event) 
            stage.setScene(displayScene);
        

    

    private class ExitHandler implements EventHandler<ActionEvent> 

        @Override
        public void handle(ActionEvent event) 
            performIO(SAVE);
            Platform.exit();
        

    



public static class MainDisplay extends AnchorPane 

    private boolean running;

    public MainDisplay() 
        running = false;
        tower = new Tower();
        setUp();
    

    private void setUp() 
        Color blue = new Color(34 / 255, 37 / 255, 47 / 255, 1.0);

        this.setBackground(new Background(new BackgroundFill(blue, null, null)));

        Background bkg = new Background(new BackgroundFill(null, null, null));
        Border menuBorder = new Border(new BorderStroke(Color.RED, BorderStrokeStyle.SOLID,
                new CornerRadii(10), null));

        Button home = new Button(Constants.HOME);
        home.setFont(Font.font("Times New Roman", 10));
        home.setTextFill(Color.WHITE);
        home.setBackground(bkg);
        home.setBorder(menuBorder);
        home.setOnAction(new HomeHandler());
        this.getChildren().add(home);
        AnchorPane.setTopAnchor(home, 10.0);
        AnchorPane.setRightAnchor(home, 10.0);
    

    public void start() 
        running = true;
    

    public boolean isRunning() 
        return running;
    

    private class HomeHandler implements EventHandler<ActionEvent> 

        @Override
        public void handle(ActionEvent event) 
            stage.setScene(startScene);
        

    




警告:有些对局可能不符合 JavaFx 的精髓,但它们会发挥作用

注意:要正确使用FX,建议使用FXML和/或SceneBuilder。

【讨论】:

【参考方案2】:

我不确定它在转换过程中是否有帮助,但我发现使用 SceneBuilder 和 fxmls 可以更轻松地构建 JavaFX 应用程序。主要是需要添加控制器类,视图内置在 .fxml 中。 也许在 SceneBuilder 中从头开始构建应用程序比繁琐的转换更容易?

【讨论】:

正如我在最后提到的,直接转换可能并不理想,但对于新用户来说它可能会有所帮助。

以上是关于从 Swing 转换为 JavaFX?的主要内容,如果未能解决你的问题,请参考以下文章

JavaFX,将 ArrayList 转换为 ObservableList

如何在 javaFX 中将颜色从 ColorPicker 转换为 String 值

如何将文件类型转换为图像?

如何将 JavaFX ComboBox 中的选择转换为字符串

使用 gradlew 将 JavaFX 转换为 Android

如何在 javafx 中将任何文本或字母转换为图像