B4J Question [ABM] Entering wind direction

Rob White

Member
Licensed User
Hi all,

I am just starting to get my head around ABMaterial! Consider I am crawling.

I am writing a web server app to enter agricultural data (Sowing, spraying etc) events
I need the all thumbs farmer to be able to indicate the direction of the wind manually.

Consider an 8 point compass:-
North
NW NE
West East
SW SE
South

I do not mind if the above are labels or image(s).
My problem is I do not know how to position these "buttons" precisely.

What are my options?
All suggestions welcome.
 

MichalK73

Well-Known Member
Licensed User
Longtime User
Maybe don't do on the buttons. Do on ABMImage.
Create a 9x9 grid. In the middle, enter Transparent Image. The remaining pictures with the direction of the wind. The advantage is that all images can be scaled depending on the size of the screen, so it will look nice. Image event handler similar to Button.

I can see it in my head so quickly, I think it will be good.
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
You could also use an ABMCanvas. Something like:

B4X:
' in BuildPage
page.AddCanvasImage("background", "../images/background.jpg")

' in ConnectPage
Dim canvas1 As ABMCanvas
canvas1.Initialize(page, "canvas1", ABM.COLOR_BLACK, ABM.INTENSITY_NORMAL,1024,569, True)
    
' create background
Dim bg As ABMCanvasObject
bg.InitializeAsRectangle(page, "bg",0,0,1024,569,False)
bg.drawImage("background", 0,0)
canvas1.AddObject(bg)
    
page.Cell(2,1).AddComponent(canvas1)

' when clicked, will raise an event
Sub canvas1_CanvasDown(x As Int, y As Int)
    Log("canvas down: " & x & " - " & y)
End Sub

Sub canvas1_CanvasUp(x As Int, y As Int)
    Log("canvas up: " & x & " - " & y)
End Sub

Then you will have to use the x and y to find out where clicked.

Note: x and y are scaled! So no matter how much the image is stretched or shrinked (e.g. becuase one resizes the browser), the click coordinates will be the ones from the original canvas size.

e.g. Canvas = 1024x569

small screen:
1625034879978.png


Returns x = 60, y = 350

big screen:
1625035042591.png


Returns the same x = 60, y = 350

Alwaysbusy
 
Upvote 0

Rob White

Member
Licensed User
Thank you ,

MichalK73 and AlwaysBusy I now have a compass displayed and can log the coordinates.
Will now see how an image can be dragged around like "Kyle"

Thank you again.
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
it is similar to the background code. All you do is add a DragZone (the boundaries you want Kyle to be draggable). Events are then canvas1_ObjectUp, canvas1_ObjectDown and canvas1_ObjectClicked. You can use ObjectDown to track when Kyle is 'Dragged' and ObjectUp when Kyle is 'dropped'. There is no 'ObjectMove' event because it would cause to many roundtrips to the server.

B4X:
Dim Kyle As ABMCanvasObject
Dim x As Int = Rnd(0,1024-109)
Dim y As Int = Rnd(0,569-136)
kyleTeller=kyleTeller+1
Kyle.InitializeAsRectangle(page, "kyle" & kyleTeller, x, y, 109,136, True)
Kyle.SetDragZone(0,0,1024,569)
Kyle.drawImage("kyle", 0,0)
canvas1.AddObject(Kyle)
canvas1.refresh

B4X:
Sub canvas1_ObjectUp(objectId As String)
    Dim canvas1 As ABMCanvas = page.Component("canvas1")
    Dim Kyle As ABMCanvasObject = canvas1.GetObject(objectId)
    ...
End Sub

Sub canvas1_ObjectDown(objectId As String)    
    Dim canvas1 As ABMCanvas = page.Component("canvas1")
    Dim Kyle As ABMCanvasObject = canvas1.GetObject(objectId)
    ...
End Sub

Sub canvas1_ObjectClicked(objectId As String)    
    Dim canvas1 As ABMCanvas = page.Component("canvas1")
    Dim Kyle As ABMCanvasObject = canvas1.GetObject(objectId)
    ...
End Sub

Alwaysbusy
 
Upvote 0

Rob White

Member
Licensed User
Me again!
I have a curious file not found situation.

