Gluon Charm TextField NPE - gluon

When you clear a TextField which is initialized with a floatText by textField.setText(null), the floatText isn't transitioned back to the bottom, and focusing the TextField again causes a NPE.
setText("") doesn't cause the NPE, but the floatText still stays on top.
public class GluonApplication extends MobileApplication {
#Override
public void init() {
addViewFactory(HOME_VIEW, () ->
{
TextField txtFloating = new TextField();
txtFloating.setFloatText("floating");
TextField txtNonFloating = new TextField();
txtNonFloating.setPromptText("non floating");
Button btnClear = new Button("clear text");
btnClear.setOnAction(e -> {
txtFloating.setText(null);
txtNonFloating.setText(null);
});
VBox boxContent = new VBox(20,txtNonFloating, txtFloating, btnClear);
boxContent.setAlignment(Pos.CENTER);
View view = new View(boxContent) {
#Override
protected void updateAppBar(AppBar appBar) {
appBar.setTitleText("Home");
}
};
return view;
});
}

Related

JavaFX more Scenes

Hi Guys i build a GUI and on this GUI is a Button and when I press the Button a second GUI appears, on the second GUI is also a Button and when i press the Button it goes back
GU1
btn.setOnAction(new EventHandler <ActionEvent>(){
public void handle(ActionEvent arg0) {
try {
new GUI2().start(primaryStage);
} catch (Exception e) {
e.printStackTrace();
}
}
});
My Questions!
Is GUI1 still running when i press the Button?
GUI2
btn.setOnAction(new EventHandler <ActionEvent>(){
public void handle(ActionEvent arg0) {
try {
//back to the main menu
new GUI1().start(primaryStage);
} catch (Exception e) {
e.printStackTrace();
}
}
});
When i press the Button, does it go back to the same instance when beginning the program? Or make it a new Instance witch has the same look, and use it more RAM;
How should it works, when i want to open the second GUI in a external Window
When i press the Button, does it go back to the same instance when beginning the program?
No, a new instance is created based on your code new GUI2().start(primaryStage);. Always remember that thenew keyword ALWAYS creates a new object.
How should it works, when i want to open the second GUI in a external Window?
There are lots of ways to do this.
Method 1
If it happen that you created two applications, both extending the Application class, this method should work.
public class MultiWindowFX {
private static final Logger logger = Logger.getGlobal();
public static class GUI1 extends Application {
private final Button buttonShowGUI2;
private final GUI2 gui2;
public GUI1() {
buttonShowGUI2 = new Button("Show GUI 2");
gui2 = new GUI2();
}
public Button getButtonShowGUI2() {
return buttonShowGUI2;
}
#Override
public void start(Stage primaryStage) throws Exception {
//add an action event on GUI2's buttonShowGUI1 to send front GUI1
gui2.getButtonShowGUI1().setOnAction(gui2ButtonEvent -> {
if (primaryStage.isShowing()) primaryStage.toFront();
else primaryStage.show();
});
//button with action to show GUI 2
buttonShowGUI2.setOnAction(actionEvent -> {
try {
if (gui2.getPrimaryStage() == null) gui2.start(new Stage());
else gui2.getPrimaryStage().toFront();
} catch (Exception ex) {
logger.log(Level.SEVERE, null, ex);
}
});
//set scene and its root
Pane root = new StackPane(buttonShowGUI2);
Scene stageScene = new Scene(root, 400, 250);
//set stage
primaryStage.setScene(stageScene);
primaryStage.centerOnScreen();
primaryStage.setTitle("GUI 1");
primaryStage.show();
}
public static void launchApp(String... args) {
GUI1.launch(args);
}
}
public static class GUI2 extends Application {
private Stage primaryStage;
private final Button buttonShowGUI1;
public GUI2() {
buttonShowGUI1 = new Button("Show GUI 1");
}
public Button getButtonShowGUI1() {
return buttonShowGUI1;
}
public Stage getPrimaryStage() {
return primaryStage;
}
#Override
public void start(Stage primaryStage) throws Exception {
//get stage reference
this.primaryStage = primaryStage;
//set scene and its root
Pane root = new StackPane(buttonShowGUI1);
Scene stageScene = new Scene(root, 400, 250);
//set stage
primaryStage.setScene(stageScene);
primaryStage.centerOnScreen();
primaryStage.setTitle("GUI 2");
primaryStage.show();
}
public static void launchApp(String... args) {
GUI2.launch(args);
}
}
public static void main(String... args) {
GUI1.launchApp(args);
}
}
Method 2
For me, this is the best approach especially if you want window ownership and modality works.
public class GUI1 extends Application {
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Show GUI2");
btn.setOnAction(actionEvent -> {
//prepare gui2
Stage gui2Stage = createGUI2();
//set window modality and ownership
gui2Stage.initModality(Modality.APPLICATION_MODAL);
gui2Stage.initOwner(primaryStage);
//show
gui2Stage.show();
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 400, 250);
primaryStage.setTitle("GUI 1");
primaryStage.setScene(scene);
primaryStage.show();
}
private Stage createGUI2() {
Button btn = new Button();
btn.setText("Show GUI1");
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 150);
Stage gui2Stage = new Stage();
gui2Stage.setTitle("GUI 2");
gui2Stage.setScene(scene);
//add an action event to GUI2's button, which hides GUI2 and refocuses to GUI1
btn.setOnAction(actionEvent -> gui2Stage.hide());
return gui2Stage;
}
public static void main(String[] args) {
launch(args);
}
}
...and among other methods. Choose the approach that fits to your requirements.

