B4J Question Graph will not display until I have clicked on the border of the Form

Johan Schoeman

Expert
Licensed User
Longtime User
I am trying to "wrap" the Pie Chart of this project via inline Java Code (in a B4J class). Funny thing is that the graph will not be displayed until such time as what I just click on the outer border of the Main Form. When running the B4J project it shows the outline of the Pane but not the graph - I need to click on the outer border of the Form to make the graph appear. Why is it behaving like this?

Sample B4J project is attached - you will also need to download the attached Jar (JHSxChart.jar) and copy it to your B4J additional library folder to run the project. Once the project has been started the Pane border should be visible but not the graph that should be displayed inside the Pane. Click on the border of the Form and then the graph appears out of thin air...

Anyone that can shed some light on this problem? Comment the last 6 jars in the B4J project - see the code uploaded in this post.

not clicked.png


border clicked.png


Code of Main:

B4J Main:
#Region Project Attributes
    #MainFormWidth: 1000
    #MainFormHeight: 800
#End Region

#AdditionalJar: JHSxChart
'#AdditionalJar: animated-gif-lib-1.4
'#AdditionalJar: commons-logging-1.2
'#AdditionalJar: fontbox-2.0.27
'#AdditionalJar: graphics2d-0.42
'#AdditionalJar: pdfbox-2.0.27
'#AdditionalJar: VectorGraphics2D-0.13


Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private xui As XUI
    Dim pieObject As JavaObject
    Private ComboBox1 As ComboBox

    Private Pane1 As Pane
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    MainForm.Show
    Sleep(1000)

    Dim piechart As xPieChart
    piechart.Initialize
 
    piechart.GraphWidth = Pane1.Width
    piechart.GraphHeight = Pane1.Height
    piechart.GraphTitle = "B4J Pie Chart Title"
    piechart.GraphCircular = True
 
    pieObject = piechart.drawPieChart
    Sleep(0)
    Pane1.AddNode(pieObject, 0, 0, Pane1.Width, Pane1.Height)
    Sleep(0)
    MainForm.RootPane.SetSize(MainForm.Width, MainForm.Height)

End Sub

Code of B4J Class with inline Java Code (xPieChart):

B4J class xPieChart:
Sub Class_Globals
    Private fx As JFX
 
    Private nativeMe As JavaObject
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
 
    nativeMe = Me
 
End Sub

'draw the pie chart
public Sub drawPieChart As JavaObject
 
    Return nativeMe.RunMethod("drawChart", Null)
 
End Sub

'set the width of the chart
public Sub setGraphWidth(wdth As Int)
 
    nativeMe.RunMethod("setGraphWidth", Array(wdth))
 
End Sub

'set the height of the chart
Public Sub setGraphHeight(hght As Int)
 
    nativeMe.RunMethod("setGraphHeight", Array(hght))
 
End Sub

'set the title of the chart
public Sub setGraphTitle(title As String)
 
    nativeMe.RunMethod("setGraphTitle", Array(title))
 
End Sub

'set the graph to be circular or to follow the width/height of the pane
public Sub setGraphCircular(circ As Boolean)
 
    nativeMe.RunMethod("setCircular", Array(circ))
End Sub


#If Java

import org.knowm.xchart.PieChart;
import org.knowm.xchart.PieChartBuilder;
//import org.knowm.xchart.SwingWrapper;
import org.knowm.xchart.style.Styler;
import javafx.scene.Node;
import javax.swing.JPanel;

import org.knowm.xchart.QuickChart;
import org.knowm.xchart.XChartPanel;
import org.knowm.xchart.XYChart;
import org.knowm.xchart.XYChartBuilder;
import org.knowm.xchart.XYSeries.XYSeriesRenderStyle;
import org.knowm.xchart.internal.chartpart.Chart;
import org.knowm.xchart.style.Styler.LegendPosition;
import javafx.embed.swing.SwingNode;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.Pane;


    private int wdth = 400;
    public void setGraphWidth(int wdth) {
        this.wdth = wdth;
    }
 
    private int hght = 400;
    public void setGraphHeight(int hght) {
        this.hght = hght;
    }
 
    private String graphTitle = "";
    public void setGraphTitle(String graphTitle) {
        this.graphTitle = graphTitle;
    }
 
    private boolean circ = false;
    public void setCircular(boolean circ) {
        this.circ = circ;
    }
 
 
    public Pane drawChart() {
        PieChart chart =
            new PieChartBuilder().width(wdth).height(hght).title(graphTitle).build();

        // Customize Chart
        chart.getStyler().setCircular(circ);
        chart.getStyler().setLegendPosition(Styler.LegendPosition.OutsideS);
        chart.getStyler().setLegendLayout(Styler.LegendLayout.Horizontal);

        // Series
        chart.addSeries("Pennies", 100);
        chart.addSeries("Nickels", 50);
        chart.addSeries("Dimes", 70);
        chart.addSeries("Quarters", 170);
   
   
        SwingNode swingNode = new SwingNode();
        JPanel chartPanel = new XChartPanel(chart);
        swingNode.setContent(chartPanel);
   
        Pane pane = new Pane(swingNode);

        return pane;
 
    }

#End If
 

Attachments

  • b4jXchartPie.zip
    3.3 KB · Views: 50
  • JHSxChart.jar
    467.1 KB · Views: 47
