Fill a ScrollAreaGadget without flickering?
Fill a ScrollAreaGadget without flickering?
If I clear and fill a ScrollAreaGadget with new gadgets, then it is very slow and flickering. You see the order in which the new gadgets pops up...
Can I change that behaviour? The problem is only on Windows. Mac OS no problems...
Can I change that behaviour? The problem is only on Windows. Mac OS no problems...
Re: Fill a ScrollAreaGadget without flickering?
That sounds very odd. Which version of PB / Windows?
Have you got some code you can post which reproduces this?
Have you got some code you can post which reproduces this?
I may look like a mule, but I'm not a complete ass.
Re: Fill a ScrollAreaGadget without delays and flickering?
Windows 10.
Please try it with Mac OS too! On Mac OS this is very, very fast without any delays and flickering....
Please try it with Mac OS too! On Mac OS this is very, very fast without any delays and flickering....
Code: Select all
#maxline = 12
#start_combo = 100
#start_string = 200
#max_item = 30
Procedure Rebuild()
For line = 0 To #maxline
If IsGadget(#start_combo + line): FreeGadget(#start_combo + line): EndIf
If IsGadget(#start_string + line): FreeGadget(#start_string + line): EndIf
Next
OpenGadgetList(0)
For line = 0 To #maxline
ComboBoxGadget(#start_combo + line, 10, 10 + line * 25, 230, 22)
For item = 0 To #max_item: AddGadgetItem(#start_combo + line, item, "Blablablup " + Str(item)): Next item
SetGadgetState(#start_combo + line, Random(#max_item))
StringGadget(#start_string + line, 250, 10 + line * 25, 80, 22, "")
Next line
CloseGadgetList()
EndProcedure
If OpenWindow(0, 0, 0, 405, 470, "ScrollAreaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ScrollAreaGadget(0, 10, 10, 390,420, 575, 555, 30)
CloseGadgetList()
ButtonGadget(1, 10, 430, 390,30, "Refresh")
Rebuild()
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
End
Case #PB_Event_Gadget
Select EventGadget()
Case 1: Rebuild()
EndSelect
EndSelect
ForEver
EndIf
Re: Fill a ScrollAreaGadget without flickering?
Japp, .... it's a known Problem with GUIs, created by PB on Windows.Lebostein wrote:The problem is only on Windows. Mac OS no problems...
You could suppress Windows redrawing using handpicked API commands or you can use [DeFlicker] if you are not confirm with API or try to deflicker your GUI in general and also to keep your source OS independent.
Deflicker by using handpicked API commands:
Code: Select all
EnableExplicit
Procedure Rebuild(Window)
Protected line, x
SendMessage_(WindowID(Window),#WM_SETREDRAW,#False,0) ; <======================
For line = 0 To 10
If IsGadget(100 + line): FreeGadget(100 + line): EndIf
If IsGadget(200 + line): FreeGadget(200 + line): EndIf
Next
OpenGadgetList(0)
For line = 0 To 10
ComboBoxGadget(100 + line, 10, 10 + line * 30, 230, 25)
For x = 0 To 30: AddGadgetItem(100 + line, x, "Blablablup " + Str(x)): Next x
StringGadget(200 + line, 250, 10 + line * 30, 80, 25, "")
SetGadgetState(100 + line, Random(29))
Next line
CloseGadgetList()
SendMessage_(WindowID(0),#WM_SETREDRAW,#True,0) ; <======================
RedrawWindow_(WindowID(0),#Null,#Null,#RDW_INVALIDATE) ; <======================
EndProcedure
If OpenWindow(0, 0, 0, 605, 470, "ScrollAreaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ScrollAreaGadget(0, 10, 10, 390,420, 575, 555, 30)
CloseGadgetList()
ButtonGadget(1, 10, 430, 390,30, "Refresh")
ListIconGadget(2,410,10,100,400, "test", 50)
Rebuild(0)
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
End
Case #PB_Event_Gadget
Select EventGadget()
Case 1: Rebuild(0)
EndSelect
EndSelect
ForEver
EndIf
Code: Select all
EnableExplicit
XIncludeFile "..\DeFlicker\Module_DeFlicker.pbi"
Procedure Rebuild(Window)
Protected line, x
DeFlicker_StartResize(Window) ; <======================
For line = 0 To 10
If IsGadget(100 + line): FreeGadget(100 + line): EndIf
If IsGadget(200 + line): FreeGadget(200 + line): EndIf
Next
OpenGadgetList(0)
For line = 0 To 10
ComboBoxGadget(100 + line, 10, 10 + line * 30, 230, 25)
For x = 0 To 30: AddGadgetItem(100 + line, x, "Blablablup " + Str(x)): Next x
StringGadget(200 + line, 250, 10 + line * 30, 80, 25, "")
SetGadgetState(100 + line, Random(29))
Next line
CloseGadgetList()
DeFlicker_EndResize() ; <======================
EndProcedure
If OpenWindow(0, 0, 0, 605, 470, "ScrollAreaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ScrollAreaGadget(0, 10, 10, 390,420, 575, 555, 30)
CloseGadgetList()
ButtonGadget(1, 10, 430, 390,30, "Refresh")
ListIconGadget(2,410,10,100,400, "test", 50)
Rebuild(0)
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
End
Case #PB_Event_Gadget
Select EventGadget()
Case 1: Rebuild(0)
EndSelect
EndSelect
ForEver
EndIf
Last edited by PureLust on Tue Feb 11, 2020 1:25 pm, edited 3 times in total.
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)
Re: Fill a ScrollAreaGadget without flickering?
I don't have a Mac, but, yes confirmed on Win 7. I can speed it up a little with some use of the #WM_SETREDRAW message and removing all the FreeGadget() calls because they are not needed (PB will free the existing gadgets each time you reuse the gadget#'s), but not a great deal of improvement.
Perhaps rather than keep recreating the gadgets in question, you can instead place them on a container and hide/show the container as required?
Perhaps rather than keep recreating the gadgets in question, you can instead place them on a container and hide/show the container as required?
I may look like a mule, but I'm not a complete ass.
Re: Fill a ScrollAreaGadget without flickering?
@ Lebostein
There is nothing wrong. You have Windows visual effects on. (Animated)
Open Explorer, right click 'Computer'
Select Properties and performance tab.
You have probably everything turned on or give Windows free reigns to
decide itself.
But then again..Not many users fiddles with this...
There is nothing wrong. You have Windows visual effects on. (Animated)
Open Explorer, right click 'Computer'
Select Properties and performance tab.
You have probably everything turned on or give Windows free reigns to
decide itself.
But then again..Not many users fiddles with this...
Current configurations:
Ubuntu 20.04/64 bit - Window 10 64 bit
Intel 6800K, GeForce Gtx 1060, 32 gb ram.
Amd Ryzen 9 5950X, GeForce 3070, 128 gb ram.
Ubuntu 20.04/64 bit - Window 10 64 bit
Intel 6800K, GeForce Gtx 1060, 32 gb ram.
Amd Ryzen 9 5950X, GeForce 3070, 128 gb ram.
Re: Fill a ScrollAreaGadget without flickering?
@PureLust: Thanks, that removes the flickering.
But the code remains slow. It seems the "AddGadgetItem" slows down the execution massively.
I have added a timer:
Mac OS: 25 ms (old MacBook from 2012)
Windows 10: 900 ms (i7-3930K 3.20 Ghz, 12 CPU)
But the code remains slow. It seems the "AddGadgetItem" slows down the execution massively.
I have added a timer:
Mac OS: 25 ms (old MacBook from 2012)
Windows 10: 900 ms (i7-3930K 3.20 Ghz, 12 CPU)
Code: Select all
#maxline = 12
#start_combo = 100
#start_string = 200
#max_item = 30
Procedure Rebuild()
start = ElapsedMilliseconds()
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
SendMessage_(WindowID(0),#WM_SETREDRAW,#False,0) ; <======================
CompilerEndIf
For line = 0 To #maxline
If IsGadget(#start_combo + line): FreeGadget(#start_combo + line): EndIf
If IsGadget(#start_string + line): FreeGadget(#start_string + line): EndIf
Next
OpenGadgetList(0)
For line = 0 To #maxline
ComboBoxGadget(#start_combo + line, 10, 10 + line * 25, 230, 22)
For item = 0 To #max_item: AddGadgetItem(#start_combo + line, item, "Blablablup " + Str(item)): Next item
SetGadgetState(#start_combo + line, Random(#max_item))
StringGadget(#start_string + line, 250, 10 + line * 25, 80, 22, "")
Next line
CloseGadgetList()
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
SendMessage_(WindowID(0),#WM_SETREDRAW,#True,0) ; <======================
RedrawWindow_(WindowID(0),#Null,#Null,#RDW_INVALIDATE) ; <======================
CompilerEndIf
SetGadgetText(1, "Press to refresh (" + Str(ElapsedMilliseconds() - start) + ")")
EndProcedure
If OpenWindow(0, 0, 0, 405, 470, "ScrollAreaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ScrollAreaGadget(0, 10, 10, 390,420, 575, 555, 30)
CloseGadgetList()
ButtonGadget(1, 10, 430, 390,30, "Refresh")
Rebuild()
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
End
Case #PB_Event_Gadget
Select EventGadget()
Case 1: Rebuild()
EndSelect
EndSelect
ForEver
EndIf
Last edited by Lebostein on Tue Feb 11, 2020 1:37 pm, edited 2 times in total.
Re: Fill a ScrollAreaGadget without flickering?
If you use disablegadget(#start_combo + line, #True) before adding itemsLebostein wrote:@PureLust: Thanks, that removes the flickering.
But the code remains slow. It seems the "AddGadgetItem" slows down the execution massively.
I have added a timer:
Mac OS: 25 ms (old MacBook from 2012)
Windows 10: 900 msCode: Select all
#maxline = 12 #start_combo = 100 #start_string = 200 #max_item = 30 Procedure Rebuild() start = ElapsedMilliseconds() SendMessage_(WindowID(0),#WM_SETREDRAW,#False,0) ; <====================== For line = 0 To #maxline If IsGadget(#start_combo + line): FreeGadget(#start_combo + line): EndIf If IsGadget(#start_string + line): FreeGadget(#start_string + line): EndIf Next OpenGadgetList(0) For line = 0 To #maxline ComboBoxGadget(#start_combo + line, 10, 10 + line * 25, 230, 22) For item = 0 To #max_item: AddGadgetItem(#start_combo + line, item, "Blablablup " + Str(item)): Next item SetGadgetState(#start_combo + line, Random(#max_item)) StringGadget(#start_string + line, 250, 10 + line * 25, 80, 22, "") Next line CloseGadgetList() SendMessage_(WindowID(0),#WM_SETREDRAW,#True,0) ; <====================== RedrawWindow_(WindowID(0),#Null,#Null,#RDW_INVALIDATE) ; <====================== SetGadgetText(1, Str(ElapsedMilliseconds() - start)) EndProcedure If OpenWindow(0, 0, 0, 405, 470, "ScrollAreaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) ScrollAreaGadget(0, 10, 10, 390,420, 575, 555, 30) CloseGadgetList() ButtonGadget(1, 10, 430, 390,30, "Refresh") Rebuild() Repeat Select WaitWindowEvent() Case #PB_Event_CloseWindow End Case #PB_Event_Gadget Select EventGadget() Case 1: Rebuild() EndSelect EndSelect ForEver EndIf
and disablegadget(#start_combo + line, #False) after..
Does that help?
Current configurations:
Ubuntu 20.04/64 bit - Window 10 64 bit
Intel 6800K, GeForce Gtx 1060, 32 gb ram.
Amd Ryzen 9 5950X, GeForce 3070, 128 gb ram.
Ubuntu 20.04/64 bit - Window 10 64 bit
Intel 6800K, GeForce Gtx 1060, 32 gb ram.
Amd Ryzen 9 5950X, GeForce 3070, 128 gb ram.
Re: Fill a ScrollAreaGadget without flickering?
No, has no effect.DK_PETER wrote: If you use disablegadget(#start_combo + line, #True) before adding items
and disablegadget(#start_combo + line, #False) after..
Does that help?
Re: Fill a ScrollAreaGadget without flickering?
As srod mentioned before, you could send specific #WM_SETREDRAW Message to suppress the redraw of the ComboBoxGadget.Lebostein wrote:@PureLust: Thanks, that removes the flickering.
But the code remains slow. It seems the "AddGadgetItem" slows down the execution massively.
I have added a timer:
Mac OS: 25 ms (old MacBook from 2012)
Windows 10: 900 ms (i7-3930K 3.20 Ghz, 12 CPU)
On my system it will speed it up by a factor of ~3 (~296ms before, ~98ms after).
Code: Select all
#maxline = 12
#start_combo = 100
#start_string = 200
#max_item = 30
Procedure Rebuild()
start = ElapsedMilliseconds()
SendMessage_(WindowID(0),#WM_SETREDRAW,#False,0) ; <======================
For line = 0 To #maxline
If IsGadget(#start_combo + line): FreeGadget(#start_combo + line): EndIf
If IsGadget(#start_string + line): FreeGadget(#start_string + line): EndIf
Next
OpenGadgetList(0)
For line = 0 To #maxline
ComboBoxGadget(#start_combo + line, 10, 10 + line * 25, 230, 22)
SendMessage_(GadgetID(#start_combo + line),#WM_SETREDRAW,#False,0) ; <##########################
For item = 0 To #max_item: AddGadgetItem(#start_combo + line, item, "Blablablup " + Str(item)): Next item
SendMessage_(GadgetID(#start_combo + line),#WM_SETREDRAW,#True,0) ; <##########################
SetGadgetState(#start_combo + line, Random(#max_item))
StringGadget(#start_string + line, 250, 10 + line * 25, 80, 22, "")
Next line
CloseGadgetList()
SendMessage_(WindowID(0),#WM_SETREDRAW,#True,0) ; <======================
RedrawWindow_(WindowID(0),#Null,#Null,#RDW_INVALIDATE) ; <======================
SetGadgetText(1, Str(ElapsedMilliseconds() - start))
EndProcedure
If OpenWindow(0, 0, 0, 405, 470, "ScrollAreaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ScrollAreaGadget(0, 10, 10, 390,420, 575, 555, 30)
CloseGadgetList()
ButtonGadget(1, 10, 430, 390,30, "Refresh")
Rebuild()
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
End
Case #PB_Event_Gadget
Select EventGadget()
Case 1: Rebuild()
EndSelect
EndSelect
ForEver
EndIf
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)
Re: Fill a ScrollAreaGadget without flickering?
@PureLust: Thanks, that speeds up the execution. I see 320 ms now instead of 900. But 300 ms compared to 25 ms is still slow...
I wonder why Mac OS can handle that redraw things automatically...
I wonder why Mac OS can handle that redraw things automatically...
Re: Fill a ScrollAreaGadget without flickering?
Speed seems to be a windows issue and not related to PB.Lebostein wrote:@PureLust: Thanks, that speeds up the execution. I see 320 ms now instead of 900. But 300 ms compared to 25 ms is still slow...
I wonder why Mac OS can handle that redraw things automatically...
If you add items directly trough API, it will not speed up:
Code: Select all
#maxline = 12
#start_combo = 100
#start_string = 200
#max_item = 30
Procedure Rebuild()
start = ElapsedMilliseconds()
SendMessage_(WindowID(0),#WM_SETREDRAW,#False,0) ; <======================
For line = 0 To #maxline
If IsGadget(#start_combo + line): FreeGadget(#start_combo + line): EndIf
If IsGadget(#start_string + line): FreeGadget(#start_string + line): EndIf
Next
OpenGadgetList(0)
For line = 0 To #maxline
ComboBoxGadget(#start_combo + line, 10, 10 + line * 25, 230, 22)
SendMessage_(GadgetID(#start_combo + line),#WM_SETREDRAW,#False,0) ; <##########################
For item = 0 To #max_item:
SendMessage_(GadgetID(#start_combo + line), #CB_ADDSTRING, 0, "Blablablup " + Str(item)) ; <*****************************
;AddGadgetItem(#start_combo + line, item, "Blablablup " + Str(item))
Next item
SendMessage_(GadgetID(#start_combo + line),#WM_SETREDRAW,#True,0) ; <##########################
SetGadgetState(#start_combo + line, Random(#max_item))
StringGadget(#start_string + line, 250, 10 + line * 25, 80, 22, "")
Next line
CloseGadgetList()
SendMessage_(WindowID(0),#WM_SETREDRAW,#True,0) ; <======================
RedrawWindow_(WindowID(0),#Null,#Null,#RDW_INVALIDATE) ; <======================
SetGadgetText(1, Str(ElapsedMilliseconds() - start))
EndProcedure
If OpenWindow(0, 0, 0, 405, 470, "ScrollAreaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ScrollAreaGadget(0, 10, 10, 390,420, 575, 555, 30)
CloseGadgetList()
ButtonGadget(1, 10, 430, 390,30, "Refresh")
Rebuild()
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
End
Case #PB_Event_Gadget
Select EventGadget()
Case 1: Rebuild()
EndSelect
EndSelect
ForEver
EndIf
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)
Re: Fill a ScrollAreaGadget without flickering?
Can I copy/duplicate a filled ComboGadget with window-API? So I can fill this thing one time an copy it as often as I need to...
I need it for a filter system like the intelligent playlist in iTunes (see picture). So every line is a condition build with 2 ComboGadgets and a string gadget with dozens of properties and operators. But every ComboGadget in each line has the same values....
I need it for a filter system like the intelligent playlist in iTunes (see picture). So every line is a condition build with 2 ComboGadgets and a string gadget with dozens of properties and operators. But every ComboGadget in each line has the same values....
Re: Fill a ScrollAreaGadget without flickering?
Closest thing to doing that would be an owner-drawn combo without the #CBS_HASSTRINGS styles. In this case you would simply draw the text yourself, taking the text from your own data structures. Quite a bit of work involved in this.
How about the following where we create the combo's just once and then simply repopulate everytime you hit the rebuild button. Together with some #WM_SETREDRAW's seems to speed up massively here. The original #WM_SETREDRAW was directed at the main window. It should instead be directed at the ScrollArea's 'inner panel' which I have corrected.
If this is not enough then your next step might be to intercept the #CBN_DROPDOWN notification and populate the combo box in question at this point only (if the combo is empty). That is, do not populate the controls all at once, only when needed.
If this is not enough then I refer you back to my original reply regarding using a container gadget!
How about the following where we create the combo's just once and then simply repopulate everytime you hit the rebuild button. Together with some #WM_SETREDRAW's seems to speed up massively here. The original #WM_SETREDRAW was directed at the main window. It should instead be directed at the ScrollArea's 'inner panel' which I have corrected.
Code: Select all
Procedure Rebuild()
hWnd = GetParent_(GadgetID(#start_combo))
SendMessage_(hWnd,#WM_SETREDRAW,#False,0) ; <======================
For line = 0 To #maxline
SendMessage_(GadgetID(#start_combo + line),#WM_SETREDRAW,#False,0) ; <##########################
For item = 0 To #max_item: AddGadgetItem(#start_combo + line, item, "Blablablup " + Str(item)): Next item
SendMessage_(GadgetID(#start_combo + line),#WM_SETREDRAW,#True,0) ; <##########################
SetGadgetState(#start_combo + line, Random(#max_item))
Next
SendMessage_(hWnd,#WM_SETREDRAW,#True,0) ; <======================
RedrawWindow_(hWnd,#Null,#Null,#RDW_INVALIDATE) ; <======================
EndProcedure
If OpenWindow(0, 0, 0, 405, 470, "ScrollAreaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ScrollAreaGadget(0, 10, 10, 390,420, 575, 555, 30)
For line = 0 To #maxline
ComboBoxGadget(#start_combo + line, 10, 10 + line * 25, 230, 22)
StringGadget(#start_string + line, 250, 10 + line * 25, 80, 22, "")
Next
CloseGadgetList()
ButtonGadget(1, 10, 430, 390,30, "Refresh")
Rebuild()
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
End
Case #PB_Event_Gadget
Select EventGadget()
Case 1: Rebuild()
EndSelect
EndSelect
ForEver
EndIf
If this is not enough then I refer you back to my original reply regarding using a container gadget!
I may look like a mule, but I'm not a complete ass.
Re: Fill a ScrollAreaGadget without flickering?
Wow .... that speeded it up A LOT . . . but . . . you missed to clear the GadgetItems first, so you add more and more items each time.srod wrote:How about the following where we create the combo's just once and then simply repopulate everytime you hit the rebuild button. Together with some #WM_SETREDRAW's seems to speed up massively here.
But ... if you clear the GadgetItem List first, this will eat up a lot of time again.
Code: Select all
ClearGadgetItems(#start_combo + line)
I wonder, why it's so much faster to add 30 items to an already filled ItemList than it takes to add them to an empty List.
Last edited by PureLust on Tue Feb 11, 2020 3:43 pm, edited 3 times in total.
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)