开发者

How to do simple ComboBoxEntry in gtk2hs?

I use the code below adapted from a tutorial. It shows the two options in the drop down, but when I select one, it gives the error at the console:

(combo:12158): Gtk-CRITICAL **: IA__gtk_entry_set_text: assertion `text != NULL' failed

import Graphics.UI.Gtk
import Graphics.UI.Gtk.Gdk.EventM
import Graphics.UI.Gtk.Gdk.GC

main = do
  initGUI
  window <- windowNew
  windo开发者_开发技巧w `onDestroy` mainQuit
  windowSetDefaultSize window 800 600
  windowSetPosition window WinPosCenter

  store <- listStoreNew ["one", "two"]
  combo <- comboBoxEntryNewWithModel store
  ren <- cellRendererTextNew
  cellLayoutPackEnd combo ren False
  cellLayoutSetAttributes combo ren store
    (\txt -> [cellText := txt])
  containerAdd window combo

  widgetShowAll window
  mainGUI


You're trying to add a renderer and set it's attributes which is all fine. But you're not telling ComboBoxEntry where the text is that should be eventually edited. The Gtk+ developers have not provisioned for extracting this text using call-back functions which is what Gtk2Hs (and you in your example) does. Instead of callbacks, Gtk+ uses column number to refer to a specific datum in a row of data. Most special functions on Models use column numbers since it is much easier to operate with these in C than callback functions are. In Gtk2Hs you can add column numbers on top of any other attribute mapping. I've modified your example to declare a ColumnId constant (which can use any integer number you haven't yet for a model). Gtk2Hs always uses callback functions, so we have to associate the extraction function id with this column number. The third modification is to tell the ComboBoxEntry to use this column number as it's text source. I've kept the part of your code inserts the text renderer but set it's attribute to a constant. Thus, the text form your store and the constant "<-- your choice" will be displayed in each row.

import Graphics.UI.Gtk
import Graphics.UI.Gtk.Gdk.EventM
import Graphics.UI.Gtk.Gdk.GC

textColumn :: ColumnId String String
textColumn = makeColumnIdString 0

main = do
  initGUI
  window <- windowNew
  window `onDestroy` mainQuit
  windowSetDefaultSize window 800 600
  windowSetPosition window WinPosCenter

  store <- listStoreNew ["one", "two"]
  customStoreSetColumn store textColumn id -- set the extraction function
  combo <- comboBoxEntryNewWithModel store
  comboBoxEntrySetTextColumn combo textColumn -- set which column should be used
  ren <- cellRendererTextNew
  cellLayoutPackEnd combo ren False
  cellLayoutSetAttributes combo ren store
    (\txt -> [cellText := "<-- your choice"])
  containerAdd window combo

  widgetShowAll window
  mainGUI


When you use a ComboBoxEntry, you need to set the Text Column explicitly. In theory you're supposed to be able to call comboBoxEntrySetTextColumn, however I couldn't make this work. I was able to do the following, though:

import Graphics.UI.Gtk
import Graphics.UI.Gtk.Gdk.EventM
import Graphics.UI.Gtk.Gdk.GC
import Control.Monad

main = do
  initGUI
  window <- windowNew
  window `onDestroy` mainQuit
  windowSetDefaultSize window 800 600
  windowSetPosition window WinPosCenter

  combo <- comboBoxEntryNewText
  store <- comboBoxEntrySetModelText combo
  mapM_ (listStoreAppend store) ["one", "two"]

  containerAdd window combo
  widgetShowAll window
  mainGUI

The difference is that when a ComboBoxEntry is created from comboBoxEntryNewText, it's already set up to use a ListStore String with the appropriate text column. It has a renderer too, so you don't need to set that either. The one big drawback is that it also sets the model store, so if you intended to use a store shared with another widget you'll need to create it here.

I suspect that comboBoxEntrySetModelText is mis-named, it looks like it should be "getModelText".


Very thanks to @Axel!

Below updating with new gtk3 libs

import           Control.Monad.IO.Class     (liftIO)
import qualified Data.Text                  as T
import           Graphics.UI.Gtk
import           Graphics.UI.Gtk.Gdk.EventM

textColumn :: ColumnId String T.Text
textColumn = makeColumnIdString 0

main = do
  initGUI
  window <- windowNew
  window `on` deleteEvent $ liftIO mainQuit >> return False
  windowSetDefaultSize window 800 600
  windowSetPosition window WinPosCenter

  store <- listStoreNew ["one", "two"]
  customStoreSetColumn store textColumn (\x -> T.pack $ "1") -- set the extraction function
  combo <- comboBoxNewWithModelAndEntry store
  comboBoxSetEntryTextColumn combo textColumn -- set which column should be used
  ren <- cellRendererTextNew
  cellLayoutPackEnd combo ren False
  cellLayoutSetAttributes combo ren store
    (\txt -> [cellText := "<-- your choice"])
  containerAdd window combo

  widgetShowAll window
  mainGUI
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