Fast gadget redraw, how?

Just starting out? Need help? Post your questions and find answers here.
karu
Enthusiast
Enthusiast
Posts: 255
Joined: Fri Jan 13, 2006 12:14 am

Fast gadget redraw, how?

Post 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
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: Fast gadget redraw, how?

Post 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
User avatar
Didelphodon
PureBasic Expert
PureBasic Expert
Posts: 450
Joined: Sat Dec 18, 2004 11:56 am
Location: Vienna - Austria
Contact:

Re: Fast gadget redraw, how?

Post 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.
Go, tell it on the mountains.
karu
Enthusiast
Enthusiast
Posts: 255
Joined: Fri Jan 13, 2006 12:14 am

Re: Fast gadget redraw, how?

Post by karu »

Thanks, but isn't there some way to redraw only one gadget or some small region of the window?
infratec
Always Here
Always Here
Posts: 7577
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Fast gadget redraw, how?

Post 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
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Fast gadget redraw, how?

Post 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
BERESHEIT
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Fast gadget redraw, how?

Post by IdeasVacuum »

Multiple OS? If Windows only, try InvalidateRect_(GadgetID(#MyGadget),#Null,#True)
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
BasicallyPure
Enthusiast
Enthusiast
Posts: 539
Joined: Thu Mar 24, 2011 12:40 am
Location: Iowa, USA

Re: Fast gadget redraw, how?

Post 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
BasicallyPure
Until you know everything you know nothing, all you have is what you believe.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Fast gadget redraw, how?

Post 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

Egypt my love
karu
Enthusiast
Enthusiast
Posts: 255
Joined: Fri Jan 13, 2006 12:14 am

Re: Fast gadget redraw, how?

Post by karu »

Thanks for everyone
Post Reply