Codename One dragged-over container quickly dissappears - java

I have an Android application that uses drag and drop operations. I haven't used drag and drop often, so I am just starting to learn how they work and what the implications might be.
In my app, whenever I drop the component over the target, the target sort of "flashes", meaning it disappears for a brief moment and than reappears again.
Here a link to the video with the app in its current stage.
I suppose this is due to the animation of the form. If so, how can I disable it, or stop the target from flashing?
Below is my code. It is still rudimentary, since I just started to work on the project.
public void testDrag () {
Container containerDropTarget = new Container();
Container container = new Container(new GridLayout(5,1));
Label label = new Label("test test test test test test");
Button buttonTwo = new Button("Test");
buttonTwo.addDragOverListener(l-> {
containerDropTarget.setUIID("DialogTest");
});
containerDropTarget.setUIID("LetterHolder");
buttonTwo.setDraggable(true);
containerDropTarget.setDropTarget(true);
container.add(label).add(containerDropTarget);
form.add(container).add(buttonTwo);
form.show();
}

I don't have the UIIDs defined so I used this code based on your test case and it worked correctly. I also added a label to the drop container so it could be found:
Container containerDropTarget = new Container() {
#Override
public void drop(Component dragged, int x, int y) {
super.drop(dragged, x, y);
setUIID("Container");
}
};
containerDropTarget.add(new Label("Drop Target"));
Form form = new Form("Test Drag", BoxLayout.y());
Container container = new Container(new GridLayout(5,1));
Label label = new Label("test test test test test test");
Button buttonTwo = new Button("Test");
buttonTwo.addDragOverListener(l-> {
//containerDropTarget.setUIID("DialogTest");
containerDropTarget.getAllStyles().setBgColor(0xff0000);
containerDropTarget.getAllStyles().setBgTransparency(0xff);
containerDropTarget.repaint();
});
containerDropTarget.setUIID("LetterHolder");
buttonTwo.setDraggable(true);
containerDropTarget.setDropTarget(true);
container.add(label).add(containerDropTarget);
form.add(container).add(buttonTwo);
form.show();

Related

Why can't I set the content again after I have fresh the web page in Vaadin?

