Removing EventListener - java

I currently have an application which will create a textarea wherever the user clicks. However, I want the pane to only be editable when a certain condition is true. The clickable area never goes away, though. How can I change this so the area is only clickable if myAnchorPane.isVisible() is true?
double oldHeight = 0;
double oldWidth = 0;
#FXML
private void handleTextButton() {
System.out.println("Text Clicked");
TextHeaderTools.setVisible(false);
BackgroundTools.setVisible(false);
VideoTools.setVisible(false);
PageTitleTools.setVisible(false);
TemplateTools.setVisible(false);
ImageTools.setVisible(false);
TextTools.setVisible(true);
workspace.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent me) {
int x = (int) me.getX();
int y = (int) me.getY();
System.out.println("(" + x +", " + y +")");
InlineCssTextArea newArea = new InlineCssTextArea();
newArea.relocate(x, y);
newArea.setStyle("-fx-background-color: transparent;");
Text textHolder = new Text();
newArea.setPrefSize(40,40);
textHolder.textProperty().bind(newArea.textProperty());
textHolder.layoutBoundsProperty().addListener(new ChangeListener<Bounds>() {
#Override
public void changed(ObservableValue<? extends Bounds> observable, Bounds oldValue, Bounds newValue) {
if (oldHeight != newValue.getHeight()) {
oldHeight = newValue.getHeight();
newArea.setPrefHeight(textHolder.getLayoutBounds().getHeight() + 30);
}
if (oldWidth != newValue.getWidth()){
oldWidth = newValue.getWidth();
newArea.setPrefWidth(textHolder.getLayoutBounds().getWidth() + 30);
}
}
});
workspace.getChildren().addAll(newArea);
} //end handle
});
}
EDIT:
The condition is
myAnchorPane.isVisible()

You can achieve this nicely with ReactFX.
Instead of workspace.addEventHandler(MOUSE_CLICKED, ...), do this:
EventStreams.eventsOf(workspace, MOUSE_CLICKED)
.suppressWhen(myAnchorPane.visibleProperty().not())
.subscribe((MouseEvent me) -> {
// handle mouse click
});
I see you use RichTextFX, so you already have ReactFX as a dependency anyway.

Related

Waiting a keyevent [duplicate]

