捕获树视图行上的右键单击事件[haskell gtk2hs]

时间:2012-02-21 19:29:40

标签: user-interface haskell glade right-click gtk2hs

我已经彻底搜查过(至少我相信)并且我没有找到任何问题的答案,所以我想请求你帮忙。 我正在尝试确定用户何时右键单击treeView(用户列表)中的行,然后显示一个弹出窗口,其中包含用于编辑和删除它们的选项。

Here's我的应用程序到目前为止的样子

以下是生成treeView的代码:

import Graphics.UI.Gtk
import System.Glib.Signals (on)
import Graphics.UI.Gtk.Glade
import Graphics.UI.Gtk.ModelView as New
import SzuDB

data GUI = GUI {
                mainWindow :: Window,
                --Buttony
                dodajUczBt :: Button,
                cancelAddUczBt :: Button,
                zapiszUczBtn :: Button,
                --TreeView
                listaUczView :: TreeView,
                -- Dialogi
                dodajUzDialog :: Dialog,
                -- Entry
                nImie :: Entry,
                nNazwisko :: Entry,
                nWiek :: SpinButton,
                lblLiczbaUcz :: Label

               }

-- Różne listy

data ListStores = ListStores { uczestnicy :: ListStore Uczestnik }


main = do
        initGUI

        dbh <- connect "szu.db"

        gui <- loadGlade "szu.glade" dbh

        -- lapiemy uzytkownikow
        uczestnicy <- getAllUsers dbh

        labelSetText (lblLiczbaUcz gui) $ "Liczba uczestników: "++ show (length uczestnicy)

        listaUczestnikow <- New.listStoreNew uczestnicy
        New.treeViewSetModel (listaUczView gui) listaUczestnikow
        wyswietlUczestnikow (listaUczView gui) listaUczestnikow

        let liststore = ListStores $ listaUczestnikow

        loadGUIEvents gui dbh liststore


        widgetShowAll (mainWindow gui)
        mainGUI

--      loadGlade etc.

wyswietlUczestnikow view uczestnik = do
      New.treeViewSetHeadersVisible view True

      -- add a couple columns
      renderer1 <- New.cellRendererTextNew
      col1 <- New.treeViewColumnNew
      New.treeViewColumnPackStart col1 renderer1 True
      New.cellLayoutSetAttributes col1 renderer1 uczestnik $ \row -> [ New.cellText := imie row ]
      New.treeViewColumnSetTitle col1 "Imię"
      New.treeViewAppendColumn view col1

      renderer2 <- New.cellRendererTextNew
      col2 <- New.treeViewColumnNew
      New.treeViewColumnPackStart col2 renderer2 True
      New.cellLayoutSetAttributes col2 renderer2 uczestnik $ \row -> [ New.cellText := nazwisko row ]
      New.treeViewColumnSetTitle col2 "Nazwisko"
      New.treeViewAppendColumn view col2

      renderer3 <- New.cellRendererTextNew
      col3 <- New.treeViewColumnNew
      New.treeViewColumnPackStart col3 renderer3 True
      New.cellLayoutSetAttributes col3 renderer3 uczestnik $ \row -> [ New.cellText := show (wiek row) ]
      New.treeViewColumnSetTitle col3 "Wiek"
      New.treeViewAppendColumn view col3

--
-- ladujemy wydarzenia
--

-- loadGuiEvents etc.

我已经尝试在http://www.muitovar.com/gtk2hs/chap7-2.html使用该示例但是它导致编译错误(它表示eventButton与一个参数一起使用,而它不需要)。

任何帮助将不胜感激:) 干杯

1 个答案:

答案 0 :(得分:4)

好吧,我似乎是第一个为自己的问题找到答案的人:)

(1)首先http://www.muitovar.com/gtk2hs/chap7-2.html上的示例对我不起作用,因为你在gtk2hs中有两个eventButton函数,你必须使用Graphics.UI.Gtk.Gdk.Events中的函数。所以你必须在文件的开头添加:

import Graphics.UI.Gtk.Gdk.Events as Ev