Using one event handler for multiple actions

I was doing some homework today and I've accomplished all of the goals of the assignment, which I'm sure will get me full points.
In an earlier class, however, we used the same Event Handler for more than one action (in this example, you either type a color in the text field, or click a button to change the background color of the box).
I can't figure out how I would do that in this case... do I have to choose a Type in the constructor? If the first parameter could be a button or a textfield then I think that would help.
I'm just trying to figure out how to apply DRY (Don't Repeat Yourself), where ever I can.
public class ColorChooserApplication extends Application
{
#Override
public void start(Stage stage)
{
// Create all UI components
VBox backgroundBox = new VBox(10);
backgroundBox.setPadding(new Insets(10));
HBox topBox = new HBox(10);
HBox bottomBox = new HBox(10);
TextField colorPrompt = new TextField();
colorPrompt.setOnAction(new ColorHandler(colorPrompt, backgroundBox));
Button redButton = new Button("Red");
redButton.setOnAction(new ButtonHandler(redButton, backgroundBox));
Button whiteButton = new Button("White");
whiteButton.setOnAction(new ButtonHandler(whiteButton, backgroundBox));
Button blueButton = new Button("Blue");
blueButton.setOnAction(new ButtonHandler(blueButton, backgroundBox));
// Assemble
topBox.getChildren().add(colorPrompt);
bottomBox.getChildren().addAll(redButton, whiteButton, blueButton);
backgroundBox.getChildren().addAll(topBox, bottomBox);
backgroundBox.setAlignment(Pos.CENTER);
topBox.setAlignment(Pos.CENTER);
bottomBox.setAlignment(Pos.CENTER);
// Set scene and show
stage.setScene(new Scene(backgroundBox));
stage.show();
}
class ColorHandler implements EventHandler<ActionEvent>
{
TextField colorTf;
VBox bgVbox;
public ColorHandler(TextField colorTf, VBox bgVbox)
{
this.colorTf = colorTf;
this.bgVbox = bgVbox;
}
#Override
public void handle(ActionEvent event)
{
String color = colorTf.getText();
bgVbox.setStyle("-fx-background-color:" + color);
}
}
class ButtonHandler implements EventHandler<ActionEvent>
{
Button colorButton;
VBox bgVbox;
public ButtonHandler(Button colorButton, VBox bgVbox)
{
this.colorButton = colorButton;
this.bgVbox = bgVbox;
}
#Override
public void handle(ActionEvent event)
{
String color = colorButton.getText();
bgVbox.setStyle("-fx-background-color:" + color);
}
}
public static void main(String[] args)
{
launch(args);
}
}
If you're using Java 8, you can do
class ColorHandler implements EventHandler<ActionEvent> {
Supplier<String> colorSupplier ;
VBox bgVbox ;
public ColorHandler(Supplier<String> colorSupplier, VBox bgVbox) {
this.colorSupplier = colorSupplier ;
this.bgVbox = bgVbox ;
}
#Override
public void handle(ActionEvent event) {
String color = colorSupplier.get();
bgVbox.setStyle("-fx-background-color: "+color);
}
}
and then
colorPrompt.setOnAction(new ColorHandler(colorPrompt::getText, backgroundBox));
redButton.setOnAction(new ColorHandler(redButton::getText, backgroundBox));
Note that all you need to provide for the first parameter is some function that returns the correct string for use in the css. So you can do things like
whiteButton.setOnAction(new ColorHandler(() -> "#ffffff", backgroundBox));
blueButton.setOnAction(new ColorHandler(() -> "cornflowerblue", backgroundBox));
etc.

