Nous avons vu presque tout ce qu'il y a à voir sur le bouton widget. C'est assez simple. Cependant, il y a plus d'une façon de créer un bouton. Vous pouvez voir buttonNewWithLabel
ou buttonNewWithMnemonic
pour créer un bouton avec un label, utiliser buttonNewFromStock
pour créer un bouton contenant une image et un texte, ou utiliser buttonNew
pour créer un bouton vide. Libre à vous ensuite d'empaqueter ou dessiner dans ce nouveau bouton. Pour faire cela, créez une nouvelle boite, et empaquetez vos objets dans cette boite en utilisant boxPackStart
(ou boxPackEnd), et ensuite utilisez containerAdd
pour empaqueter le bouton dans la boite.
buttonNewWithMnemonic
et buttonNewFromStock
prennent tous les deux une chaîne de caractère comme premier argument. Utilisez le caractère underscore pour marquer le caractère comme mnémonique (raccourcis au clavier). En appuyant sur Alt et cette touche, cela active le bouton. Dans la seconde fonction, la chaîne est un stockId
, c'est à dire l'identifiant d'une liste prédéfinie d'images avec des labels.
Voici un exemple d'utilisation de buttonNew
pour créer un bouton avec une image et un label.
import Graphics.UI.Gtk
main :: IO ()
main = do
initGUI
window <- windowNew
set window [windowTitle := "Pix",
containerBorderWidth := 10]
button <- buttonNew
onClicked button (putStrLn "button clicked")
box <- labelBox "info.xpm" "cool button"
containerAdd button box
containerAdd window button
widgetShowAll window
onDestroy window mainQuit
mainGUI
labelBox :: FilePath -> String -> IO HBox
labelBox fn txt = do
box <- hBoxNew False 0
set box [containerBorderWidth := 2]
image <- imageNewFromFile fn
label <- labelNew (Just txt)
boxPackStart box image PackNatural 3
boxPackStart box label PackNatural 3
return box
La fonction labelBox peut être utilisée pour empaqueter des images et des labels dans n'importe quel widget de type conteneur. L'image provient d'un fichier en utilisant imageNewFromFile
et le label vient de labelNew qui prend comme argument Maybe String. Nothing signifie pas de label.
Le widget Button possède les signaux suivant, qui sont assez explicites:
onPressed
:
émis lorsque le bouton est pressé.
onReleased
:
émis lorsque le bouton est relâché.
onClicked
:
émis lorsque le bouton est pressé puis relâché.
onEnter
:
émis lorsque le curseur passe sur le bouton.
onLeave
:
émis lorsque le curseur sort du bouton.
Les boutons bascules sont dérivés des boutons normaux et sont très similaires, sauf qu'ils seront toujours dans un état ou dans l'autre, modifiés par un clic. Lorsque vous cliquez dessus, ils se figent à l'état "pressé" et si vous cliquez à nouveau dessus ils se relâchent et restent à l'état "relâché".
Les boutons bascules sont les bases pour les cases à cocher et les boutons radio aussi, les appels utilisés pour les bascules sont hérités par les boutons radio et les cases à cocher. Nous les aborderons plus loin.
Créons un nouveau bouton bascule:
toggleButtonNew :: IO ToggleButton
toggleButtonNewWithLabel :: String -> IO Togglebutton
toggleButtonNewWithMnemonic :: String -> IO ToggleButton
Comme on pouvait l'imaginer, ils fonctionnent de façon identique aux appels du bouton "normal". Le premier crée un bouton bascule vide, et le dernier un bouton avec un label directement empaqueté dedans. De la même manière on peut créer un mnémonique avec le caractère underscore (tiret bas) devant le caractère voulu.
Pour connaître l'état du widget (ainsi que pour les cases à cocher et les boutons radio), on utilise:
toggleButtonGetActive :: ToggleButtonClass self => self -> IO Bool
Cela retourne True si le bouton est "pressé", et False s’il est "relaché"
Pour forcer l'état d'un bouton bascule ainsi que les boutons radio et les cases à cocher, on utilise la fonction:
toggleButtonSetActive :: ToggleButtonClass self => self -> Bool -> IO ()
L'appel ci-dessus peut être utilisé pour définir l'état du bouton bascule et ses descendants, les boutons radio et les cases à cocher. Le premier argument est le bouton dont on veut modifier l'état et le second, l'état du bouton que l'on veut lui imposer, True pour l'état "pressé" et False pour l'état relâché.
Notez que lorsque vous utilisez la fonction toggleButtonSetActive
et que l'état est modifié, cela cause l'émission des signaux onClicked
et onToggled
depuis le bouton.
Les cases à cocher héritent de plusieurs propriétés et fonctions des boutons bascules, mais ont un aspect un peu différent. Plutôt que d'être des boutons avec du texte à l'intérieur, ce sont de petites cases avec du texte à leur droite. Elles sont souvent utilisées dans des applications pour activer ou non certaines options.
Les fonctions de création sont similaires au bouton classique.
checkButtonNew :: IO CheckButton
checkButtonNewWithLabel :: String -> IO Checkbutton
checkButtonNewWithMnemonic :: String -> IO CheckButton
La fonction checkButtonNewWithLabel
crée une case à cocher avec un label à côté d'elle.
CheckButton
est une instance de ToggleButtonClass
et le signal onToggled
est utilisé lorsq'un CheckButton
est coché ou décoché, comme le bouton bascule.
Les boutons radio sont similaires aux cases à cocher sauf qu'ils sont regroupés de telle sorte qu'un seul peut être sélectionné à la fois. Ils sont adaptés pour les choix dans une courte liste d'options. Créer un nouveau bouton radio se fait avec un de ces appels:
radioButtonNew :: IO RadioButton
radioButtonNewWithLabel :: String -> IO RadioButton
radioButtonNewWithMnemonic :: String -> IO RadioButton
radioButtonNewFromWidget :: RadioButton -> IO RadioButton
radioButtonNewWithLabelFromWidget :: RadioButton -> String -> IO RadioButton
radioButtonNewWithMnemonicFromWidget :: RadioButton -> String -> IO RadioButton
Vous noterez la présence d'un argument supplémentaire dans les trois dernières fonctions. Il est utilisé pour lier les nouveaux boutons à ceux déjà créés plus tôt dans un groupe.
C'est aussi une bonne idée de définir explicitement quel est le bouton qui doit être "pressé" par défaut avec:
toggleButtonSetActive :: ToggleButtonClass self => self -> Bool -> IO ()
Ceci est décrit dans la section des boutons bascules et fonctionne de la même manière. Une fois que les boutons radio sont groupés ensemble, seulement un bouton du groupe peut être activé à la fois. Si l'utilisateur clique sur un bouton radio, et ensuite sur un autre, le premier bouton radio émettra d'abord un signal onToggled
(pour signaler le passage à l'état inactif), puis le second émettra un signal onToggled
(pour signaler le passage à l'état actif).
L'exemple suivant crée un groupe de boutons radio avec trois boutons.Lorsque l'utilisateur presse un des boutons radio, ceux qui sont déclenchés écriront sur la sortie standard stdout en utilisant putStrLn
dans la fonction setRadioState
définie plus loin.
import Graphics.UI.Gtk
main :: IO ()
main = do
initGUI
window <- windowNew
set window [windowTitle := "Radio Button", containerBorderWidth := 5,
windowDefaultWidth := 200, windowDefaultHeight := 150]
box1 <- vBoxNew False 0
containerAdd window box1
box2 <- vBoxNew False 10
containerSetBorderWidth box2 10
boxPackStart box1 box2 PackNatural 0
button1 <- radioButtonNewWithLabel "button 1"
boxPackStart box2 button1 PackNatural 0
button2 <- radioButtonNewWithLabelFromWidget button1 "button 2"
boxPackStart box2 button2 PackNatural 0
button3 <- radioButtonNewWithLabelFromWidget button2 "button 3"
boxPackStart box2 button3 PackNatural 0
toggleButtonSetActive button2 True
onToggled button1 (setRadioState button1)
onToggled button2 (setRadioState button2)
onToggled button3 (setRadioState button3)
sep <- hSeparatorNew
boxPackStart box1 sep PackNatural 0
box3 <- vBoxNew False 10
containerSetBorderWidth box3 10
boxPackStart box1 box3 PackNatural 0
closeb <- buttonNewWithLabel "close"
boxPackStart box3 closeb PackNatural 0
onClicked closeb mainQuit
widgetShowAll window
onDestroy window mainQuit
mainGUI
setRadioState :: RadioButton -> IO ()
setRadioState b = do
state <- toggleButtonGetActive b
label <- get b buttonLabel
putStrLn ("State " ++ label ++ " now is " ++ (show state))