然后将Ev.前缀添加到eventButtonRightButtoneventSent。它现在可以工作了:))

(2)如何响应treeView行上的右键单击:

解决了上述问题后,我偶然发现了this示例,其中显示了如何响应在treeView中选择行。所以我混合了这两个解决方案并提出了类似的东西(大部分代码都来自treeview示例,其中有一些我的调整):

module Main where

 {- an example how to select from a list
   not satisfactory yet:
       - there should be a simpler way to render a simple list
       - i could not convert the model i got back to a list 
           from which to get the value

       - the interface offers a great number of functions 
           and it is very difficult to find which ones are 
           really needed for simple tasks
  -}

import Graphics.UI.Gtk
import Graphics.UI.Gtk.ModelView as Model
import Graphics.UI.Gtk.Gdk.Events as Ev

main :: IO ()
main = do
   initGUI       -- is start
   window <- windowNew

   list <- listStoreNew ["Vince", "Jhen", "Chris", "Sharon"]

   treeview <- Model.treeViewNewWithModel list
   Model.treeViewSetHeadersVisible treeview True

           -- there should be a simpler way to render a list as the following!
   col <- Model.treeViewColumnNew
   Model.treeViewColumnSetTitle col "colTitle"
   renderer <- Model.cellRendererTextNew
   Model.cellLayoutPackStart col renderer False
   Model.cellLayoutSetAttributes col renderer list
           $ \ind -> [Model.cellText := ind]
   Model.treeViewAppendColumn treeview col

   --tree <- Model.treeViewGetSelection treeview
   --Model.treeSelectionSetMode tree  SelectionSingle
   --Model.onSelectionChanged tree (oneSelection list tree)

   set window [ windowDefaultWidth := 100
               , windowDefaultHeight := 200
               , containerChild := treeview
              ]

   -- here comes the right-click popup       

   eda <- actionNew "EDA" "Edit" Nothing Nothing
   pra <- actionNew "PRA" "Process" Nothing Nothing
   rma <- actionNew "RMA" "Remove" Nothing Nothing
   saa <- actionNew "SAA" "Save" Nothing Nothing

   agr <- actionGroupNew "AGR1" 
   mapM_ (actionGroupAddAction agr) [eda,pra,rma,saa]

   uiman <- uiManagerNew
   uiManagerAddUiFromString uiman uiDecl
   uiManagerInsertActionGroup uiman agr 0

   maybePopup <- uiManagerGetWidget uiman "/ui/popup"
   let pop = case maybePopup of 
            (Just x) -> x
            Nothing -> error "Cannot get popup from string"

   onButtonPress treeview (\x -> if (Ev.eventButton x) == Ev.RightButton
                                 then do 
                               menuPopup (castToMenu pop) Nothing
                               return (Ev.eventSent x)
                                 else return (Ev.eventSent x))

   mapM_ (prAct treeview list) [eda,pra,rma,saa]    


   onDestroy window mainQuit
   widgetShowAll window
   mainGUI
   return ()

uiDecl = "<ui> \
\          <popup>\
\            <menuitem action=\"EDA\" />\
\            <menuitem action=\"PRA\" />\
\            <menuitem action=\"RMA\" />\
\            <separator />\
\            <menuitem action=\"SAA\" />\
\          </popup>\
\        </ui>"   

-- Handle the right-click. You can write a function that'll respond to various 
-- actions, like for example: handleAction "EDA" = do something, etc.    

prAct treeview list a = onActionActivate a $ do 
        name <- actionGetName a
            -- getting the selected row

        tree <- Model.treeViewGetSelection treeview

        -- you can also use treeSelectionGetSelected to get the Iter object
            -- and then convert it to Int by using listStoreIterToIndex and so get
            -- the ListStore item at given index

          sel <- Model.treeSelectionGetSelectedRows tree
        let s = head  (head sel)
        v <- Model.listStoreGetValue list s
        putStrLn ("Action Name: " ++ name ++ " | Item: " ++ v)

我希望它对某人有帮助:)。

干杯