How to get event on finish drawing bar chart in jFreeChart? - java

I'm using jFreeChart via JFreeChartWrapper in Vaadin and have problems on drawing it.
Data for charts is getting in runtime and it could take some time.
So I want to add progress indicator to notify the user about image loading (before it closes the window).
I tried to resolve this problem by adding temporary layout for ProgressIndicator and using it until receiving some event from charts:
final AbsoluteLayout loadLayout = new AbsoluteLayout();
loadLayout.setImmediate(true);
ProgressIndicator progress = new ProgressIndicator();
progress.setIndeterminate(true);
progress.setVisible(true);
loadLayout.addComponent(progress, "right: 500px; top: 200px;");
setContent(loadLayout);
Meanwhile, chart are added in another layout:
JFreeChart barChart = ChartFactory.createBarChart("Text", "", "", res, PlotOrientation.VERTICAL, true, false, false);
barChart.addProgressListener(new ChartProgressListener() {
#Override
public void chartProgress(ChartProgressEvent arg0) {
if (arg0.getType() == ChartProgressEvent.DRAWING_FINISHED) {
loadLayout.setVisible(false);
setContent(layout);
layout.setVisible(true);
}
}
});
JFreeChartWrapper chartWrap = new JFreeChartWrapper(barChart);
layout.addComponent(chartWrap);
But what I get - is only progress indicator, I never get ChartProgressEvent. And I don't see where this event if fired in JFreeChart.
Is it possible to fix it or I should better use other Vaadin plugin for charts?

To receive such events, you need to add your chart to a ChartPanel, as discussed here.

Related

Using ProgressBar in Java Lanterna

I tried to use ProgressBar as below:
ProgressBar Prog=new ProgressBar(0,100,50);
Prog.setValue(0)
//
BufferedReader bf = new BufferedReader(new FileReader(file1));
String line = bf.readLine();
while (line != null) {
lines.add(line);
Prog.setValue((int)(100*(double)lines.size()/MaxLen)); //ProgressBar will ot be updated
line = bf.readLine();
}
bf.close();
I also tried this method:
ProgressBar.DefaultProgressBarRenderer DP=new ProgressBar.DefaultProgressBarRenderer();
DP.drawComponent((TextGUIGraphics)gui.getScreen().newTextGraphics(),Prog );
GUI is MultiWindowTextGUI belong to contex, but it does not work because of Cast Problem:
com.googlecode.lanterna.screen.AbstractScreen$1 cannot be cast to com.googlecode.lanterna.gui2.TextGUIGraphics
Edit2:in component aproach, it need this:
Prog.setRenderer(new ProgressBar.DefaultProgressBarRenderer());
and a timer:
Timer timer = new Timer("ProgressBar-timer", true);
timer.schedule(new TimerTask() {
#Override
public void run() {
//Do some thing
}
}, 10, 10);
Assume you wanted to draw a progress-bar on the screen somehow.
Issue
But gui.getScreen().newTextGraphics() is giving TextGraphics and not desired TextGUIGraphics.
Draw on the screen
Given your renderer, you can use it to draw the progressBar on your screen.
Therefore, use the renderer's method drawComponent(TextGUIGraphics graphics, ProgressBar component):
// Given
MultiWindowTextGUI textGui = createGuiOn(screen);
TextGraphics textGraphics = screen.newTextGraphics();
// What you need, but don't get
TextGUIGraphics graphics = null; // WARNING: There is no method to get the graphics object from!
// Then
renderer.drawComponent( graphics, progressBar );
The drawing is a low-level rendering action. See Tutorial 3.
And there seems neither a constructor, nor a public method, that gives you that TextGUIGraphics, see the search on the GitHub repo.
Instead consider to work with components like ProgressBar.
Work with components
ProgressBar is a component. So you can add it simply to your TextGUI:
final Window window = new BasicWindow("My Root Window"); // create window
window.setComponent(progressBar); // set component of window
textGUI.addWindowAndWait(window); // add window to gui
See Tutorial 4 for working with components.

Switching between HorizontalScrollView and BarChart scroll