I have loaded two images in the Build page routine:-
B4X:
    '║ 11,1                                                                                                                              ║
    '╠═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
    '║                    | 12,1                           |          | 12,2                           |                                ║
    '╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝

    page.AddRows(1,True,"").AddCells12(1,"")
    page.AddRows(5,True,"").AddCellsOS(1,0,0,0,2,2,2,"").AddCellsOS(1,0,0,0,6,6,6,"").AddCellsOS(1,3,3,3,1,1,1,"")
    page.AddRows(2,True,"").AddCellsOS(1,0,0,0,2,2,2,"").AddCellsOS(1,0,0,0,6,6,6,"")
    page.AddRows(1,True,"").AddCells12(1,"")
    page.AddRows(1,True,"").AddCellsOS(1,0,0,0,2,2,2,"").AddCellsOS(1,0,0,0,5,5,5,"")
    'page.AddRows(1,True,"").AddCells12(1,"")
    'page.AddRows(1,True,"").AddCellsOS(1,2,2,2,3,3,3,"").AddCellsOS(1,1,1,1,3,3,3,"")
    page.BuildGrid ' IMPORTANT!
#End Region
    page.AddCanvasImage("background", "../images/compass.png")
    page.AddCanvasImage("RedSpot", "../images/redspot.png")
End Sub

public Sub ConnectPage()
    page.ShowGridInfo=True

If I set a break point over page.AddCanvasImage("background", "../images/compass.png")
and run the server. Stepping past both page.add line gives no errors. Here is the log file:

B4X:
Waiting for debugger to connect...
Program started.
ExecuteListOfMaps: SELECT * FROM SeedType
(ArrayList) [{ID=1, Name=Wheat}, {ID=2, Name=Barley}, {ID=3, Name=Oats}, {ID=4, Name=Canola}, {ID=5, Name=Grazing canola}]

