2012-01-16 19 views
5

Để thêm Dải phân cách giữa các hàng trong lưới, một cách tôi biết cách thực hiện bằng cách sử dụng tùy chọn Dividers. Nhưng điều này được sử dụng ở cuối, và sau đó người ta phải biết số hàng mà một dải phân cách cần phải ở dưới nó. Vì vậy, đối với lưới lớn, tôi thấy mình sử dụng thử và sai cho đến khi tôi tìm thấy số hàng chính xác. Sau đó, khi tôi thay đổi lưới sau này, tôi phải làm thử và sai lần nữa để đặt dải phân cách vào đúng vị trí trong trường hợp nó di chuyển sau khi thay đổi của tôi.bất kỳ thủ thuật nào để thêm Dải phân cách bên trong lưới giữa các hàng tại điểm cần thiết

Trong ví dụ này, có một mạng lưới với 3 hàng và tôi muốn thêm chia dưới đây nói hàng thứ hai, vì vậy tôi có thể làm điều này:

Grid[{ 
    {1}, 
    {2}, 
    {3} 
    }, Frame -> True, Dividers -> {All, 3 -> True}] 

Một cách khác, là đưa FalseTrue, theo đúng thứ tự mà tôi muốn một gốc cây, như thế này

Grid[{ 
    {1}, 
    {2}, 
    {3} 
    }, Frame -> True, Dividers -> {All, {True, False, True, True}}] 

Nó sẽ được tốt đẹp nếu tôi có thể làm điều gì đó như này (như người ta có thể làm cho thao tác) (ofcourse này dưới đây không làm việc ở đây)

Grid[{ 
    {1}, 
    {2}, 
    Delimiter, 
    {3} 
    }, Frame -> True] 

hoặc

Grid[{ 
    {1}, 
    {Item[2,Dividers->True]}, 
    {3} 
    }, Frame -> True] 

hoặc điều như vậy.

Nó sẽ giúp bảo trì mã dễ dàng hơn.

Tôi đã xem sử dụng Mục và như vậy cho điều này, nhưng không thể tìm ra.

Bất kỳ ai biết về một mẹo để làm điều đó?

chỉnh sửa:

btw, Thủ thuật này nếu có thể, không chỉ áp dụng đối với Bộ chia. Nhưng nó sẽ rất hữu ích để có thể làm được nhiều tùy chọn Grid khác, mà bây giờ được thực hiện ở mức Grid, được thực hiện cũng như ở cấp độ item. Ví dụ, nếu tôi muốn thêm một không gian phụ sau một số hàng, nó sẽ dễ dàng hơn để nói như vậy ngay tại tốc độ tôi muốn thực hiện điều này. Ngoài ra, nếu tôi muốn thay đổi kích thước mục, dễ dàng hơn để làm điều đó tại chỗ, tương tự cho Spacings, vv. Vì vậy, khi di chuyển/sao chép mã cho toàn bộ hàng hoặc mục, nó là khép kín và sao chép nó với tất cả cùng nhau.

Tôi nghĩ rằng bây giờ điều này có thể yêu cầu một tùy chọn mới thêm vào Mathematica Grid để làm cho nó hoạt động đúng và phù hợp với trên tất cả các thiết kế lưới.

Đây là tất cả cho đến khi trình xây dựng GUI được tạo cho Mathematica.

Tôi thấy rằng tôi dành hơn 60% thời gian của mình khi tôi viết bản trình diễn để GUI phù hợp và nhìn đúng. Với trình tạo GUI, tôi có thể dành thời gian này để làm việc trên thuật toán thay thế. Khi tôi sử dụng Matlab GUIDE để tạo GUI, tôi mất ít hơn 5% thời gian để tạo một GUI tương tự.

Tôi ước rằng WRI sẽ tạo trình xây dựng GUI cho Mathematica, tôi nghĩ đây sẽ là ứng dụng sát thủ cho Mathematica nếu bạn hỏi tôi. Nhưng cơ thể không hỏi tôi :)

chỉnh sửa (2)

bình luận về ông Hướng dẫn giải pháp tốt đẹp dưới đây.
Tôi chủ yếu muốn tính năng này cho Lưới mà tôi sử dụng để điều khiển bố cục cho Manipulate. Dưới đây là một ví dụ đơn giản:

