使用JavaFX PopOver作为选项卡窗格选项卡查看其内容

使用JavaFX PopOver作为选项卡窗格选项卡查看其内容,javafx,popover,tabpanel,Javafx,Popover,Tabpanel,我尝试为选项卡窗格创建一个Peek控件。因此,如果面板已打开,则会保存一个快照。当用户将鼠标悬停在选项卡上时将显示一个弹出窗口。这类似于Windows Aero Peek 我的问题是,PopOver在不应该隐藏的时候被隐藏了。。。因为它从选项卡图形接收一个hide()事件 我创建了一个小的可运行示例来演示这个问题: import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import org

我尝试为
选项卡窗格
创建一个
Peek
控件
。因此,如果面板已打开,则会保存一个
快照。当用户将鼠标悬停在
选项卡上时
将显示一个
弹出窗口
。这类似于Windows Aero Peek

我的问题是,
PopOver
在不应该隐藏的时候被隐藏了。。。因为它从
选项卡
图形
接收一个
hide()
事件

我创建了一个小的可运行示例来演示这个问题:

import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import org.controlsfx.control.PopOver;
import org.controlsfx.control.PopOver.ArrowLocation;

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.Label;
import javafx.scene.control.SingleSelectionModel;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Main extends Application {
    Peek peek;
    Tab lastPeek;
    boolean show = false;

    public static void main(String[] args) {
        System.out.println("WE HAVE PROBLEMS WITH FOCUS HERE");
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        peek = new Peek();
        primaryStage.setTitle("Tabs");
        Group root = new Group();
        Scene scene = new Scene(root, 400, 250, Color.WHITE);

        TabPane tabPane = new TabPane();

        BorderPane borderPane = new BorderPane();

        final PopOver popOver = new PopOver();
        popOver.setArrowLocation(ArrowLocation.TOP_LEFT);
        final ImageView preview = new ImageView();
        preview.setFitHeight(100);
        preview.setSmooth(true);
        preview.setPreserveRatio(true);
        popOver.setContentNode(preview);

        for (int i = 0; i < 5; i++) {
            Tab tab = new Tab();
            HBox hbox = new HBox();
            hbox.getChildren().add(new Label("", new ImageView(new Image(Main.class.getResourceAsStream(i + ".jpg")))));
            hbox.setAlignment(Pos.CENTER);
            tab.setContent(hbox);
            tabPane.getTabs().add(tab);

            final Label decoration = new Label("Tab" + i);
            tab.setGraphic(decoration);
            System.out.println("tab.getGraphic() = " + tab.getGraphic());

            final int index = i;
            tab.getGraphic().setOnMouseEntered(mouseEvent -> {
                boolean show = false;
                if (lastPeek != tab) {
                    // Show PopOver when mouse enters label
                    Image previewImage = peek.get(tab);
                    if (previewImage != null) {
                        show = true;
                    }
                    System.out.println("previewImage = " + previewImage);
                    preview.setImage(previewImage);
                    System.out.println("show() " + "Tab" + index);
                    lastPeek = tab;
                }
                if (!tab.isSelected() && !tab.isDisabled() && show) {
                    popOver.show((Node) mouseEvent.getSource(), -3);
                }
            });

            tab.getGraphic().setOnMouseExited(mouseEvent -> {
                // Hide PopOver when mouse exits label
                // how can we handle this correct??
                 popOver.hide();
                System.out.println("hide() " + "Tab" + index);
            });

        }

        tabPane.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>() {
            @Override
            public void changed(ObservableValue<? extends Tab> ov, Tab oldTab, Tab newTab) {
                Image preview = oldTab.getContent().snapshot(new SnapshotParameters(), null);
                peek.set(oldTab, preview);
            }
        });
        tabPane.selectionModelProperty().addListener(new ChangeListener<SingleSelectionModel<Tab>>() {

            @Override
            public void changed(ObservableValue<? extends SingleSelectionModel<Tab>> ov,
                    SingleSelectionModel<Tab> oldValue, SingleSelectionModel<Tab> newValue) {
            }
        });

        // bind to take available space
        borderPane.prefHeightProperty().bind(scene.heightProperty());
        borderPane.prefWidthProperty().bind(scene.widthProperty());

        borderPane.setCenter(tabPane);
        root.getChildren().add(borderPane);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

}

事实上,这是因为你展示的流行音乐。一旦弹出框显示出来,它就占据了焦点,一个MouseExit事件被发送到选项卡的图形中
您可以通过在弹出窗口中添加更大的偏移量来观察它:

popOver.show((Node) mouseEvent.getSource(), -15);
或者只需从选项卡顶部而不是底部输入鼠标(问题不再出现)

此外,由于事件似乎没有很好地同步(当鼠标从一个选项卡快速移动到另一个选项卡时),我建议您按选项卡创建一个PopOver

