从 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 中的选择转换为字符串