Wicket 6 AjaxFormComponentUpdatingBehavior event working on first row of ListView but not for subsequent ones

I'm trying to handle a DropDownChoice onchange event in a listView that can display a modal window. It seems working fine for first element but not for subsequent added elements.
final ModalWindow modal = new ModalWindow("modal");
modal.setOutputMarkupId(true);
form.add(modal);
final ListView<CommandeFournisseurDetails> myView = new ListView<CommandeFournisseurDetails>(
"rowsList",
new PropertyModel<List<CommandeFournisseurDetails>>(this,
"rows")) {
#Override
protected void populateItem(
final ListItem<CommandeFournisseurDetails> item) {
final CommandeCollectionJDBC myCollection = new CommandeCollectionJDBC();
CommandeFournisseurDetails row = item.getModelObject();
item.add(new Label("index",
new AbstractReadOnlyModel<Integer>() {
#Override
public Integer getObject() {
return item.getIndex() + 1;
}
}));
final DropDownChoice<String> ID_PRODUIT = new DropDownChoice(
"ID_PRODUIT", new PropertyModel<String>(row,
"ID_PRODUIT"), myCollection.getProduit());
ID_PRODUIT.setOutputMarkupId(true);
ID_PRODUIT.setMarkupId("ID_PRODUIT");
ID_PRODUIT.setLabel(Model.of("Produit"));
ID_PRODUIT.setRequired(true);
AjaxFormComponentUpdatingBehavior behavior = new AjaxFormComponentUpdatingBehavior(
"onChange") {
protected void onUpdate(AjaxRequestTarget target) {
if (!ID_PRODUIT.getDefaultModelObjectAsString()
.isEmpty()) {
final PageParameters params = new PageParameters();
params.set("message",
ID_PRODUIT.getDefaultModelObjectAsString());
params.set("type", "Produit");
modal.setPageCreator(new ModalWindow.PageCreator() {
public Page createPage() {
// Use this constructor to pass a reference
// of this page.
return new ModalContentPage(modal, params);
}
});
modal.show(target);
target.add(modal);
target.add(ID_PRODUIT);
}
}
protected void onError(AjaxRequestTarget target,
RuntimeException e) {
System.out.println(e.toString());
}
};
ID_PRODUIT.add(behavior);
AbstractSubmitLink remove = new SubmitLink("removeRowLink") {
#Override
public void onSubmit() {
getList().remove(item.getModelObject());
getParent().getParent().removeAll();
};
}.setDefaultFormProcessing(false);
item.add(remove);
}
}.setReuseItems(true);
form.add(new SubmitLink("addRowLink") {
#Override
public void onSubmit() {
rows.add(new CommandeFournisseurDetails());
}
}.setDefaultFormProcessing(false));
myView.setOutputMarkupId(true);
form.add(myView);
Any idea why the other elements do not inherit the same event?
Thanks for your help.
All ID-PRODUIT dropdownchoices (the first, but also the rest) have the same markupId, thanks to:
ID_PRODUIT.setMarkupId("ID_PRODUIT");
Try giving them a unique MarkupId. Perhaps by adding the index of the listitem:
ID_PRODUIT.setMarkupId("ID_PRODUIT" + item.getIndex());
or remove that line of code altogether.

JavaFX stop Timeline