public class Main extends Application {

   Peek peek;

   Tab lastPeek;

   HashMap<Label, PopOver> popMap = new HashMap<>();

   boolean show = false;

   public static void main(String[] args) {
      System.out.println("WE HAVE PROBLEMS WITH FOCUS HERE");
      Application.launch(args);
   }

   @Override
   public void start(Stage primaryStage) {
      peek = new Peek();
      primaryStage.setTitle("Tabs");
      Group root = new Group();
      Scene scene = new Scene(root, 400, 250, Color.WHITE);

      TabPane tabPane = new TabPane();

      BorderPane borderPane = new BorderPane();

      for(int i = 0; i < 5; i++) {
         Tab tab = new Tab();
         HBox hbox = new HBox();
         hbox.getChildren()
               .add(new Label("", new ImageView(new Image(Main.class.getResourceAsStream(i + ".jpg")))));
         hbox.setAlignment(Pos.CENTER);
         tab.setContent(hbox);
         tabPane.getTabs().add(tab);

         final Label decoration = new Label("Tab" + i);
         tab.setGraphic(decoration);
         System.out.println("tab.getGraphic() = " + tab.getGraphic());
         final PopOver popOver = new PopOver();
         popOver.setArrowLocation(ArrowLocation.TOP_LEFT);
         final ImageView preview = new ImageView();
         preview.setFitHeight(100);
         preview.setSmooth(true);
         preview.setPreserveRatio(true);
         popOver.setContentNode(preview);

         popMap.put(decoration, popOver);
         final int index = i;
         decoration.setOnMouseEntered(mouseEvent -> {

            PopOver lPop = popMap.get((Label) mouseEvent.getSource());

            boolean show = false;
            if(lastPeek != tab) {
               // Show PopOver when mouse enters label
               Image previewImage = peek.get(tab);
               if(previewImage != null) {
                  show = true;
               }
               System.out.println("previewImage = " + previewImage);
               preview.setImage(previewImage);
               System.out.println("show() " + "Tab" + index);

            }
            if(!tab.isSelected() && !tab.isDisabled() && show) {
               lPop.show((Node) mouseEvent.getSource(), -decoration.getHeight() / 2);
            }
         });

         tab.getGraphic().setOnMouseExited(mouseEvent -> {
            // Hide PopOver when mouse exits label
            // how can we handle this correct??
            PopOver lPop = popMap.get((Label) mouseEvent.getSource());
            if(lPop.isShowing())
               lPop.hide();
            System.out.println("hide() " + "Tab" + index);
         });

      }

      tabPane.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>() {

         @Override
         public void changed(ObservableValue<? extends Tab> ov, Tab oldTab, Tab newTab) {
            Image preview = oldTab.getContent().snapshot(new SnapshotParameters(), null);
            peek.set(oldTab, preview);
         }
      });
      tabPane.selectionModelProperty().addListener(new ChangeListener<SingleSelectionModel<Tab>>() {

         @Override
         public void changed(ObservableValue<? extends SingleSelectionModel<Tab>> ov,
               SingleSelectionModel<Tab> oldValue, SingleSelectionModel<Tab> newValue) {
         }
      });

      // bind to take available space
      borderPane.prefHeightProperty().bind(scene.heightProperty());
      borderPane.prefWidthProperty().bind(scene.widthProperty());

