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

JavaFX - 在鼠标所在的位置绘制弹出窗口?

陆飞鸿
2023-03-14

我目前有以下扩展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();
        }
    }
}

老实说,代码并不重要,请相信我,当用户将鼠标悬停在我的< code>Item对象上时,它会显示一个弹出窗口,如下所示:

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

这有可能让弹出窗口显示在某个位置吗?

谢谢。

共有1个答案

顾炎彬
2023-03-14

找不到一个好的答案,所以我只是做了:

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

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

    super.show();
}

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

 类似资料:
  • 我有以下代码来显示(自定义by-mvn repo) 问题是, > 我希望在鼠标输入时显示弹出窗口-工作正常。 我希望在用户从标签退出鼠标时隐藏弹出窗口,但在弹出窗口中输入鼠标时不隐藏弹出窗口。 我已经在标签上添加了鼠标插入和鼠标退出操作,但如何处理另一种情况,即如果用户输入鼠标进入弹出窗口,我不想隐藏弹出窗口。

  • 嗨,我有javafx应用程序,它只有一个stage.On标签键按下文本字段的事件,一个弹出窗口显示在应用程序的主要阶段 我不点击弹出窗口,也不选择弹出窗口中的任何内容。我会点击它后面的舞台。我希望popup被关闭,但在执行popup的focusedProperty侦听器之前,它给了我IllegalArgumentException。 如果popup位于不同的阶段(应用程序的主阶段除外),根据阶段f

  • 我使用以下代码在inkcanvas上的鼠标位置绘制一个正方形。但它不会在鼠标位置的中心绘制形状,而是稍微向右,再低一些,如下图所示: 此外,当我点击向画布添加形状时,我想停止笔的绘制。 怎样才能正确定位,停止画笔呢?

  • 问题内容: 我有一个3d渲染程序,该程序根据鼠标在屏幕上的位置围绕观察者旋转世界。这条线定义了地球旋转的弧度量 其中xy [0]是屏幕中心的x坐标 这意味着观察者视野的旋转量受到鼠标可以移动的距离的限制。如果我能使鼠标回到屏幕中央,则可以解决此问题。有任何想法吗? 问题答案: 好消息是有一种方法可以做到。 中间的消息是,它没有很好的记录。 坏消息是它仅在某些平台上有效。 另一个中间消息是,您至少可

  • 我想要一个舞台,是相同的大小,屏幕是完全透明的,接收鼠标事件在任何地方。在下面的示例中,我只在鼠标位于圆圈上方时才获得鼠标事件。我在使用Java 8U11的Windows XP和Windows 7上都看到了这个问题 有趣的是,如果我将填充颜色的alpha部分设置为它的绝对最小值,那么我会得到鼠标事件。然而,我不想使用这个变通方法,而是要真正深入到问题的底部。我的结论是,在JavaFX或Window

  • 我有一个控制器。用于场景的java。fxml和控制器设置。用于WindowsSettings.fxml的java。在控制器中。java I使用以下方法创建一个新的弹出窗口(无对话框): 我想在关闭新弹出窗口时保存设置,但这不适用于stage.setOnCloseRequest。