Frage

Ich habe gründlich gesucht (zumindest glaube ich das) und keine Antwort auf mein Problem gefunden. Deshalb möchte ich Sie um Hilfe bitten. Ich versuche festzustellen, wann ein Benutzer mit der rechten Maustaste auf eine Zeile in meiner Baumansicht (Liste der Benutzer) klickt, und dann ein Popup-Fenster mit Optionen zum Bearbeiten und Löschen anzuzeigen.

So sieht meine App bisher aus

Hier ist der Code, der die treeView generiert:

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.

Ich habe bereits versucht, das Beispiel unter http://www.muitovar.com zu verwenden/gtk2hs/chap7-2.html führte jedoch zu einem Kompilierungsfehler (eventButton wird mit einem Argument verwendet, während keines erforderlich ist).

Jede Hilfe wäre sehr dankbar :) Prost

War es hilfreich?

Lösung

Okay, es scheint, ich werde der erste sein, der eine Antwort auf meine eigene Frage findet :)

(1) Zunächst das Beispiel unter http://www.muitovar.com /gtk2hs/chap7-2.html hat bei mir nicht funktioniert, da Sie in gtk2hs zwei eventButton-Funktionen haben und die aus Graphics.UI.Gtk.Gdk.Events verwenden müssen. Sie müssen also am Anfang der Datei Folgendes hinzufügen:

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

und fügen Sie dann das Präfix Ev. zu eventButton, RightButton und eventSent hinzu. Es wird jetzt funktionieren :)

(2) So reagieren Sie auf Rechtsklicks auf die treeView-Zeile:

Nachdem ich das oben genannte Problem gelöst hatte, stieß ich auf dieses Beispiel, in dem es gezeigt wird So reagieren Sie auf die Auswahl einer Zeile in treeView. Also habe ich diese beiden Lösungen gemischt und mir so etwas ausgedacht (der größte Teil des Codes stammt aus dem Treeview-Beispiel mit einigen meiner Optimierungen):

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)

Ich hoffe, es ist hilfreich für jemanden :)

Prost

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top