Manipulate[x, 

Grid[{ 
    {Control[{{x, 0, "x"}, 0, 10, 1}]}, 
    {Control[{{y, 0, "y"}, 0, 10, 1}]} 
    }, Frame -> None, Dividers -> {None, {False, True, False}} 
    ] 
] 

enter image description here

(và tôi phải sử dụng Grid lập các điều khiển). Tôi không thể sử dụng các cuộc gọi chức năng ở đây. Tôi không thể viết, sử dụng giải pháp Wizard dưới đây, như sau:

Manipulate[x, 

myGrid[{ 
    {Control[{{x, 0, "x"}, 0, 10, 1}]}, 
    spec["Divider"], 
    {Control[{{y, 0, "y"}, 0, 10, 1}]} 
    }, Frame -> None 
    ], 

Initialization :> 
    { 
    specfunc["Divider", lst_] := Dividers -> {None, # -> True & /@ lst}; 

    myGrid[dat_, opts : OptionsPattern[]] := 
    Module[{x = 1}, 
    Grid[#, opts, Sequence @@ #2] & @@ 
     Reap[If[MatchQ[#, _spec], Sow[x, #[[1]]]; ## &[], x++; #] & /@ 
     dat, _, specfunc] 
    ] 

    } 
] 

này đưa ra một lỗi, vì Mathematica cố gắng đầu tiên đọc nội dung của Thao tác để phân tích nó, trước khi đọc và xử lý phần khởi tạo.

Nhưng bên ngoài thao tác, nó sẽ làm việc ofcourse:

myGrid[{ 
    {Control[{{x, 0, "x"}, 0, 10, 1}]}, 
    spec["Divider"], 
    {Control[{{y, 0, "y"}, 0, 10, 1}]} 
    }, Frame -> None 
] 

specfunc["Divider", lst_] := Dividers -> {None, # -> True & /@ lst}; 
myGrid[dat_, opts : OptionsPattern[]] := 
Module[{x = 1}, 
    Grid[#, opts, Sequence @@ #2] & @@ 
    Reap[If[MatchQ[#, _spec], Sow[x, #[[1]]]; ## &[], x++; #] & /@ 
    dat, _, specfunc] 
    ] 

enter image description here

tôi cần phải dành nhiều thời gian về vấn đề này, để xem nếu tôi có thể lấy nó để làm việc bên trong thao tác.

btw, việc làm như thế này hoạt động bên trong Thao tác thực sự khó khăn. Chỉ lừa mà tôi biết là sử dụng các macro với mẫu With[{},.... Grid....] tôi đã học được từ Leonid.

Đối với ví dụ về những khó khăn như vậy, xem câu hỏi này của tôi

How to define constants for use with With[] in one place and then apply them later?

chỉnh sửa (3) của tôi là tôi làm sai điều gì, nhưng tôi nhận được một số lỗi trong thao tác:

ví dụ đầu tiên:

Manipulate[x, 

[email protected][{ 
    {Control[{{x, 0, "x"}, 0, 10, 1}]} 
    } 
    ], 

Initialization :> 
    { 
    grid[tab_, opts___] := 
    Module[{divlocal, divglobal, div, pos}, 
     divglobal = (Dividers /. opts) /. Dividers -> {False, False}; 
     If[Depth[divglobal] == 1, divglobal = {divglobal, divglobal}]; 
     If[Length[divglobal] == 1, AppendTo[divglobal, False]]; 
     pos = Position[tab, Dividers -> _, 1]; 
     divlocal = 
     MapIndexed[# - #2[[1]] + 1 -> Dividers /. tab[[#]] &, 
     Flatten[pos]]; 
     divglobal[[2]] = {divglobal[[2]], divlocal}; 
     Grid[Delete[tab, pos], Dividers -> divglobal, opts]]; 


    } 
] 

cho erro r:

ReplaceAll::rmix: Elements of {False,{}} are a mixture of lists and nonlists. >> 

cùng nếu tôi thay thế ở trên với

[email protected][{ 
    Dividers -> {Thick, Blue}, 
    {Control[{{x, 0, "x"}, 0, 10, 1}]} 
    } 
    ], 

Cố gắng [email protected] ở vị trí của [email protected] không may mắn. có thể sửa chữa nhỏ là tất cả những gì cần thiết? hoặc tôi không sử dụng nó phải không?

+0

hi Mike. Có, tôi biết nơi tôi muốn thêm dải phân cách, nhưng trong lưới phức tạp dài, việc thêm đoạn mã vào vị trí tôi muốn được thêm vào sẽ dễ dàng hơn, thay vì đặt mã ở dưới cùng và phải đếm và thực hiện sai lầm. Sau đó làm lại, khi thay đổi lưới. Đó là quan điểm của tôi. Cảm ơn – Nasser

+0

Toàn bộ vấn đề của một người xây dựng gui và mã hóa tay của giao diện người dùng là một cái gì đó cũng được thảo luận ở nhiều nơi trên mạng. Tôi muốn nói về nó nhiều hơn, nhưng tôi không nghĩ đây là nơi thích hợp cho nó. Có thể là khi chúng ta có diễn đàn Mathematica riêng của mình, chúng ta có thể nói nhiều hơn về nó. Nhưng từ kinh nghiệm của tôi, sử dụng một trình xây dựng GUI tiết kiệm rất nhiều thời gian lập trình trên mã hóa tay. phân tích chi phí/thời gian ưu tiên sử dụng trình tạo GUI. Thời gian lưu có thể được sử dụng cho nhiều thứ quan trọng khác. btw, tôi đang nói ở đây về giao diện người dùng phức tạp lớn, không phải là một đơn giản hoặc 2 thanh trượt và một Nút và một giao diện kiểu lô. – Nasser

+1

Để có được 'Thao tác' trong chỉnh sửa (2) để làm việc, bạn có thể thay thế điều khiển bằng' Dynamic @ myGrid [...] '. – Heike

Trả lời

4

giải pháp này sẽ cho phép bạn kết hợp kỹ thuật cho vách ngăn giữa các hàng quy định trong bảng với những quy định sử dụng Dividers tùy chọn.

grid[tab_, opts___] := 
Module[{divlocal, divglobal, div, pos}, 

    (* extract option value of Dividers from opts to divglobal *) 
    (* default value is {False, False} *) 
    divglobal = (Dividers /. {opts}) /. Dividers -> {False, False}; 

    (* transform divglobal so that it is in the form {colspecs, rowspecs} *) 
    If[Head[divglobal] =!= List, divglobal = {divglobal, divglobal}]; 
    If[Length[divglobal] == 1, AppendTo[divglobal, False]]; 

    (* Extract positions of dividers between rows from tab *) 
    pos = Position[tab, Dividers -> _, 1]; 

    (* Build list of rules for divider specifications between rows *) 
    divlocal = MapIndexed[# - #2[[1]] + 1 -> Dividers /. tab[[#]] &, Flatten[pos]]; 

    (* Final settings for dividers are {colspecs, {rowspecs, divlocal}} *) 
    divglobal[[2]] = {divglobal[[2]], divlocal}; 
    Grid[Delete[tab, pos], Dividers -> divglobal, opts]] 

Để xác định một chia giữa hàng bạn cần phải chèn Dividers->spec tại vị trí mong muốn nơi spec là một trong hai False, True, hoặc một chỉ thị đồ họa (màu sắc, độ dày, vv). Ví dụ

tab = {{1, 2, 3}, Dividers -> {Thick, Blue}, {4, 5, 6}, {7, 8, 9}, 
    Dividers -> False, {10, 11, 12}}; 

grid[tab, Dividers -> All] 

Mathematica graphics

Sửa

Tôi đã thêm một số ý kiến ​​để mã của tôi theo yêu cầu của ông Wizard.

+0

+1, tuy nhiên tôi sẽ đánh giá cao một số giải thích cho mỗi dòng mã: –

+0

Ngoài ra, tôi nghĩ bạn cần '/. {Opts}' –

+0

Heike, cảm ơn. Tôi đã thử tính năng Dynamic @ and Evaluate @ nhưng có một số lỗi sẽ hiển thị các ví dụ mà tôi đã thử trong bản chỉnh sửa của mình (3) – Nasser

2

Tôi đề nghị bạn sử dụng đầu mới có thể giữ các hướng dẫn (spec bên dưới) và chức năng mới xử lý các hướng dẫn này (specfunc bên dưới) theo yêu cầu riêng. Lợi ích là điều này dễ dàng được khái quát hóa cho các hướng dẫn xen kẽ khác nhau và mỗi phương pháp có thể được xử lý theo một cách tùy ý.

specfunc["Divider", lst_] := Dividers -> {All, # -> True & /@ lst} 

myGrid[dat_, opts:OptionsPattern[]] := 
Module[{x = 1}, 
    Grid[#, opts, Sequence @@ #2] & @@ 
    Reap[ 
    If[MatchQ[#, _spec], Sow[x, #[[1]]]; ## &[], x++; #] & /@ dat, 
    _, 
    specfunc 
    ] 
] 

Cách sử dụng:

dat = 
{ 
    {1, 2, 3}, 
    {4, 5, 6}, 
    spec["Divider"], 
    {7, 8, 9}, 
    spec["Divider"], 
    {"a", "b", "c"} 
}; 

myGrid[dat, Frame -> True] 

Mathematica graphics


Nếu mỗi hướng dẫn có thể là một chuỗi duy nhất như "Divider" và bạn không có xung đột sử dụng chúng theo cách này, bạn có thể loại bỏ spec và sử dụng MatchQ[#, _String]Sow[x, #].


Phát biểu câu hỏi cập nhật của bạn, như tôi đã nói trong một chú thích dưới đây, tôi tin rằng nó có ý nghĩa hơn để sử dụng các yếu tố cơ bản nhất trong đối tượng thức Manipulate của bạn, và viết các công cụ để giúp bạn tạo đối tượng này một cách dễ dàng nhất. Tôi tin rằng cố gắng làm cho các loại tùy chỉnh này bên trong chính khối Manipulate sẽ bị thất bại, và có thể theo những cách kỳ lạ và mờ đục.

Tuy nhiên, đối với trường hợp đặc biệt này này dường như làm việc, mặc dù tôi nghi ngờ nó là mạnh mẽ:

Manipulate[x, 
Evaluate[ 
    {specfunc["Divider", lst_] := Dividers -> {All, # -> True & /@ lst}; 
    myGrid[dat_, opts : OptionsPattern[]] := 
    Module[{x = 1}, 
    Grid[#, opts, Sequence @@ #2] & @@ 
     Reap[If[MatchQ[#, _spec], Sow[x, #[[1]]]; ## &[], x++; #] & /@ 
     dat, _, specfunc]]}; 
    myGrid[{{Control[{{x, 0, "x"}, 0, 10, 1}]}, 
    spec["Divider"], {Control[{{y, 0, "y"}, 0, 10, 1}]}}, 
    Frame -> True] 
    ] 
] 
+0

Cảm ơn, điều này thực sự gọn gàng và tôi có thể sử dụng nó. Nhưng việc sử dụng chính tôi có cho tính năng này là trong việc xây dựng các điều khiển cho thao tác. Và tôi không thể sử dụng nó như trong bối cảnh đó. Tôi cần dành nhiều thời gian hơn để xem tôi có thể thích ứng với điều đó không. Tôi đang thêm chỉnh sửa (2) ngay bây giờ để giải thích rõ hơn ý tôi. Vấn đề là trong Thao tác kiểm soát khu vực, môi trường là một chút hạn chế hơn và một cái gì đó mà làm việc bên ngoài, không làm việc dễ dàng ở đó. – Nasser

+1

@Nasser Tôi xin lỗi, tôi không xây dựng bản demo và tôi không biết cách làm mọi thứ bên trong một 'Thao tác 'theo cách bạn đang cố gắng. Tôi chỉ có thể gợi ý lập trình meta, nghĩa là, viết các công cụ dễ sử dụng để tạo ra đối tượng 'Thao tác 'phức tạp mà chắc chắn là bắt buộc. Trong trường hợp của bạn 'Grid' hoạt động, vì vậy tôi sẽ sử dụng nó; thay vào đó, hãy tạo một công cụ để viết đối tượng 'Grid' dễ dàng hơn. Điều này có giúp ích gì không? –

+0

MrWizard, Heike vừa chỉ ra một sửa chữa đơn giản. Chỉ cần thêm Động lực xung quanh toàn bộ sự việc. Tôi đã thử bản thân mình, và tôi chỉ quên làm điều đó. Cảm ơn vì một giải pháp rất tốt đẹp. – Nasser

Các vấn đề liên quan