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.
Related
I was trying to write a program. I'm using tkinter and I've created a label and a menu bar. I would like to open a PDF from the menu bar (HELP --> Instruction for use), but I don't know how. I've tried the module filedialog.askopenfile but it is not appropriate for me because I want to dispay a specific PDF on screen and not browse through them.
Here is the code for the menu bar:
subMenu = Menu (menubar, tearoff = 0)
menubar.add_cascade (label = "Help")
subMenu.add_command (label =" Instruction for use", command = help)
def help ():
I have been trying to develop keyboard and touch indexed game, playable on PC browsers and phone. How can I index?
Tried some samples in Godot Sample menu. None of them helped. Either for keyboard or touch screen
func _unhandled_input(event):
if event is InputEventScreenTouch:
if event.pressed:
# Down
if !_os2own.has(event.index): # Defensively discard index if already known
var ptr_id = _find_free_pointer_id()
state[ptr_id] = event.position
_os2own[event.index] = ptr_id
else:
# Up
if _os2own.has(event.index): # Defensively discard index if not known
var ptr_id = _os2own[event.index]
state.erase(ptr_id)
_os2own.erase(event.index)
return true
Need to touching and clicking game. Both for APK and HTML
For simple input handling (e.g. pressed and released) you'll want to map input to actions. You can add actions via "Project Settings -> Input Map" or InputMap singleton.
From the "Project Settings -> Input Map" you can map mouse, keyboard, and controller input to actions.
For touch screens you can use a TouchScreenButton and set it's action. When pressed or released it will send that action event down the scene tree via _input(). TouchScreenButton hides the logic needed to write in _input() to handle presses and releases, such as: is this finger index new? which finger index moved last frame? is this finger area in bounds of input area? and more. While also having the advantage over a plain Button by also emitting an action and can have no texture as it uses a Shape for input detection.
So this creates an one-to-many relationship from actions to inputs like:
my_action -> left mouse button pressed,
-> controller r1 pressed,
-> right half of touch screen pressed,
-> control-shift-f pressed
Using the action
func _input(event):
if not event.is_action('my_action'):
return
if event.is_action_pressed('my_action'):
start_something()
else:
stop_something()
Going further
Since the post specified keyboard and touch input, I only covered press and release input action mapping. However, you can map complex inputs like gestures to actions as well. You can inherit from InputEvent or any of it's subclasses to extend or create a new event. You can map the new event class to an action and then manually process input to find an event. Then you stop the propagation of the event, form the event from your new event class, and then call Input.parse_input_event(my_new_event) to send it down the tree.
Custom Action
# SomeLeafNode.gd
class MyEvent extends InputEvent:
var my_custom_message = 'Hello, World'
func _ready():
InputMap.add_action('my_event')
InputMap.action_add_event('my_event', MyEvent.new())
func _input(event):
# ... logic to see if event could be MyEvent
get_tree().set_input_as_handled()
var my_event = MyEvent.new()
my_event.my_custom_message = 'Caught my event!'
Input.parse_input_event(my_event)
# SomeInputHandlingGameplayNode.gd
func _input(event):
if event.is_action('my_event'):
print(event.my_custom_message) # prints 'Caught my event!'
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'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