JavaFX - 在哪里绘制Popup鼠标?

时间:2016-01-27 08:55:41

标签: java user-interface javafx popup

我目前有以下课程extends Popup

package application;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Popup;
import javafx.util.Duration;
import logic.Item;
import logic.ItemQuality;
import logic.Manager;

/**
 * Frame which displays an Item, ideally used
 * for when the user hovers over a given element.
 * The frame's labels are all made to look
 * Diablo 2-esque which ends up creating a nice 
 * looking frame which fades in and out on use.
 * @author Kevin
 *
 */
class ItemFrame_Animated extends Popup
{
    private final BooleanProperty hiding;

    ItemFrame_Animated(Item reference)
    {
        VBox frame = new VBox();
        frame.setAlignment(Pos.CENTER);
        frame.setPadding(new Insets(10));
        frame.setSpacing(4);

        Color titleColor = reference.getQuality().getColor();

        // This item has a surname, such as 'ENGIMA'.
        if (!reference.getSpecialName().isEmpty())
        {
            Label surname = new Label(reference.getSpecialName());
            surname.setTextFill(titleColor);
            frame.getChildren().add(surname);
        }

        // Base name, such as 'Long Bow'.
        Label basename = new Label(reference.getIdentifier());
        // One special case is that if the quality is runeword, the item's base needs to be Gray.
        basename.setTextFill((reference.getQuality() == ItemQuality.RUNEWORD) ?
                ItemQuality.BASE_MODIFIED.getColor() : titleColor);
        frame.getChildren().add(basename);

        // If the item has a level.
        if (reference.getLevel() > 0)
        {
            Label level = new Label("Required Level: " + reference.getLevel());
            // Level is ALWAYS white colored.
            level.setTextFill(ItemQuality.BASE.getColor());
            frame.getChildren().add(level);
        }

        // Add the Affixes.
        for (String i : reference.getAffixes())
        {
            Label affix = new Label(i);
            // Affixes are ALWAYS blue colored.
            affix.setTextFill(ItemQuality.MAGIC.getColor());
            frame.getChildren().add(affix);
        }

        if (reference.getSockets() > 0)
        {
            Label sockets = new Label("Socketed: (" + reference.getSockets() + ")");
            sockets.setTextFill(ItemQuality.BASE_MODIFIED.getColor());
            frame.getChildren().add(sockets);
        }

        // Change the font of every label.
        for (Node i : frame.getChildren())
        {
            i.getStyleClass().clear();
            ((Label) i).setFont(GUI.diabloFont);
        }

        // Add the item's picture to the Frame.
        String path = "./res/Images/" + Manager.itemDatabase.get(reference.getIdentifier()).getImageURL().hashCode() + ".jpg";
        ImageView itemImage = new ImageView(new Image(new File(path).toURI().toString()));
        frame.getChildren().add(itemImage);

        // Set the content of the page to the VBox.
        getContent().add(frame);
        frame.setStyle("-fx-background-color: #020202;");

        // Don't allow this Popup to be closed.
        setHideOnEscape(false);
        setWidth(400);
        setHeight(500);

        this.hiding = new SimpleBooleanProperty(this, "hiding", false);
    }

    public ReadOnlyBooleanProperty hidingProperty()
    {
        return hiding;
    }

    public boolean isHiding()
    {
        return hiding.get();
    }

    @Override public void hide()
    {
        // If the Window is not already in the process of being hidden...
        if (!hiding.get())
        {
            // Inform the Popup that we are now attempting to hide.
            hiding.set(true);

            // Grab all the nodes in this PopUp and track their opacities.
            final ObservableList<Node> nodes = this.getContent();
            final Map<Node, Double> opacities = new HashMap<Node, Double>();
            KeyValue[] keyValues = new KeyValue[nodes.size()];
            for (int i = 0; i < keyValues.length; i++)
            {
                // Set the KeyValues for each node.
                Node node = nodes.get(i);
                opacities.put(node, node.getOpacity());
                keyValues[i] = new KeyValue(nodes.get(i).opacityProperty(), 0);
            }

            KeyFrame frame = new KeyFrame(Duration.seconds(1), keyValues);
            Timeline timeline = new Timeline(frame);
            timeline.setOnFinished(e ->
            {
                // We are no longer hiding the frame.
                hiding.set(false);
                ItemFrame_Animated.super.hide();
                for (Node node : nodes)
                {
                    node.setOpacity(opacities.get(node));
                }
            });

            // Play the animation.
            timeline.play();
        }
    }
}

老实说,代码并不重要,只要相信我,当用户将鼠标悬停在我的Item个对象上时,它会显示一个Popup,如下所示:

Item Frame

此弹出窗口在我的屏幕中间打开。如果我移动窗口,弹出窗口将在同一位置打开。我需要弹出窗口以某种方式在鼠标指针下打开。我知道Tooltip具有此功能(据称),但我已经承诺设计此Popup窗口,其中包含许多设计目标。

是否可以让Popup窗口显示在某个位置?

谢谢。

1 个答案:

答案 0 :(得分:0)

无法找到一个好的答案所以我刚刚做了:

@Override public void show()
{       
    Point mouseLocation = MouseInfo.getPointerInfo().getLocation();

    setX(mouseLocation.getX());
    setY(mouseLocation.getY());

    super.show();
}

可能有更好的解决方案,但这就是我能想到的。