I got a strange issue. My web application works as it don't remove text/numbers from text boxes or resetting check boxes when I refresh the web page from the web browser.
But when I refresh the web page then I got the problem:
java.lang.IllegalStateException: Can't move a node from one state tree to another. If this is intentional, first remove the node from its current state tree by calling removeFromTree
java.lang.IllegalStateException: Unregistered node was not found based on its id. The tree is most likely corrupted.
And
Assertion error: No child node found with id 28
Assertion error: Node 3 is already registered
So why can't I set the content again after I have fresh the web page in Vaadin? I'm using Vaadin 14. If I don't refresh the web page, then I can change the content as much as I want. But as long I don't refresh the web page, then I will not get an error.
Notice that I have #PreserveOnRefresh enabled. Without that, I get no error. But then the text/values and all information will disappear when I refresh the page.
Here is my code.
#Route("")
#Viewport("width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes, viewport-fit=cover")
#PreserveOnRefresh
public class MainView extends AppLayout {
/**
*
*/
private static final long serialVersionUID = 1L;
public MainView() {
// Get the components
BuildPredictValidateTemplate buildPredictValidateTemplate = new BuildPredictValidateTemplate();
LoadExportTemplate loadExportTemplate = new LoadExportTemplate();
// Create logo and drawer
Image barImage = new Image("img/barImage.png", "Fisherfaces Logo");
barImage.setHeight("55px");
addToNavbar(new DrawerToggle(), barImage);
// Create tabs and add listeners to them
Tab buildPredictValidate = new Tab("Build & Predict & Validate");
buildPredictValidate.getElement().addEventListener("click", e -> {
setContent(buildPredictValidateTemplate.getBuildButtonPredictButtonValidateButtonTextArea());
});
Tab loadExport = new Tab("Load & Export");
loadExport.getElement().addEventListener("click", e -> {
setContent(loadExportTemplate.getSubjectCounterExportButtonUploaders());
});
// Add them and place them as vertical
Tabs tabs = new Tabs(buildPredictValidate, loadExport);
tabs.setOrientation(Tabs.Orientation.VERTICAL);
addToDrawer(tabs);
}
}
And
#Data
//#Component
public class BuildPredictValidateTemplate {
private VerticalLayout buildButtonPredictButtonValidateButtonTextArea;
public BuildPredictValidateTemplate() {
// Create the complete form layout
buildButtonPredictButtonValidateButtonTextArea = createBuildButtonPredictButtonValidateButtonTextArea();
}
private VerticalLayout createBuildButtonPredictButtonValidateButtonTextArea() {
// Text area that works like a terminal
TextArea textTerminal = new TextArea();
textTerminal.setPlaceholder("");
textTerminal.setWidthFull();
textTerminal.setHeightFull();
// Progressbar
ProgressBar progressBar = new ProgressBar();
progressBar.setValue(0);
// Buttons for Builing, Predicting and Validate
Button build = new Button("Build");
build.addClickListener(e -> {
System.out.println("Building");
});
Button predict = new Button("Predict");
predict.addClickListener(e -> {
System.out.println("Predicting");
});
Button validate = new Button("Validate");
validate.addClickListener(e -> {
System.out.println("Validating");
});
// Uploader for prediction
//Upload upload = new PictureUpload().getUpload();
// Add them all now
HorizontalLayout horizon = new HorizontalLayout(build, validate, predict);
return new VerticalLayout(horizon, progressBar, textTerminal);
}
}
And also
#Data
//#Component
public class LoadExportTemplate {
private VerticalLayout subjectCounterExportButtonUploaders;
public LoadExportTemplate() {
// Create layout for the uploads
VerticalLayout uploadsLayout = new VerticalLayout();
// Create subject counter for how many uploaders we should have
NumberField subjectCounter = createSubjectCounter(uploadsLayout);
// Create layout for holding subject counter, export button and uploaders
subjectCounterExportButtonUploaders = createLayoutForSubjectCounterExportButtonUploaders(subjectCounter, uploadsLayout);
}
private VerticalLayout createLayoutForSubjectCounterExportButtonUploaders(NumberField subjectCounter, VerticalLayout uploadsLayout) {
// Create SubjectCounter and ExportButton on a row
Button exportButton = new Button("Export to MATLAB code");
exportButton.addClickListener(e -> {
System.out.println("Exported to MATLAB code.");
});
HorizontalLayout layoutHorizon = new HorizontalLayout(subjectCounter, exportButton);
// Add the uploaders under the horizontal layout
return new VerticalLayout(layoutHorizon, uploadsLayout);
}
private NumberField createSubjectCounter(VerticalLayout uploadsLayout) {
NumberField subjectCounter = new NumberField();
subjectCounter.setValue(1d);
subjectCounter.setHasControls(true);
subjectCounter.setMin(1);
subjectCounter.addValueChangeListener(e-> {
// First clear, then fill with new uploaders
uploadsLayout.removeAll();
for(Double i = 0.0; i < e.getValue(); i++) {
PictureUpload pictureUpload = new PictureUpload();
uploadsLayout.add(pictureUpload.getUpload());
}
});
// Add one to begin with
//PictureUpload pictureUpload = new PictureUpload();
//uploadsLayout.add(pictureUpload.getUpload());
return subjectCounter;
}
}
I believe this is a bug in Vaadin, at least it is not what I would expect to happen.
I have created an issue for it here https://github.com/vaadin/flow/issues/8286
Edit:
As a workaround, you can toggle visibility instead. But this would require you to add all components to e.g. a Div, and set that as the content.
E.g setContent(new Div(component1, component2));
Then when clicking on a tab, you would have to hide all components except the one clicked, e.g.
getContent().getChildren().forEach(component -> {
boolean visible = component.equals(theComponentIWantToShow);
component.setVisible(visible);
});

Graph not rendering in JavaFX on startup under Java 11

