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.
Couple of issues that I don't know how to correct.
- the TableForm doesn't show the values in a table format. Instead it shows a List of Lists.
- after modifying a value via TableView, the values displayed by TableForm all change to strings. That is each value is surrounded by double quotes.
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.
Input Choice #2: with 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 ]
Dynamic[TableForm[xyData]]
instead. Very few functions do something sensible when you putDynamic
in as an argument. UseTableView[Dynamic[xyData], Number]
if you want to make sure that the data in represented stays numeric. $\endgroup$