2011-09-26 9 views
12

To jest trochę związane z tym pytaniemJak zdefiniować część definicji zmiennej Manipulacja kontrola zmniejszyć powielania kodu

Define control as variable in Mathematica

Ale powyższe pytanie nie odpowiedział mój problem, ponieważ opowiada o pełnej definicja sterowania. (Próbowałem także niektórych pokazanych tam sztuczek, ale one nie działają na mój problem).

Pytam teraz o definicję tylko części kontroli. (Bardzo trudno jest też sprawdzić stare pytanie przy użyciu tego formatu forum, ponieważ przy użyciu małego obszaru komentarzy trudno jest zapytać i pokazać więcej, gdy zadajesz nowe pytanie, gdzie przestrzeń jest większa, i można wkleić kod i obrazy).

Wszystkie próby, które zrobiłem, nie działają. Zacznę od prostego przykładu, aby wyjaśnić problem.

Przyjmuje się jeden chce napisać

Clear["Global`*"]; 

Manipulate[Plot[f*g, {x, -1, 1}], 
Grid[{ 
    {Style["f(x)="], 
    PopupMenu[Dynamic[f], {x, x^2, x^3}, ImageSize -> Tiny]},{Style["g(x)="], 
    PopupMenu[Dynamic[g], {x, x^2, x^3}, ImageSize -> Tiny]} 
    }] 
] 

widać istnieje przydzieleniu kodu powielania w każdej definicji sterowania. (Rzeczy, jak ImageSize, Spacings-> i wielu innych ustawień dekoracji, są powtarzane w kółko za każdym kontrolą.

enter image description here

Co będzie wielki, jeśli mogę coś napisać jak

Manipulate[Plot[f*g, {x, -1, 1}], 
Grid[{ 
    {Style["f(x)="], PopupMenu[Dynamic[f], [email protected]@v]}, 
    {Style["g(x)="], PopupMenu[Dynamic[g], [email protected]@v]} 
    }], 

Initialization :> 
    (
    v = {{x, x^2, x^3}, ImageSize -> Tiny} 
    ) 
] 

ale to nie działa. i próbuje wiele innych rzeczy wzdłuż powyższej linii, a nic nie działa. Jak

{Style["f(x)="], PopupMenu[Dynamic[f], v]}, 

i

{Style["f(x)="], PopupMenu[Dynamic[f], [email protected]]} 

i

Manipulate[Plot[f*g, {x, -1, 1}], 

{{v, {{x, x^2, x^3}, ImageSize -> Tiny}}, None}, 
Grid[{ 
    {Style["f(x)="], PopupMenu[Dynamic[f], [email protected]]}, 
    {Style["g(x)="], PopupMenu[Dynamic[g], v]} 
    }] 
] 

nie może zmusić go do pracy.

Ale tutaj są zasady gry: To będzie na demo, stąd kod musi zaczynać się od Manipulowania. Nie można mieć modułu poza manipulacją. Ponadto, nie może używać funkcji Hold i jej przyjaciół. Ale może używać Unevaluated.

Miałem nadzieję, że eksperci tutaj mogą mieć podstęp, aby to zrobić. Spowoduje to zmniejszenie rozmiaru kodu, jeśli jest to możliwe, ponieważ wiele elementów sterujących, które mam, zawiera wiele "opcji", takich jak powyższe, które są takie same, a możliwość wykonania powyższych czynności sprawi, że kod będzie łatwiejszy do odczytania i zarządzania .

dziękuję,

ps. To o co proszę, jest podobne do tego, co robimy, powiedzmy Opcje wydruku, gdzie można użyć SetOptions, aby ustawić niektóre typowe domyślne opcje, aby nie musiały ich duplikować dla każdego polecenia wydruku za każdym razem. Ale nie ma czegoś takiego w tym przypadku.

aktualizacja

Stosując metodę pokazaną poniżej, Leonid (Macro sprawę), chciałem go użyć, aby pomóc mi określić liczbę kontroli, wszystko za pomocą jednego wspólnego ustawienia. Oto, co próbowałem:

Manipulate[{x, y}, 

[email protected][ 
    { 
    control1 = Function[{var, initialValue, str, from, to, incr}, 
     { 
     {{var, initialValue, str}, from, to, incr, ImageSize -> Tiny} 
     } 
     , 
     HoldAll 
     ] 
    }, 

    { 
     [email protected][x, 0, "x=", 0, 1, .1], 
     [email protected][y, 0, "y=", 0, 2, .1], 
     [email protected][z, 0, "z=", 0, 10, .1] 
    }, 

    ] 
] 

Problem jest tylko dodatkowym {} wokół całości, w przeciwnym razie zadziała. Będzie nadal próbować rozwiązać ten problem. Ale zbliża się. Próbowałem sekwencji [] i Spłaszczam [..., 1] i takie, ale nie mogę tego jeszcze zrobić. Sporządzenie większej ilości kawy powinno pomóc.

Aktualizacja 2

to jest poniżej przykład stosując metodę Simon użyć w celu określenia wspólnych definicji na więcej niż jedno urządzenie sterujące. W ten sposób można go użyć do ograniczenia powielania kodu dla typowych opcji na zestawie oddzielnych formantów.

Zauważ, że musiał użyć Control[], aby uzyskać kontrolę.

Manipulate[{x, y, z}, 

Dynamic[Grid[{ 
    {control1[x, 0, "x=", 0, 1, .1]}, 
    {control1[y, 0, "y=", 0, 2, .1]}, 
    {control1[z, 0, "z=", 0, 10, .1]} 
    }]], 

{{control1, 
    Function[{var, initialValue, str, from, to, incr}, 
    Control[{{var, initialValue, str}, from, to, incr, 
     ImageSize -> Tiny}], HoldFirst]}, None} 

] 

enter image description here

Update 3

I got metoda Leonid pracować również na więcej niż jednej kontroli. Sztuką jest użycie Control[]. Nie można użyć zwykłego starego {{x,0,"x"},...} [EDYTUJ, tak, możesz, po prostu potrzebujesz metody Sequence @@ jak pokazano poniżej przez aktualizację Leonid.].

Oto ona:

Manipulate[{x, y, z}, 

[email protected][ 
    { 
    control1 = Function[{var, initialValue, str, from, to, incr}, 
     Control[{{var, initialValue, str}, from, to, incr, 
     ImageSize -> Tiny}] 
     , HoldAll 
     ] 
    }, 

    Grid[{ 
    {control1[x, 0, "x=", 0, 1, .1]}, 
    {control1[y, 0, "y=", 0, 2, .1]}, 
    {control1[z, 0, "z=", 0, 10, .1]} 
    }] 

    ] 
] 

enter image description here

Postaram się zintegrować jedną z tych metod do mojego głównego demo (ma ponad 600 linii kodu tylko dla układu sterującego tak daleko i rośnie z minuty na minutę, miejmy nadzieję, że te metody zmniejszą to przez całkiem sporo)

Update 9/26/11. 7 pm

Pomyślałem, że mogę napisać widok "oka ptaków" zapisu kodu za pomocą "makr", aby zdefiniować kontrolki, które zawierają wiele wspólnego kodu płyty kotła. Oto zrzut ekranu przed i po.

Jeszcze raz dziękuję za wszystkie odpowiedzi i pomoc.

enter image description here

+1

Dzięki wszystkim odpowiedzi (Leonid, Simon, WReach). Wszystkie świetne odpowiedzi. Wybrałem metodę makro przez Leonida tylko dlatego, że nie używa ona Dynamics, i nie jestem zbyt dobra z Dynamics i wydaje mi się, że wpadam w kłopoty z nimi :). Mimo że obie metody działają bardzo dobrze, wszystkie rzeczy są równe, wolę metodę, która nie używa dynamiki, tylko osobistą preferencję i brak mi doświadczenia z dynamiką. Wysłałem aktualizację powyżej pokazującą redukcję kodu, którą uzyskałem, ponieważ zacząłem integrować ten nowy sposób układania kontroli w wersji demonstracyjnej, którą piszę, a zapisywanie kodu jest niesamowite. – Nasser

