4
$\begingroup$

I am trying to create a dynamic construct that takes a large list of expressions and allows the user to interactively select any number of entries for further manipulation. This is what I have envisioned so far:

Construct[largeListOfEntries_] := DynamicModule[{loadButton, viewPane, testlabels, 
 valuesPicked, dsFunction, buttonPressed = False},
loadButton = Button["Load Initial List", buttonPressed = True; 
testlabels = largeListOfEntries[[;; , 2]]];
viewPane = Panel[
 Pane[
  Dynamic@If[buttonPressed != False,
             CheckboxBar[Dynamic[valuesPicked], 
                         MapThread[#1 -> #2 &, {Range[Length@testlabels], testlabels}],
                         Appearance -> "Vertical"],
            "Load List..."],
  ImageSize -> {500, 340}, ImageSizeAction -> "Scrollable", Scrollbars -> {True, True}],
 Style["Sample Pane", 12, Bold, Purple]];
dsFunction = Button["Modify Selected Element", 
                    Print[largeListOfEntries[[valuesPicked, 1]]]];

Column[{loadButton, viewPane, dsFunction}]]

Given a large list such as this:

largeListOfEntries = {#, "label"} & /@ RandomReal[1, 3000]
Construct[largeListOfEntries]

enter image description here

I would then be able to select any number of elements that I want and apply the downstream function to them (for example purposes here the function just prints the value of the selected element).

Everything appears to be working but for large lists simply the act of clicking the Checkbox takes a really long time.

I suspect this is due to the fact that DynamicModule stores all the values at the FrontEnd and with large lists it can get really slow. If i simply use Module or keep the everything global then the process is significantly faster but I need to localize my variables and from what I've read using Module with Dynamic objects is not recommended and my Dynamic variables become red indicating conflict.

Is there something that I'm fundamentally doing wrong that is having such a drastic impact on performance?


EDIT (03.18.14)

As Kuba pointed out it is possible to see the hit in performance simply by using:

largeListOfEntries = RandomReal[1, 3000]; 
CheckboxBar[Dynamic@valuesPicked,largeListOfEntries]

Indicating that the issue may be directly associated with Dynamic variables in CheckboxBar. However if that construct is then wrapped with a DynamicModule, the performance hit is even worse than before, so the Module itself is also contributing.

$\endgroup$
0

2 Answers 2

4
$\begingroup$

After some significant time browsing related questions on this site as well as trial and error, I believe that I have managed to create a solution for what I was trying to accomplish.

Taking the advice from Ariel I have essentially created my own custom array of checkboxes that do not experience any major delay when one of them is clicked.

I have utilized EventHandler to create a dynamic grid of entries that will place a clicked entry into a selection list and change color to reflect that this particular entry has been selected. The code is below:

Construct[largeListOfEntries_] := 
 DynamicModule[{loadButton, viewPane, testlabels, valuesPicked = {}, 
   colors, dsFunction, buttonPressed = False}, 
  loadButton = Button["Load Initial List", buttonPressed = True; 
                       testlabels = largeListOfEntries[[;; , 2]]];
  colors = ConstantArray[Lighter[Blue, 0.95], {Length@largeListOfEntries}];
  viewPane = 
   Panel[Pane[
     Dynamic@If[buttonPressed != False, 
       Grid[MapIndexed[
         EventHandler[
           Style[#1, 12, Selectable ->False], {"MouseClicked" :> (valuesPicked = 
               If[MemberQ[valuesPicked, First@#2], 
                DeleteCases[valuesPicked, First@#2], 
                Append[valuesPicked, First@#2]]; 
              colors[[First@#2]] = 
              colors[[First@#2]] /. {Lighter[Blue, 0.95] -> Lighter[Green, 0.6], 
               Lighter[Green, 0.6] -> Lighter[Blue, 0.95]})}] &, 
            Partition[testlabels, 1], {2}],
        Alignment -> {Center, Center}, Spacings -> {.6, .6}, Frame -> All, 
        Background -> Dynamic@{None, 
         MapThread[#1 -> #2 &, {Range[1, Length@testlabels], colors}]}], "Load List..."], 
        ImageSize -> {500, 340}, 
     ImageSizeAction -> "Scrollable", Scrollbars -> {True, True}], 
    Style["Sample Pane", 12, Bold, Purple]];
  dsFunction = 
   Button["Modify Selected Element", 
    Print[largeListOfEntries[[valuesPicked, 1]]]];

  Column[{loadButton, viewPane, dsFunction}]]

Given the same input, this is what the result now looks like (with the 3rd and 6th element selected):

largeListOfEntries = {#, "label"} & /@ RandomReal[1, 3000]
Construct[largeListOfEntries]

image

I am sure tinkering with the formatting of the grid, one can easily tailor it to look more like an actual CheckboxBar but the current formatting has been working well for me. I have not noticed a slowdown in performance even for lists with over 10000 entries.

$\endgroup$
1
  • 1
    $\begingroup$ You can use Framed@Style[#1... instead of Frame->All, now you don't have to click directly on the text. You may also be interesetd in Deploy and MouseAppearance[#, "LinkHand"]& but that is just about styling details. +1 $\endgroup$
    – Kuba
    Mar 26, 2014 at 18:45
2
$\begingroup$

Your question is whether you are doing something fundamentally wrong. My answer is that you are not doing anything wrong but that the behavior you are experiencing is normal for CheckboxBar.

I think that there are several potential causes for the slow behavior of CheckboxBar when it is fed with too many items but the final effect is that it is not a scalable tool. I agree that the problem is even worse when the CheckboxBar is inside a DynamicModule. I have experienced this problem and my solution to this problem was to create my own CheckboxBar which can hold thousands of elements and still work nicely and efficiently even when it is wrapped with DynamicModule. Additionally, my solution also provides the option of a tabular Appearance of the checkboxes to improve visibility.

$\endgroup$
3
  • $\begingroup$ So you won't share? :) $\endgroup$
    – Kuba
    Mar 21, 2014 at 17:50
  • $\begingroup$ The problem is that the solution is an application of SpreadsheetViewMXL which is too much code to share. I can make it available to anyone that has bought BEST Viewpoints or via some kind of consulting agreement with anyone who would need to use it for a comercial application. $\endgroup$ Mar 21, 2014 at 18:34
  • $\begingroup$ Thanks for the answer! I suppose it's good that I'm not doing anything wrong; it is very unfortunate though that such a seemingly simple thing can lead to such complications. From your comment it seems that there is no easy workaround to this aside from writing a lot of custom code. I'll have to keep trying and see what I can come up with while I see if anyone has managed to come up with a simple solution. $\endgroup$
    – Msafrano
    Mar 21, 2014 at 21:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.