If I now press Run
B4X:
Waiting for debugger to connect...
Program started.
ExecuteListOfMaps: SELECT * FROM SeedType
(ArrayList) [{ID=1, Name=Wheat}, {ID=2, Name=Barley}, {ID=3, Name=Oats}, {ID=4, Name=Canola}, {ID=5, Name=Grazing canola}]
Start B4J Analyse!
When an error occurs, check the B4JAnalyse.log file in the Objects folder to see the last B4J line it was working on.
Collecting data from B4J source files... (1/2)
Act.bas
DBM.bas
DBUtils.bas
PadInfoDB.bas
PD.bas
ABMShared.bas
ABMUploadHandler.bas
ABMCacheControl.bas
ABMCacheScavenger.bas
ABMCustomComponentTemplate.bas
ABMErrorHandler.bas
ABMRootFilter.bas
ABMApplication.bas
HomePage.bas
SeedTypePage.bas
SelectPaddockPage.bas
SowDataPage.bas
SprayDataPage.bas
ABMPageTemplate.bas
ABMPageTemplateAlternative.bas
EFPR.b4j
Analysing data from B4J source files... (2/2)
loading C:\ABMATE~2\EFSOWI~1\Objects: copymewithjar.needs...
Using cache system: 3.0
Needs material/awesome icons
Building C:\ABMATE~2\EFSOWI~1\Objects\copymewithjar.js.needs
Building core.min.1625097709113.css...
2021-07-01 10:03:58.083:INFO::main: Logging initialized @129951ms to org.eclipse.jetty.util.log.StdErrLog
2021-07-01 10:03:58.335:INFO:oejs.Server:main: jetty-9.4.z-SNAPSHOT; built: 2018-05-03T15:56:21.710Z; git: daa59876e6f384329b122929e70a80934569428c; jvm 11.0.1+13
2021-07-01 10:03:58.526:INFO:oejs.session:main: DefaultSessionIdManager workerName=node0
2021-07-01 10:03:58.526:INFO:oejs.session:main: No SessionScavenger set, using defaults
2021-07-01 10:03:58.530:INFO:oejs.session:main: node0 Scavenging every 660000ms
2021-07-01 10:03:58.773:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@536f2a7e{/,file:///C:/ABMaterial4_3/EF%20SowInfo/Objects/www/,AVAILABLE}
2021-07-01 10:03:58.780:INFO:oejs.AbstractNCSARequestLog:main: Opened C:\ABMaterial4_3\EF SowInfo\Objects\logs\b4j-2021_07_01.request.log
2021-07-01 10:04:00.116:INFO:oejs.AbstractConnector:main: Started ServerConnector@5c86a017{HTTP/1.1,[http/1.1]}{0.0.0.0:50002}
2021-07-01 10:04:00.118:INFO:oejs.Server:main: Started @131988ms
Emulated network latency: 100ms
2021-07-01 10:04:00.159:INFO:oejs.AbstractConnector:main: Stopped ServerConnector@5c86a017{HTTP/1.1,[http/1.1]}{0.0.0.0:50002}
2021-07-01 10:04:00.161:INFO:oejs.session:main: node0 Stopped scavenging
2021-07-01 10:04:00.166:INFO:oejsh.ContextHandler:main: Stopped o.e.j.s.ServletContextHandler@536f2a7e{/,file:///C:/ABMaterial4_3/EF%20SowInfo/Objects/www/,UNAVAILABLE}
2021-07-01 10:04:00.229:INFO:oejs.Server:main: jetty-9.4.z-SNAPSHOT; built: 2018-05-03T15:56:21.710Z; git: daa59876e6f384329b122929e70a80934569428c; jvm 11.0.1+13
2021-07-01 10:04:00.291:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@536f2a7e{/,file:///C:/ABMaterial4_3/EF%20SowInfo/Objects/www/,AVAILABLE}
2021-07-01 10:04:00.293:INFO:oejs.AbstractNCSARequestLog:main: Opened C:\ABMaterial4_3\EF SowInfo\Objects\logs\b4j-2021_07_01.request.log
2021-07-01 10:04:00.294:INFO:oejs.session:main: DefaultSessionIdManager workerName=node0
2021-07-01 10:04:00.294:INFO:oejs.session:main: No SessionScavenger set, using defaults
2021-07-01 10:04:00.294:INFO:oejs.session:main: node0 Scavenging every 660000ms
2021-07-01 10:04:00.301:INFO:oejs.AbstractConnector:main: Started ServerConnector@5c86a017{HTTP/1.1,[http/1.1]}{0.0.0.0:50002}
2021-07-01 10:04:00.303:INFO:oejs.Server:main: Started @132174ms
2021-07-01 10:04:00.304:INFO:oejs.session:main: node0 Scavenging every 990000ms

The server is running. There is one curious line in the log:-
Needs material/awesome icons
As I am not using any icons at this stage I have ignored it. I that OK

Anyhow pressing refresh in the Browser returns the code to my breakpoint with the following messages in the log:-

B4X:
2021-07-01 10:04:00.304:INFO:oejs.session:main: node0 Scavenging every 990000ms
/EFPR/images/redspot.png
Not Found
java.lang.NullPointerException
    at anywheresoftware.b4j.object.WebSocketModule$Adapter.onWebSocketText(WebSocketModule.java:121)
    at org.eclipse.jetty.websocket.common.events.JettyListenerEventDriver.onTextMessage(JettyListenerEventDriver.java:189)
    at org.eclipse.jetty.websocket.common.message.SimpleTextMessage.messageComplete(SimpleTextMessage.java:69)
    at org.eclipse.jetty.websocket.common.events.AbstractEventDriver.appendMessage(AbstractEventDriver.java:66)
    at org.eclipse.jetty.websocket.common.events.JettyListenerEventDriver.onTextFrame(JettyListenerEventDriver.java:158)
    at org.eclipse.jetty.websocket.common.events.AbstractEventDriver.incomingFrame(AbstractEventDriver.java:162)
    at org.eclipse.jetty.websocket.common.WebSocketSession.incomingFrame(WebSocketSession.java:476)
    at org.eclipse.jetty.websocket.common.extensions.AbstractExtension.nextIncomingFrame(AbstractExtension.java:183)
    at org.eclipse.jetty.websocket.common.extensions.compress.PerMessageDeflateExtension.nextIncomingFrame(PerMessageDeflateExtension.java:105)
    at org.eclipse.jetty.websocket.common.extensions.compress.CompressExtension.forwardIncoming(CompressExtension.java:143)
    at org.eclipse.jetty.websocket.common.extensions.compress.PerMessageDeflateExtension.incomingFrame(PerMessageDeflateExtension.java:85)
    at org.eclipse.jetty.websocket.common.extensions.ExtensionStack.incomingFrame(ExtensionStack.java:220)
    at org.eclipse.jetty.websocket.common.Parser.notifyFrame(Parser.java:220)
    at org.eclipse.jetty.websocket.common.Parser.parse(Parser.java:245)
    at org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.readParse(AbstractWebSocketConnection.java:560)
    at org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.onFillable(AbstractWebSocketConnection.java:391)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:281)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
    at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126)
    at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:760)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:678)
    at java.base/java.lang.Thread.run(Thread.java:834)

Note the line "
page.AddCanvasImage("RedSpot", "../images/redspot.png")

has note even been executed a second time.

The files are in folder:-

