Я пытаюсь создать Peek
Control
для TabPane
.Таким образом, если панель уже открыта, Snapshot
сохраняется.Когда пользователь наводит курсор на Tab
, он показывает PopOver
.Это похоже на Windows Aero Peek
.
Моя проблема в том, что PopOver
скрывается, когда не должно ... потому что он получает событие hide()
от Tabs
Graphic
.
Я создал небольшой исполняемый пример, чтобы продемонстрировать проблему:
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();
}
}
, и это класс Peek
, который объединяет Snapshots
public class Peek {
ObservableMap<Object, Image> peeks = FXCollections.observableHashMap();
public void set(Object key, Image preview) {
peeks.put(key, preview);
}
public Image get(Object key) {
Image preview = peeks.get(key);
return preview;
}
}