+0

Niestety, w wielu przypadkach taka redukcja kodu jest raczej trudna do uzyskania w Mathematica, ponieważ trudno jest kontrolować ewaluacje/zapisywać makra. Myślę, że jeszcze nie odkryto lepszych sposobów, aby to zrobić w mma (jestem szczególnie zainteresowany tym tematem). –

+0

Po zerknięciu na zrzut ekranu zauważyłem, że pominięto atrybut 'HoldAll' w czystej funkcji (makro). Chociaż będzie to działało przez większość czasu, posiadanie wstępnie zdefiniowanych wartości dla zmiennych używanych w Manipulate może prowadzić do problemów (nie wiem, czy może to rzeczywiście nastąpić w kontekście demonstracji). Dodając atrybut, będziesz chronić swój kod przed takimi przypadkami (jest to ten atrybut, który konwertuje funkcję na makro, pod względem semantyki) –

Odpowiedz

10

Co o tym

Manipulate[Plot[f*g, {x, -1, 1}], 
[email protected] 
    With[{styleAndpopup = 
     Function[{st, fun}, 
     { 
      Style[st], 
      PopupMenu[Dynamic[fun], {x, x^2, x^3}, ImageSize -> Tiny] 
     }, 
     HoldAll]}, 
    Grid[{styleAndpopup["f(x)=", f], styleAndpopup["g(x)=", g]}]]] 

