質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.02%
Haskell

Haskellは高い機能性をもった関数型プログラミング言語で、他の手続き型プログラミング言語では難しいとされている関数でも容易に行うことができます。強い静的型付け、遅延評価などに対応しています。

Q&A

解決済

haskell-giのtreeviewで複数列を扱いたい

apo
apo

総合スコア348

Haskell

Haskellは高い機能性をもった関数型プログラミング言語で、他の手続き型プログラミング言語では難しいとされている関数でも容易に行うことができます。強い静的型付け、遅延評価などに対応しています。

1回答

0グッド

0クリップ

639閲覧

投稿2021/06/21 00:51

前提・実現したいこと

HaskellでGUIプログラミング(haskell-gi)を勉強しています。
サンプルプログラムを色々探して、表をtreeviewで表示できましたが単列の表となっております。
複数列(項目)の表を表示したいのですが、どのようにコーディングしたらよいのかわかりません。

該当のソースコード

Haskell

1{-# LANGUAGE OverloadedStrings #-} 2{-# LANGUAGE OverloadedLabels #-} 3{-# LANGUAGE ScopedTypeVariables #-} 4 5module Main where 6 7import Data.GI.Base 8import Control.Monad 9import Data.Text (Text, pack) 10import Data.GI.Base.GType (gtypeString) 11import qualified GI.Gtk as Gtk 12import qualified GI.Pango as Pango 13 14demoList::[Text] 15demoList = ["1 James","2 John","3 Robert","4 Michael","5 William","6 David","7 Richard","8 Joseph","9 Thomas","10 Charles"] 16 17setValuesToListStore :: Gtk.ListStore -> [Text] -> Int -> IO Gtk.TreeIter 18setValuesToListStore lsts artx counter = do 19 let stT::Text = artx !! counter 20 gv <- toGValue (Just stT) 21 if (counter == (length artx)-1) then Gtk.listStoreInsertWithValuesv lsts (-1) [0] [gv] 22 else do 23 m <- (Gtk.listStoreInsertWithValuesv lsts (-1) [0] [gv]) 24 setValuesToListStore lsts artx (counter + 1) 25 26main :: IO () 27main = do 28 void $ Gtk.init Nothing 29 30 window <- new Gtk.Window [] 31 on window #destroy Gtk.mainQuit 32 33 column <- new Gtk.TreeViewColumn [ #title := "Column name" ] 34 render <- new Gtk.CellRendererText [ #ellipsize := Pango.EllipsizeModeEnd 35 , #editable := False ] 36 #packStart column render True 37 #addAttribute column render "text" 0 38 39 mlistStore <- Gtk.listStoreNew [gtypeString] 40 41 setValuesToListStore mlistStore demoList 0 42 43 view <- new Gtk.TreeView[#enableTreeLines := True, #headersVisible := True] 44 lk <- (Gtk.treeViewSetModel view (Just mlistStore)) 45 46 #appendColumn view column 47 48 #expandAll view 49 #add window view 50 #showAll window 51 52 Gtk.main

全てのソースコード

試したこと

上記コード上の数字をいじってみましたが複数列にはなりませんでした。
haskell-giの基になるGTKを調べてみると、列の設定にはListStoreを使っているようで、haskell-giのListStoreを調べるとhttps://hackage.haskell.org/package/gi-gtk-4.0.4/docs/GI-Gtk-Objects-ListStore.htmlだとわかりましたが、具体的にどのようにコーディングしたらよいのかわかりませんでした。
「haskell-gi treeview liststore」などでググったり、GithubやQiitaを見てみましたが参考になるようなサイトやコードは見つけられませんでした。

補足情報(FW/ツールのバージョンなど)

lts: 18.0
stack: Version 2.7.1
haskell-gi: 0.25
OS: ArchLinux
GNOME: GNOME Shell 40.2

よろしくお願いします。

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答1

1

ベストアンサー

Haskellは知りません。
とりあえずHaskell抜きでお話します。

TreeViewウィジェットは、いろんなクラスを元に動作しています。

まぁこれ全部を使うわけではないのですが、とりあえず質問者さんのソースコードで使われているものを抜粋します。

  • GtkTreeView - TreeViewウィジェット本体
  • GtkTreeViewColumn - TreeViewカラム
  • GtkCellRendererText - セルの描画オブジェクト
  • GtkListStore - データモデルオブジェクト

というわけで、列を増やすのであればまず**GtkTreeViewColumnを増やさなければならないのですが、それとともに、データを管理しているのはGtkListStoreですので、GtkListStoreのカラムも増やさなければなりません。**

Haskellは知らない、とは言いましたが、他言語でもGTK+をやっていれば知らない言語でもおおよそ何をやっているかは想像がつくので、軽く説明します。

まず、GtkListStoreについて。

haskell

1 mlistStore <- Gtk.listStoreNew [gtypeString]

GtkListStoreの生成する際に、各カラムの型をカラム数分指定します。
元はカラムが一つしかないので、列を増やすのであれば2つ指定する必要があります

haskell

1setValuesToListStore :: Gtk.ListStore -> [Text] -> Int -> IO Gtk.TreeIter 2setValuesToListStore lsts artx counter = do 3 let stT::Text = artx !! counter 4 gv <- toGValue (Just stT) 5 if (counter == (length artx)-1) then Gtk.listStoreInsertWithValuesv lsts (-1) [0] [gv] 6 else do 7 m <- (Gtk.listStoreInsertWithValuesv lsts (-1) [0] [gv]) 8 setValuesToListStore lsts artx (counter + 1)

gtk_list_store_insert_with_valuesv(HaskellだとGtk.listStoreInsertWithValuesv)で、データモデルであるGtkListStoreにデータを追加します。
一番目の引数にGtkListStoreオブジェクト、二番目に追加する場所(-1であれば最後)を指定します。
三番目と四番目に、「カラム番号」と「そのカラムにセットするデータ値」を指定します。ここも元はカラムが一つしかなかったので各々一つのみしかありませんが、列を増やすのであれば2つ指定します。(他にも方法がありますが、説明を省きます)

次に、GtkTreeViewColumnGtkCellRendererTextについて。

haskel

1 column <- new Gtk.TreeViewColumn [ #title := "Column name" ] 2 render <- new Gtk.CellRendererText [ #ellipsize := Pango.EllipsizeModeEnd 3 , #editable := False ] 4 #packStart column render True 5 #addAttribute column render "text" 0 6 7 #appendColumn view column

ここが表示カラムを追加している箇所です。
複数のカラムを表示するのであれば、上記の処理をその回数分実行しなければなりません。

その際に注意しなければならないのは、gtk_tree_view_column_add_attribute(#addAttribute)です。
最後の「0」は、GtkListStoreの0番目のカラムを参照するという指定になりますから、2番めのカラムは「1」を指定して、1番目のカラムを参照するようにしなければなりません。

Haskellを知らない自分が説明できるのはこの辺りまでですが、参考までに、Pythonで書いたソースコードを載せておきます。

python

1# coding: utf-8 2 3import gi 4gi.require_version('Gtk', '3.0') 5from gi.repository import Gtk, GObject, Pango 6 7demoList = [("1", "James"),("2", "John"),("3", "Robert"),("4", "Michael"),("5", "William"),("6", "David"),("7", "Richard"),("8", "Joseph"),("9", "Thomas"),("10", "Charles")] 8 9def setValuesToListStore(lsts, artx, counter): 10 v0, v1 = artx[counter] 11 gv0 = GObject.Value(GObject.TYPE_STRING, v0) 12 gv1 = GObject.Value(GObject.TYPE_STRING, v1) 13 if counter == len(artx) - 1: 14 lsts.insert_with_valuesv(-1, [0, 1], [gv0, gv1]) 15 else: 16 lsts.insert_with_valuesv(-1, [0, 1], [gv0, gv1]) 17 setValuesToListStore(lsts, artx, counter + 1) 18 19def main(): 20 window = Gtk.Window() 21 window.connect('destroy', Gtk.main_quit) 22 23 column0 = Gtk.TreeViewColumn(title='Column0') 24 render = Gtk.CellRendererText(ellipsize=Pango.EllipsizeMode.END, editable=False) 25 26 column0.pack_start(render, True) 27 column0.add_attribute(render, 'text', 0) 28 29 column1 = Gtk.TreeViewColumn(title='Column1') 30 render = Gtk.CellRendererText(ellipsize=Pango.EllipsizeMode.END, editable=False) 31 32 column1.pack_start(render, True) 33 column1.add_attribute(render, 'text', 1) 34 35 mlistStore = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING) 36 37 setValuesToListStore(mlistStore, demoList, 0) 38 39 view = Gtk.TreeView(enable_tree_lines=True, headers_visible=True) 40 view.set_model(mlistStore) 41 42 view.append_column(column0) 43 view.append_column(column1) 44 45 view.expand_all() 46 window.add(view) 47 window.show_all() 48 49 Gtk.main() 50 51if __name__ == '__main__': 52 main() 53

投稿2021/06/21 12:35

katsuko

総合スコア3255

apo👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

apo

2021/06/23 23:42 編集

pythonのコードを実行してみました、このようなことをしたいです。ご提示頂いたコードを参考にHaskellに組み直してみます。ありがとうございます。
apo

2021/06/23 23:23

ご教示頂いたPythonコードをそのままHaskellに書き直したらできました。 ``` {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedLabels #-} {-# LANGUAGE ScopedTypeVariables #-} module Main where import Data.GI.Base import Control.Monad import Data.Text (Text, pack) import Data.GI.Base.GType (gtypeString) import qualified GI.Gtk as Gtk import qualified GI.Pango as Pango demoList::[(Text, Text)] demoList = [("1","James"),("2","John"),("3","Robert"),("4","Michael"),("5","William"),("6","David"),("7","Richard"),("8","Joseph"),("9","Thomas"),("10"," Charles")] setValuesToListStore :: Gtk.ListStore -> [(Text, Text)] -> Int -> IO Gtk.TreeIter setValuesToListStore lsts artx counter = do let (stT::Text, stT2::Text) = artx !! counter gv <- toGValue (Just stT) gv2 <- toGValue (Just stT2) if (counter == (length artx)-1) then Gtk.listStoreInsertWithValuesv lsts (-1) [0, 1] [gv, gv2] else do m <- (Gtk.listStoreInsertWithValuesv lsts (-1) [0, 1] [gv, gv2]) setValuesToListStore lsts artx (counter + 1) main :: IO () main = do void $ Gtk.init Nothing window <- new Gtk.Window [] on window #destroy Gtk.mainQuit column <- new Gtk.TreeViewColumn [ #title := "Column name" ] render <- new Gtk.CellRendererText [ #ellipsize := Pango.EllipsizeModeEnd , #editable := False ] #packStart column render True #addAttribute column render "text" 0 column2 <- new Gtk.TreeViewColumn [ #title := "Column name2" ] render <- new Gtk.CellRendererText [ #ellipsize := Pango.EllipsizeModeEnd , #editable := False ] #packStart column2 render True #addAttribute column2 render "text" 1 mlistStore <- Gtk.listStoreNew [gtypeString, gtypeString] setValuesToListStore mlistStore demoList 0 view <- new Gtk.TreeView[#enableTreeLines := True, #headersVisible := True] lk <- (Gtk.treeViewSetModel view (Just mlistStore)) #appendColumn view column #appendColumn view column2 #expandAll view #add window view #showAll window Gtk.main ``` [https://github.com/ringo-apo/haskell-gi_treeview/blob/main/app/Main.hs](https://github.com/ringo-apo/haskell-gi_treeview/blob/main/app/Main.hs) ありがとうございます!
apo

2021/06/24 00:30

細かな解説もすごく勉強になりました。ありがとうございます。

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.02%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Haskell

Haskellは高い機能性をもった関数型プログラミング言語で、他の手続き型プログラミング言語では難しいとされている関数でも容易に行うことができます。強い静的型付け、遅延評価などに対応しています。