The issue I'm having is that the mxGraph object does not load correctly on startup. It requires me to click a cell inside of it for it to appear, and even then it does not reveal the entire graph, just the cell that was clicked. In order to reveal all of it I have to refresh the graph via another control or drag a cell around the entire graph area.
When I initially developed this I was working with Java 8 and this was not an issue. This has only occurred since updating to Java 11 (OpenJDK). Everything else was kept the same when upgrading to 11, only the updated dependencies changed.
I am wrapping the mxGraphComponent inside of a SwingNode in order to place it inside of a JavaFX node. I've had issues in the past with Swing nodes inside JavaFX but I am creating all of the Swing components using the SwingUtilities.invokeLater() method. I am using the 3.9.8.1 version of JGraphX from Maven, but I have also tried the updated 4.0.0 from GitHub with no success.
Here's my MCVE:
public final class Main {
public static void main(final String[] args) {
Application.launch(JGraphExample.class);
}
}
public final class JGraphExample extends Application {
private mxGraph graph;
#Override
public void start(final Stage primaryStage) {
final SwingNode value = new SwingNode();
final BorderPane root = new BorderPane();
root.setCenter(value);
root.setBottom(createRefreshButton());
SwingUtilities.invokeLater(() -> value.setContent(buildGraphComponent()));
primaryStage.setWidth(500);
primaryStage.setHeight(500);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
private mxGraphComponent buildGraphComponent() {
graph = buildGraph();
return new mxGraphComponent(graph);
}
private mxGraph buildGraph() {
final mxGraph graph = new mxGraph();
graph.insertVertex(graph.getDefaultParent(), "x", "Hello", 100, 100, 100, 100);
return graph;
}
private Button createRefreshButton() {
final Button refresh = new Button("Refresh");
refresh.setOnAction(actionEvent -> graph.refresh());
return refresh;
}
}
Until clicking the refresh button the graph will not render correctly. This was not the case with Java 8 as it worked as intended. It seems the update to 11 has teased this issue out.
Has anyone come across this before or have any ideas? Thanks in advance.

How to save/store variables after clicking a button in javafx

I am super new to JavaFX, with some knowledge of Java tho.
My target is to develop a desktop broad game.
It should ask players for certain options and determine how the game would proceed (like voting, selection rooms, etc)
It works perfectly in Java using Scanner but not in JavaFX;
Whenever I click a button, it only affect the variable in the block.
I do need these chosen options to be used later to support the game logic.
Please help.
Updated - I move the if statement into the action block but it still not set scene to welcome.
public class Main extends Application{
Button startGame,howTOPlay, viewRoomButton, viewItemListButton;
List<Scene> playersenes = new ArrayList<>();
Scene welcomeScene, playerRedScene, playerYellowScene, playerBlueScene, playerGreenScene, playerBrownScene, playerBlackScene;
Stage mainWindow;
static int numberOfPlayers;
final static int WIDTH =800;
final static int HEIGHT=600;
;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
//mainWidow setup
mainWindow = primaryStage;
mainWindow.setTitle("Mall of Horror");
//startgameScene
List<Integer> numberOfPlayersOptions = new ArrayList<>();
numberOfPlayersOptions.add(4);
numberOfPlayersOptions.add(5);
numberOfPlayersOptions.add(6);
GameBroad gameBroad=new GameBroad(1);
PlayersChoice playersChoice = new PlayersChoice();
startGame = new Button();
startGame.setText("Start Game");
startGame.setOnAction(event -> {
//numberwindow.display is a new stage with a method return a static int
//gamebroad is class with models, which require the number of players to support its logic.
gameBroad.setPlayersNumber(NumberWindow.display(numberOfPlayersOptions, "please select how many players"));
//playerChoise is a class, ok is default fault boolean. set Ok is method to set the ok boolean to true;
playersChoice.setOk();
mainWindow.setScene(welcomeScene);
if (playersChoice.isOk()){//it stop working here
//welcomeScene;
Label welcome = new Label();
welcome.textProperty().setValue("Welcome players " + gameBroad.getPlayersNumber() );
Button ok1 = new Button("OK");
ok1.setOnAction(event1 -> {
mainWindow.setScene(playerRedScene);
});
VBox welcomePlayerslayout = new VBox();
welcomePlayerslayout.getChildren().addAll(welcome,ok1);
welcomeScene = new Scene(welcomePlayerslayout, WIDTH, HEIGHT);
//playerRedScene;
viewRoomButton = new Button();
viewRoomButton.setText("Rooms");
viewItemListButton = new Button();
viewItemListButton.setText("Items");
VBox playerRedLayout = new VBox();
playerRedLayout.getChildren().addAll(viewRoomButton,viewItemListButton);
playerRedScene = new Scene(playerRedLayout, 800,600);
}
System.out.println(playersChoice.isOk()); //it shows true here;
});
howTOPlay = new Button();
howTOPlay.setText("How to Play");
VBox firstlayout = new VBox();
firstlayout.getChildren().addAll(startGame, howTOPlay);
Scene firstscene = new Scene(firstlayout, WIDTH, HEIGHT);
primaryStage.setScene(firstscene);
mainWindow.show();
}
}
if (playersChoice.isOk()){//it stop working here
It did not stop working there. It didn't start to work. It defaults to false until you click startGame, and the action does not check again if the choice is okay.
Therefore, you need to setup your welcome actions within the start button action, which only runs after you click the button.
In the current code, that if statement is ran before the button click despite the code having been written below the action. In other words, GUI programming does not explicitly run top to bottom.
Your next issue is that you have mainWindow.setScene(welcomeScene); before welcomeScene = new Scene(welcomePlayerslayout, WIDTH, HEIGHT);

mobileapplication.mobileevent BACK_BUTTON_PRESSED

I've got 2 android native audio instances in two of my views. I'm trying to get the audio to stop when the user presses the back button and leaves the view as it's not happening automatically. I've looked at the documentation and seen the MobileEvent class. I've tried implementing it's constructor with no luck. This is my first app altogether and I've only just learnt Java and JavaFX on my own for this purpose so some help would be great. My current attempt is below.
public void MobileEvent(javafx.event.EventTarget source,
javafx.event.EventType<MobileApplication.MobileEvent> BACK_BUTTON_PRESSED) {
service.backPressed();
}
This is a Gluon application.
The idea of a custom event like MobileEvent.BACK_BUTTON_PRESSED is that you can subscribe to it using an event handler.
For instance, if you create a layer and you want to close it when the user presses the back button:
public BasicView(String name) {
super(name);
// create a custom layer
MobileApplication.getInstance().addLayerFactory("My Layer", () -> new Layer() {
private final Node root;
private final double size = 300;
{
root = new StackPane(new Button("A custom layer"));
root.setStyle("-fx-background-color: lightgreen;");
getChildren().add(root);
getApp().getGlassPane().getLayers().add(this);
// Add event handler to listen to Android Back Button Pressed event, hiding the layer
addEventHandler(MobileApplication.MobileEvent.BACK_BUTTON_PRESSED, e -> {
hide();
e.consume();
});
}
#Override
public void hide() {
setShowing(false);
super.hide();
}
#Override
public void layoutChildren() {
root.setVisible(isShowing());
if (!isShowing()) {
return;
}
root.resize(size, size);
resizeRelocate(0, 0, size, size);
}
});
Button button = new Button("Show Layer");
button.setOnAction(e -> MobileApplication.getInstance().showLayer("My Layer"));
VBox controls = new VBox(15.0, button);
controls.setAlignment(Pos.CENTER);
setCenter(controls);
}
If you create a Single View project, use the snippet above, and deploy it on an Android device, you can verify that when you click the button the layer shows up, and if you hit the Android back button, it will close the layer.
Notice that if you hit it again, it will close the app: The home view already has a listener on this event, that's why the app gets closed. Or if you are in a secondary view, with this event you will return to the previous view.
While you can subscribe to this event at any point in your code, like I've done in the example above, there are already other events that you can track more easily. For instance, the LifecycleEvent events, likeSHOWINGorHIDING`, are already used by all the Views.
So you can add to your custom view a listener to any of those events:
public BasicView(String name) {
super(name);
Label label = new Label("This is a custom view");
VBox controls = new VBox(15.0, label);
controls.setAlignment(Pos.CENTER);
setCenter(controls);
setOnShowing(e -> System.out.println("Showing Event"));
setOnHiding(e -> System.out.println("Hiding Event"));
}
Note that in your case, you can easily find out when the user leaves the view, and then react accordingly calling the service to stop the audio:
setOnHiding(e -> {
Services.get(MyAudioService.class).ifPresent(service -> service.stop());
});

Adding Single Selection and Context Sensitive Right Clicking to Zest Graph

I've been playing with the Zest GraphViewer for over a week now trying to discover what it can do for my application, but I haven't been able to get it's behaviour in-line with my requirements thus far.
I'm hoping that someone can point me to the resources I need, becasue I just can't find all that much of use with Google, or can tell me if what I want is possible.
Version
I've got Zest core 1.3.0 and Zest layout 1.1.0 in my dependencies for the RCP project. This came from the download site I took from the Zest site.
Requirements
Single Node/Edge selection.
De-selection of node/edge when white-space is selected (which may be a bug?)
Right click functionality to change when over a node. (detect when mouse is over a node)
The right click functionality could come from the single selection since I could have the popup anywhere but base it on the current selected node, but I'd rather not do that.
Without being able to do this, due to the nature or our application and users, I may also have a requirement to find another RCP/SWT based Graph drawing package that does have this functionality.
Any help on any of these issues would be greatly appreciated.
Glen x
Based on the Zest tutorial by Vogella, I came up with this:
public static void main(String[] args) throws FontFormatException, IOException
{
Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
final Graph graph = new Graph(shell, SWT.NONE);
GraphNode node1 = new GraphNode(graph, SWT.NONE, "Jim");
GraphNode node2 = new GraphNode(graph, SWT.NONE, "Jack");
GraphNode node3 = new GraphNode(graph, SWT.NONE, "Joe");
GraphNode node4 = new GraphNode(graph, SWT.NONE, "Bill");
/* Context menu */
graph.addMenuDetectListener(new MenuDetectListener()
{
#Override
public void menuDetected(MenuDetectEvent e)
{
Point point = graph.toControl(e.x, e.y);
IFigure fig = graph.getFigureAt(point.x, point.y);
if (fig != null)
{
Menu menu = new Menu(shell, SWT.POP_UP);
MenuItem exit = new MenuItem(menu, SWT.NONE);
exit.setText("Hello! This is " + ((GraphLabel) fig).getText());
menu.setVisible(true);
}
else
{
Menu menu = new Menu(shell, SWT.POP_UP);
MenuItem exit = new MenuItem(menu, SWT.NONE);
exit.setText("Nothing here...");
menu.setVisible(true);
}
}
});
/* Lets have a directed connection */
new GraphConnection(graph, ZestStyles.CONNECTIONS_DIRECTED, node1, node2);
/* Lets have a dotted graph connection */
new GraphConnection(graph, ZestStyles.CONNECTIONS_DOT, node2, node3);
/* Standard connection */
new GraphConnection(graph, SWT.NONE, node3, node1);
/* Change line color and line width */
GraphConnection graphConnection = new GraphConnection(graph, SWT.NONE, node1, node4);
graphConnection.changeLineColor(shell.getDisplay().getSystemColor(SWT.COLOR_GREEN));
/* Also set a text */
graphConnection.setText("This is a text");
graphConnection.setHighlightColor(shell.getDisplay().getSystemColor(SWT.COLOR_RED));
graphConnection.setLineWidth(3);
graph.setLayoutAlgorithm(new SpringLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING), true);
graph.addSelectionListener(new SelectionAdapter()
{
#Override
public void widgetSelected(SelectionEvent e)
{
System.out.println(e.item);
/* Make sure that only the newest item is selected */
graph.setSelection(new GraphItem[]{(GraphItem)e.item});
}
});
shell.pack();
shell.open();
shell.setSize(400, 300);
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
It supports single node/edge selection, de-selection and right-click functionality as requested.
Looks like this:
If you use the GraphViewer example of the tutorial and add this to the View code, it still works fine:
final Graph graph = viewer.getGraphControl();
graph.addSelectionListener(new SelectionAdapter()
{
#Override
public void widgetSelected(SelectionEvent e)
{
System.out.println(e.item);
graph.setSelection(new GraphItem[]{(GraphItem)e.item});
}
});

Categories

Resources