B4J Question Timer in class instance works not as expected

welu1805

Active Member
Licensed User
Longtime User
Hi all,

here is a problem (for me) that makes me stupid!

I have a class "clsTest" in which I create a label on the MainForm.
In a method "Show" of this class the label becomes visible.
A timer will in Timer1_Tick make the label invisible.

In the MainForm is a button. If I click on it the label in the class is created and shown.
After 5 seconds the label disappears as expected.

But if I click sometimes within the timer delaytime only the last label disapperas. How is this possible? Everytime I click on the button a new instance of my class is created with its OWN timer.

No idea.

Lutz

B4X:
#Region  Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 400
#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private btnStart As Button
    Private Msg As clsTest
    Private top As Int
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.SetFormStyle("UNIFIED")
    'MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
   
    btnStart.Initialize("btnStart")
    MainForm.RootPane.AddNode(btnStart, 250, 200, 100, 100)
    btnStart.Text = "Create Instance"
    top = 0
   
    MainForm.Show
End Sub

Sub btnStart_MouseClicked (EventData As MouseEvent)
    Msg.Initialize(MainForm, 5000, top)
    Msg.Show("This is a test message.")
    top = top + 10
End Sub

And a class modul "clsTest":

B4X:
Class module
Sub Class_Globals
    Private fx As JFX
   
    Private Timer1 As Timer
    Private Label1 As Label
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize(AParent As Form, ATime As Int, ATop as int)
    Label1.Initialize("")
    AParent.RootPane.AddNode(Label1, 100, ATop, 400, 50)
   
    Label1.Visible = False
    Timer1.Initialize("Timer1", ATime)
End Sub

Public Sub Show(AText As String)
    Label1.Text = AText
    Label1.Visible = True
    Timer1.Enabled = True
End Sub

Private Sub Timer1_Tick
    Timer1.Enabled = False
    Label1.Visible = False
    Label1.RemoveNodeFromParent
End Sub
 

stevel05

Expert
Licensed User
Longtime User
Because you are using the same global variable for all the Msg objects, put them in a list or map, then add a callback to remove them once the label has been removed.
 
Upvote 0

welu1805

Active Member
Licensed User
Longtime User
That was the solution. I removed the variable Msg from Process_Globals and put them into btnStart_MouseClicked method.
So a new variable Msg everytime is created in MouseClicked. Now it works as expected!

Thank you very much. You saved my weekend!
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
You are welcome. just one point, if you don't hold the objects in a global variable there is a chance (however small) that the objects will be destroyed and the process fail if the system carries out a garbage collection while the class is still processing.
 
Upvote 0

welu1805

Active Member
Licensed User
Longtime User
In Process_Globals:

Private MsgList As List

In btnStart_MouseClicked:

Dim Msg As clsTest
MsgList.Add(Msg)

Additional method:

Sub RemoveMsg
MsgList.RemoveAt(0)
End Sub

In the class in Timer1_Tick:

CallSub(Main, "RemoveMsg")

Now OK?
 
Upvote 0

welu1805

Active Member
Licensed User
Longtime User
stevel05, this is an important point because later the programm sometimes could crash and I don't know why
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Yes, that should do it.
 
Upvote 0
Top