      borderPane.setCenter(tabPane);
      root.getChildren().add(borderPane);
      primaryStage.setScene(scene);
      primaryStage.show();
   }
}
public类主扩展应用程序{
偷看;
拉斯皮克;
HashMap popMap=新的HashMap();
布尔显示=假;
公共静态void main(字符串[]args){
System.out.println(“我们这里的焦点有问题”);
应用程序启动(args);
}
@凌驾
公共无效开始(阶段primaryStage){
peek=新peek();
初级阶段。设置标题(“制表符”);
组根=新组();
场景=新场景(根,400,250,颜色.白色);
TabPane TabPane=新建TabPane();
BorderPane BorderPane=新的BorderPane();
对于(int i=0;i<5;i++){
Tab Tab=新选项卡();
HBox HBox=新的HBox();
hbox.getChildren()
.add(新标签(“),新图像视图(新图像(Main.class.getResourceAsStream(i+”.jpg“)”));
hbox.设置校准(位置中心);
tab.设置内容(hbox);
tabPane.getTabs().add(tab);
最终标签装饰=新标签(“标签”+i);
tab.设置图形(装饰);
System.out.println(“tab.getGraphic()=”+tab.getGraphic());
最终PopOver PopOver=新PopOver();
popOver.setArrowLocation(箭头位置,左上角);
最终ImageView预览=新建ImageView();
预览。设置高度(100);
preview.setSmooth(真);
预览。设置保留比率(真);
setContentNode(预览);
popMap.put(装饰,popOver);
最终int指数=i;
装饰。setOnMouseEntered(mouseEvent->{
PopOver lPop=popMap.get((Label)mouseEvent.getSource());
布尔显示=假;
如果(lastPeek!=选项卡){
//当鼠标进入标签时显示弹出框
图像预览图像=peek.get(选项卡);
如果(预览图像!=null){
show=true;
}
System.out.println(“previewImage=“+previewImage”);
preview.setImage(previewImage);
System.out.println(“show()”+“Tab”+索引);
}
如果(!tab.isSelected()&&&!tab.isDisabled()&&show){
lPop.show((节点)mouseEvent.getSource(),-decoration.getHeight()/2);
}
});
tab.getGraphic().setOnMouseExited(mouseEvent->{
//鼠标退出标签时隐藏弹出框
//我们如何正确处理这个问题??
PopOver lPop=popMap.get((Label)mouseEvent.getSource());
if(lPop.isShowing())
lPop.hide();
System.out.println(“hide()”+“Tab”+索引);
});
}
tabPane.getSelectionModel().SelectEditeProperty().addListener(新的ChangeListener()){
@凌驾
公共无效已更改(可观察值)
public class Main extends Application {

   Peek peek;

   Tab lastPeek;

   HashMap<Label, PopOver> popMap = new HashMap<>();

   boolean show = false;

   public static void main(String[] args) {
      System.out.println("WE HAVE PROBLEMS WITH FOCUS HERE");
      Application.launch(args);
   }

   @Override
   public void start(Stage primaryStage) {
      peek = new Peek();
      primaryStage.setTitle("Tabs");
      Group root = new Group();
      Scene scene = new Scene(root, 400, 250, Color.WHITE);

      TabPane tabPane = new TabPane();

      BorderPane borderPane = new BorderPane();

      for(int i = 0; i < 5; i++) {
         Tab tab = new Tab();
         HBox hbox = new HBox();
         hbox.getChildren()
               .add(new Label("", new ImageView(new Image(Main.class.getResourceAsStream(i + ".jpg")))));
         hbox.setAlignment(Pos.CENTER);
         tab.setContent(hbox);
         tabPane.getTabs().add(tab);

         final Label decoration = new Label("Tab" + i);
         tab.setGraphic(decoration);
         System.out.println("tab.getGraphic() = " + tab.getGraphic());
         final PopOver popOver = new PopOver();
         popOver.setArrowLocation(ArrowLocation.TOP_LEFT);
         final ImageView preview = new ImageView();
         preview.setFitHeight(100);
         preview.setSmooth(true);
         preview.setPreserveRatio(true);
         popOver.setContentNode(preview);

         popMap.put(decoration, popOver);
         final int index = i;
         decoration.setOnMouseEntered(mouseEvent -> {

            PopOver lPop = popMap.get((Label) mouseEvent.getSource());

            boolean show = false;
            if(lastPeek != tab) {
               // Show PopOver when mouse enters label
               Image previewImage = peek.get(tab);
               if(previewImage != null) {
                  show = true;
               }
               System.out.println("previewImage = " + previewImage);
               preview.setImage(previewImage);
               System.out.println("show() " + "Tab" + index);

            }
            if(!tab.isSelected() && !tab.isDisabled() && show) {
               lPop.show((Node) mouseEvent.getSource(), -decoration.getHeight() / 2);
            }
         });

         tab.getGraphic().setOnMouseExited(mouseEvent -> {
            // Hide PopOver when mouse exits label
            // how can we handle this correct??
            PopOver lPop = popMap.get((Label) mouseEvent.getSource());
            if(lPop.isShowing())
               lPop.hide();
            System.out.println("hide() " + "Tab" + index);
         });

      }

      tabPane.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>() {

         @Override
         public void changed(ObservableValue<? extends Tab> ov, Tab oldTab, Tab newTab) {
            Image preview = oldTab.getContent().snapshot(new SnapshotParameters(), null);
            peek.set(oldTab, preview);
         }
      });
      tabPane.selectionModelProperty().addListener(new ChangeListener<SingleSelectionModel<Tab>>() {

         @Override
         public void changed(ObservableValue<? extends SingleSelectionModel<Tab>> ov,
               SingleSelectionModel<Tab> oldValue, SingleSelectionModel<Tab> newValue) {
         }
      });

      // bind to take available space
      borderPane.prefHeightProperty().bind(scene.heightProperty());
      borderPane.prefWidthProperty().bind(scene.widthProperty());

      borderPane.setCenter(tabPane);
      root.getChildren().add(borderPane);
      primaryStage.setScene(scene);
      primaryStage.show();
   }
}