Directory of C:\ABMaterial4_3\EF SowInfo\Objects\www\EFPR\images

30/06/2021 06:17 PM <DIR> .
30/06/2021 06:17 PM <DIR> ..
30/06/2021 04:10 PM 13,600 compass.png
30/06/2021 06:15 PM 342 RedSpot.png
2 File(s) 13,942 bytes
2 Dir(s) 733,274,968,064 bytes free

C:\ABMaterial4_3\EF SowInfo\Objects\www\EFPR\images>

What's going ON?


"
 
Upvote 0

Rob White

Member
Licensed User
Well I have done a lot of testing but not going all that far forward!
Here is my current concept
WindDial.png

The user will drag the red spot to indicate wind direction and the distance from the centre will be the wind speed.

My problem is that as soon as I start to drag the spot it disappears. The code is based heavily on Alwaysbusy's ABMCanvas example and code above. Here is the complete page of code
B4X:
'Class module
Sub Class_Globals
    Private ws As WebSocket 'ignore
    ' will hold our page information
    Public page As ABMPage
    ' page theme
    Private theme As ABMTheme
    ' to access the constants
    Private ABM As ABMaterial 'ignore   
    ' name of the page, must be the same as the class name (case sensitive!)
    Public Name As String = "TstCanPage"  '<-------------------------------------------------------- IMPORTANT
    ' will hold the unique browsers window id
    Private ABMPageId As String = ""
    ' your own variables   
    
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
    ' build the local structure IMPORTANT!
    BuildPage       
End Sub

#Region ABM
Private Sub WebSocket_Connected (WebSocket1 As WebSocket)   
    Log("Connected")
        
    ws = WebSocket1       
    
    ABMPageId = ABM.GetPageID(page, Name,ws)
    
    Dim session As HttpSession = ABM.GetSession(ws, ABMShared.SessionMaxInactiveIntervalSeconds)
    If session.IsNew Then
        session.Invalidate
        ABMShared.NavigateToPage(ws, "", "./")
        Return
    End If
        
    If ABMShared.NeedsAuthorization Then
        If session.GetAttribute2("IsAuthorized", "") = "" Then
            ABMShared.NavigateToPage(ws, ABMPageId, "../")
            Return
        End If
    End If       
    ABM.UpdateFromCache(Me, ABMShared.CachedPages, ABMPageId, ws)       
    If page.ComesFromPageCache Then
        ' when we have a page that is cached it doesn't matter if it comes or not from a new connection we serve the cached version.
        Log("Comes from cache")       
        page.Refresh       
        page.FinishedLoading       
    Else
        If page.WebsocketReconnected Then
            Log("Websocket reconnected")
            ' when we have a client that doesn't have the page in cache and it's websocket reconnected and also it's session is new - basically when the client had internet problems and it's session (and also cache) expired before he reconnected so the user has content in the browser but we don't have any on the server. So we need to reload the page.
            ' when a client that doesn't have the page in cache and it's websocket reconnected but it's session is not new - when the client had internet problems and when he reconnected it's session was valid but he had no cache for this page we need to reload the page as the user browser has content, reconnected but we have no content in cache
            ABMShared.NavigateToPage (ws, ABMPageId, "./" & page.PageHTMLName)
        Else
            ' when the client did not reconnected it doesn't matter if the session was new or not because this is the websockets first connection so no dynamic content in the browser ... we are going to serve the dynamic content...
            Log("Websocket first connection")
            page.Prepare
            ConnectPage           
        End If
    End If
    Log(ABMPageId)       
End Sub

Private Sub WebSocket_Disconnected
    Log("Disconnected")
End Sub

Sub Page_ParseEvent(Params As Map)
    Dim eventName As String = Params.Get("eventname")
    Dim eventParams() As String = Regex.Split(",",Params.Get("eventparams"))
    
    Log(eventName)
    
    If eventName = "beforeunload" Then
        Log("preparing for url refresh")
        ABM.RemoveMeFromCache(ABMShared.CachedPages, ABMPageId)
        Return
    End If
    Dim caller As Object = page.GetEventHandler(Me, eventName)
    If caller = Me Then
        If SubExists(Me, eventName) Then
            Params.Remove("eventname")
            Params.Remove("eventparams")
            If eventName = "page_dropped" Then
                page.ProcessDroppedEvent(Params)
            End If
            Select Case Params.Size
                Case 0
                    CallSub(Me, eventName)
                Case 1
                    CallSub2(Me, eventName, Params.Get(eventParams(0)))
                Case 2
                    If Params.get(eventParams(0)) = "abmistable" Then
                        Dim PassedTables As List = ABM.ProcessTablesFromTargetName(Params.get(eventParams(1)))
                        CallSub2(Me, eventName, PassedTables)
                    Else
                        CallSub3(Me, eventName, Params.Get(eventParams(0)), Params.Get(eventParams(1)))
                    End If
                Case Else
                    ' cannot be called directly, to many param
                    CallSub2(Me, eventName, Params)
            End Select
        End If
    Else
        CallSubDelayed2(caller, "ParseEvent", Params) 'ignore
    End If
