Android Question B4XView events

microfan

Member
Hello all,

I am starting to develop a cross-platform app, so I chose B4XPages. I am using B4J for speed. But I have a stupid and basic question, which can not solve.

In the visual designer I've put a few views, but I am not able to use their events. For example, I've put a Button1 (type Button).
Then I used the menu to generate the event, and it created Private Sub Button1_Click() in the B4XMainPage module (correct, I think).

But that subroutine is never invoked (of course I run the program and click the button).

I also declared then button in the Sub Class_Globals: "Private Button1 As B4XView", but this does not help (I supposed that).

So, what are the requisite to put a view in the visual designer, and write event handlers for it?

Meanwhile - I should also use "composite" buttons, i.e. buttons which contain graphics and text. I used a Pane, then put two labels inside it. The graphical aspect is ok, but then can I click the Pane like it was a button with elements inside?

Thank you in advance, have a happy Christmas everyone.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
I also declared then button in the Sub Class_Globals: "Private Button1 As B4XView", but this does not help (I supposed that).
Not needed.

So, what are the requisite to put a view in the visual designer, and write event handlers for it?
Just the sub with the correct event name.

The problem is somewhere else. Upload your project.
 
Upvote 0

microfan

Member
Thank you Erel. Sorry for delay in reply.

I upload the project. Apart from this problem (I am sure I am missed something), I will need to have "composite" buttons. Some suggesiton would be appreciated.
 

Attachments

  • CPA-Copertura.zip
    7.2 KB · Views: 12
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
There are several mistakes that i see:

1.
B4X:
    B4XPages.AddPage("Impianti", pgImpianti)  'adds Page1 to the B4XPages list

    pgImpianti.Initialize
You should first initialize the page and only then call B4XPages.AddPage.

2. The warnings are correct. The global variables are never assigned and this also hints on the reason that the events are not raised.
The relevant layout file is loaded in the second page. This means that the variables and the events subs should be in that page.

3. The ImageView in the main page is mistakenly anchored to both sides but is very far from the borders. This is a mistake. If you want to have an ImageView in the center then add this designer script:
B4X:
ImageView1.HorizontalCenter = 50%x
ImageView1.VerticalCenter = 50%y
 
Upvote 0

microfan

Member
How stupid I am!

The event handlers were in the wrong file, and the variables were too. I am not enough used to the IDE and didn't notice that.
Moved them in the correct file and it works - **without** declaring any GUI related variable (btAggiungi and so on). You (and me) were right: it is not needed.

Then I tried to declare them (in the intended file). They are not explicitely assigned, but the warnings about not assigning them don't fire up. How can the compiler know that those variables are declared in a .bjl file? I am missing something.

Then I tried to declare a variable Button2 as B4XView (only in code, not in Designer). The warning about a variable never assigned to appears again. The project still works, so this kind of warning does not impede the program to work.

So, the problem was that the event handlers where declared in the wrong file. Me stupid!

But now I have another problem. I see that clicking the "composite" button btAggiungi (which is in reality a Pane), the mouseClicked event raises when the mouse button is released (quite correct); when the mouse button si pressed, nothing happens -- but I would like to give the user the classic effect of a button pressed, or something like that, some form of feedback. But I don't see an event like MouseDown.

So the last (I promise) question is: how can I have composite buttons, either:

1) Constructed with panels or other containers, but having a MouseDown or TouchDown event to give feedback
...or...
2) A real button (which gives feedback) with child items in it

The thing should work for B4A and B4I, B4J is only for quick development. If it is impossible in B4J but doable in B4I and B4A it's ok.

I upload the corrected project; regards,
 

Attachments

  • CPA-Copertura-after Erel.zip
    7.3 KB · Views: 9
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
BTW, I tested your project with the new CodeBundle tool: https://www.b4x.com/android/forum/t...a-single-json-for-ai-analysis.169835/#content

Then asked ChatGPT:

1766994135365.png


Short answer: the button is on a different B4XPage than the code handling it, so the event is never wired.


What’s happening​


  • Button1 is defined in the imieiimpianti layout/page
  • Button1_Click is written in B4XMainPage
  • In B4XPages, events only fire in the page that loaded the layout
  • You then call ShowPageAndRemovePreviousPages("Impianti"), so B4XMainPage is no longer active anyway

Result: Button1_Click in B4XMainPage will never be raised.


I then asked it to "find other bugs":
The first point is moot, but the other are correct.



Here are other real issues / likely bugs I see in your project (besides the Button1_Click page/layout mismatch):




1) B4XPagesManager is local in AppStart (can break the app)​


In Main.AppStart you do:


  • create Dim PagesManager As B4XPagesManager
  • PagesManager.Initialize(MainForm)
  • then AppStart ends
In the standard B4XPages template, PagesManager is Process_Globals, not local, so it stays alive. With a local variable, you’re relying on internal references to keep it from being collected / lost.


Fix (recommended):





Sub Process_Globals
Private fx As JFX
Private MainForm As Form
Private PagesManager As B4XPagesManager
End Sub

Sub AppStart (Form1 As Form, Args() As String)
MainForm = Form1
MainForm.Show
PagesManager.Initialize(MainForm)
End Sub




2) You add the page before initializing the page object​


In B4XMainPage.B4XPage_Created you do:


  • B4XPages.AddPage("Impianti", pgImpianti)
  • only later: pgImpianti.Initialize
If pgImpianti isn’t initialized yet, this is the wrong order (and can lead to subtle “page not working / events not firing / state missing” behavior).


Fix:





pgImpianti.Initialize
B4XPages.AddPage("Impianti", pgImpianti)


(Or use AddPageAndCreate if you want B4XPages to create it.)




3) B4XMainPage declares views that are not in the layout it loads


B4XMainPage loads "MainPage"


…but its globals include btAggiungi, Label4, Button1 and it even checks Label4.IsInitialized Those views are in the other layout (imieiimpianti), which is loaded in the other page (i_miei_impianti)
.


So in B4XMainPage, those fields + event subs are essentially dead code and misleading.


Fix: Remove them from B4XMainPage, or move the relevant handlers into i_miei_impianti.




4) Sleep(1000) inside B4XPage_Created + “remove previous pages” is a foot-gun​


You do:


  • Sleep(1000)
  • then ShowPageAndRemovePreviousPages("Impianti")
This can cause hard-to-debug timing issues (especially during startup / slow machines) and makes it easy to accidentally “remove” the page that contains the code you expect to run.


Fix idea: don’t use Sleep here; navigate immediately, or wait for a real condition (like “page created” / “data loaded”).




5) Duplicate input handlers on the same control (btAggiungi_Touch and _MouseClicked)​


You have both:


  • btAggiungi_Touch(...) and
  • btAggiungi_MouseClicked(...)
On B4J you normally stick to mouse events; having both can lead to “double” messages or inconsistent behavior depending on control type and platform.


Fix: keep one (usually _MouseClicked for B4J desktop).
 
Upvote 0

microfan

Member
ChatGPT is awesome.

For point #2, I tried again the old (wrong) version (first add page, then initialize it). It works anyway (for now). It is not clear to me why the page should be initialized beforehand, but who cares, it costs very little to initialize it before adding it.

For point #3, correct. That was the problem. I am unable to understand how powerful is AI to come to this conclusion.

For point #4, I disagree. The first page is a splash screen: I really want to wait for about 1 second or so. And I also find a little picky the idea that '...it makes it easy to accidentally “remove” the page...'. I am a programmer, I know very well that it is easy to accidentally introduce bugs.

For point #5, ok. Both events are there because I was exploring, and ChatGPT didn't know.
 
Upvote 0
Top