如何在 gtk2hs 中做简单的 ComboBoxEntry?

发布于 2024-10-19 18:22:17 字数 707 浏览 6 评论 0原文

我使用以下改编自教程的代码。它在下拉列表中显示了两个选项,但是当我选择一个时,它会在控制台上给出错误:

(combo:12158): Gtk-CRITICAL **: IA__gtk_entry_set_text: 断言 `text != NULL' 失败

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

main = do
  initGUI
  window <- windowNew
  window `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

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
  window `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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

红尘作伴 2024-10-26 18:22:17

您正在尝试添加渲染器并设置它的属性,这一切都很好。但是您并没有告诉 ComboBoxEntry 最终应该编辑的文本的位置。 Gtk+ 开发人员尚未提供使用回调函数提取此文本的功能,而这正是 Gtk2Hs(以及您在示例中)所做的。 Gtk+ 使用列号来引用一行数据中的特定数据,而不是回调。模型上的大多数特殊函数都使用列号,因为在 C 中使用这些列号比回调函数更容易操作。在 Gtk2Hs 中,您可以在任何其他属性映射之上添加列号。我修改了您的示例以声明 ColumnId 常量(它可以使用您尚未用于模型的任何整数)。 Gtk2Hs总是使用回调函数,因此我们必须将提取函数id与该列号相关联。第三个修改是告诉 ComboBoxEntry 使用此列号作为其文本源。我保留了插入文本渲染器的代码部分,但将其属性设置为常量。因此,来自您的商店的文本和常量“<--您的选择”将显示在每行中。

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

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
风吹短裙飘 2024-10-26 18:22:17

当您使用ComboBoxEntry时,您需要显式设置文本列。理论上你应该能够调用comboBoxEntrySetTextColumn,但是我无法做到这一点。不过,我能够执行以下操作:

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

不同之处在于,当从 comboBoxEntryNewText 创建 ComboBoxEntry 时,它已经设置为使用带有适当文本列的 ListStore String 。它也有一个渲染器,所以你也不需要设置它。一个很大的缺点是它还设置模型存储,因此如果您打算使用与另一个小部件共享的存储,则需要在此处创建它。

我怀疑 comboBoxEntrySetModelText 命名错误,看起来应该是“getModelText”。

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".

蓝眼睛不忧郁 2024-10-26 18:22:17

非常感谢@Axel!

下面使用新的 gtk3 库进行更新

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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文