当前位置: 首页 > 知识库问答 >
问题:

如何将多个按钮添加到tilepane?

萧丁雨
2023-03-14

我在边框的中心有一个标题栏。对于链接哈希图中的每个条目,我想在标题栏中添加一个按钮。这个标题栏已经存在于fxml文件中,并且具有fx: id field dContainer。

如果一次添加一个键值对,按钮将一个接一个出现。但是,当我试图通过从文本文件导入链接的hashmap一次添加它们时,按钮不会出现。它将加载一个条目,然后抛出nullpointerexception。

导入文本文件和将条目添加到地图的方法似乎都运行良好。我认为问题出在field dContainer上。我不明白为什么它只会一个接一个地添加按钮,而不是一次全部添加。有人能解释一下我的代码出了什么问题吗?

更新:我通过将field dContainer分配给Controller类顶部的一个新TilePane来修复nullpointerxcept:

@FXML
private TilePane fieldContainer = new TilePane();

错误消失了,它会打印整个地图,但仍然不会显示按钮。任何人

FXML:

<BorderPane fx:id="container" stylesheets="/css/main.css" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<top>
// Some code
</top>

<center>
    <TilePane fx:id="fieldContainer" prefColumns="2" prefTileHeight="100.0" prefTileWidth="135.0">
    </TilePane>
</center>

<bottom>
// Some code
</bottom>

类寄存器(使用导入方法):

public class Register {
    private Controller ctrl;

    public Register(Controller ctrl) {
        this.ctrl = ctrl;
    }

    public void exportTo(File file) {
        LinkedHashMap<String, BigDecimal> pMap = ctrl.getProductMap();
        try (
                FileOutputStream fos = new FileOutputStream(file);
                PrintWriter writer = new PrintWriter(fos);
        ) {
            for(Map.Entry<String, BigDecimal> entry : pMap.entrySet()) {
                writer.printf("%s|%s%n",
                        entry.getKey(),
                        entry.getValue());
            }
        } catch(IOException ioe) {
            System.out.printf("Problem saving %s %n", file);
            ioe.printStackTrace();
        }
    }

    public void importFrom(File file) {
        try (
                FileInputStream fis = new FileInputStream(file);
                BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
        ) {
            String line;
            while((line = reader.readLine()) != null) {
                String[] args = line.split("\\|");
                ctrl.addProduct(args[0], new BigDecimal(args[1]));
            }
        } catch(IOException ioe) {
            System.out.printf("Problems loading %s %n", file);
            ioe.printStackTrace();
        }
    }
}

类控制器(按钮创建):

public class Controller {
    private static LinkedHashMap<String, BigDecimal> mProductMap = new LinkedHashMap<>();

    @FXML
    private TilePane fieldContainer;

    public LinkedHashMap<String, BigDecimal> getProductMap() {
        return mProductMap;
    }

    // Puts key and value to the Map and creates a button for each entry
    public void addProduct(String product, BigDecimal price) {
        mProductMap.put(product, price);
        System.out.println(mProductMap);

        fieldContainer.getChildren().clear();

        for (Map.Entry<String, BigDecimal> entry : mProductMap.entrySet()) {
            StackPane newField = new StackPane();
            Button main = new Button();
            Button multiply = new Button("X");
            Button subtract = new Button("-");
            main.setText(entry.getKey() + "\n" + entry.getValue());
            multiply.getStyleClass().add("inner-button");
            subtract.getStyleClass().add("inner-button");
            StackPane.setAlignment(multiply, Pos.BOTTOM_LEFT);
            StackPane.setAlignment(subtract, Pos.BOTTOM_CENTER);
            StackPane.setMargin(multiply, new Insets(0, 0, 8, 8));
            StackPane.setMargin(subtract, new Insets(0, 0, 8, 16));
            // Three buttons on top of each other
            newField.getChildren().add(main);
            newField.getChildren().add(multiply);
            newField.getChildren().add(subtract);

            fieldContainer.setAlignment(Pos.TOP_LEFT);
            // this should add a button for each entry, 
            // but it only works when you add them one by one
            fieldContainer.getChildren().add(newField);
        }
    }
}