End Sub

public Sub BuildTheme()
    ' start with the base theme defined in ABMShared
    theme.Initialize("pagetheme")
    theme.AddABMTheme(ABMShared.MyTheme)

    ' add your specific page themes
    
End Sub

public Sub BuildPage()
    ' initialize the theme
    BuildTheme
    
    ' initialize this page using our theme
    page.InitializeWithTheme(Name, "/ws/" & ABMShared.AppName & "/" & Name, False, ABMShared.SessionMaxInactiveIntervalSeconds, theme)
    page.ShowLoader=True
    page.PageHTMLName = "index.html"
    page.PageTitle = "Template"
    page.PageDescription = "Template"
    page.PageKeywords = ""
    page.PageSiteMapPriority = ""
    page.PageSiteMapFrequency = ABM.SITEMAP_FREQ_YEARLY
        
    page.ShowConnectedIndicator = True
                
    ' adding a navigation bar
    ' ABMShared.BuildNavigationBar(page, "My Page","../images/logo.png", "", "", "")   
            
    ' create the page grid
    page.AddRowsM(2,True,20,0, "").AddCells12MP(1,0,0,0,0,"")   
    
    page.BuildGrid 'IMPORTANT once you loaded the complete grid AND before you start adding components
    page.AddCanvasImage("background", "../images/compass.png")
    page.AddCanvasImage("spt", "../images/RedSpot.png")

End Sub

public Sub ConnectPage()           
    '    connecting the navigation bar
    ' ABMShared.ConnectNavigationBar(page)
    Dim canvas2 As ABMCanvas
    canvas2.Initialize(page, "canvas2", ABM.COLOR_BLACK, ABM.INTENSITY_NORMAL, 300,300, False)

    Dim clock As ABMCanvasObject = BuildClock
    canvas2.AddObject(clock)

    Dim Spot As ABMCanvasObject
    Spot.InitializeAsRectangle(page,"spot",50,50,30,30,True)
    'Spot.InitializeAsCircle(page,"spot",50,50,10,True)
    Spot.SetDragZone(0,0,200,200)
    Spot.drawImage("spt",30,30)
    'Spot.Refresh
    canvas2.AddObject(Spot)
    canvas2.Refresh
    
    page.Cell(1,1).AddComponent(canvas2)
    
    ' refresh the page
    page.Refresh
    
    ' Tell the browser we finished loading
    page.FinishedLoading
    ' restoring the navigation bar position
    'page.RestoreNavigationBarPosition   
End Sub
#end region

#Region ABMPage
' clicked on the navigation bar

Sub BuildClock() As ABMCanvasObject
    Dim clock As ABMCanvasObject
    Dim Radius As Double = 150
    
    clock.InitializeAsRectangle(page, "clock", 0,0,300,300, True)
    
    Radius = Radius * 0.9
    
    ' make background transparent
    clock.clearRect(0,0,300,300)
        
    ' draw face
    clock.translate(150,150)
    clock.beginPath
    clock.arc(0,0,Radius, 0, 2*cPI)
    clock.fillStyleColor("#FFFFFF")
    clock.fill
    clock.strokeStyleRadialGradient(0,0,Radius*0.95,0,0,Radius*1.05, Array As Double(0,0.5,1), Array As String("#333", "green", "#333"))
    clock.lineWidth(Radius*0.1)
    clock.stroke()
    
    clock.beginPath
    clock.arc(0, 0, Radius*0.1, 0, 2*cPI)
    clock.fillStyleColor("#333")
    'clock.fill
    
    'draw numbers
    clock.font("arial", Radius*0.15)
    clock.textBaseline(ABM.CANVAS_TEXTBASELINE_MIDDLE)
    clock.textAlign(ABM.CANVAS_TEXTALIGN_CENTER)
    Dim ang As Double
    Dim dir() As String = Array As String ("N","NE","E","SE","S","SW","W","NW","Calm")
    
    For num = 1 To 8
        ang = num * cPI / 4
        clock.rotate(ang)
        clock.translate(0, -Radius*0.85)
        clock.rotate(-ang)
        clock.fillText("" & dir(num-1), 0, 0)
        clock.rotate(ang)
        clock.translate(0, Radius*0.85)
        clock.rotate(-ang)
    Next
    clock.fillText(dir(8), 0, 0)
    
    
    ' draw time
    'Dim hour As Double = DateTime.GetHour(DateTime.Now)
    'Dim minute As Double = DateTime.GetMinute(DateTime.Now)
    'Dim second As Double = DateTime.GetSecond(DateTime.Now)
    'hour = hour Mod 12
    'hour = (hour*cPI/6)+(minute*cPI/(6*60))+(second*cPI/(360*60))
    'BuildHand(clock, hour, Radius*0.5, Radius*0.07)
    'minute=(minute*cPI/30)+(second*cPI/(30*60))
    'BuildHand(clock, minute, Radius*0.8, Radius*0.07)
    'second=(second*cPI/30)
    'BuildHand(clock, second, Radius*0.9, Radius*0.02)
    
    Return clock
