Is there a way to add mouseover state to a marker in Google Maps embedded in Java app via JxMaps? I was looking for a way to show whether the marker is clickable or not on hover. However, I didn’t find a suitable method that sets this icon the API
To implement functionality like this, you have to attach to marker mouse events and change marker icon (using Marker.setIcon method) depending on mouse position.
marker.addEventListener("mouseover", new MapEvent() {
#Override
public void onEvent() {
marker.setIcon(hoverIcon);
}
}});
marker.addEventListener("mouseout", new MapEvent() {
#Override
public void onEvent() {
marker.setIcon(normalIcon);
}
}});
Related
I was trying, with ViewPager2, to get default gallery-like experience of common Android SmartPhone, where you can zoom an image with pan and pinch controls along with the ability to navigate to another photo by swipe gestures.
I faced a problem in which when the zoomed image is swiped expecting it to get panned, instead of that, the ViewPager2 switched to another page.
ViewPager2 responds to the swipe event and causes page change and it doesn’t let zoomable view to respond to that event.
How do I solve the problem? Thanks.
The only solution I found is to use the old ViewPager with which it is possible to intercept events and if the photo is enlarged, it is possible to disable the page change and allow the management of the zoom.
First I defined a field, in a static class, to keep track of the state the photo is in:
public class Utilities {
....
static boolean isZoomed;
private Utilities () { }
static public void setIsZoomed (boolean z) {
isZoomed = z;
}
static public boolean getIsZoomed () {
return isZoomed;
}
....
}
Then in the custom class for managing the zoom I detect the status of the photo:
public class TouchImageView extends ImageView {
...
Utilities.setIsZoomed(normalizedScale != 1);
...
}
Finally, in the ViewPager custom class I disable or allow pagination based on the state of the photo:
public class CustomViewPager extends ViewPager {
public CustomViewPager (Context context) {
super(context);
}
public CustomViewPager (Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onInterceptTouchEvent (MotionEvent ev) {
try {
if (Utilities.getIsZoomed())
return false;
else
return super.onInterceptTouchEvent(ev);
} catch (IllegalArgumentException e) {
return false;
}
}
}
The title seems a little bit confusing, but I'll explain everything.
I'm developing a project where I show the image captured by a webcam in a JPanel, Java Swing. Now I have to integrate this with JavaFx.
I have a controller where I have the method startRecording, that would initialize the cameraThread and tell the class Camera to startRecording, inside Camera class a have a method DrawFrame(BufferedImage, JPanel panel) where I call the function drawImage from OpenCV to draw in the Panel:
Controller:
public void startRecording(){
cameraInstance.setCameraRGBPanel(windowsInstance.getCameraRGBPanel());
cameraInstance.setCameraHSVPanel(windowsInstance.getCameraHSVPanel());
cameraInstance.setCameraThresholdPanel(windowsInstance.getCameraThresholdPanel());
cameraInstance.setRecord(true);
cameraThread = new Thread(cameraInstance);
cameraThread.start();
}
Class camera:
private void drawFrame(BufferedImage buff, JPanel pane){
pane.getGraphics().drawImage(buff, 0, 0, null);
}
To start with, JavaFX has no JPanel and the Pane (an option) has no getGraphics, I've tried to use a SwingNode, add the JPanel and then do everything as usual, but the image simply won't be shown.
The following code was a test, that's why it seems to be so 'bad'.
public void start(Stage stage) throws Exception {
stage.setTitle("Tela Teste");
pCamera = new Pane();
SwingNode swing = new SwingNode();
pCamera.getChildren().add(swing);
createAndSetSeingContent(swing);
Group root = new Group();
root.getChildren().add(pCamera);
stage.setScene(new Scene(root , 500, 500));
stage.setResizable(true);
stage.show();
}
private void createAndSetSeingContent(SwingNode swing) {
ControllerCamera control = new ControllerCamera();
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
JPanel panel = new JPanel();
JLabel label = new JLabel("Abc");
//panel.add(label);
swing.setContent(panel);
Button teste = new Button("A");
pCamera.getChildren().add(teste);
teste.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
control.startRecording(panel);
System.out.println("abc");
}
});
}
I changed to method startRecording to something like:
public void startRecording(JPanel panel){
cameraInstance.setCameraRGBPanel(panel);
cameraInstance.setRecord(true);
cameraThread = new Thread(cameraInstance);
cameraThread.start();
}
Still nothing appears in the panel, but if I add a label or button, then it appear and works as intended to. The "abc" is always shown in the console.
I think that's all the code related to the problem. Something else I want to say is that yesterday was the first day I was dealing with FX, let's say the project is divided, the other guy is also working on the problem, but we haven't gotten anywhere so far, that's why I decided to ask you here.
Edit 1: everything was working perfectly before all this situation (everything works with Swing, but not in FX).
The simplest way to display an Image in JavaFX is with an ImageView. You can create a single ImageView and update its image by calling setImage(...), passing in a javafx.scene.image.Image. I don't know the camera API you are working with: you might be able to generate a JavaFX image directly, in which case your draw frame method looks as simple as:
private void drawFrame(Image image, ImageView imageView) {
imageView.setImage(image);
}
If you can only generate BufferedImages, you can do
private void drawFrame(BufferedImage buff, ImageView imageView) {
imageView.setImage(SwingFXUtils.toFXImage(buff, null));
}
In either case, you can just create the ImageView, put it in a Pane subclass of some kind, put the Pane in a scene and display it in the Stage:
public void start(Stage stage) throws Exception {
stage.setTitle("Tela Teste");
pCamera = new Pane();
ImageView imageView = new ImageView();
pCamera.getChildren().add(imageView);
Group root = new Group();
root.getChildren().add(pCamera);
stage.setScene(new Scene(root , 500, 500));
stage.setResizable(true);
stage.show();
}
Then just pass the imageView to your drawFrame method as needed.
So once again we are in the process of converting our existing Java application that was using entirely Swing to using JavaFX. However, the application will not be using JavaFX entirely. This seems to be causing some issues with Alerts/Dialogs and modality. We are currently using Java 8u40.
The main application is basically in a JFrame that has a Menu. The main content pane is JDesktopPane and clicking a MenuItem opens new JInternalFrames within the DeskopPane. Screens we are converting to JavaFX are basically JFXPanels within a JInternalFrame at the moment. Any Alerts/Dialogs that are opened from the JFXPanels are modal to the panel itself, but not to the JInternalFrame, DeskopPane, Menu, etc.
I read in the DialogPane documentation that they are planning to introduce some lightweight dialogs and even possibly InternalFrames in future releases of JavaFX, so maybe we'll just have to wait it out a little longer for this functionality. But, ideally when opening a new Alert/Dialog it would be modal to the entire Application.
EDIT:
Currently doing the following for modal dialogs:
((Stage)getDialogPane().getScene().getWindow()).setAlwaysOnTop(true);
This makes the dialog always appear on top, however the dialog also remains on top of other applications even if our main application is minimized. It also does not block input to any Swing components in the frame.
You can use the following work-around which creates an invisible JDialog when the Alert is shown and disposes the JDialog when the Alert is closed. This approach extends the modality to the whole application, including the Swing part.
// create Alert
Alert alert = new Alert(AlertType.INFORMATION, "Hello");
// create invisible JDialog and "show" it
JDialog dialog = new JDialog();
dialog.setModal(true);
dialog.setUndecorated(true);
dialog.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
SwingUtilities.invokeLater(() -> dialog.setVisible(true));
// show Alert
alert.showAndWait();
// close JDialog after Alert is closed
dialog.dispose();
I don't think i understand your question completely. But here is my guess - You are trying to make an alert window from some JFXPanel that will be modal (i.e. user will not be able to click in your application until she closes that alert window) to your entire application which is written partially using swing components.
If your application would be written in purely JavaFX then you would do something like (Assuming you have created a button somewhere in your JFXPanel)
button.setOnAction(evt -> {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.initModality(Modality.APPLICATION_MODAL);
// This will not work in your code
alert.initOwner(button.getScene().getWindow());
alert.show();
});
but since initOwner requires a javafx.stage.window object passing a swing component won't work in your code. As of Java 8u40 i don't think there is a right way(i.e. not hacks) to set ownership of Alert objects to swing component. Not surprisingly such questions has already been asked here and not answered as of writing this.
For your requirements you can use JOptionPane.showMessageDialog method and its look alike as workaround.
button.setOnAction(evt -> {
JOptionPane.showMessageDialog(desktopPane,"My message");
});
These dialog boxes are modal by default so no work is necessary. You can call these from any event handler methods of JavaFX components.
I've done a little workaround with a small interface which is implemented in my JavaFXFrame:
public interface DialogParent {
void setOnFocusGained(EventHandler<FocusEvent> focusHandler);
void setOnCloseRequest(EventHandler<WindowEvent> closeHandler);
}
And my JavaFXFrame implementation
public class JavaFXFrame implements DialogParent {
private JFrame frame;
private EventHandler<ch.irix.sumadmin.util.FocusEvent> focusGainedHandler;
private EventHandler<javafx.stage.WindowEvent> windowClosingHandler;
public void JavaFXFrame() {
final JFXPanel fxPanel = new JFXPanel();
frame = new JFrame();
frame.add(fxPanel);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
tryClosing(this);
}
});
frame.addWindowFocusListener(new WindowAdapter() {
#Override
public void windowGainedFocus(WindowEvent e) {
if (focusGainedHandler != null) {
focusGainedHandler.handle(new FocusEvent());
}
}
});
}
public void setVisible(boolean visible) {
frame.setVisible(visible);
}
private void tryClosing(WindowListener listener) {
javafx.stage.WindowEvent windowEvent = new javafx.stage.WindowEvent(null, javafx.stage.WindowEvent.WINDOW_CLOSE_REQUEST);
if (windowClosingHandler != null) {
windowClosingHandler.handle(windowEvent);
}
if (!windowEvent.isConsumed()) {
frame.setVisible(false);
}
}
#Override
public void setOnFocusGained(EventHandler<ch.irix.sumadmin.util.FocusEvent> focusGainedHandler) {
this.focusGainedHandler = focusGainedHandler;
}
#Override
public void setOnCloseRequest(EventHandler<javafx.stage.WindowEvent> windowClosingHandler) {
this.windowClosingHandler = windowClosingHandler;
}
}
And showing an Alert:
public static void showAlert(Alert alert) {
DialogPane dialogPane = alert.getDialogPane();
final Stage stage = new Stage();
stage.setScene(dialogPane.getScene());
List<ButtonType> buttonTypes = dialogPane.getButtonTypes();
for (ButtonType buttonType : buttonTypes) {
ButtonBase button = (ButtonBase) dialogPane.lookupButton(buttonType);
button.setOnAction(evt -> {
dialogPane.setUserData(buttonType);
stage.close();
});
}
dialogParent.setOnFocusGained(event -> {
stage.toFront();
});
dialogParent.setOnCloseRequest(Event::consume);
stage.setOnCloseRequest(event -> {
dialogParent.setOnFocusGained(null);
dialogParent.setOnCloseRequest(null);
});
stage.show();
}
Hope this will help you
I want to add a ClickListener to an Item of a MenuBar in Vaadin.
I know about the normal situation, which i got working:
MenuBar menubar = new MenuBar();
menubar.addItem("Item", new MenuBar.Command() {
#Override
public void menuSelected(MenuItem selectedItem) {
//Do sth. when item is clicked
}
});
In my application, I'm working with MVP, so the code which should run, is in an other class than the code which is defining the menubar.
Is there a way to add a listener to a specific item in the menubar ?
When you add an item to your MenuBar the function addItem(String,Command) actually returns a MenuItem which can be used later. You can do this :
MenuItem select = menuBar.addItem("Select", null);
And in another context you can add a listener on that MenuItem like this:
select.setCommand(new Command() {
#Override
public void menuSelected(MenuItem selectedItem) {
System.out.println("You clicked on "+selectedItem.getText());
}
});
I used the SimpleSwingBrowser example (http://docs.oracle.com/javafx/2/swing/SimpleSwingBrowser.java.htm) and added some code of my own for log tailing.
I wanted to add a search bar ability to it (Search and Highlight text).
After googling for hours and self experiments, I didn't find a way to do it.
Can someone give me a kick-off direction for writing such ability.
Suggestions for a JavaScript based solution
Use an existing JavaScript highlighting library such as jQuery highlight or hilitor.js.
Suggestions for a Java based solution
Use the Java w3c DOM API to perform operations on the WebEngine document object after the document has been loaded.
To get a Search API in the JavaFX WebView core implementation
I created feature request RT-23383 Text search support for WebView. The feature request is currently open and unactioned - you can create an account in the issue tracker and vote for or comment on the feature request.
Sample
This sample uses jQuery highlight. The user types the word to be highlighted into the text field, then presses the highlight button to highlight all occurrences of the word in the page or to remove highlight button to clear all marked highlights. You could modify the sample to allow further jQuery based searches to scroll to a next and previously highlighted word.
I tried to get it to work with any arbitrary web page, but that logic defeated me. If you control the source of the page you want to search and can add the reference to the jQuery highlight plugin and it's style class to your page, something like this sample program might be an option.
import javafx.application.Application;
import javafx.event.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.web.*;
import javafx.stage.Stage;
public class WebViewSearch extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
final WebView webView = new WebView();
final WebEngine engine = webView.getEngine();
engine.load("http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html");
final TextField searchField = new TextField("light");
searchField.setPromptText("Enter the text you would like to highlight and press ENTER to highlight");
searchField.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
if (engine.getDocument() != null) {
highlight(
engine,
searchField.getText()
);
}
}
});
final Button highlightButton = new Button("Highlight");
highlightButton.setDefaultButton(true);
highlightButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
searchField.fireEvent(new ActionEvent());
}
});
final Button removeHighlightButton = new Button("Remove Highlight");
removeHighlightButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
removeHighlight(
engine
);
}
});
removeHighlightButton.setCancelButton(true);
HBox controls = new HBox(10);
controls.getChildren().setAll(
highlightButton,
removeHighlightButton
);
VBox layout = new VBox(10);
layout.getChildren().setAll(searchField, controls, webView);
searchField.setMinHeight(Control.USE_PREF_SIZE);
controls.setMinHeight(Control.USE_PREF_SIZE);
controls.disableProperty().bind(webView.getEngine().getLoadWorker().runningProperty());
searchField.disableProperty().bind(webView.getEngine().getLoadWorker().runningProperty());
primaryStage.setScene(new Scene(layout));
primaryStage.show();
webView.requestFocus();
}
private void highlight(WebEngine engine, String text) {
engine.executeScript("$('body').removeHighlight().highlight('" + text + "')");
}
private void removeHighlight(WebEngine engine) {
engine.executeScript("$('body').removeHighlight()");
}
}