7
$\begingroup$

How could one create a table or list of buttons, such that clicking on a button removes the button itself from the list?

$\endgroup$
5
  • $\begingroup$ like a self destruct mode? :-) $\endgroup$
    – chris
    Commented Nov 7, 2012 at 17:29
  • $\begingroup$ Kind of, what I'm actually building is an array of arrays (of buttons) - each line of buttons has a 'delete this line' button, but I thought an answer to the simplest case would suffice for me. $\endgroup$
    – Cuboid
    Commented Nov 7, 2012 at 17:33
  • $\begingroup$ This is a bit Slaughterhouse-Five-ish :-) $\endgroup$
    – Yves Klett
    Commented Nov 7, 2012 at 17:47
  • $\begingroup$ Take a look at this related question if you need more complicated applications: mathematica.stackexchange.com/questions/6211/… $\endgroup$
    – Szabolcs
    Commented Nov 7, 2012 at 18:53
  • $\begingroup$ Thanks for all the helpful answers. $\endgroup$
    – Cuboid
    Commented Nov 8, 2012 at 22:55

3 Answers 3

4
$\begingroup$

The crux of the problem is defining an identity for the buttons. As such a nice way is to keep them unevaluated in the list and define a structure to display them as buttons, this makes identifying them and deleting them simple:

 list = Table[button[i], {i, 5}];

 SetAttributes[display, HoldAll]
 display[list_] := list /. button[id_] :> 
     Button["#" <> ToString[id] <> " Press me!", list = DeleteCases[list, button[id]]]

 Dynamic[display[list]]

Button row after item #4 was clicked and deleted

The above images shows the state after #4 was clicked and deleted. Using this method, the list is quite simply the line:

{button[1], button[2], button[3], button[4], button[5]}

Which is easy to handle and manipulate, and the buttons are just a visual representation of it. And it makes it very easy to put new buttons back, just run AppendTo[list,button[42]] and you get a new button, without having to retype all the code related to how it works in the dynamic display.

$\endgroup$
8
$\begingroup$

Of course!

button := Button["Press me!",
  list = Drop[list, 1]];
list = Table[button, {5}];
Dynamic[list]
$\endgroup$
4
  • $\begingroup$ May be Dynamic[Row@list] is even better for cosmetic beauty. When the list is empty it does not show the sad empty list {}! $\endgroup$ Commented Nov 7, 2012 at 17:49
  • $\begingroup$ This is not actually an answer to the question. This is a list of buttons that when pressed will delete the first button in the list.The question was for a button capable of deleting itself. $\endgroup$
    – jVincent
    Commented Nov 8, 2012 at 14:25
  • $\begingroup$ @MarkMcClure I never called your answer trash. I raised what I believe is a quite objective critique, that your answer will visually appear to solve the question, but in fact does not do what was asked for. I stand by that post, but feel forced to delete responses to any you delete. I would urge you not to urge users to delete their comments critiquing your solutions. And if ever you feel the need to state in a comment that you will delete it, I urge you to not post it all. $\endgroup$
    – jVincent
    Commented Nov 8, 2012 at 15:31
  • $\begingroup$ @MarkMcClure This point has been raised in cases where comments suggesting improvements lead to the improvement being implemented and therefore becoming moot. Not in cases where flaws are pointed out and the author argues back that since he's answer was accepted the flaw should be ignored. If you where to improve you answer based on the comment, then it would be moot and deletion would be natural. And again urging other users to delete comments because they don't suit you is in bad tasted in any case, as is posting comments with immediate deletion in mind. In such cases you should use the chat $\endgroup$
    – jVincent
    Commented Nov 8, 2012 at 15:45
6
$\begingroup$

If you only want to remove one button, the solution is easy:

list = {Button[1], Button[2, list = Delete[list, 2]], Button[3]};
Dynamic@list

If you want to remove multiple unique buttons, you have to use some kind of identification for each button other than the actual position in the list, as that is changed when one of them is removed. Here I use a $position \rightarrow button$ identifier:

list2 = (# -> Button[#, list2 = DeleteCases[list2, _[#, _], 1]]) & /@ Range@4;
Dynamic@(Last /@ list2)

After v10, it is even simpler with associations:

a = AssociationMap[Button[#, a = KeyDrop[a, #]] &, Range@4];
Dynamic@Values@a
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.