Właściwie jest to mały przykład kodu generacji w pracy, ponieważ jeśli spojrzeć na FullForm powstałej Manipulate, widać to samo wyrażenie, z którego początkowo zacząłeś. styleAndpopup w rzeczywistości nie jest tu funkcją, ale makrem, zdefiniowanym lokalnie przy użyciu With.

EDIT

Na żądanie OP - uogólniając wielu kontroli. Najłatwiejszą metodą jest wstawienie [email protected]@... jako Sequence @@ {[email protected][.... Jednak istnieją pewne obce rzeczy, które mogą być usunięte, a także:

Manipulate[{x, y}, 
[email protected][{control1 = 
    Function[{var, initialValue, str, from, to, incr}, 
     [email protected]{{var, initialValue, str}, from, to, incr, ImageSize -> Tiny}, 
     HoldAll]}, 
    Sequence @@ { 
    control1[x, 0, "x=", 0, 1, .1], 
    control1[y, 0, "y=", 0, 2, .1], 
    control1[z, 0, "z=", 0, 10, .1]}]] 
+0

jak używać tej metody do definiowania więcej niż jednego elementu sterującego za pomocą "wspólnych" definicji? Zobacz moją edycję 2 z tego, co próbowałem. Myślę, że jestem blisko. Dzięki – Nasser

+0

@Nasser edit2? Widzę tylko jedną aktualizację. –

+0

@sorry, tylko aktualizacja, tylko jedna, nie 2. dzięki! – Nasser

7

miałem zamiar dać rozwiązanie prawie taka sama jak Leonid i użyć With wstawić kod, ale on pokazał mi to, więc oto alternatywny sposób. Definiują dynamiczną funkcję lokalnego przy użyciu ControlType -> None który wykonuje swoją stylizację:

Manipulate[Plot[{f, g + 1}, {x, -1, 1}], 
Dynamic[Grid[{{Style["f(x)="], pu[f]}, 
     {Style["g(x)="], pu[g]}}]], 
{{pu, Function[{f}, PopupMenu[Dynamic[f], {x, x^2, x^3}, ImageSize -> Tiny], 
     HoldFirst]}, None}] 

By the way, Style[] w Style["f(x)="] jest zbędny, ponieważ nie są właściwie ustalone wszystkie style ...

+0

Ładna alternatywa - +1. Właściwie, w moim rozwiązaniu 'With' nie jest kluczowe, może być zastąpione przez' Module' say (chociaż, 'With' wydaje mi się tu nieco czystsze, ale jest to kwestia gustu). –

+0

@Simon, nie jestem pewien czy rozumiem, powyższy kod nie działa, jestem na V 8.01. Czy może być jakiś brakujący kod? Skopiowałem i uruchomiłem, zobacz edycję 1 dla wyniku na moim komputerze. (System Windows 7). (i zacząłem od nowego jądra) dzięki. – Nasser

+0

@Nasser: Przepraszam, brakowało 'Dynamic' ... – Simon

1

Można by to zrobić:

Manipulate[ 
    Plot[f*g, {x, -1, 1}] 
, Grid[ 
    { {Style["f(x)="], PopupMenu[Dynamic[f], opts]} 
    , {Style["g(x)="], PopupMenu[Dynamic[g], opts]} 
    } 
    ] 
] /. opts -> Sequence[{x, x^2, x^3}, ImageSize -> Tiny] 

Jeśli ktoś jest w zwyczaju przypisywania wartości w dół do symboli, których nazwiska nie zaczynają się $, to byłoby rozsądne, aby zawinąć całość w Block[{x, opts}, ...] w przypadku x i opts ma zdefiniowane globalnie wartości.

Podobna technika jest możliwe dla przypadku wielokrotnych kontroli:

Manipulate[ 
    {x, y, z} 
, Grid[ 
    { {control1[x, 0, "x=", 0, 1, .1]} 
    , {control1[y, 0, "y=", 0, 2, .1]} 
    , {control1[z, 0, "z=", 0, 10, .1]} 
    } 
    ] 
] /. control1[var_, initialValue_, str_, from_, to_, incr_] :> 
     Control[{{var, initialValue, str}, from, to, incr, ImageSize -> Tiny}] 
+1

Problem polega na tym, że kod nie zaczyna się od 'Manipulate' - zamiast tego zaczyna się od' ReplaceAll'. Niezależnie od tego, czy jest to akceptowalne dla demonstracji, których nie znam, ale nie spełnia specyfikacji OP w tym zakresie. Z pewnością, jeśli zwolnimy ten warunek, możliwe są jeszcze inne sposoby osiągnięcia żądanego celu. –

+0

@Leonid Za to, co jest warte, pomyślnie przesłałem ten kod do Demonstracji Wolfram. OP może dyskwalifikować go na podstawie innych wymagań. – WReach

+0

Dobrze wiedzieć. Nie próbowałem siebie, więc polegałem na tym, co stwierdził @Nasser. +1. –

Powiązane problemy