我使用FXML和CSS创建一个简单的JavaFx应用程序,以便在运行时更改UI主题。 场景中有三个Button和一个Label。我为Label定义了不同的CSS,为CSS文件中的BorderPane定义了“-fx-background-image”(PNG格式,大小为1.23M)。 应用程序可以通过单击“样式”按钮切换UI主题。 但是当我单击“样式”按钮之一时,Mem使用将提升并且不会释放。切换主题后应用程序将OutOfMemoryError大约30次。我不知道如何解决它。有人可以帮助我吗?
java.lang.OutOfMemoryError: Java heap space
at java.awt.image.DataBufferInt.<init>(DataBufferInt.java:75)
at java.awt.image.Raster.createPackedRaster(Raster.java:467)
at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:1032)
at java.awt.image.BufferedImage.<init>(BufferedImage.java:359)
at com.sun.prism.j2d.J2DTexture.<init>(J2DTexture.java:46)
at com.sun.prism.j2d.J2DResourceFactory.createTexture(J2DResourceFactory.java:72)
at com.sun.prism.impl.BaseResourceFactory.createTexture(BaseResourceFactory.java:127)
我的环境:jdk1.7.0_51,Windows Server 2003 x86,3G RAM
很抱歉,我不知道如何将IMG文件(background.png)发布到论坛。
点击“AutoSwitch”按钮进行自动切换主题。
源代码: 的 Main.Java
public class Main extends Application {
private Stage primaryStage;
public Stage getPrimaryStage() {
return primaryStage;
}
public void setPrimaryStage(Stage primaryStage) {
this.primaryStage = primaryStage;
}
private BorderPane rootPane;
public BorderPane getRootPane() {
return rootPane;
}
@Override
public void start(Stage primaryStage) {
try {
setPrimaryStage(primaryStage);
URL url = new URL(getClass().getResource("AppFrame.fxml").toExternalForm());
FXMLLoader loader =new FXMLLoader(url);
rootPane = (BorderPane)loader.load();
Scene scene = new Scene(rootPane,400,400);
primaryStage.setScene(scene);
//MAX screen
Screen screen = Screen.getPrimary();
Rectangle2D bounds = screen.getVisualBounds();
primaryStage.setX(bounds.getMinX());
primaryStage.setY(bounds.getMinY());
primaryStage.setWidth(bounds.getWidth());
primaryStage.setHeight(bounds.getHeight());
primaryStage.show();
AppFrameController appFrameController = (AppFrameController)loader.getController();
appFrameController.setAppMain(this);
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
AppFrameController.java
public class AppFrameController {
private String style1Url = getClass().getResource("FxStyle1.css").toExternalForm();
private String style2Url = getClass().getResource("FxStyle2.css").toExternalForm();
@FXML private Label lblSceneTitle;
private Main appMain;
public Main getAppMain() {
return appMain;
}
public void setAppMain(Main appMain) {
this.appMain = appMain;
}
private int switchCount=0;
public AppFrameController()
{
}
public void handleClickStyle1()
{
ObservableList<String> stylesheets = getAppMain().getRootPane().getStylesheets();
stylesheets.remove(style2Url);
if(!stylesheets.contains(style1Url))
{
stylesheets.add(style1Url);
}
}
public void handleClickStyle2()
{
ObservableList<String> stylesheets = getAppMain().getRootPane().getStylesheets();
stylesheets.remove(style1Url);
if(!stylesheets.contains(style2Url))
{
stylesheets.add(style2Url);
}
}
public void handleClickSwitch()
{
SwitchCssTask handleTask = new SwitchCssTask();
new Thread(handleTask).start();
}
private class SwitchCssTask implements Runnable {
@Override
public void run() {
while (true) {
if (switchCount % 2 == 0) {
handleClickStyle1();
} else {
handleClickStyle2();
}
switchCount++;
System.out.println("Switch count=" + switchCount);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
AppFrame.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane prefHeight="362.0" prefWidth="749.3739013671875" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="application.AppFrameController">
<!-- TODO Add Nodes -->
<center>
<BorderPane id="center-pane" prefHeight="-1.0" prefWidth="-1.0" BorderPane.alignment="CENTER">
<center>
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0" spacing="20.0">
<children>
<Button mnemonicParsing="false" onAction="#handleClickStyle1" prefHeight="70.0" prefWidth="148.0" text="Style1" />
<Button mnemonicParsing="false" onAction="#handleClickStyle2" prefHeight="70.0" prefWidth="148.0" text="Style2" />
<Button mnemonicParsing="false" onAction="#handleClickSwitch" prefHeight="70.0" prefWidth="148.0" text="AutoSwitch" />
</children>
</VBox>
</center>
</BorderPane>
</center>
<stylesheets>
<URL value="@FxStyle2.css" />
</stylesheets>
<top>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" spacing="10.0" BorderPane.alignment="CENTER">
<children>
<Label id="scene-title" fx:id="lblSceneTitle" alignment="TOP_CENTER" prefWidth="371.0" text="Test FxStyle" />
</children>
<padding>
<Insets bottom="15.0" left="12.0" right="12.0" top="15.0" />
</padding>
</HBox>
</top>
</BorderPane>
FxStyle1.css
#center-pane {
-fx-background-image: url("background.png");
}
#scene-title {
-fx-font-family: "Tahoma";
-fx-background-insets: 0;
-fx-text-fill: green;
-fx-font-weight: bold;
-fx-font-size: 4em;
-fx-effect: dropshadow( one-pass-box , rgba(0,0,0,0.9) , 1, 0.0 , 0 , 1 );
}
FxStyle2.css
#center-pane {
-fx-background-image: url("background.png");
}
#scene-title {
-fx-font-family: "Courier New";
-fx-background-insets: 0;
-fx-text-fill: red;
-fx-font-weight: bold;
-fx-font-size: 4em;
-fx-effect: dropshadow( one-pass-box , rgba(0,0,0,0.9) , 1, 0.0 , 0 , 1 );
}