I want to write a little game where I can move a ball on a JavaFX Panel using the W, A, S, D keys.
I have a getPosX() and setPosX() but I don't know how to write a KeyListener which will e.g. calculate setPosX(getPosX()+1) if I press D.
What do I have to do?
From a JavaRanch Forum post.
Key press and release handlers are added on the scene and update movement state variables recorded in the application. An animation timer hooks into the JavaFX pulse mechanism (which by default will be capped to fire an event 60 times a second) - so that is a kind of game "loop". In the timer the movement state variables are checked and their delta actions applied to the character position - which in effect moves the character around the screen in response to key presses.
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.*;
import javafx.scene.image.*;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
/**
* Hold down an arrow key to have your hero move around the screen.
* Hold down the shift key to have the hero run.
*/
public class Runner extends Application {
private static final double W = 600, H = 400;
private static final String HERO_IMAGE_LOC =
"http://icons.iconarchive.com/icons/raindropmemory/legendora/64/Hero-icon.png";
private Image heroImage;
private Node hero;
boolean running, goNorth, goSouth, goEast, goWest;
#Override
public void start(Stage stage) throws Exception {
heroImage = new Image(HERO_IMAGE_LOC);
hero = new ImageView(heroImage);
Group dungeon = new Group(hero);
moveHeroTo(W / 2, H / 2);
Scene scene = new Scene(dungeon, W, H, Color.FORESTGREEN);
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
switch (event.getCode()) {
case UP: goNorth = true; break;
case DOWN: goSouth = true; break;
case LEFT: goWest = true; break;
case RIGHT: goEast = true; break;
case SHIFT: running = true; break;
}
}
});
scene.setOnKeyReleased(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
switch (event.getCode()) {
case UP: goNorth = false; break;
case DOWN: goSouth = false; break;
case LEFT: goWest = false; break;
case RIGHT: goEast = false; break;
case SHIFT: running = false; break;
}
}
});
stage.setScene(scene);
stage.show();
AnimationTimer timer = new AnimationTimer() {
#Override
public void handle(long now) {
int dx = 0, dy = 0;
if (goNorth) dy -= 1;
if (goSouth) dy += 1;
if (goEast) dx += 1;
if (goWest) dx -= 1;
if (running) { dx *= 3; dy *= 3; }
moveHeroBy(dx, dy);
}
};
timer.start();
}
private void moveHeroBy(int dx, int dy) {
if (dx == 0 && dy == 0) return;
final double cx = hero.getBoundsInLocal().getWidth() / 2;
final double cy = hero.getBoundsInLocal().getHeight() / 2;
double x = cx + hero.getLayoutX() + dx;
double y = cy + hero.getLayoutY() + dy;
moveHeroTo(x, y);
}
private void moveHeroTo(double x, double y) {
final double cx = hero.getBoundsInLocal().getWidth() / 2;
final double cy = hero.getBoundsInLocal().getHeight() / 2;
if (x - cx >= 0 &&
x + cx <= W &&
y - cy >= 0 &&
y + cy <= H) {
hero.relocate(x - cx, y - cy);
}
}
public static void main(String[] args) { launch(args); }
}
On filters, handlers and focus
To receive key events, the object that the event handlers are set on must be focus traversable. This example sets handlers on the scene directly, but if you were to set handlers on the pane instead of the scene, it would need to be focus traversable and have focus.
If you want a global intercept point to override or intercept events that are to be routed through the in-built event handlers which will consume events you want (e.g. buttons and text fields), you can have an event filter on the scene rather than a handler.
To better understand the difference between a handler and a filter, make sure that you study and understand the event capturing and bubbling phases as explained in the JavaFX event tutorial.
Generic input handler
Please ignore the rest of this answer if the information already provided is sufficient for your purposes.
While the above solution is sufficient to answer this question, if interested, a more sophisticated input handler (with a more general and separated, input and update handling logic), can be found in this demo breakout game:
Breakout input handler.
Example generic input handler from the sample breakout game:
class InputHandler implements EventHandler<KeyEvent> {
final private Set<KeyCode> activeKeys = new HashSet<>();
#Override
public void handle(KeyEvent event) {
if (KeyEvent.KEY_PRESSED.equals(event.getEventType())) {
activeKeys.add(event.getCode());
} else if (KeyEvent.KEY_RELEASED.equals(event.getEventType())) {
activeKeys.remove(event.getCode());
}
}
public Set<KeyCode> getActiveKeys() {
return Collections.unmodifiableSet(activeKeys);
}
}
While an ObservableSet with an appropriate set change listener could be used for the set of active keys, I have used an accessor which returns an unmodifiable set of keys which were active at a snapshot in time, because that is what I was interested in here rather than observing changes to the set of active keys in real-time.
If you want to keep track of the order in which keys are pressed, a Queue, List, or TreeSet can be used rather than a Set (for example, with a TreeSet ordering events on the time of keypress, the most recent key pressed would be the last element in the set).
Example generic input handler usage:
Scene gameScene = createGameScene();
// register the input handler to the game scene.
InputHandler inputHandler = new InputHandler();
gameScene.setOnKeyPressed(inputHandler);
gameScene.setOnKeyReleased(inputHandler);
gameLoop = createGameLoop();
// . . .
private AnimationTimer createGameLoop() {
return new AnimationTimer() {
public void handle(long now) {
update(now, inputHandler.getActiveKeys());
if (gameState.isGameOver()) {
this.stop();
}
}
};
}
public void update(long now, Set<KeyCode> activeKeys) {
applyInputToPaddle(activeKeys);
// . . . rest of logic to update game state and view.
}
// The paddle is sprite implementation with
// an in-built velocity setting that is used to
// update its position for each frame.
//
// on user input, The paddle velocity changes
// to point in the correct predefined direction.
private void applyInputToPaddle(Set<KeyCode> activeKeys) {
Point2D paddleVelocity = Point2D.ZERO;
if (activeKeys.contains(KeyCode.LEFT)) {
paddleVelocity = paddleVelocity.add(paddleLeftVelocity);
}
if (activeKeys.contains(KeyCode.RIGHT)) {
paddleVelocity = paddleVelocity.add(paddleRightVelocity);
}
gameState.getPaddle().setVelocity(paddleVelocity);
}
Scene myScene = new Scene();
KeyCombination cntrlZ = new KeyCodeCombination(KeyCode.Z, KeyCodeCombination.CONTROL_DOWN);
myScene.setOnKeyPressed(new EventHandler<KeyEvent>(){
#Override
public void handle(KeyEvent event) {
if(contrlZ.match(event)){
//Do something
}
}
});
using JNativeHook:
https://github.com/kwhat/jnativehook
<!-- https://mvnrepository.com/artifact/com.1stleg/jnativehook -->
<dependency>
<groupId>com.1stleg</groupId>
<artifactId>jnativehook</artifactId>
<version>2.1.0</version>
</dependency>
private void initKeyListener(Stage primaryStage){
/* Note: JNativeHook does *NOT* operate on the event dispatching thread.
* Because Swing components must be accessed on the event dispatching
* thread, you *MUST* wrap access to Swing components using the
* SwingUtilities.invokeLater() or EventQueue.invokeLater() methods.
*/
try {
GlobalScreen.registerNativeHook();
} catch (NativeHookException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
GlobalScreen.addNativeKeyListener(new NativeKeyListener() {
public void nativeKeyPressed(NativeKeyEvent e) {
if ( (e.getModifiers() & NativeKeyEvent.CTRL_MASK) != 0
&& (e.getModifiers() & NativeKeyEvent.ALT_MASK) != 0
&& (e.getKeyCode() == NativeKeyEvent.VC_B)){
logger.debug("key :Hide");
primaryStage.hide();
}
if ( (e.getModifiers() & NativeKeyEvent.CTRL_MASK) != 0
&& (e.getModifiers() & NativeKeyEvent.SHIFT_MASK) != 0
&& (e.getModifiers() & NativeKeyEvent.ALT_MASK) != 0
&& (e.getKeyCode() == NativeKeyEvent.VC_B)){
logger.debug("key :Show");
primaryStage.show();
}
//System.out.println("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
}
public void nativeKeyReleased(NativeKeyEvent e) {
//System.out.println("Key Released: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
}
public void nativeKeyTyped(NativeKeyEvent e) {
//System.out.println("Key Typed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
}
});
/*
GlobalScreen.addNativeMouseListener(new NativeMouseListener() {
#Override
public void nativeMouseReleased(NativeMouseEvent arg0) {
// TODO Auto-generated method stub
System.out.println("MouseReleased()");
}
#Override
public void nativeMousePressed(NativeMouseEvent arg0) {
// TODO Auto-generated method stub
System.out.println("MousePressed()");
}
#Override
public void nativeMouseClicked(NativeMouseEvent arg0) {
// TODO Auto-generated method stub
System.out.println("MouseClicked()");
}
});
*/
}

Not calling SwingUtilities.invokeLater() causes NullPointerException

I have a created a class of ComboBox popup menu listener to change the width of popup menu from the actual width of combobox.
protected void customizePopup(BasicComboPopup popup)
{
scrollPane = getScrollPane(popup);
if (popupWider)
popupWider( popup );
checkHorizontalScrollBar( popup );
// For some reason in JDK7 the popup will not display at its preferred
// width unless its location has been changed from its default
// (ie. for normal "pop down" shift the popup and reset)
Component comboBox = popup.getInvoker();
Point location = comboBox.getLocationOnScreen();
if (popupAbove)
{
int height = popup.getPreferredSize().height;
popup.setLocation(location.x, location.y - height);
}
else
{
int height = comboBox.getPreferredSize().height;
popup.setLocation(location.x, location.y + height - 1);
popup.setLocation(location.x, location.y + height);
}
}
And this method is called from
public void popupMenuWillBecomeVisible(PopupMenuEvent e)
{
JComboBox comboBox = (JComboBox)e.getSource();
if (comboBox.getItemCount() == 0) return;
final Object child = comboBox.getAccessibleContext().getAccessibleChild(0);
if (child instanceof BasicComboPopup)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run() {
customizePopup((BasicComboPopup)child);
}
});
}
}
calling method CustomizePopup() outside EDT causes NullPointerException.
Can anyone tell me what is the reason??
Why do we need another EDT to process CustomizePopup()?
public void popupMenuWillBecomeVisible(PopupMenuEvent e)
{
JComboBox comboBox = (JComboBox)e.getSource();
if (comboBox.getItemCount() == 0) return;
final Object child = comboBox.getAccessibleContext().getAccessibleChild(0);
if (child instanceof BasicComboPopup)
{
customizePopup((BasicComboPopup)child);
}
}

