Page 1 of 1

SetGadgetText for 1 second, howto?

Posted: Thu Mar 28, 2019 7:16 pm
by droadje
Hi Purebasic,

Busy with a guitar fretboard learning ap, how can i set the text in a button for 1 seccond?

Code: Select all

Procedure Button1_0(EventType)  
  If GetGadgetText(Button1_0) = ""  
           SetGadgetText(Button1_0, "E") 
           Delay(1000)
           SetGadgetText(Button1_0, "") 
    Else  
      SetGadgetText(Button1_0, "") 
   EndIf
EndProcedure
Tried (see code) with Delay(1000) and then SetGadgetText(Button1_0, "") but then the eventloop gets sloppy.
What i want is, if i press the button, the letter E is displayed for 1 second in the button and then automaticaly empties it, or click again and the E is removed...
Is there a way to start a procedure outside the eventloop?
Thanks in advance....

Re: SetGadgetText for 1 second, howto?

Posted: Thu Mar 28, 2019 7:46 pm
by RASHAD
Delay() stops the execution completely
Use AddWindowTimer() and #PB_Event_Timer to calculate the ElapsedMilliseconds()

Re: SetGadgetText for 1 second, howto?

Posted: Thu Mar 28, 2019 8:10 pm
by TI-994A
droadje wrote:What i want is, if i press the button, the letter E is displayed for 1 second in the button and then automaticaly empties it, or click again and the E is removed...
This does the trick, but like RASHAD mentioned, a timer solution would be better:

Code: Select all

#buttonEvent = #PB_Event_FirstCustomValue

