Page 1 of 1

Fast gadget redraw, how?

Posted: Mon Feb 04, 2013 1:05 pm
by karu
Hi, i have on big list that is loading about 30 sec minimum. In that loading time i have to show in stringgadget, how much lines are loaded. Problem is, that if i redraw whole window after every loaded lines, the loading process is 10 times slower. How i can redraw only one gadget?

Code: Select all

 If OpenWindow(0, 100, 100, 300, 430, "ListIcon Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   ListIconGadget(0, 5, 5, 290, 390, "Name", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection)
   StringGadget(1, 5, 405, 85, 20, "")
   AddGadgetColumn(0, 1, "Address", 250)
   
   For i = 1 To 35000
     AddGadgetItem(0, -1, Str(i)+Chr(10)+"PureBasic Road, BigTown, CodeCity")
     SetGadgetText(1,Str(i))
     While WindowEvent() : Wend ; this is to slow
   Next
   
   Repeat
     Event = WaitWindowEvent()
   Until Event = #PB_Event_CloseWindow
 EndIf

Re: Fast gadget redraw, how?

Posted: Mon Feb 04, 2013 1:15 pm
by Danilo

Code: Select all

 If OpenWindow(0, 100, 100, 300, 430, "ListIcon Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   ListIconGadget(0, 5, 5, 290, 390, "Name", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection)
   StringGadget(1, 5, 405, 85, 20, "")
   AddGadgetColumn(0, 1, "Address", 250)
   
   SendMessage_(GadgetID(0),#WM_SETREDRAW,#False,0)

       For i = 1 To 35000
         AddGadgetItem(0, -1, Str(i)+Chr(10)+"PureBasic Road, BigTown, CodeCity")
         SetGadgetText(1,Str(i))
         While WindowEvent() : Wend ; this is to slow
       Next

   SendMessage_(GadgetID(0),#WM_SETREDRAW,#True,0)
   RedrawWindow_( GadgetID(0), #Null, #Null, #RDW_ERASE | #RDW_FRAME | #RDW_INVALIDATE | #RDW_ALLCHILDREN)
   
   Repeat
     Event = WaitWindowEvent()
   Until Event = #PB_Event_CloseWindow
 EndIf
:?:

With ProgressbarGadget():

Code: Select all

 If OpenWindow(0, 100, 100, 300, 430, "ListIcon Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   ListIconGadget(0, 5, 5, 290, 390, "Name", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection)
   ProgressBarGadget(1, 5, 405, 85, 20, 0,35000)
   AddGadgetColumn(0, 1, "Address", 250)
   
   SendMessage_(GadgetID(0),#WM_SETREDRAW,#False,0)

       For i = 1 To 35000
         AddGadgetItem(0, -1, Str(i)+Chr(10)+"PureBasic Road, BigTown, CodeCity")
         SetGadgetState(1,i+1)
         SetGadgetState(1,i)
         While WindowEvent() : Wend ; this is to slow
       Next

   SendMessage_(GadgetID(0),#WM_SETREDRAW,#True,0)
   RedrawWindow_( GadgetID(0), #Null, #Null, #RDW_ERASE | #RDW_FRAME | #RDW_INVALIDATE | #RDW_ALLCHILDREN)
   
   Repeat
     Event = WaitWindowEvent()
   Until Event = #PB_Event_CloseWindow
 EndIf

Re: Fast gadget redraw, how?

Posted: Mon Feb 04, 2013 1:32 pm
by Didelphodon
Hide the ListIconGadget during loading via HideGadget and unhide it when loading is done. Should be much faster this way. And through the WindowEvent out of the for-loop cuz thats a massive slowdown imho.

Re: Fast gadget redraw, how?

Posted: Mon Feb 04, 2013 3:15 pm
by karu
Thanks, but isn't there some way to redraw only one gadget or some small region of the window?

Re: Fast gadget redraw, how?

Posted: Mon Feb 04, 2013 4:58 pm
by infratec
Hi,

maybe not the right answer, but this way you can work already while it is loading:

Code: Select all

Procedure Thread(*Dummy)
  Protected i.i
  For i = 1 To 35000
    AddGadgetItem(0, -1, Str(i)+Chr(10)+"PureBasic Road, BigTown, CodeCity")
    SetGadgetText(1,Str(i))
  Next
EndProcedure


 If OpenWindow(0, 100, 100, 300, 430, "ListIcon Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   ListIconGadget(0, 5, 5, 290, 390, "Name", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection)
   StringGadget(1, 5, 405, 85, 20, "")
   AddGadgetColumn(0, 1, "Address", 250)
   
   CreateThread(@Thread(), #Null)
   
   Repeat
     Event = WaitWindowEvent()
   Until Event = #PB_Event_CloseWindow
 EndIf
Bernd

Re: Fast gadget redraw, how?

Posted: Tue Feb 05, 2013 12:20 am
by netmaestro
The thread in and of itself won't speed it up, but it's a good idea as it allows for the user giving up if he wants to. Here's my shot at speeding it up:

Code: Select all

Procedure Thread(void)
  Protected i.i
  t = ElapsedMilliseconds()
  a = 1
  HideGadget(0,1)
  HideGadget(2,0)
  For i = 1 To 35000
    AddGadgetItem(0, -1, Str(i)+Chr(10)+"PureBasic Road, BigTown, CodeCity")
    If ElapsedMilliseconds()-t > 400
      t=ElapsedMilliseconds()
      a=1-a:SetGadgetState(2, ImageID(a))
    EndIf
    If i%1000=0
      SetGadgetText(1,Str(i))
    EndIf
  Next
  SetGadgetText(1,Str(i-1))
  HideGadget(2,1)
  HideGadget(0,0)
EndProcedure

If OpenWindow(0, 100, 100, 300, 430, "ListIcon Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ListIconGadget(0, 5, 5, 290, 390, "Name", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection)
  AddGadgetColumn(0, 1, "Address", 187)
  StringGadget(1, 5, 405, 85, 20, "")
  ImageGadget(2, 5, 5, 290, 390,0)
  CreateImage(1, 290,390,24)
  hdc = StartDrawing(ImageOutput(1))
    header = SendMessage_(GadgetID(0), #LVM_GETHEADER,0,0)
    SendMessage_(GadgetID(0), #WM_PRINTCLIENT, hdc, 0)
    SendMessage_(header, #WM_PRINTCLIENT, hdc, 0)
    DrawingFont(GetStockObject_(#DEFAULT_GUI_FONT))
    txt$ = "Please wait while records load..."
    w = TextWidth(txt$)
    h = TextHeight(txt$)
    x = GadgetWidth(0)/2-w/2
    y = GadgetHeight(0)/2-h/2
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawText(x,y, txt$, #Black)
    GrabDrawingImage(0,0,0,ImageWidth(1),ImageHeight(1))
  StopDrawing()
  hdc = StartDrawing(ImageOutput(0))
    DrawingFont(GetStockObject_(#DEFAULT_GUI_FONT))
    DrawText(x+TextWidth("Please wait while records load"),y, "   ", #Black,#White)
  StopDrawing()
  
  SetGadgetState(2, ImageID(0))
  
  tid = CreateThread(@Thread(), #Null)
  
  Repeat
    Event = WaitWindowEvent()
    If Event = #PB_Event_CloseWindow And IsThread(tid)
      KillThread(tid)
      WaitThread(tid)
    EndIf
  Until Event = #PB_Event_CloseWindow
EndIf

Re: Fast gadget redraw, how?

Posted: Tue Feb 05, 2013 1:37 am
by IdeasVacuum
Multiple OS? If Windows only, try InvalidateRect_(GadgetID(#MyGadget),#Null,#True)

Re: Fast gadget redraw, how?

Posted: Tue Feb 05, 2013 7:08 am
by BasicallyPure
You could speed it up quite a bit if you didn't update the string gadget after every line.
With this code you can still see the progress and also have the option to abort the program.

Code: Select all

If OpenWindow(0, 100, 100, 300, 430, "ListIcon Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   ListIconGadget(0, 5, 5, 290, 390, "Name", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection)
   StringGadget(1, 5, 405, 85, 20, "")
   AddGadgetColumn(0, 1, "Address", 250)
   
   update = 0
   
   For i = 1 To 35000
      AddGadgetItem(0, -1, Str(i)+Chr(10)+"PureBasic Road, BigTown, CodeCity")
      If update = 0
         update = 499
         SetGadgetText(1,Str(i))
         Repeat
            Event = WindowEvent()
            If Event = #PB_Event_CloseWindow : End : EndIf
         Until Event = 0
      Else
         update - 1
      EndIf
   Next
   
   SetGadgetText(1,Str(i-1))
   
   Repeat
      Event = WaitWindowEvent()
   Until Event = #PB_Event_CloseWindow
EndIf

Re: Fast gadget redraw, how?

Posted: Tue Feb 05, 2013 8:52 am
by RASHAD
1 - Using Timer

Code: Select all

 
 If OpenWindow(0, 0, 0, 300, 430, "ListIcon Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   ListIconGadget(0, 5, 5, 290, 390, "Name", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection)
   StringGadget(1, 5, 405, 85, 20, "")
   AddGadgetColumn(0, 1, "Address", 250)
   AddWindowTimer(0,125,1)
   
   Repeat
     Event = WindowEvent()
      If Event = #PB_Event_Timer And K < 35000
        k + 1
        AddGadgetItem(0, -1, Str(k)+Chr(10)+"PureBasic Road, BigTown, CodeCity")
        SetGadgetText(1,Str(k))
      EndIf    
   Until Event = #PB_Event_CloseWindow
 EndIf
OR

Code: Select all

 If OpenWindow(0, 0, 0, 300, 430, "ListIcon Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   ListIconGadget(0, 5, 5, 290, 390, "Name", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection)
   StringGadget(1, 5, 405, 85, 20, "")
   AddGadgetColumn(0, 1, "Address", 250)
   AddWindowTimer(0,125,1)
   
   Repeat
     Event = WindowEvent()
      If Event = #PB_Event_Timer And K < 35000
        For x = k To k+100
          AddGadgetItem(0, -1, Str(x)+Chr(10)+"PureBasic Road, BigTown, CodeCity")
          SetGadgetText(1,Str(x))
        Next
        k + 100
      EndIf   
   Until Event = #PB_Event_CloseWindow
 EndIf
2- Using Thread without stop redrawing (You can do something else while filling the data)

Code: Select all

 
Procedure FillLI(Parameter)
While k < 35000
  k + 1
  AddGadgetItem(0, -1, Str(k)+Chr(10)+"PureBasic Road, BigTown, CodeCity")
  SetGadgetText(1,Str(k))
Wend
    
EndProcedure
 
 If OpenWindow(0, 100, 100, 300, 430, "ListIcon Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   ListIconGadget(0, 5, 5, 290, 390, "Name", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection)
   StringGadget(1, 5, 405, 85, 20, "")
   AddGadgetColumn(0, 1, "Address", 250)
   Thread =  CreateThread(@FillLI(), 1)
   
   
   Repeat
     Event = WaitWindowEvent()
  
   Until Event = #PB_Event_CloseWindow
 EndIf

3- Using Virtual ListIcon

Code: Select all

#ItemCount = 35000

#LVSICF_NOINVALIDATEALL = 1 
#LVN_ODCACHEHINT = #LVN_FIRST - 13 

Global Dim myItems.s(#ItemCount,1)

Procedure WinCallback(hwnd, msg, wParam, lParam) 
  result = #PB_ProcessPureBasicEvents 
  Select msg 
    Case #WM_NOTIFY 
      *pnmh.NMHDR = lParam 
      Select *pnmh\code 
        Case #LVN_ODCACHEHINT 
          result = 0 
        Case #LVN_GETDISPINFO                ;
          *pnmlvdi.NMLVDISPINFO = lParam 
          If *pnmlvdi\item\mask & #LVIF_TEXT
            *pnmlvdi\item\pszText = @myItems(*pnmlvdi\item\iItem,*pnmlvdi\item\iSubItem)
            SetGadgetText(1,Str(#ItemCount))
          EndIf 
               ;
      EndSelect 
  EndSelect 
  ProcedureReturn result 
EndProcedure 
;
If OpenWindow(0, 0, 0, 300, 430, "Virtual ListIconGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  SetWindowCallback(@WinCallback()) 
  Licon = ListIconGadget(0,5,5,290,390,"Name",50,#LVS_OWNERDATA)
  StringGadget(1,5,405,85,20,"")
  SendMessage_(Licon, #LVM_SETITEMCOUNT, #ItemCount, #LVSICF_NOINVALIDATEALL) 
  AddGadgetColumn(0,2,"Address",300) 
  For i=0 To #ItemCount 
    myItems(i,0) = Str(i) 
    myItems(i,1) = "PureBasic Road, BigTown, CodeCity"
  Next i 
  
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow 
EndIf


Re: Fast gadget redraw, how?

Posted: Wed Feb 06, 2013 11:51 pm
by karu
Thanks for everyone