I'm having difficulty getting widgets to space properly with GTK, I'm trying to make a simple window that displays a TextView in the majority of the window, and has a little bar at the top with a few buttons. I'm thinking something like this:
------------------------------
- -
------------------------------
- -
- -
- -
- -
- -
------------------------------
But GTK is actually giving me something more like this:
-----------------------------
- -
- -
- -
-----------------------------
- -
- -
- -
-----------------------------
I don't want the respective boxes to be split in half like that. How can I fix my code?
import Graphics.UI.Gtk
main :: IO ()
main = do
initGUI
window <- windowNew
windowBox <- vBoxNew True 2
menuBox <- hBoxNew True 2
buttonOne <- buttonNewWithLabel "Button 1"
buttonTwo <- buttonNewWithLabel "Button 2"
textBuf <- textBufferNew Nothing
textView <- textViewNewWithBuffer textBuf
textBufferSetText textBuf "some text"
boxPackStart menuBox buttonOne PackNatural 0
boxPackStart menuBox buttonTwo PackNatural 0
boxPackStart windowBox menuBox PackNatural 0
boxPackStart windowBox textView PackGrow 0
set window [containerChild := windowBox]
widgetShowAll window
mainGUI
The "windowBox" is being created with homogeneous set to True. Simply setting this to False will give the desired result:
windowBox <- vBoxNew False 2
See: http://hackage.haskell.org/package/gtk-0.12.3/docs/Graphics-UI-Gtk-Layout-VBox.html
Related
i'm working on a gtk proyect using haskell. I have a table and a textview in an horizontalBox, and i need to scroll this table at the same time as the textview. I've tried some combinations but i couldn't do it.
This is mi code with the scrollingWindow working only for the textView.
vb <- vBoxNew False 0
containerAdd window vb
boxPackStart vb toolbar PackNatural 2
hseparator <- hSeparatorNew
boxPackStart vb hseparator PackNatural 2
horizontalBox <- hBoxNew False 5
sw <- scrolledWindowNew Nothing Nothing
containerAdd vb horizontalBox
table<- tableNew totalRows 1 True
tableGetColSpacing table 0
widgetSetSizeRequest table 50 675
containerAdd horizontalBox table
textview <- textViewNew
textViewSetWrapMode textview WrapChar
widgetSetSizeRequest textview 700 400
containerAdd sw textview
containerAdd horizontalBox sw
I'm working on a program that contains a text editor on it and will be used for programming (which means that the font is monospaced and has the same size in the entire text). As such, it would be useful if it were possible to see the number of each line (paragraph, not display line) at the side of the TextView widget.
In another question (GTK+ line numbering for Text View), it was said that the SourceView widget does the job, but this widget doesn't seem to exist in gtk2hs, so I'm stuck with TextView.
Does the library offer a simple solution to this problem, or do I have to do it the hard way?
The minimalist code for using a SourceView with numbered lines with Haskell and Gtk2Hs is :
import Graphics.UI.Gtk
import Graphics.UI.Gtk.SourceView
main :: IO ()
main= do
initGUI
window <- windowNew
set window [ windowTitle := "SourceView"
, windowDefaultWidth := 100
, windowDefaultHeight := 100
, windowResizable :=True ]
sview <- sourceViewNew
sourceViewSetShowLineNumbers sview True
containerAdd window sview
onDestroy window mainQuit
widgetShowAll window
mainGUI
I need entry controls to automatically select-all text when they receive focus. If you run the code and press tab to switch focus between the two controls, all of the text in the control is automatically selected. I need the same behavior when using the mouse to select the other control. My question is: what GTK event is signaled when an entry control is clicked with the mouse?
import Graphics.UI.Gtk
main :: IO ()
main = do
initGUI
vbox <- vBoxNew False 4
window <- windowNew
set window [ containerBorderWidth := 8,
containerChild := vbox ]
mkEntry "Entry 1" vbox
mkEntry "Entry 2" vbox
onDestroy window mainQuit
widgetShowAll window
mainGUI
mkEntry :: String -> VBox -> IO Entry
mkEntry txt vbox = do
entry <- entryNew
entrySetText entry txt
boxPackStart vbox entry PackNatural 0
-- selects all text when tabbing into the control
entry `on` entryActivate $ do editableSelectRegion entry 0 (-1)
return entry
The main problem is that the click itself causes the entry selection to be changed by GTK+ itself. I got this working by
Using focusInEvent as the trigger
Changing the selection in an idle callback, once everything is sufficiently "calmed down"
Put together:
-- selects all text when tabbing into the control
on entry focusInEvent $ do
liftIO $ flip idleAdd priorityDefaultIdle $ do
editableSelectRegion entry 0 (-1)
return False
return True
I have menus created with Glade in my gtk2hs application. Is it possible to use this in my Haskell code to write actions for each activated menu item? Is there a simple example somewhere or project on Hackage that can be used as an illustrative example?
The only menu example I was able to find http://www.muitovar.com/gtk2hs/chap7-1.html does not seem to help to work with Gtk Builder XML.
Here two examples from an application of mine. In main, I bind the GTK widgets to variables and those to callback functions that I implement in other modules.
--To load the Glade file:
gui <- builderNew
builderAddFromFile gui "myGUI.glade"
-- To close the application:
-- bind the window "mainWindow" (defined in the Glade file) to a variable
mainWindow <- builderGetObject gui castToWindow "mainWindow"
-- bind the menu item "menu_Quit" (defined in the Glade file) to a variable
mQuit <- builderGetObject gui castToMenuItem "menu_Quit"
-- bind the menu item to the GTK function "widgetDestroy"
on mQuit menuItemActivate $ widgetDestroy mainWindow
-- bind mainWindow's event "objectDestroy" to the GTK function "mainQuit"
on mainWindow objectDestroy mainQuit
-- To call a function when the user selects another menu item, say "menu_About":
-- bind the menu item to a variable
mAbout <- builderGetObject gui castToMenuItem "menu_About"
-- make the menu item show the About Dialog (defined in the Glade file)
on mAbout menuItemActivate $ do
aboutDialog <- builderGetObject gui castToDialog "aboutDialog"
set aboutDialog [ widgetVisible := True ]
dialogRun aboutDialog
set aboutDialog [ widgetVisible := False ]
You could place the do block in a function, maybe in a module where you define all your responses to GTK events:
showAboutDialog :: Builder -> IO ()
showAboutDialog gui = [insert do block here]
Then you could substitute the do block after menuItemActivate with just:
on mAbout menuItemActivate $ showAboutDialog gui
Note that I pass the Builder object to showAboutDialog because that function needs to get the dialog from the Glade file.
I'm writing a simple calculator in GTK using Haskell and the gtk2hs bindings.
I'm trying to implement a Basic/Scientific view like in windows calculator using Glade.
I've got a GTKTable of buttons, but when I try and hide some of them a blank space is left where the buttons where. To hide the buttons I'm have some code like this:
bSqrt <- xmlGetWidget xml castToButton "bSqrt"
widgetHide bSqrt
But when I hide the four buttons I want I have a gap like below on the right hand side:
I'm new to GTK and I couldn't find layout managers like you get in java swing. Is there an easier way to do this? Can I somehow invoke the layout manager to resize the buttons for me? I haven't been able to find a method for doing this in the documentation.
Thanks in advance,
Consider using a nested combination of HBox and VBox to achieve a table-like effect. Calling widgetHideAll on a VBox of "scientific" buttons will hide that column and refresh the display as desired.
import Control.Monad (forM_)
import Data.IORef as IORef
import qualified Graphics.UI.Gtk as Gtk
data Mode = Basic | Scientific
main = do
Gtk.initGUI
window <- Gtk.windowNew
outerVbox <- Gtk.vBoxNew False 0
-- Create a "table" of buttons as an HBox of VBoxes.
hbox <- Gtk.hBoxNew True 5
-- Load the "table" with dummy 'basic' buttons.
forM_ [0..2] $ \i -> do
vbox <- Gtk.vBoxNew False 5
forM_ [0..2] $ \j -> do
dummy <- Gtk.buttonNewWithLabel $ show (3*i+j :: Int)
Gtk.boxPackStartDefaults vbox dummy
Gtk.boxPackStartDefaults hbox vbox
-- Load rightmost column with 'scientific' buttons.
scibox <- Gtk.vBoxNew False 5
forM_ [0..2] $ \j -> do
dummy <- Gtk.buttonNewWithLabel $ "sci" ++ show (j :: Int)
Gtk.boxPackStartDefaults scibox dummy
Gtk.boxPackStartDefaults hbox scibox
-- Begin in Scientific mode.
let mode = Scientific
modeRef <- IORef.newIORef mode
-- Create a mode-toggling Button.
button <- Gtk.buttonNewWithLabel $ getButtonText mode
Gtk.on button Gtk.buttonActivated $
toggleMode button modeRef scibox
-- Pack the "table" and button vertically into window.
Gtk.boxPackStartDefaults outerVbox hbox
Gtk.boxPackStartDefaults outerVbox button
Gtk.containerAdd window outerVbox
-- Standard Gtk stuff.
Gtk.onDestroy window Gtk.mainQuit
Gtk.widgetShowAll window
Gtk.mainGUI
getButtonText Basic = "Switch to Scientific"
getButtonText Scientific = "Switch to Basic"
toggleMode button modeRef scibox = do
mode <- IORef.readIORef modeRef
case mode of
Basic -> do
IORef.writeIORef modeRef Scientific
Gtk.buttonSetLabel button $ getButtonText Scientific
Gtk.widgetShowAll scibox
Scientific -> do
IORef.writeIORef modeRef Basic
Gtk.buttonSetLabel button $ getButtonText Basic
Gtk.widgetHideAll scibox