Procedure ButtonEvent() 
  caption$ = ""
  If EventData() > 0
    button = EventData()
  Else    
    button = EventGadget()
  EndIf  
  If GetGadgetText(button) = "" 
    Select button
      Case 1
        caption$ = "A"    
      Case 2
        caption$ = "B"    
      Case 3
        caption$ = "C"    
    EndSelect    
  EndIf
  SetGadgetText(button, caption$)  
  If caption$ <> ""
    Delay(1000)
    PostEvent(#buttonEvent, 0, 0, 0, button)
  EndIf 
EndProcedure

wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(0, #PB_Ignore, #PB_Ignore, 190, 200, "Delay Event", wFlags)
ButtonGadget(1, 10, 10, 50, 90, "")
ButtonGadget(2, 70, 10, 50, 90, "")
ButtonGadget(3, 130, 10, 50, 90, "")
BindGadgetEvent(1, @ButtonEvent())
BindGadgetEvent(2, @ButtonEvent())
BindGadgetEvent(3, @ButtonEvent())
BindEvent(#buttonEvent, @ButtonEvent())
While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend

Re: SetGadgetText for 1 second, howto?

Posted: Thu Mar 28, 2019 8:32 pm
by droadje
thanks for the quick respond.
I tried TI-994A solution, but get the same result i already had. Perhaps because i am on Linux, will try Windows later. (hangs for 1 second with black background, not text)
So i have to learn the method Rashad has given.
Perhaps i should start smaller, because i now have a guitar fretboard made with 6 rows of 12 pushbuttons and 7 checkboxes, thats a lot of procedures and events......lol

Re: SetGadgetText for 1 second, howto?

Posted: Thu Mar 28, 2019 8:35 pm
by Jagermeister

Code: Select all

;======================================
;WHO:   JAGERMEISTER
;WHAT:  SAMPLE CODE
;WHEN:  2019 03 28
;WHERE: https://www.purebasic.fr/english/viewtopic.php?f=13&t=72540
;COPYRIGHT: FOSS - FREE TO USE, MODIFY, DISTRIBUTE
;======================================

;-ENUMERATIONS

Enumeration
  #window_main
  #button
  #font_segoe_32_b
EndEnumeration

;-FONTS

LoadFont(#font_segoe_32_b , "segoe ui" , 32 , #PB_Font_Bold)


;-PROCEDURES

Procedure button_press(x)
  
  SetGadgetText(#button , "E")
  Delay(1000)
  SetGadgetText(#button, "")
  
EndProcedure


;-WINDOW

OpenWindow(#window_main , 0 , 0 , 200 , 100 , "Temporary Button Text Example" , #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

pad = 8 ; My favored UI padding value
ButtonGadget(#button , pad , pad , WindowWidth(window) - (pad * 2) , WindowHeight(window) - (pad * 2) , "")
SetGadgetFont(#button , FontID(#font_segoe_32_b))


;-LOOP

Repeat
  event = WaitWindowEvent()
  
  Select event
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #button
          If Not IsThread(thread)
            thread = CreateThread(@button_press() , 0)
          Else
            Debug "Thread already running"
          EndIf
      EndSelect
  EndSelect
  
Until event = #PB_Event_CloseWindow
End

Re: SetGadgetText for 1 second, howto?

Posted: Thu Mar 28, 2019 8:39 pm
by droadje
thanks, that did the trick.

Re: SetGadgetText for 1 second, howto?

Posted: Thu Mar 28, 2019 8:49 pm
by droadje
In my program it works now also, like this:

Code: Select all

; Snaar 1 ***********************************************
Procedure Button1_0(EventType)  
  If GetGadgetText(Button1_0) = ""  
    SetGadgetText(Button1_0, "E")    
    CreateThread(@empty(), Button1_0)
    Else  
      SetGadgetText(Button1_0, "")
    EndIf
EndProcedure

Procedure empty(String1)
  Delay(1000)
  SetGadgetText(String1, "")   
  EndProcedure 

Thanks very much!

Re: SetGadgetText for 1 second, howto?

Posted: Thu Mar 28, 2019 8:54 pm
by mk-soft
Threads and GUI not work under Linux and macOS...

But i have a Idee...

Code: Select all

;-TOP
; Comment : DoIt Later
; Author  : mk-soft
; Version : v0.02
; Create  : 27.03.2019
; OS      : All

Enumeration
  #SetGadgetText
  #SetGadgetState
  #SetGadgetColor
EndEnumeration

Structure udtDoItLater
  Command.i
  Gadget.i
  Text.s
  Param.i
  Param2.i
  Time.i
  Start.i
EndStructure

Global NewList DoItLater.udtDoItLater()
Global MutexDoItLater = CreateMutex()

Procedure SetGadgetTextDelay(Gadget, Text.s, Time)
  LockMutex(MutexDoItLater)
  LastElement(DoItLater())
  AddElement(DoItLater())
  With DoItLater()
    \Command = #SetGadgetText
    \Gadget = Gadget
    \Text = Text
    \Time = Time
    \Start = ElapsedMilliseconds()
  EndWith
  UnlockMutex(MutexDoItLater)
EndProcedure

Procedure SetGadgetStateDelay(Gadget, State, Time)
  LockMutex(MutexDoItLater)
  LastElement(DoItLater())
  AddElement(DoItLater())
  With DoItLater()
    \Command = #SetGadgetState
    \Gadget = Gadget
    \Param = State
    \Time = Time
    \Start = ElapsedMilliseconds()
  EndWith
  UnlockMutex(MutexDoItLater)
EndProcedure

Procedure SetGadgetColorDelay(Gadget, ColorType, Color, Time)
  LockMutex(MutexDoItLater)
  LastElement(DoItLater())
  AddElement(DoItLater())
  With DoItLater()
    \Command = #SetGadgetColor
    \Gadget = Gadget
    \Param = ColorType
    \Param2 = Color
    \Time = Time
    \Start = ElapsedMilliseconds()
  EndWith
  UnlockMutex(MutexDoItLater)
EndProcedure

Procedure DoEventDoItLater()
  Protected Time = ElapsedMilliseconds()
  With DoItLater()
    LockMutex(MutexDoItLater)
    ForEach DoItLater()
      If (Time - \Start) >= \Time
        If IsGadget(\Gadget)
          Select \Command
            Case #SetGadgetText
              SetGadgetText(\Gadget, \Text)
            Case #SetGadgetState
              SetGadgetState(\Gadget, \Param)
            Case #SetGadgetColor
              SetGadgetColor(\Gadget, \Param, \Param2)
          EndSelect
        EndIf
        DeleteElement(DoItLater(), 1)
      EndIf
    Next
    UnlockMutex(MutexDoItLater)
  EndWith
EndProcedure

;- Example

Procedure Main()
  Protected event, index, x, y
  
  If OpenWindow(0 , #PB_Ignore, #PB_Ignore, 620, 80, "Do It Later", #PB_Window_SystemMenu)
    x = 10
    y = 10
    For index = 0 To 9
      ButtonGadget(index, x, y, 55, 25, "---")
      x + 60
    Next
    StringGadget(10, 10, 45, 120, 25, "")
    
    BindEvent(#PB_Event_Timer, @DoEventDoItLater(), 0, 999)
    AddWindowTimer(0, 999, 50)
    
    Repeat
      event = WaitWindowEvent()
      Select event
        Case #PB_Event_CloseWindow
          Break
        Case #PB_Event_Gadget
          index = EventGadget()
          Select index
            Case 0 To 9
              SetGadgetText(index, "-" + index + "-")
              SetGadgetTextDelay(index, "---", 800)
            Case 10
              If EventType() = #PB_EventType_Focus
                SetGadgetColor(10, #PB_Gadget_BackColor, #Red)
                SetGadgetColorDelay(10, #PB_Gadget_BackColor, #PB_Default, 150)
              EndIf
          EndSelect
      EndSelect
    ForEver
  EndIf
EndProcedure : Main()

Re: SetGadgetText for 1 second, howto?

Posted: Thu Mar 28, 2019 8:56 pm
by TI-994A
This one uses the timer, and works on Linux as well:

Code: Select all

Procedure ButtonTimerEvent() 
  For button = 1 To 3
    buttonDown = GetGadgetData(button)
    If buttonDown > 0
      If (ElapsedMilliseconds() - buttonDown) > 1000
        SetGadgetData(button, 0)
        SetGadgetText(button, "")
      EndIf
    EndIf
  Next button  
EndProcedure

Procedure ButtonEvent() 
  caption$ = ""
  button = EventGadget()
  If GetGadgetText(button) = "" 
    Select button
      Case 1
        caption$ = "A"    
      Case 2
        caption$ = "B"    
      Case 3
        caption$ = "C"    
    EndSelect    
  EndIf
  SetGadgetText(button, caption$)  
  SetGadgetData(button, ElapsedMilliseconds())
EndProcedure

wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(0, #PB_Ignore, #PB_Ignore, 190, 200, "Delay Event", wFlags)
AddWindowTimer(0, 0, 100)
ButtonGadget(1, 10, 10, 50, 90, "")
ButtonGadget(2, 70, 10, 50, 90, "")
ButtonGadget(3, 130, 10, 50, 90, "")
BindGadgetEvent(1, @ButtonEvent())
BindGadgetEvent(2, @ButtonEvent())
BindGadgetEvent(3, @ButtonEvent())
BindEvent(#PB_Event_Timer, @ButtonTimerEvent())
While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend

Re: SetGadgetText for 1 second, howto?

Posted: Thu Mar 28, 2019 9:05 pm
by #NULL

Code: Select all

win = OpenWindow(#PB_Any, 50,100, 100, 50, "title")
AddKeyboardShortcut(win, #PB_Shortcut_Escape, 10)
button = ButtonGadget(#PB_Any, 10, 10, 80, 30, "button")

Repeat
  WaitWindowEvent()
  If Event() = #PB_Event_Gadget
    If EventGadget() = button
      SetGadgetText(button, "clicked")
      AddWindowTimer(win, 123, 1000)
    EndIf
  ElseIf Event() = #PB_Event_Timer
    If EventTimer() = 123
      SetGadgetText(button, "button")
      RemoveWindowTimer(win, 123)
    EndIf
  EndIf
Until Event() = #PB_Event_CloseWindow Or Event() = #PB_Event_Menu
<edit>
I forgot RemoveWindowTimer()

Re: SetGadgetText for 1 second, howto?

Posted: Thu Mar 28, 2019 9:12 pm
by droadje
Ha, boys, thanks, all your code works and looks like it does the same thing.

And threads and gui DO seem to work on my Manajaro Linux

Plenty to learn now from the code you have given, thanks.

Re: SetGadgetText for 1 second, howto?

Posted: Thu Mar 28, 2019 9:22 pm
by mk-soft
droadje wrote: And threads and gui DO seem to work on my Manajaro Linux
Is not running stable... Show my Link to ThreadToGUI