5
$\begingroup$

Many years ago, I made a handy little program in Flash.

It consisted of a number of input fields, each representing a variable that was dependent on all the others. As soon as any field changed, the other followed, no matter which of them I changed.

So they where effectively both in- and output fields.

A simple algorithm kept track of which field would output the result, (usually the one which had experienced no change or with oldest edit).

EDIT: Only one variable is calculated each time a value is changed.

It may be partly exemplified by the following code. However, in this case only the last InputField "c-variable" is calculated, while the goal is to arbitrarily be able to chose which is to be calculated. The latter can be achieved either by a checkbox or algorithmically.

    Clear[a, b, c]; Row[{Labeled[
   InputField[Dynamic[a], Number, ContinuousAction -> True, 
    FieldSize -> Tiny], "a-variable", Top], 
  Labeled[InputField[Dynamic[b], Number, ContinuousAction -> True, 
    FieldSize -> Tiny], "b-variable", Top], 
  Labeled[InputField[N@Dynamic[c = (a*b)/2], Number, 
    ContinuousAction -> True, FieldSize -> Tiny], "c-variable", Top]}]

So my question:

Is there a simple way of programmatically switching the properties as to make any arbitrary field an output field?

Another question comes into mind: The exemplified InputFields above can't handle backspace. To change the first digit one has to double-click. How could this be accomplished?

EDIT 2: I have answered some of the points in my answer below.

$\endgroup$
2
  • $\begingroup$ Let's say you can edit c. And let's say you double it, how this should affect a and b? Both equally multiplied by sqrt(2) or one of them and why? $\endgroup$
    – Kuba
    Jan 2, 2015 at 22:22
  • $\begingroup$ Hi Kuba, well this is merely an example. Of course my original program only changed one variable at a time. I use it every day, so I can assure you it is useful. The way I implemented it, It kept track of the most likely to be changed. Lets say you entered a value for a and b - then c changed. If c and a was entered - then b was calculated. Very simple indeed, however extremely useful. $\endgroup$
    – MathLind
    Jan 3, 2015 at 4:01

2 Answers 2

2
$\begingroup$

I'm still not sure about details of behaviour you are after but you can certainly build on this:

Basicaly you can use the second argument of Dynamic.

ClearAll[a, b, c];
a = b = c = 1;
Grid[{
  {"a", "b", "c"},
  {
   InputField[ Dynamic[a, (a = #; If[# =!= Null, c = a b/2]) &]],
   InputField[ Dynamic[b, (b = #; If[# =!= Null, c = a b/2]) &]],
   InputField[ Dynamic[c, (c = #; If[# =!= Null, b = 2 c/a]) &]]
   }}]
$\endgroup$
1
  • $\begingroup$ Thank you Kuba,that looks great. Now try to squeeze ContinuousAction into it and get rid of the backspace-problem and manage ato be calculated. Meanwhile, shall I bring the popcorn? :) $\endgroup$
    – MathLind
    Jan 3, 2015 at 11:02
0
$\begingroup$

So I found a way:

  1. Using InputFields for both in- and output arbitrarily.
  2. Ranking the InputFields to automatically choose the field for output, although this could be achieved in many other ways, e.g. checkboxes etc.
  3. Achieving immediate responsiveness in all Inputfields upon editing using ContinuousAction.

Help-function, ranking and choosing result field:

(*Choose the initial order of calculation*)
{a, b, c} = {2, 1, 0};
chooseFunction[aa_: 0, bb_: 0, cc_: 0] := (
  a = a + aa; b = b + bb; c = c + cc;
  (*Ranks which InputField is last edited, i.e. becomes resultfield*)
  {a, b, c} = Ordering@Ordering@{a, b, c};

  If[a == 1, field1 = Round[field3/field2, 0.00001]];
  If[b == 1, field2 = Round[field3/field1, 0.00001]];
  If[c == 1, field3 = Round[field1*field2, 0.00001]];
  )

Grid with InputFields and Dynamic with two arguments as suggested by Kuba.

field1 = field2 = field3 = 1;
Grid[{{"a", "b" , "", "a*b"}, {
   InputField[Dynamic[field1, (field1 = #;
        chooseFunction[3, 0, 0]) &], Number, ContinuousAction -> True,
      FieldSize -> Tiny],
   InputField[Dynamic[field2, (field2 = #;
        chooseFunction[0, 3, 0]) &], Number, ContinuousAction -> True,
      FieldSize -> Tiny], " = ",
   InputField[Dynamic[field3, (field3 = #;
        chooseFunction[0, 0, 3]) &], Number, ContinuousAction -> True,
      FieldSize -> Tiny]}}]  

However the following problems remain unsolved:

  1. Zeros are not permitted after the decimal point.
  2. All but the leftmost digit can be erased by backspace.

Any suggestions anyone?

EDIT
Well, sitting at work thinking about the two before-mentioned problems, it suddenly seems rather obvious.

With the options Number and ContinuousAction -> True I ask for action on every keystroke. So that is what I get.
Trying to erase the leftmost (last) digit through backspace, will not be permitted since that wouldn't constitute a number.
Pressing 1 and 0 evaluates to 10, whereas pressing 1 . 0 5 will halt at 1. since this will be evaluated to 1 and not 1.0

$\endgroup$

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.