End Sub

Sub canvas2_objectup(objectId As String)
    Log(objectId)
    Dim c2 As ABMCanvas = page.Component("canvas2")
    Dim S As ABMCanvasObject = c2.GetObject("spot")
    Dim Pos As ABMPoint = S.GetPosition
    S.Refresh
    If Pos <> Null Then
        Log(Pos.x &" - "& Pos.y)
    End If
End Sub

Sub canvas2_CanvasUp(x As Int, y As Int)
    Log("canvas up: " & x & " - " & y)
End Sub

Sub BuildHand(clock As ABMCanvasObject, pos As Int, length As Double, width As Double)
    clock.beginPath
    clock.lineWidth(width)
    clock.lineCap(ABM.CANVAS_LINECAP_ROUND)
    clock.moveTo(0,0)
    clock.rotate(pos)
    clock.lineTo(0, -length)
    clock.stroke
    clock.rotate(-pos)
End Sub

Sub Page_NavigationbarClicked(Action As String, Value As String)
    ' saving the navigation bar position
    page.SaveNavigationBarPosition
    If Action = "LogOff" Then
        ABMShared.LogOff(page)
        Return
    End If

    ABMShared.NavigateToPage(ws, ABMPageId, Value)
End Sub

Sub Page_DebugConsole(message As String)
    Log("---> " & message)
End Sub
#end region

There is some sort of problem (not sure if it is to do with the disappearnce of the spot or not) at line 163 if the refresh is uncommented then there is a null pointer exception. Here 's the log

