Add and remove widgets dynamically

I want to dynamically add and remove widgets in a wxHaskell application.

My problems:

  • the window can be changed, but when it is done manually, pressing the “bigger” button shows that it quickly returns to the minimum size. Without a call, the windowReLayoutwindow does not resize at all.

  • windowRemoveChildIt looks the way I want, but it is not exported from WXCore, so I assume that it is not intended to be used at this level ( Edit:) . find a way to use it without crashing the program, because it tries to draw into a nonexistent window, even if it first removes it from the layout and then removes it from its parent). But I could not find an alternative. This answer suggests simply hiding the widget, but in my real application, I use a complex custom widget that I would like to garbage collect.

  • the parent / child relationship is already defined when creating widgets, can I do this again for the layout? For example, can I give the panel a layout that automatically applies row 5to all its children without having to rebuild the layout for each change? (If I just remove the children from the layout, but don’t remove them from my parent, they will just be located at the origin, are they controlled by default by default?)

Here is a minimal example showing how I am currently adding widgets and how I tried to remove them.

module Main where

import Graphics.UI.WX

main :: IO ()
main = start $ do
   count <- varCreate 100
   items <- varCreate []
   f <- frame []
   cont <- panel f []

   -- add a button
   more <- button f
      [ text := "more"
      , on command := do
            n <- varGet count
            varSet count (n + 1)
            new <- button cont
                     [ text := show n
                     , on command := print n ]
            is <- varGet items
            let is' = new : is
            varSet items is'
            set cont [ layout := row 5 (map widget is') ]
            windowReLayout f
      ]

   -- remove a button
   less <- button f
      [ text := "less"
      , on command := do
            is <- varGet items
            case is of
               i : is' -> do
                  -- windowRemoveChild f i   -- crash
                  set i [ visible := False ] -- leak
                  set cont [ layout := row 5 (map widget is') ]
                  varSet items is'
                  return ()
               _ -> return ()
      ]

   set f [ layout := margin 5
                   $ column 5 [ row 5 [ widget more
                                      , widget less ]
                              , widget cont ] ]
+4
source share

All Articles