I have a MPAndroidChart BarChart which is placed inside a HorizontalScrollView. Now, I have multiple bars in the chart view and also the chart width is fixed as per my requirement. Since, there is a default scroll behaviour of chart, I can see all the bars.
The only problem is the scroll behaviour is not smooth and it lags a lot.
My idea is to disable the HorizontalScrollView once I start scrolling the chart and enable it back when I touch outside the chart. Can someone please tell me how I can do it? I hope my question is clear enough and there is no need to share any XML for it. Thanks in advance.
I faced similar issue while using Mpchart inside horizontal scroll view.
I had a workaround with MpChart setOnChartGestureListener.
barChart.setOnChartGestureListener(new OnChartGestureListener() {
#Override
public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
horizontalScrollView.requestDisallowInterceptTouchEvent(true);
}
#Override
public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
horizontalScrollView.requestDisallowInterceptTouchEvent(false);
}
//.....//
#Override
public void onChartTranslate(MotionEvent me, float dX, float dY) {
Log.i("GESTURE", "onChartTranslate");
if(barChart.getLowestVisibleX() == barChart.getXAxis().getAxisMinimum() || barChart.getHighestVisibleX() == barChart.getXAxis().getAxisMaximum()) {
horizontalScrollView.requestDisallowInterceptTouchEvent(false);
} else {
horizontalScrollView.requestDisallowInterceptTouchEvent(true);
}
}
});
the horizontalScrollView object is where the chart reside.

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());
});

How do I implement drag and drop on a canvas?

More specifically, how would I go about implementing a drag and drop feature so that the image file dragged on to the canvas would be drawn on the canvas? I've tried using a VBox listener on top of the canvas, but that didn't work. The source code of by program is available here.
In my controllers initialize() function, I have the following code. canvas is passed from the FXML file via the #FXML annotation:
public void initialize() {
GraphicsContext g = canvas.getGraphicsContext2D();
// Setter for brush type
setBrushBrush();
// Get screen dimensions and set the canvas accordingly
Dimension screenSize = getScreenSize();
double screenWidth = screenSize.getWidth();
double screenHeight = screenSize.getHeight();
canvas.setHeight(screenHeight/1.5);
canvas.setWidth(screenWidth/1.5);
canvas.setOnMouseDragged(e -> {
//Drawing code here
});
canvas.setOnDragOver(e -> {
// Need to read data of dragged image
});
canvas.setOnMouseDragReleased(e -> {
// Need to put dragged data on to canvas
});
}
The mouseDragReleased event is the wrong event to listen for here. That event is triggered when the mouse is released during a "full press-drag-release gesture" within the application; not when data is dropped during a "platform-supported drag-and-drop gesture" (see the documentation for MouseEvent for a description of these different dragging modes). So instead of canvas.setOnMouseDragReleased(...), you need:
canvas.setOnDragDropped(e -> {
// ...
});
Assuming the implementations of the handlers are correct, this should enable you to drop an image from a file and draw it on the canvas.

GWT - CSS animation after adding element to the page

If the button is clicked, I want to add a Label to page and fade it in via an CSS animation. I thougt, I could just create and add the label with the CSS class "hidden" attached, which has the opacity = 0 and after that remove the class and CSS will do the rest.
But i was wrong. GWT seems to execute the code in the onClick() in some kind of bulk mode -> The label gets added already without the "hidden" class. How can i prevent or do it that better? If I add/remove the "hidden" class manually in the browser, the animation works finde.
The java code looks like this:
Button submitButton = new Button("send");
submitButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Label l = new Label("test");
l.addStyleName("hidden");
RootPanel.get().add(l);
l.removeStyleName("hidden");
}
});
RootPanel.get().add(submitButton);
Das CSS sieht folgendermaßen aus:
.gwt-Label{
transition-property: opacity;
transition-duration: 1s;
}
.hidden{
opacity:0;
}
Probably you have to add some delay function before remove hidden class.
Here you have example (in JS but it's only to show):
http://jsfiddle.net/matku/PXnPZ/
$(".myElement").delay(50).queue( function(){
$(this).removeClass("hidden");
});
And another way I found on google:
http://map-notes.blogspot.com/2012/11/fade-animation.html

Categories

Resources