B4X:
Waiting for debugger to connect...
Program started.
Start B4J Analyse!
When an error occurs, check the B4JAnalyse.log file in the Objects folder to see the last B4J line it was working on.
Collecting data from B4J source files... (1/2)
DBM.bas
ABMShared.bas
ABMUploadHandler.bas
ABMCacheControl.bas
ABMCacheScavenger.bas
ABMCustomComponentTemplate.bas
ABMErrorHandler.bas
ABMRootFilter.bas
ABMApplication.bas
TstCanPage.bas
ABMPageTemplate.bas
ABMPageTemplateAlternative.bas
TestCanvas.b4j
Analysing data from B4J source files... (2/2)
loading C:\ABMATE~2\Testing\TESTCA~1\Objects: copymewithjar.needs...
Using cache system: 3.0
Needs material/awesome icons
Building C:\ABMATE~2\Testing\TESTCA~1\Objects\copymewithjar.js.needs
Building core.min.1625140674112.css...
2021-07-01 21:57:55.259:INFO::main: Logging initialized @1761ms to org.eclipse.jetty.util.log.StdErrLog
2021-07-01 21:57:55.501:INFO:oejs.Server:main: jetty-9.4.z-SNAPSHOT; built: 2018-05-03T15:56:21.710Z; git: daa59876e6f384329b122929e70a80934569428c; jvm 11.0.1+13
2021-07-01 21:57:55.612:INFO:oejs.session:main: DefaultSessionIdManager workerName=node0
2021-07-01 21:57:55.612:INFO:oejs.session:main: No SessionScavenger set, using defaults
2021-07-01 21:57:55.616:INFO:oejs.session:main: node0 Scavenging every 600000ms
2021-07-01 21:57:55.670:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@2ed2d9cb{/,file:///C:/ABMaterial4_3/Testing/TestCanvas/Objects/www/,AVAILABLE}
2021-07-01 21:57:55.679:INFO:oejs.AbstractNCSARequestLog:main: Opened C:\ABMaterial4_3\Testing\TestCanvas\Objects\logs\b4j-2021_07_01.request.log
2021-07-01 21:57:56.292:INFO:oejs.AbstractConnector:main: Started ServerConnector@55a147cc{HTTP/1.1,[http/1.1]}{0.0.0.0:51042}
2021-07-01 21:57:56.294:INFO:oejs.Server:main: Started @2802ms
Emulated network latency: 100ms
2021-07-01 21:57:56.351:INFO:oejs.AbstractConnector:main: Stopped ServerConnector@55a147cc{HTTP/1.1,[http/1.1]}{0.0.0.0:51042}
2021-07-01 21:57:56.352:INFO:oejs.session:main: node0 Stopped scavenging
2021-07-01 21:57:56.359:INFO:oejsh.ContextHandler:main: Stopped o.e.j.s.ServletContextHandler@2ed2d9cb{/,file:///C:/ABMaterial4_3/Testing/TestCanvas/Objects/www/,UNAVAILABLE}
2021-07-01 21:57:56.386:INFO:oejs.Server:main: jetty-9.4.z-SNAPSHOT; built: 2018-05-03T15:56:21.710Z; git: daa59876e6f384329b122929e70a80934569428c; jvm 11.0.1+13
2021-07-01 21:57:56.399:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@2ed2d9cb{/,file:///C:/ABMaterial4_3/Testing/TestCanvas/Objects/www/,AVAILABLE}
2021-07-01 21:57:56.409:INFO:oejs.AbstractNCSARequestLog:main: Opened C:\ABMaterial4_3\Testing\TestCanvas\Objects\logs\b4j-2021_07_01.request.log
2021-07-01 21:57:56.409:INFO:oejs.session:main: DefaultSessionIdManager workerName=node0
2021-07-01 21:57:56.409:INFO:oejs.session:main: No SessionScavenger set, using defaults
2021-07-01 21:57:56.409:INFO:oejs.session:main: node0 Scavenging every 600000ms
2021-07-01 21:57:56.415:INFO:oejs.AbstractConnector:main: Started ServerConnector@55a147cc{HTTP/1.1,[http/1.1]}{0.0.0.0:51042}
2021-07-01 21:57:56.416:INFO:oejs.Server:main: Started @2923ms
2021-07-01 21:57:56.417:INFO:oejs.session:main: node0 Scavenging every 990000ms
Connected
Waiting for value (100 ms)
java.nio.channels.ClosedChannelException
    at org.eclipse.jetty.websocket.common.io.FrameFlusher.succeedEntries(FrameFlusher.java:246)
    at org.eclipse.jetty.websocket.common.io.FrameFlusher.succeeded(FrameFlusher.java:234)
    at org.eclipse.jetty.io.WriteFlusher.write(WriteFlusher.java:342)
    at org.eclipse.jetty.io.AbstractEndPoint.write(AbstractEndPoint.java:380)
    at org.eclipse.jetty.websocket.common.io.FrameFlusher.flush(FrameFlusher.java:218)
    at org.eclipse.jetty.websocket.common.io.FrameFlusher.process(FrameFlusher.java:157)
    at org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:241)
    at org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:224)
    at org.eclipse.jetty.websocket.common.io.FrameFlusher.enqueue(FrameFlusher.java:90)
    at org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.outgoingFrame(AbstractWebSocketConnection.java:495)
    at org.eclipse.jetty.websocket.common.WebSocketSession.close(WebSocketSession.java:223)
    at org.eclipse.jetty.websocket.common.WebSocketSession.close(WebSocketSession.java:190)
    at anywheresoftware.b4j.object.WebSocket.Close(WebSocket.java:351)
    at com.ab.template.abmshared._navigatetopage(abmshared.java:101)
    at com.ab.template.tstcanpage._websocket_connected(tstcanpage.java:600)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:632)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:237)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:91)
    at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:98)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:78)
    at anywheresoftware.b4j.object.WebSocketModule$Adapter$ThreadHandler.run(WebSocketModule.java:188)
    at anywheresoftware.b4a.keywords.SimpleMessageLoop.runMessageLoop(SimpleMessageLoop.java:30)
    at anywheresoftware.b4a.StandardBA.startMessageLoop(StandardBA.java:26)
    at anywheresoftware.b4a.shell.ShellBA.startMessageLoop(ShellBA.java:119)
    at anywheresoftware.b4a.keywords.Common.StartMessageLoop(Common.java:153)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:309)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:91)
    at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:98)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:78)
    at anywheresoftware.b4j.object.JServlet.createInstance(JServlet.java:65)
    at anywheresoftware.b4j.object.BackgroundWorkersManager$1.run(BackgroundWorkersManager.java:21)
    at anywheresoftware.b4a.keywords.SimpleMessageLoop.runMessageLoop(SimpleMessageLoop.java:30)
    at anywheresoftware.b4a.StandardBA.startMessageLoop(StandardBA.java:26)
    at anywheresoftware.b4a.shell.ShellBA.startMessageLoop(ShellBA.java:119)
    at anywheresoftware.b4a.keywords.Common.StartMessageLoop(Common.java:153)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:309)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:91)
    at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:98)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:78)
    at com.ab.template.main.main(main.java:29)