Javafx slider value at mousemoved event

I am making a media player and am trying to get the playback slider value at the cursor position when hovering over the slider bar. In an attempt to do this, i have used the following:
timeSlider.addEventFilter(MouseEvent.MOUSE_MOVED, event -> System.out.println("hovering"));
which prints "hovering" whenever the mouse changes position over the slider. Can anyone please show me how to get the value of the slider at the current cursor position? I can only figure out how to get the value at the thumb position.
Thanks in advance.
Here is a bit (maybe more than a bit) of a hack that works if you are showing the axis under the slider. It relies on looking up the axis via its css class, converting the mouse coordinates to coordinates relative to the axis, and then using API from ValueAxis to convert to the value:
import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.chart.NumberAxis;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.StackPane;
import javafx.stage.Popup;
import javafx.stage.Stage;
public class TooltipOnSlider extends Application {
#Override
public void start(Stage primaryStage) {
Slider slider = new Slider(5, 25, 15);
slider.setShowTickMarks(true);
slider.setShowTickLabels(true);
slider.setMajorTickUnit(5);
Label label = new Label();
Popup popup = new Popup();
popup.getContent().add(label);
double offset = 10 ;
slider.setOnMouseMoved(e -> {
NumberAxis axis = (NumberAxis) slider.lookup(".axis");
Point2D locationInAxis = axis.sceneToLocal(e.getSceneX(), e.getSceneY());
double mouseX = locationInAxis.getX() ;
double value = axis.getValueForDisplay(mouseX).doubleValue() ;
if (value >= slider.getMin() && value <= slider.getMax()) {
label.setText(String.format("Value: %.1f", value));
} else {
label.setText("Value: ---");
}
popup.setAnchorX(e.getScreenX());
popup.setAnchorY(e.getScreenY() + offset);
});
slider.setOnMouseEntered(e -> popup.show(slider, e.getScreenX(), e.getScreenY() + offset));
slider.setOnMouseExited(e -> popup.hide());
StackPane root = new StackPane(slider);
primaryStage.setScene(new Scene(root, 350, 80));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This is mostly a bug-track-down: James's answer is perfect - only hampered by 2 issues:
the axis has to be visible, that is at least one of ticks or labels must be showing (in practice not a big obstacle: if you want to get the values at mouseOver you'r most probably showing the ticks anyway)
A bug in SliderSkin which introduce a slight skew of axis value vs slider value.
To see the latter, here's a slight variation of James's code. To see the asynchronicity, move the mouse over the slider then click. We expect the value of the popup to be the same as the value of the slider (shown in the label at the bottom). With core SliderSkin, they differ slightly.
public class TooltipOnSlider extends Application {
private boolean useAxis;
#Override
public void start(Stage primaryStage) {
Slider slider = new Slider(5, 25, 15);
useAxis = true;
// force an axis to be used
slider.setShowTickMarks(true);
slider.setShowTickLabels(true);
slider.setMajorTickUnit(5);
// slider.setOrientation(Orientation.VERTICAL);
// hacking around the bugs in a custom skin
// slider.setSkin(new MySliderSkin(slider));
// slider.setSkin(new XSliderSkin(slider));
Label label = new Label();
Popup popup = new Popup();
popup.getContent().add(label);
double offset = 30 ;
slider.setOnMouseMoved(e -> {
NumberAxis axis = (NumberAxis) slider.lookup(".axis");
StackPane track = (StackPane) slider.lookup(".track");
StackPane thumb = (StackPane) slider.lookup(".thumb");
if (useAxis) {
// James: use axis to convert value/position
Point2D locationInAxis = axis.sceneToLocal(e.getSceneX(), e.getSceneY());
boolean isHorizontal = slider.getOrientation() == Orientation.HORIZONTAL;
double mouseX = isHorizontal ? locationInAxis.getX() : locationInAxis.getY() ;
double value = axis.getValueForDisplay(mouseX).doubleValue() ;
if (value >= slider.getMin() && value <= slider.getMax()) {
label.setText("" + value);
} else {
label.setText("Value: ---");
}
} else {
// this can't work because we don't know the internals of the track
Point2D locationInAxis = track.sceneToLocal(e.getSceneX(), e.getSceneY());
double mouseX = locationInAxis.getX();
double trackLength = track.getWidth();
double percent = mouseX / trackLength;
double value = slider.getMin() + ((slider.getMax() - slider.getMin()) * percent);
if (value >= slider.getMin() && value <= slider.getMax()) {
label.setText("" + value);
} else {
label.setText("Value: ---");
}
}
popup.setAnchorX(e.getScreenX());
popup.setAnchorY(e.getScreenY() + offset);
});
slider.setOnMouseEntered(e -> popup.show(slider, e.getScreenX(), e.getScreenY() + offset));
slider.setOnMouseExited(e -> popup.hide());
Label valueLabel = new Label("empty");
valueLabel.textProperty().bind(slider.valueProperty().asString());
BorderPane root = new BorderPane(slider);
root.setBottom(valueLabel);
primaryStage.setScene(new Scene(root, 350, 100));
primaryStage.show();
primaryStage.setTitle("useAxis: " + useAxis + " mySkin: " + slider.getSkin().getClass().getSimpleName());
}
public static void main(String[] args) {
launch(args);
}
#SuppressWarnings("unused")
private static final Logger LOG = Logger.getLogger(TooltipOnSlider.class
.getName());
}
Note that there's an open issue which reports a similar behavior (though not so easy to see)
Looking into the code of SliderSkin, the culprit seems to be an incorrect calculation of the relative value from a mouse event on the track:
track.setOnMousePressed(me -> {
...
double relPosition = (me.getX() / trackLength);
getBehavior().trackPress(me, relPosition);
...
});
where track is positioned in the slider as:
// layout track
track.resizeRelocate((int)(trackStart - trackRadius),
trackTop ,
(int)(trackLength + trackRadius + trackRadius),
trackHeight);
Note that the active width (aka: trackLenght) of the track is offset by trackRadius, thus calculating the relative distance with the raw mousePosition on the track gives a slight error.
Below is a crude custom skin that replaces the calc simply as a test if the little application behaves as expected. Looks terrible due the need to use reflection to access super's fields/methods but now has slider and axis value in synch.
The quick hack:
/**
* Trying to work around down to the slight offset.
*/
public static class MySliderSkin extends SliderSkin {
/**
* Hook for replacing the mouse pressed handler that's installed by super.
*/
protected void installListeners() {
StackPane track = (StackPane) getSkinnable().lookup(".track");
track.setOnMousePressed(me -> {
invokeSetField("trackClicked", true);
double trackLength = invokeGetField("trackLength");
double trackStart = invokeGetField("trackStart");
// convert coordinates into slider
MouseEvent e = me.copyFor(getSkinnable(), getSkinnable());
double mouseX = e.getX();
double position;
if (mouseX < trackStart) {
position = 0;
} else if (mouseX > trackStart + trackLength) {
position = 1;
} else {
position = (mouseX - trackStart) / trackLength;
}
getBehavior().trackPress(e, position);
invokeSetField("trackClicked", false);
});
}
private double invokeGetField(String name) {
Class clazz = SliderSkin.class;
Field field;
try {
field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.getDouble(this);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return 0.;
}
private void invokeSetField(String name, Object value) {
Class clazz = SliderSkin.class;
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
field.set(this, value);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Constructor - replaces listener on track.
* #param slider
*/
public MySliderSkin(Slider slider) {
super(slider);
installListeners();
}
}
A deeper fix might be to delegate all the dirty coordinate/value transformations to the axis - that's what it is designed to do. This requires the axis to be part of the scenegraph always and only toggle its visibilty with ticks/labels showing. A first experiment looks promising.

Javafx - Bounds are zero until seen

In an attempt to fix a problem with printing within the margins, I'm trying to scale my forms so that they'd shrink to the size of the paper it will be printed to.
Inside Printable.java that extends VBox
public void scaleToFit(){
double maxWidth = 497.0;
this.requestLayout();
double width = this.getWidth();
if(width > maxWidth){
double widthFrac = maxWidth / width;
this.setScaleX(widthFrac);
}
System.out.println(this.getWidth());
//edited out same process for height
}
Printable will be kept in a HashMap data.table. When my printing window is loaded I run scaleToFit for each of them. main is a ScrollPane.
Inside ModPrintCycle.java that extends VBox
//inside constructor
main.sceneProperty().addListener(new ChangeListener<Scene>(){
#Override
public void changed(ObservableValue<? extends Scene> observable, Scene oldValue, Scene newValue) {
System.out.println("new Scene");
newValue.windowProperty().addListener(new ChangeListener<Window>(){
public void changed(ObservableValue<? extends Window> arg0, Window arg1, Window arg2) {
System.out.println("new Window");
arg2.setOnShown(new EventHandler<WindowEvent>(){
#Override
public void handle(WindowEvent event) {
Platform.runLater(new Runnable(){
#Override
public void run() {
System.out.println(event.toString());
lookingAt = data.tables.size();
while(lookingAt-1 >= 0 ){
showNext(-1);
}
}
});
}
});
}
});
}
});
Just for this example, I also added scaleToFit() in the button that changes between these Printables. [EDIT: Added the scripts that explicitly show the use of scaleToFit()] Note that data.tables is a HashMap containing the Printables.
Inside ModPrintCycle.java continuation
private void showNext(int move){
boolean k = false;
if(move > 0 && lookingAt+move < data.tables.size()){
k = true;
}
else if(move < 0 && lookingAt+move >=0){
k = true;
}
if(k){
lookingAt+= move;
}
show();
}
private void show(){
if(data.tables.size() > 0){
if(lookingAt >= 0 && lookingAt < data.tables.size()){
//tableOrder is an ArrayList<String> for the arrangement of data.tables
if(tableOrder.size() > 0){
Printable pt = data.tables.get(tableOrder.get(lookingAt));
main.setContent(pt);
pt.scaleToFit();
}
}
else{
if(lookingAt < 0){
lookingAt = 0;
show();
}
else if(lookingAt >= data.tables.size()){
lookingAt = data.tables.size()-1;
show();
}
}
txtStatus.setText((lookingAt+1) + " / " + data.tables.size());
}else{
main.setContent(null);
txtStatus.setText("Empty");
}
}
public void printAll(ArrayList<String> pageList){
//PrinterJob pj is global
//conditions and try declarations
pj = PrinterJob.createPrinterJob(curP);
PageLayout pp = curP.createPageLayout(Paper.LEGAL, PageOrientation.PORTRAIT, MarginType.DEFAULT);
PageLayout pl = curP.createPageLayout(Paper.LEGAL, PageOrientation.LANDSCAPE, MarginType.DEFAULT);
for(String p : pageList){
Printable pt = data.tables.get(p);
pt.scaleToFit();
if(pt.isLandscape()){
pj.printPage(pl,pt);
}
else{
pj.printPage(pp,pt);
}
}
pj.endJob();
// catch statements
}
However, whenever scaleToFit() is called for the first time (when ModPrintCycle is loaded), it tells me that the widths are 0, thus will not scale yet. The second time it is called (when I change between them for the first time), it's still 0. When it finally runs a 3rd time (when I look back at the Printable), it finally works and changes the widths as needed.
Since these Printables need to be printed, I cannot ensure that the forms are scaled until someone looks through all of them twice.
How do I force the forms to take their bounds before having to load them?
Since the code you posted is not fully executable (i.e. not MCVE or SSCCE), the problem cannot be reproduced. It is also difficult to guess the cause. But I see your purpose, so I suggest instead of scaling it manually, let the printable scale itself automatically through listener:
#Override
public void start( Stage stage )
{
ScrollPane scrollPane = new ScrollPane( new Printable( new Label( "looong loooong loooooong looooong loooong text" ) ) );
stage.setScene( new Scene( scrollPane ) );
stage.show();
}
class Printable extends VBox
{
public Printable( Node... children )
{
super( children );
Printable me = this;
this.widthProperty().addListener( new ChangeListener<Number>()
{
#Override
public void changed( ObservableValue<? extends Number> observable, Number oldValue, Number newValue )
{
double maxWidth = 100.0;
double width = newValue.doubleValue();
if ( width > maxWidth )
{
double widthFrac = maxWidth / width;
me.setScaleX( widthFrac );
}
}
} );
}
}

MouseOver of FlexTable with GWT

Hello everyone
I have a FlexTable that contains images (one for each cell). I wish I had an event that you move your mouse over the cell comes out a popup that should contain the title of the image.
Someone can give me a hand?
I tried to insert this code does what he must do (at least for me) but the popup remains active when I remove the mouse pointer .where I wrong?
private FlexTable createHTML(ImageResult result,int row,final int i,int currentCol) {
immagine[i]=new Image(result.getThumbnailUrl());
resultsTableImm.setWidget(row, currentCol, immagine[i]);
titleImm[i]=result.getTitleNoFormatting();
contentImm[i]=result.getContentNoFormatting();
urlImm[i]=result.getUnescapedUrl();
immagine[i].addMouseOverHandler(new MouseOverHandler() {
#Override
public void onMouseOver(MouseOverEvent event) {
PopupPanel p = new PopupPanel(true);
Widget source = (Widget) event.getSource();
int x = source.getAbsoluteLeft() + 10;
int y = source.getAbsoluteTop() + 10;
p.add(new HTML("<b>"+titleImm[i]+"</b><br>"+contentImm[i]));
p.setPopupPosition(x, y);
p.show();
}
});
return resultsTableImm;
}
Thank you and have a nice day
JD
FlexTable hasn't onMouseOverHandler. It only has clickHandler. So you can't attach mouse over handler to the table(cell). One way is addMouseOverHandler to the image show them in the popuplike that
Image image= new Image();
image.addMouseOverHandler(new MouseOverHandler() {
#Override
public void onMouseOver(MouseOverEvent event) {
PopupPanel p = new PopupPanel(true);
Widget source = (Widget) event.getSource();
int x = source.getAbsoluteLeft() + 10;
int y = source.getAbsoluteTop() + 10;
p.add(image);
p.setPopupPosition(x, y);
p.show();
}
});
If you use gwt2.1 then I suggest you to use CellTable
Look at this example Cell Table
You can make custom widget with registered onmouseover handler and place it to flex table (idea is not trying to add listener for cell, but have it on widget itself which resides in cell).
Or you can try something like this:
http://www.java2s.com/Code/Java/GWT/TableMouseOverEvent.htm
Boiling down Xorty's example to the essentials of the present question you may adapt the following extension of FlexTable:
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.FlexTable;
public class PTable extends FlexTable {
public static final String ROW_STYLE_NAME = "pm-PTable-row";
PTable() {
setStyleName("pm-PTable");
sinkEvents(Event.ONMOUSEOVER |Event.ONMOUSEOUT);
}
#Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
Element td = getEventTargetCell(event);
if (td == null) return;
Element tr = DOM.getParent(td);
switch (DOM.eventGetType(event)) {
case Event.ONMOUSEOVER: {
tr.addClassName(ROW_STYLE_NAME + "-mouseover");
break;
}
case Event.ONMOUSEOUT: {
tr.removeClassName(ROW_STYLE_NAME + "-mouseover");
break;
}
}
}
}

Categories

Resources