I use FXML. I've created a button to stop/restart a live chart. For the animation I've used Timeline. I'would like to control it from the guiController (from an other class), but it is not working. How can I stop a Timeline from an other class?
Thank you!
FXML:
<Button id="button" layoutX="691.0" layoutY="305.0" mnemonicParsing="false" onAction="#btn_startmes" prefHeight="34.0" prefWidth="115.0" text="%start" />
guiController:
#FXML
private void btn_stopmes(ActionEvent event) {
MotionCFp Stopping = new MotionCFp();
Stopping.animation.stop();
}
MotionCFp.java:
#Override
public void start(final Stage stage) throws Exception {
else{
ResourceBundle motionCFp = ResourceBundle.getBundle("motionc.fp.Bundle", new Locale("en", "EN"));
AnchorPane root = (AnchorPane) FXMLLoader.load(MotionCFp.class.getResource("gui.fxml"), motionCFp);
final guiController gui = new guiController();
Scene scene = new Scene(root);
stage.setTitle(motionCFp.getString("title"));
stage.setResizable(false);
stage.setScene(scene);
root.getChildren().add(gui.createChart());
animation = new Timeline();
animation.getKeyFrames().add(new KeyFrame(Duration.millis(1000/60), new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent actionEvent) {
// 6 minutes data per frame
for(int count=0; count < 6; count++) {
gui.nextTime();
gui.plotTime();
animation.pause();
animation.play();
}
}
}));
animation.setCycleCount(Animation.INDEFINITE);
stage.show();
animation.play();
}
}
What you need is a reference in your controller to the original animation created in the start method of your application. This will allow you to code the button event handler in the controller to stop the animation.
The MotionCFp class can contain the code:
final FXMLLoader loader = new FXMLLoader(
getClass().getResource("gui.fxml"),
ResourceBundle.getBundle("motionc.fp.Bundle", new Locale("en", "EN"))
);
final Pane root = (Pane) loader.load();
final GuiController controller = loader.<GuiController>getController();
...
animation = new Timeline();
controller.setAnimation(animation);
And the GuiController class can contain the code:
private Timeline animation;
public void setAnimation(Timeline animation) {
this.animation = animation;
}
#FXML private void btn_stopmes(ActionEvent event) {
if (animation != null) {
animation.stop();
}
}
MotionCFp is your application class. You only need one instance of it. That instance is created by the the JavaFX launcher, you should never do new MotionCFp().
Please note that these kinds of questions are much easier to answer quickly and correctly if the code in the question is simple, complete, compilable and executable.

Return from a pushed BlackBerry screen to the parent screen

I have a main menu in Blackberry application. I want to access different screens when I enter the menu items and need to come back to the main menu. How can I do it?
Here is what I tried but caught up a runtime exception when pressed Back button:
package com.stockmarket1;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.decor.*;
import net.rim.blackberry.api.push.PushApplication;
public class StockMarket extends UiApplication implements FieldChangeListener {
public Screen _clientList;
public Screen _comments;
public Runnable _popRunnable;
public static void main(String[] args)
{
StockMarket theApp = new StockMarket();
theApp.enterEventDispatcher();
}
public StockMarket() {
//Code for MainScreen
final MainScreen baseScreen = new MainScreen();
baseScreen.setTitle("Colombo Stock Exchange");
ButtonField clientList = new ButtonField("View Client List", ButtonField.CONSUME_CLICK);
clientList.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
pushScreen(_clientList);
}
});
ButtonField comments= new ButtonField("View Comments", ButtonField.CONSUME_CLICK);
comments.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
pushScreen(_comments);
}
});
Bitmap bitmap = Bitmap.getBitmapResource("logo1.png");
BitmapField logo = new BitmapField(bitmap, BitmapField.FIELD_HCENTER);
LabelField newLine = new LabelField("\n");
baseScreen.add(logo);
baseScreen.add(newLine);
baseScreen.add(clientList);
baseScreen.add(comments);
//Code for _comments
_comments = new FullScreen();
_comments.setBackground(BackgroundFactory.createSolidBackground(Color.LIGHTCYAN));
LabelField title = new LabelField("Comments",LabelField.FIELD_HCENTER);
LabelField comment = new LabelField("Type");
RichTextField rtfComment = new RichTextField();
_comments.add(title);
_comments.add(comment);
_comments.add(rtfComment);
//Code for _clientList
_clientList = new FullScreen();
_clientList.setBackground(BackgroundFactory.createSolidBackground(Color.LIGHTBLUE));
LabelField clientTitle = new LabelField("Listed Companies\n\n", LabelField.FIELD_HCENTER);
LabelField line = new LabelField("__", LabelField.USE_ALL_HEIGHT);
ButtonField closeClient = new ButtonField("Close", ButtonField.CONSUME_CLICK);
closeClient.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
pushScreen(baseScreen);
}
});
_clientList.add(clientTitle);
_clientList.add(line);
//Events
pushScreen(baseScreen);
}
public void fieldChanged(Field field, int context) {
// TODO Auto-generated method stub
}
}
The code for your 'Close' button is a problem, but I think you said you get a RuntimeException when hitting the 'back' button on the device, which I think has a different cause.
Instead of pushing the menu screen onto the screen stack, you should just pop the current screen. This will return to the menu screen that was displayed previously:
closeClient.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
// previous code:
// pushScreen(baseScreen);
// correct code:
popScreen(_clientList);
}
});

Resources