【问题标题】:JavaFX remove Node from ToolBar ContextMenuJavaFX 从工具栏上下文菜单中删除节点
【发布时间】:2017-03-14 13:40:04
【问题描述】:

我在使用工具栏时遇到问题。我提供了一个小程序来演示我正在尝试做的事情和问题。基本上我向工具栏添加了一个“自定义”按钮。 “自定义”按钮上有一个 X 图像,它们有一个动作,可以让它们从工具栏中删除自己。这工作正常。问题是当添加到工具栏的按钮多于显示它们的宽度时,工具栏执行显示选项以查看 ContextMenu/popup 以显示其他按钮的良好行为。这也很有效。从工具栏中删除按钮时出现问题。删除在工具栏上可见的按钮效果很好,但是如果您尝试从 ContextMenu 中删除按钮,当它变为可见时,它不会重绘自身,因此按钮看起来还没有被删除。如果 ContextMenu 被隐藏然后重新显示,则 Button 已被删除,所以这只是一个重绘问题。

无论如何我可以强制它从父节点(工具栏)向下重绘吗?

    package ToolbarTest;

import java.net.URL;
import java.util.LinkedHashMap;
import java.util.ResourceBundle;

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToolBar;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;

public class ToolbarHolderController implements Initializable {

    @FXML
    ToolBar toolBar;
    @FXML
    BorderPane borderPane;
    @FXML
    Button addButton;
    @FXML
    Button removeButton;
    @FXML
    private LinkedHashMap<String, ToggleButton> toggleButtonHash = new LinkedHashMap<>();

    @Override
    public void initialize(URL location, ResourceBundle resources) {

        IntegerProperty i = new SimpleIntegerProperty(0);

        addButton.setOnAction(e -> {
            ImageView closeImageView = new ImageView(new Image(getClass().getResource("tabclose2.png").toString()));
            String text="B:" + i.get();
            RemoveableToggleButton tButton = new RemoveableToggleButton(text, closeImageView, new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent e) {
                    if (toggleButtonHash.containsKey(text)) {
                        toolBar.getItems().remove(toggleButtonHash.get(text));
                        toggleButtonHash.remove(text);
                    }
                    e.consume();
                }
            });
            toolBar.getItems().add(tButton);
            toggleButtonHash.put(text, tButton);
            i.set(i.get() + 1);
        });

        removeButton.setOnAction(e->{
                toolBar.getItems().remove(toolBar.getItems().size()-1);
            }
        );
    }

    class RemoveableToggleButton extends ToggleButton {

        private Button close = new Button();

        public RemoveableToggleButton(String text, Node graphic, EventHandler<ActionEvent> closeEvent) {
            this.close.setGraphic(graphic);
            this.close.setOnAction(closeEvent);
            this.close.setMouseTransparent(false);
            this.textProperty().set(text);
            this.setGraphic(close);
        }

    }
}

ToolBarHolder.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>

<BorderPane fx:id="borderPane" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ToolbarTest.ToolbarHolderController">
   <top>
      <ToolBar fx:id="toolBar" prefHeight="40.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
   </top>
   <center>
      <HBox spacing="5.0" BorderPane.alignment="CENTER_LEFT">
         <children>
            <Button fx:id="addButton" mnemonicParsing="false" text="add" />
             <Button fx:id="removeButton" mnemonicParsing="false" text="remove" />
         </children>
         <padding>
            <Insets bottom="5.0" left="5.0" top="5.0" />
         </padding>
      </HBox>
   </center>
</BorderPane>

【问题讨论】:

    标签: java javafx-8


    【解决方案1】:

    我们也有同样的问题。通过一堆试验和错误,我能够弄清楚您不仅需要从toolbar.getItems()中删除按钮,还需要从“溢出”按钮生成的上下文菜单中删除。

    试试这个:

    // if the button is inside of a context menu, remove it from there as well
    if (buttonToClose.getParent() != null &&
        buttonToClose.getParent().getParent() != null &&
        buttonToClose.getParent().getParent().getParent() != null &&
        buttonToClose.getParent().getParent().getParent() instanceof ContextMenuContent) {
    
        ContextMenuContent contextMenuContent = buttonToClose.getParent().getParent().getParent();
        contextMenuContent.getItemsContainer().getChildren().remove(buttonToClose.getParent());
    }
    

    我知道它看起来很老套,并且对上下文菜单的构成有内幕消息,但它确实有效。

    【讨论】:

    • 我唯一需要做的就是强制转换为 ContextMenuContent,非常感谢您发布此内容:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-17
    • 1970-01-01
    • 2016-07-03
    • 2011-10-20
    • 1970-01-01
    • 1970-01-01
    • 2012-01-17
    相关资源
    最近更新 更多