1
$\begingroup$

Considering using TableView to present data and allowing the user make small adjustments to the values. Would like some help with Dynamic and TableView. Below is a basic example. In the more complete system, TableForm would be changed to ListPlot, additional operations would be done on the data, and this would all be wrapped up in Manipulate or DynamicModule. But, this example gets at the core idea.

xVals = Sort@Round[RandomReal[{0, 1}, 10], 0.01];
yVals = Sort@Round[RandomReal[{0, 1}, 10], 0.01];
xyData = Transpose[{xVals, yVals}];

Row[{TableForm[Dynamic[xyData]], TableView[Dynamic[xyData] ] }] 

This displays a list of values. On the left is the output of the TableForm command and on the right is the output of the TableView command. And, good news, modifying a value in the TableView causes the corresponding value displayed by TableForm to update. enter image description here

Couple of issues that I don't know how to correct.

  1. the TableForm doesn't show the values in a table format. Instead it shows a List of Lists.
  2. after modifying a value via TableView, the values displayed by TableForm all change to strings. That is each value is surrounded by double quotes. after modifying a value on TableView

A similar discussion was started in this thread, where the concern was when a value was changed to a blank. The concerns here are slightly different, but maybe the underlying cause is the same.

Can these issues be addressed with some changes to the code?

Update #1: Putting Dynamic in the right places (maybe)

After following the suggestions in the comment, the revised code allows the user to edit the content of the TableView and the ListPlot will dynamically update. Also, provided an option for the reverse: the content of a table updates from the position of Locators on the ListPlot. Code is below.

One issue, regarding the number of rows in the TableView after a reset operation. Sometimes it works OK, sometimes not. If the number of rows chosen for the reset operation is less than the current number of rows, TableView shows some blank rows at the bottom. Would like to fix this, as it could cause errors. Suggestions?

Input Choice #1: with TableView dynamically controlling the ListPlot. TableView Dynamically controlling the ListPlot

Input Choice #2: with Locators on the ListPlot dynamically controlling the table content.
Locators on the ListPlot dynamically controlling the table content

Code

makeXYplots[xy_] := Module[{}, ListLinePlot[xy
   , PlotRange -> {{-0.05, 1.01}, {-0.05, 1.05}}
   , Frame -> True
   , GridLines -> Automatic
   , ImageSize -> 600
   , Epilog -> {Red, AbsolutePointSize[4], Point[xy] }] ]
makeXYtable[xy_] := Module[{}, TableForm[xy]] 
initPts[n_Integer] := Module[{xVals, yVals },
  xVals = Sort@Round[RandomReal[{0, 1}, n], 0.01];
  yVals = Sort@Round[RandomReal[{0, 1}, n], 0.01];
   Transpose[{xVals, yVals}]
  ]

testManip = DynamicModule[{xyData, iCount, status, lcpBackground},
   Manipulate[
    iCount = iUpdate ;
    (*myValues = Dynamic[xyData];*)
    lcpBackground = Dynamic[makeXYplots[xyData]] ;
    If[inputType == 0,
     Row[{LocatorPane[ Dynamic[xyData], lcpBackground, 
        LocatorAutoCreate -> True, ContinuousAction -> False]
       , Spacer[10]
       , Dynamic[Framed[ makeXYtable[xyData]]]
        }] ,
     Row[{Dynamic[makeXYplots[xyData]]
       , Spacer[10]
       , TableView[Dynamic[xyData] , Number, 
        AllowedDimensions -> {2, Dynamic[Length@xyData]} ]
        }] 
     ]
    , Delimiter(*=======================*)
    , Style["Calculation Control", Black, Italic,  12]
    , {{inputType, 0, "Input Type"}, {0 -> "Locator Points", 
      1 -> "Table"}, ControlType -> RadioButtonBar}
    , Button["Update"
     , status = Style["updating ...", Darker@Blue, 14, Bold]; 
     FinishDynamic[]; iUpdate = iUpdate + 1;
     , Method -> "Queued"
     ]
    , Delimiter (*=======================*)
    , Style["Reset", Black, Italic,  12]
    , Button["Reset"
     , status = Style["updating ...", Darker@Blue, 14, Bold];
     xyData = initPts[npts];
     iCount = 0;
     iUpdate = 0;
     status = Style["Ready to Start", Darker@ Green, Bold];
     FinishDynamic[];
     iUpdate = iUpdate + 1;
     , Method -> "Queued"
     ]
    , {{npts, 7, "N pts"}, 1, 20, 1, Appearance -> "Labeled"}
    (*future use:  track iUpdate to trigger long calculations*)
    , {iUpdate, None}
    , ControlPlacement :> {Left, Left}
    , TrackedSymbols :> {iUpdate, inputType}
    , Initialization :> (
      xyData = initPts[7];
      iCount = 0;
      iUpdate = 0;
      status = Style["Ready to Start", Darker@ Green, Bold];
      )
    , SynchronousUpdating -> False
    ]
   ];

Button["start Test", CellPrint@testManip ]
$\endgroup$
1
  • $\begingroup$ Use Dynamic[TableForm[xyData]] instead. Very few functions do something sensible when you put Dynamic in as an argument. Use TableView[Dynamic[xyData], Number] if you want to make sure that the data in represented stays numeric. $\endgroup$ – Sjoerd Smit Jul 18 '20 at 17:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.