主要内容:

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setScene(new Scene(root, 300, 500));
        primaryStage.show();

        Controller controller = new Controller();
        Register register = new Register(controller);
        register.importFrom(new File("prices.txt"));
    }

    @Override
    public void stop(){
        Controller controller = new Controller();
        Register register = new Register(controller);
        register.exportTo(new File("prices.txt"));
    }

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

错误:

Exception in Application start method
{Coffee=1.50}  // the first entry from the Map prints
java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:473)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:372)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:945)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:973)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:198)
    at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.lang.NullPointerException
    at sample.Controller.addProduct(Controller.java:54) // fieldContainer.getChildren().clear();
    at sample.Register.importFrom(Register.java:40) // ctrl.addProduct(args[0], new BigDecimal(args[1]));
    at sample.Main.start(Main.java:23) // register.importFrom(new File("prices.txt"));
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:919)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$11(PlatformImpl.java:449)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$9(PlatformImpl.java:418)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:417)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:175)
    ... 1 more
Exception running application sample.Main

共有1个答案

滕成双
2023-03-14

我自己修的。现在,所有按钮都会在运行Main时立即加载。下面是我所做的:

我没有在main中调用寄存器的importFrom方法,而是从控制器类中调用它,就像在initialize方法中那样:

private Register mRegister;

public Controller() {
    this.mRegister = new Register(this);
}

@FXML
private void initialize() {
    mRegister.importFrom(new File("prices.txt"));
}
 类似资料:
  • 问题内容: 我搜索了在jtable中添加按钮的教程,并从http://tips4java.wordpress.com/2009/07/12/table-button- column/ 找到了一个类文件, 该按钮在哪里设置? 问题答案: 它是通过DefaultTableModel中的数据在表渲染器和编辑器中自动设置的。例如,对于表编辑器,代码为: 表模型的值在哪里。有关详细信息,请参见ButtonC

  • 我有两件事情要做:在鼠标悬停时突出显示JPanel,在鼠标拖动时移动一个蓝色方块。问题是,这需要我将MouseListeners添加到不同的组件中。当我这样做时,我只能使用一个功能——另一个被阻止了。我该怎么做才能让两个功能都工作? 注意:有时候JFrame不会显示任何东西——你只需要一直运行它,直到它显示为止(通常需要2-3次尝试)。如果它做了任何其他奇怪的事情,就继续运行它,直到它工作。如果之

  • 问题内容: 我有一个 JFrame 。 我也有一个 Box 类,它扩展了 Component 。该box类具有一个 paint 方法,该方法可以创建一个填充的矩形。 当我将这些Box组件的多个添加到我的JFrame时,当我在JFrame上调用 重绘 时,仅显示最近添加的一个。 我看了一下布局管理器,但是我不确定那不是我想要的。我所希望的是能够在屏幕上的任何位置制作整个矩形的动画。 (我还尝试创建一

  • 问题内容: 我有一些与它们相关联的jQueryUI按钮的项目列表。完成一个动作(删除一个项目)后,我想通过ajax重新加载列表。 唯一的问题是,当我这样做时,JQueryUI按钮不再显示,仅显示标准标记。 我知道我可以动态添加点击处理程序等,但是如何将jQueryUI 应用于它们? 问题答案: 通过ajax重新加载时,请在该上下文中调用(或使用的任何变体),如下所示: 这将 仅在响应中的*元素上运

  • 问题内容: 我想添加除“确定”按钮以外的另一个按钮,该按钮应仅关闭警报。我希望其他按钮调用某个功能。 我如何在此警报中添加另一个按钮,然后单击该按钮,然后允许它调用一个函数,因此可以说我们希望新按钮进行调用: 问题答案: Swifty方法是使用新的UIAlertController和闭包: 斯威夫特3:

  • 我是一个新的android工作室,所以很抱歉,如果这是一个非常愚蠢的问题,但我不能找到答案在任何地方网上。非常感谢任何帮助! 我已经建立了一个小的应用程序,有两个屏幕:一个主屏幕,一个屏幕二。主屏幕只是导航到屏幕二。从另一个屏幕,你可以播放/暂停/停止一首特定的歌曲,或者回到主屏幕。 我遇到的问题是当我导航到屏幕二时,当我按下“后退”按钮返回主屏幕时,我无法弄清楚如何将“停止”方法添加到这个按钮上