beforeunload
preparing for url refresh
Disconnected
Connected
Waiting for value (100 ms)
Saving the first instance
Waiting for value (116 ms)
Websocket first connection
Error occurred on line: 163 (TstCanPage)
java.lang.NullPointerException
    at com.ab.abmaterial.ABMCanvasObject.Refresh(Unknown Source)
    at com.ab.template.tstcanpage._connectpage(tstcanpage.java:394)
    at com.ab.template.tstcanpage._websocket_connected(tstcanpage.java:653)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:632)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:237)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
    at jdk.internal.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:91)
    at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:98)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:78)
    at anywheresoftware.b4j.object.WebSocketModule$Adapter$ThreadHandler.run(WebSocketModule.java:188)
    at anywheresoftware.b4a.keywords.SimpleMessageLoop.runMessageLoop(SimpleMessageLoop.java:30)
    at anywheresoftware.b4a.StandardBA.startMessageLoop(StandardBA.java:26)
    at anywheresoftware.b4a.shell.ShellBA.startMessageLoop(ShellBA.java:119)
    at anywheresoftware.b4a.keywords.Common.StartMessageLoop(Common.java:153)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:309)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:91)
    at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:98)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:78)
    at anywheresoftware.b4j.object.JServlet.createInstance(JServlet.java:65)
    at anywheresoftware.b4j.object.BackgroundWorkersManager$1.run(BackgroundWorkersManager.java:21)
    at anywheresoftware.b4a.keywords.SimpleMessageLoop.runMessageLoop(SimpleMessageLoop.java:30)
    at anywheresoftware.b4a.StandardBA.startMessageLoop(StandardBA.java:26)
    at anywheresoftware.b4a.shell.ShellBA.startMessageLoop(ShellBA.java:119)
    at anywheresoftware.b4a.keywords.Common.StartMessageLoop(Common.java:153)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:309)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:91)
    at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:98)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:78)
    at com.ab.template.main.main(main.java:29)
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
There is some sort of problem (not sure if it is to do with the disappearnce of the spot or not) at line 163 if the refresh is uncommented
This is normal, only after page.refresh are all objects flushed to the browser. You are trying to refresh something that is not yet available in the browser. In fact, try removing canvas2.Refresh on line 165 too, as the same thing applies. See if helps.
 
Upvote 0

Rob White

Member
Licensed User
Thanks alwaysbusy.
That solved the NullPointerException

My main problem now is that I can not get the position of a click event, well not even seeing the click event.
I have this code in the top of Page_ParseEvent
B4X:
Sub Page_ParseEvent(Params As Map)
    Dim eventName As String = Params.Get("eventname")
    Dim eventParams() As String = Regex.Split(",",Params.Get("eventparams"))
    
    #If DEBUG
    Log($"Evt fired --->${eventName} Number params = ${Params.Size}"$)
    For i = 0 To Params.Size-1
        Log($"    Key = ${Params.GetKeyAt(i)}, value = ${Params.GetValueAt(i)}"$)
    Next
    Log("-----------------------------------------------------")
    #End if

The only events seen are
B4X:
Evt fired --->canvas2_objectdown Number params = 3
    Key = eventparams, value = objectid
    Key = eventname, value = canvas2_objectdown
    Key = objectid, value = clock
-----------------------------------------------------
Evt fired --->canvas2_objectup Number params = 3
    Key = eventparams, value = objectid
    Key = eventname, value = canvas2_objectup
    Key = objectid, value = clock
-----------------------------------------------------
Waiting for value (100 ms)

How can I get the x,y position when I am not seeing any _CanvasUp(x as int,Y as int) events
 
Upvote 0
Top