Page 1 of 2

ClearGadgetItems() doesn't clear first row in EditorGadget?

Posted: Thu Mar 31, 2016 2:53 pm
by Lord
Hi!

I got in my program the situation that I clear an EditorGadget
within a procedure. After that, there is some work and then
I set some new text.
What happens now is, that the text is cleared, but not the
first line.

I reduced my code to show this behaviour:
Just click in StringGadget and hit return, then do this again.

Code: Select all

Procedure SetSomeText()
  Static x
  ClearGadgetItems(2)
  x=1-x
  If x
    SetGadgetText(2, "1111111111111111111"+#CRLF$+"1111111111111111111")
    Delay(500)
  Else
    SetGadgetText(2, "2222222222222222222"+#CRLF$+"2222222222222222222")
    Delay(500)
  EndIf
EndProcedure

OpenWindow(1, 10, 10, 640, 480, "")
StringGadget(1, 55, 5, 580, 20, "")
EditorGadget(2, 5, 30, 630, 445, #PB_Editor_WordWrap)
AddKeyboardShortcut(1, #PB_Shortcut_Return, 10)
BindEvent(#PB_Event_Menu, @SetSomeText(), 1)

Quit=#False 
Repeat
  Event=WaitWindowEvent()
  Select Event
    Case #PB_Event_CloseWindow
      Quit=#True
  EndSelect
Until Quit=#True
SetGadgetText(#Gadget, "") also leaves text in first row.

What went wrong?

Re: ClearGadgetItems() doesn't clear first row in EditorGadg

Posted: Thu Mar 31, 2016 3:43 pm
by collectordave
I think it is because you need to leave some time for it all to happen.

I have modyfied your code and added a button. Click the button to add text and then clear text one step at a time and it seems to work fine.

Code: Select all

Procedure SetSomeText()
  Static x
  SetGadgetText(2,"")
  x=1-x
  Delay(50)
  SetGadgetText(2, "1111111111111111111"+#CRLF$+"1111111111111111111")
  Delay(1000)
  SetGadgetText(2,"")
  Delay(500) 
  SetGadgetText(2, "2222222222222222222"+#CRLF$+"2222222222222222222")
  Delay(500)
  
EndProcedure

Global settxt.i

OpenWindow(1, 10, 10, 640, 480, "")
StringGadget(1, 55, 5, 580, 20, "")
ButtonGadget(3, 50, 30, 70, 20, "")
EditorGadget(2, 5, 60, 630, 445, #PB_Editor_WordWrap)
;AddKeyboardShortcut(1, #PB_Shortcut_Return, 10)
;BindEvent(#PB_Event_Menu, @SetSomeText(), 1)

Quit=#False
Repeat
  Event=WaitWindowEvent()
  Select Event
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 3
          Select settxt
            Case 0
              SetGadgetText(2, "1111111111111111111"+#CRLF$+"1111111111111111111")
              settxt = settxt + 1
            Case 1
              SetGadgetText(2,"")
              settxt = settxt + 1
            Case 2
              SetGadgetText(2, "2222222222222222222"+#CRLF$+"2222222222222222222")
              settxt = settxt + 1
            Case 3
              SetGadgetText(2,"")
              settxt = 0
           EndSelect                 
      EndSelect
    Case #PB_Event_CloseWindow
      Quit=#True
  EndSelect
Until Quit=#True
Regards

CD

Re: ClearGadgetItems() doesn't clear first row in EditorGadg

Posted: Fri Apr 01, 2016 12:00 pm
by Lord
Sorry, but your code does not the same as mine.

1. You are not using BindEvent() anymore
2. You need an extry click to set the new text

I modify your code

Code: Select all

Global settxt.i

OpenWindow(1, 10, 10, 640, 480, "")
StringGadget(1, 55, 5, 580, 20, "")
ButtonGadget(3, 50, 30, 70, 20, "")
EditorGadget(2, 5, 60, 630, 445, #PB_Editor_WordWrap)

Quit=#False
Repeat
  Event=WaitWindowEvent()
  Select Event
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 3
          Select settxt
            Case 0
              ClearGadgetItems(2)
              Delay(500)
              SetGadgetText(2, "1111111111111111111"+#CRLF$+"1111111111111111111")
              settxt = 1-SetText
            Case 1
              ClearGadgetItems(2)
              Delay(500)
              SetGadgetText(2, "2222222222222222222"+#CRLF$+"2222222222222222222")
              settxt = 1-settxt
           EndSelect                 
      EndSelect
    Case #PB_Event_CloseWindow
      Quit=#True
  EndSelect
Until Quit=#True

the EditorGadget shows the same behaviour: the first line ist not erased.

Re: ClearGadgetItems() doesn't clear first row in EditorGadg

Posted: Fri Apr 01, 2016 12:19 pm
by infratec
Hi,

you made still the same fault in your thinking.

It is a windows program, which is event driven.
A call to something which modifies the GUI is not handled immediately.
At least one round through the event loop is needed.

Your Delay(500) stop the code from doing this.

What you can do is to add a timer for 500ms and disable the window for this time.

But why do you want a delay after SetGadgetText() ?

Bernd

Re: ClearGadgetItems() doesn't clear first row in EditorGadg

Posted: Fri Apr 01, 2016 4:20 pm
by PureLust
As Infratec said, it has to do with Windows Events.

The refreshing of Gadgets is done during Window-Events.

Because you clear the Gadget within an Event-Callback, the Event for repainting the Gadget can not be processed until you finish the Event-Procedure you are in.

To proof this, just add "While WindowEvent() : Wend" after your "ClearGadgetItems(2)".
This will force to process outstanding Events - so your List will be cleared immediately.

Hint/Warning: This only works with disabled debugger, because it's not a good way (and prohibited by the debugger) to read/manipulate the Event-List while you are in an Event-Callback.
So - don't see this as an solution - it was just to show you what causes the effect you mentioned !!!

Life with it or find another way to do your time consuming calculation outside the Event (e.g. by doing it within a thread you start within the Event-Callback).

Further I assume, it's a Windows-Only Problem and it will not be noticeable on Linux or OS-X.

Re: ClearGadgetItems() doesn't clear first row in EditorGadg

Posted: Fri Apr 01, 2016 7:01 pm
by Lord
Thanks for both answers, but it does not answer the
question why the EditorGadget is cleared but not the
first line.

Re: ClearGadgetItems() doesn't clear first row in EditorGadg

Posted: Fri Apr 01, 2016 7:22 pm
by Gadget
Hi Lord,

I gave your code a go and can confirm that the first line isn't cleared but the later lines are (PB 5.42 and Win 10). Hence, it appears that events are being handled okay and this is an oddity in the EditorGadget itself (presumably the Delay(500) is for the effect to be visible).

I don't know the solution but hopefully my confirmation helps your sanity :)

Cheers,

Gadget

Re: ClearGadgetItems() doesn't clear first row in EditorGadg

Posted: Fri Apr 01, 2016 8:07 pm
by collectordave
The editorgadget is not cleared as it is not given the time to clear. Window events need to be processed for the gadget to clear completely.

If you try the code below it appears to clear fully every time

Code: Select all

Global settxt.i,StartTime.i,WaitTime.i

Procedure SetSomeText()
  
  Static x
  ClearGadgetItems(2)
  While WindowEvent() ;Added to allow windows events to be processed
  Wend
  Delay(500) ;Enough to see that the gadget is cleared?
  x=1-x
  If x
    SetGadgetText(2, "1111111111111111111"+#CRLF$+"1111111111111111111")
    ;no delay needed just wait a second before pressing the return key
  Else
    SetGadgetText(2, "2222222222222222222"+#CRLF$+"2222222222222222222")
    ;no delay needed just wait a second before pressing the return key
  EndIf
EndProcedure

OpenWindow(1, 10, 10, 640, 480, "")
StringGadget(1, 55, 5, 580, 20, "")
ButtonGadget(3, 50, 30, 70, 20, "")
EditorGadget(2, 5, 60, 630, 445, #PB_Editor_WordWrap)
SetGadgetText(2, "000000000000000000"+#CRLF$+"000000000000000000")
AddKeyboardShortcut(1, #PB_Shortcut_Return, 10)
BindEvent(#PB_Event_Menu, @SetSomeText(), 1)

Quit=#False
Repeat
  Event=WaitWindowEvent()
  Select Event
    Case #PB_Event_CloseWindow
      Quit=#True
  EndSelect
Until Quit=#True

Re: ClearGadgetItems() doesn't clear first row in EditorGadg

Posted: Sat Apr 02, 2016 1:38 pm
by Lord
@Gadget:
Thank you for confirmation.

@all:
So it is not possible to have text cleared and set in
a good looking manner when there is some time
consuming code in a procedure called via BindEvent?

Next Example:

Code: Select all

Procedure SetSomeText()
  Dim Text.s(1)
  Static x
  
  ClearGadgetItems(2)
  x=1-x
  If x
    For i=1 To 25
      Text(x)+"11111111111111111111111111111111"+#CRLF$
    Next
    SetGadgetText(2, Text(x))
    ; some time consuming things after Settext
    For i=1 To 1000000
      y=Pow(2, i)
    Next
    SetGadgetText(2, Text(x))
  Else
    For i=1 To 25
      Text(x)+"22222222222222222222222222222222"+#CRLF$
    Next
    SetGadgetText(2, Text(x))
    ; some time consuming things before Settext
    For i=1 To 1000000
      y=Pow(2, i)
    Next
  EndIf
EndProcedure

OpenWindow(1, 10, 10, 640, 480, "")
StringGadget(1, 5, 5, 630, 20, "")
EditorGadget(2, 5, 30, 630, 445, #PB_Editor_WordWrap)
AddKeyboardShortcut(1, #PB_Shortcut_Return, 10)
BindEvent(#PB_Event_Menu, @SetSomeText(), 1)
Quit=#False
Repeat
  Event=WaitWindowEvent()
  Select Event
    Case #PB_Event_CloseWindow
      Quit=#True
  EndSelect
Until Quit=#True

Re: ClearGadgetItems() doesn't clear first row in EditorGadg

Posted: Sun Apr 03, 2016 4:32 am
by collectordave
Hi

It is not just bindevent but any event handling where you need to do some really time consuming stuff. the more time consuming, and by that I mean where you are processing some info etc which prevents your programme from returning to the repeat waitwindowevent() loop, it becomes more likely that the OS will see you programme as non responsive. So do be carefull with all time consuming procedures.

One way round this is to use a thread for the time consuming part of your code which then allows your GUI to react. Example below:-

Code: Select all

Procedure TimeConsumer(Param)

    For i=1 To 1000000
      y=Pow(2, i)
    Next
    Debug "Time Comsuming process Finished"
    
EndProcedure

Procedure SetSomeText()
  Dim Text.s(1)
  Static x
 
  ClearGadgetItems(2)
  x=1-x
  If x
    For i=1 To 25
      Text(x)+"11111111111111111111111111111111"+#CRLF$
    Next
    SetGadgetText(2, Text(x))
    ; some time consuming things after Settext
    CreateThread(@TimeConsumer(),23)
    SetGadgetText(2, Text(x))
  Else
    For i=1 To 25
      Text(x)+"22222222222222222222222222222222"+#CRLF$
    Next
    SetGadgetText(2, Text(x))
    ; some time consuming things before Settext
    CreateThread(@TimeConsumer(),23)
  EndIf
EndProcedure

OpenWindow(1, 10, 10, 640, 480, "")
StringGadget(1, 5, 5, 630, 20, "")
EditorGadget(2, 5, 30, 630, 445, #PB_Editor_WordWrap)
AddKeyboardShortcut(1, #PB_Shortcut_Return, 10)
BindEvent(#PB_Event_Menu, @SetSomeText(), 1)
Quit=#False
Repeat
  Event=WaitWindowEvent()
  Select Event
    Case #PB_Event_CloseWindow
      Quit=#True
  EndSelect
Until Quit=#True
So it is possible to clear the text etc. Hope this helps

Regards
CD

Re: ClearGadgetItems() doesn't clear first row in EditorGadg

Posted: Sun Apr 03, 2016 11:14 am
by Lord
Sorry but this is no solution as it prevents clearing and setting
text on EditorGadget during a "time consuming" code part.
At least it is flickering.

Re: ClearGadgetItems() doesn't clear first row in EditorGadg

Posted: Sun Apr 03, 2016 1:20 pm
by Sirius-2337
Do you realy need to clear it first?
..since using SetGadgetText replaces the whole content.

Code: Select all

Procedure SetSomeText()
  Static x
;   ClearGadgetItems(2)
  x=1-x
  If x
    SetGadgetText(2, "1111111111111111111"+#CRLF$+"1111111111111111111")
    Delay(500)
  Else
    SetGadgetText(2, "2222222222222222222"+#CRLF$+"2222222222222222222")
    Delay(500)
  EndIf
EndProcedure

OpenWindow(1, 10, 10, 640, 480, "")
StringGadget(1, 55, 5, 580, 20, "")
EditorGadget(2, 5, 30, 630, 445, #PB_Editor_WordWrap)
AddKeyboardShortcut(1, #PB_Shortcut_Return, 10)
BindEvent(#PB_Event_Menu, @SetSomeText(), 1)

Quit=#False
Repeat
  Event=WaitWindowEvent()
  Select Event
    Case #PB_Event_CloseWindow
      Quit=#True
  EndSelect
Until Quit=#True

Re: ClearGadgetItems() doesn't clear first row in EditorGadg

Posted: Sun Apr 03, 2016 5:17 pm
by collectordave
Sorry but this is no solution as it prevents clearing and setting
text on EditorGadget during a "time consuming" code part.
Ok, you want to set and clear the gadget while running the time consuming code?

This then comes back to allowing the gadget time to update after setting or clearing.

I have changed your code a little. There is now a button on top of the gadget which when clicked will start the time consuming code. While that time consuming code is running you can press the return key and see the gadget clear, display all 1's and then display all 2's then clear again in a continuous cycle even after the timeconsuming code has finished.

Code: Select all


Global Text.s

Procedure SetSomeText()

  Static x
 

  x = x + 1
  If x > 2 
    x = 0
  EndIf
  
  Select x
    Case 0
      ClearGadgetItems(2)
      While WindowEvent() : Wend 
      Text = ""
      
    Case 1
      
      For i=1 To 25
        Text = Text +"11111111111111111111111111111111"+#CRLF$
      Next
      SetGadgetText(2, Text)
      While WindowEvent() : Wend
      Text = ""
    
    Case 2
      
      For i=1 To 25
        Text = Text +"22222222222222222222222222222222"+#CRLF$
      Next
      SetGadgetText(2, Text)   
      While WindowEvent() : Wend
      text = ""
    
 EndSelect

EndProcedure

Procedure TimeConsumingCode()
  For i=1 To 5000000
    While WindowEvent() : Wend
    y=Pow(2, i)
  Next
  Debug "Time Consuming Code Finished"
EndProcedure

OpenWindow(1, 10, 10, 640, 480, "")
ButtonGadget(1, 5, 5, 100, 20, "")
EditorGadget(2, 5, 30, 630, 445, #PB_Editor_WordWrap)
AddKeyboardShortcut(1, #PB_Shortcut_Return, 10)
BindEvent(#PB_Event_Menu, @SetSomeText(), 1)
Quit=#False

For i=1 To 25
  Text = Text +" 0000000000000000000000000000000000"+ #CRLF$
Next
SetGadgetText(2, Text)
Text = ""

TimeConsumingCode()

Repeat
  Event=WaitWindowEvent()
  Select Event
    Case #PB_Event_CloseWindow
      Quit=#True
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1
          Debug "Time Consuming Code Started"
          TimeConsumingCode()
      EndSelect 
  EndSelect
Until Quit=#True

Re: ClearGadgetItems() doesn't clear first row in EditorGadg

Posted: Mon Apr 04, 2016 12:58 pm
by Lord
Sorry, but While WindowEvent() isn't allowed in
an 'binded' Procedure. This throws an error.

Secondly I am not using a button to start a
text output. Text is generated depending on
some results in that "time consuming procedure"
and are to be displayed, sometimes the text
area has to be cleared.

but thanks for trying to help anyway.

Re: ClearGadgetItems() doesn't clear first row in EditorGadg

Posted: Mon Apr 04, 2016 2:15 pm
by collectordave
Sorry, but While WindowEvent() isn't allowed in
an 'binded' Procedure. This throws an error.
No error thrown on my machine. However there is no need for the windowevent bits in the setsometext procedure. the problem is the timeconsumingcode. If the procedure does not allow time for things to happen then they will not happen. must also be carefull with Delay(1000) as that halts programme execution, so nothing happens.
Secondly I am not using a button to start a
text output. Text is generated depending on
some results in that "time consuming procedure"
and are to be displayed, sometimes the text
area has to be cleared.
I have modyfied the code as per the above. You can still set the text by pressing the return key but text is also set by the time consuming code. I know there is a "While WindowEvent() : Wend" loop in the time consuming code, this is to allow the OS time to update everything. if you do not have that somewhere in your timeconsuming code then you need to find some other way of returning to the main event loop of your programme either by doing the time consuming code in a thread as shown above or by breaking down your timeconsuming code into smaller blocks. The button is only there so you can keep checking.

Remember while your code is running, and not picking up events from your queue with waitwindow event or windowevent then the OS will eventually tell the user that your application has crashed with the (Not Responding) message. Bindevent does not clear the event queue so cannot be used for that purpose as all the other events will still build up until your queue is full.

Code: Select all

Global Text.s

Procedure SetSomeText()

  Static x
Debug x

 
  Select x
    Case 0
      ClearGadgetItems(2)
      Text = ""
     
    Case 1
     
      For i=1 To 25
        Text = Text +"11111111111111111111111111111111"+#CRLF$
      Next
      SetGadgetText(2, Text)
      Text = ""
   
    Case 2
     
      For i=1 To 25
        Text = Text +"22222222222222222222222222222222"+#CRLF$
      Next
      SetGadgetText(2, Text)   
      text = ""
   
 EndSelect
  x = x + 1
  If x > 2
    x = 0
  EndIf
  
EndProcedure

Procedure TimeConsumingCode()
  
  For i=1 To 5000000
    
    Select i
        
      Case 1000000
        text = "Just testing after first 1000000"
        SetGadgetText(2, Text)

      Case 2000000
        SetSomeText()
      
      Case 3000000
        
        SetSomeText()
        
      Case 4000000
        
        SetSomeText()
        
    EndSelect      
    
    While WindowEvent() : Wend
    
    y=Pow(2, i)
    
  Next
  
  Debug "Time Consuming Code Finished"
  
EndProcedure

OpenWindow(1, 10, 10, 640, 480, "")
ButtonGadget(1, 5, 5, 100, 20, "")
EditorGadget(2, 5, 30, 630, 445, #PB_Editor_WordWrap)
AddKeyboardShortcut(1, #PB_Shortcut_Return, 10)
BindEvent(#PB_Event_Menu, @SetSomeText(), 1)
Quit=#False

Text = ""

TimeConsumingCode()

Repeat
  Event=WaitWindowEvent()
  Select Event
    Case #PB_Event_CloseWindow
      Quit=#True
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1
          Debug "Time Consuming Code Started"
          TimeConsumingCode()
      EndSelect
  EndSelect
Until Quit=#True
All you need to do is run the programme and the text will be set from the time consuming code.