Last edited:

GMan

Well-Known Member
Licensed User
Longtime User
Is there some kind of Invalidate for that ?
 
Upvote 0

GMan

Well-Known Member
Licensed User
Longtime User
Can you do the Click via the Software ?
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
Can you do the Click via the Software ?
It can probably be done but is not a "clean" solution. Trying to understand why it is behaving this way. Have done the same with some other charts/graphs but never had this strange behaviour. It boggles my mind...
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
I tried your code. It works fine on my system. Must be some timing problem. It looks like MainForm has lost focus, or has not yet achieved it on your system.
Note I had to comment out the un-needed other jars, they must already be part of JHSxChart

B4X:
#AdditionalJar: JHSxChart
'#AdditionalJar: animated-gif-lib-1.4
'#AdditionalJar: commons-logging-1.2
'#AdditionalJar: fontbox-2.0.27
'#AdditionalJar: graphics2d-0.42
'#AdditionalJar: pdfbox-2.0.27
'#AdditionalJar: VectorGraphics2D-0.13

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    MainForm.Show
    'Sleep(1000)
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
This is driving me insane....Just cannot get the chart to display unless I click on and move either the left or top of the form. What am I missing here? Does it have something to do with the fact that I am converting Swing to FX? I am using Java 11....is this the problem? Have tried a billion different ways to display the chart but no joy unless I move the left or top border of the Form (as in resizing).

Moving the right and bottom of the Form does nothing. Chart only displays when moving the left and top of the Form.
 

Attachments

  • JHSxChart.jar
    300.2 KB · Views: 51
  • b4jXchartPie.zip
    3 KB · Views: 54
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
Since we can't replicate the problem, it becomes a (painful) process of elimination.
I too use C:\Java\jdk-11.0.1\jdk-11.0.1\bin\javac.exe, so that's not it.

Swing to FX can cause problems it you have routines with the same name in both and import (parts) of both.
I got this from Stackoverflow, but it may not be the case for your situation.

"Basically for any swing component (often start with J, JTextField, JTextArea etc.) find the javafx equivalent
(for example javafx.scene.control.TextField, javafx.scene.control.TextArea) and learn how to use them
(they will have a different api). In the end you should not have an import statement for java.awt or javax.swing."

But have not used Swing, so I could be wrong.
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
View attachment 141241

Your project does show the Chart without moving anything for me.
Manfred and William, so what is the solution to this problem? It is a Dell Laptop so maybe I should just toss it out of the window....It is mind boggling that you both can run it without seeing what I am seeing. I would hate to go through a new Java and B4J installation. Other similar projects that I have done have no issue. What is behind this phenomenon?

@Erel , can you maybe have a look at it when you have a chance to do so? Maybe it is because I am on the other side of the equator...should maybe try it while standing on my head or bring a really strong magnet close to my laptop so that it thinks it is in the Northern hemisphere.
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
It sounds like a JavaFX <-> display driver issue. First step is to check with OpenJDK 14: https://www.b4x.com/b4j.html
Second step is to switch to software acceleration:
B4X:
#VirtualMachineArgs: -Dprism.order=sw
@Erel - Java 14 makes no difference (with or without #VirtualMachineArgs: -Dprism.order=sw). Is it maybe a Dell specific issue? Find it hard to believe but then never knows.


1681648816152.png


Form after compiling the B4J project....

1681649147954.png


Form after moving the Left or Top border of the form being displayed. This is really mind boggling.
1681649226461.png


Moving the right or bottom border of the frame does not display the chart. Only when moving the left or top border of the frame.
 
Last edited:
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
@Johan Schoeman
Don't throw out your Dell yet.
And you can eliminate the Hemisphere hypothesis.

I just tried it on my HP laptop (Windows 10) and see the same effect as you.
My previous test was on Windows 11.

So whatever causes it is in the code you posted.

If @DonManfred also tested it on Windows 11, than it could be something to do
with the difference between Windows 11 and 10, interacting with some Swing API's.
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
I also noticed that dragging the window left also make the chart appear.
So this actually works on my HP laptop.

B4X:
'last two lines in AppStart
   Sleep(100)  '50 is not enough
   MainForm.WindowLeft = MainForm.WindowLeft - 1
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
I also noticed that dragging the window left also make the chart appear.
So this actually works on my HP laptop.

B4X:
'last two lines in AppStart
   Sleep(100)  '50 is not enough
   MainForm.WindowLeft = MainForm.WindowLeft - 1
Have done it in a similar way to get the chart to display but not the ideal solution. I will go back to the original Github posting to see if the author(s) mention anything about it being Windows version "specific". I am using Windows 10 (seem to be "no Windows").
 
Last edited:
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
I also noticed that dragging the window left also make the chart appear.
So this actually works on my HP laptop.

B4X:
'last two lines in AppStart
   Sleep(100)  '50 is not enough
   MainForm.WindowLeft = MainForm.WindowLeft - 1
This it what it mentions about "no-Windows"

  • Windows: In the cmd command window, execute the command java -cp xchart-demo-3.8.0.jar;xchart-3.8.0.jar org.knowm.xchart.demo.XChartDemo; In the PowerShell command window, execute the command java -cp "xchart-demo-3.8.0.jar;xchart-3.8.0.jar" org.knowm.xchart.demo.XChartDemo.
 
Upvote 0
Top