更高级别的Python GUI工具包,例如为TreeView / Grid传递字典 [英] higher level Python GUI toolkit, e.g. pass dict for TreeView/Grid

查看:120
本文介绍了更高级别的Python GUI工具包,例如为TreeView / Grid传递字典的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用PyGTK开始我的第一个Python宠物项目。虽然它是一个功能非常强大的GUI工具包,看起来非常出色,但我还是有一些宠物。所以我想过转向别的东西,因为它还不是太广泛。浏览 SO python documentation ,但没有得到好的概述。



PyGTK有什么好处:




  • Glade文件

  • self.signal_autoconnect({...})

  • self.get_widget()as __getattr __



然而,这让我感到困扰:


  • 手动gobject.idle_add(lambda:...和False)
  • 没有用于保存应用程序/窗口状态的标准功能

  • TreeView需要数组构建

  • widget.get_selection()。get_selected(),model.get_value(iter,liststore_index)


TreeView :因为这是主界面元素,所以它是最让人分心的。基本上我的应用程序建立了一个要显示的字典列表name = column + row => value。要使用GTK显示它,需要手动转换过程,排序,类型转换。这似乎是一个很大的开销,我希望在这里面向更多的面向对象。 PyGtk在gtk +上有很多抽象,但仍然显得相当低级。我宁愿按原样传递我的字典,并以某种方式预先定义列。 (GtkBuilder可以预定义TreeView列,但这并不能解决数据表示的开销)。

当我在我的TreeView列表上获得mousclick时,我也必须将所有回到我的应用程序数据结构中。而且,如果PyGTK从非主线程运行,它不会用gobject.idle本身来包装gtk +调用,这也令人厌烦。现在有很多GUI代码,我认为这不应该是必要的,或者可以合理化。



所以,是PyGTK上可能还有额外的包装。或者其他工具包支持更简单的接口来显示Grid / TreeView。我读过很多关于wxPython最受欢迎的人,但在Linux上它不太成熟。和 PyQT 似乎大部分与PyGTK的抽象级别相同。还没有使用 TkInter ,所以不知道它是否具有更简单的接口,但无论如何看起来没有吸引力。与 PyFLTK 一样。睡衣听起来很迷人,但已经太远了(桌面应用程序)。



因此,GUI工具包与字典 - >网格显示。你会选择哪一个?



就像展览一样,这是我目前的TreeView映射函数。一些作品,但我宁愿有标准的东西:

 # - 填充treeview 

#从数据字典中添加treeviewcolumns / cellrenderers和liststore。
#它的数据映射和表格内容可以通过一个或两个步骤提供。
#应用新数据时,不会重新创建列。

#这些列是根据datamap创建的,它描述了单元
#映射和布局。列可以有多个cellrenderers,但通常
#可以直接映射到来自条目的数据源键。

#datamap = [#标题宽度dict-key类型,渲染器,attrs
#[Name,150,[titlerow,str,text,{}] ],
#[False,0,[interndat,int,None,{}]],
#[Desc,200,[descriptn,str,text,{ }],[icon,str,pixbuf,{}]],

#相应的条目列表将包含每行的字典:
#entries = [ {titlerow:first,interndat:123},{titlerow:...},]
#数据映射中未提及的键会被忽略,并应用默认值
#缺少cols。但是,所有的值必须已经是正确的类型。

@staticmethod
def列(widget,datamap = [],entries = [],pix_entry = False):

#create treeviewcolumns?
if(not widget.get_column(0)):
#通过标题循环
datapos = 0
for n_col,desc in enumerate(datamap):

#检查标题
if(type(desc [0])!= str):
datapos + = 1#如果没有,这只是一个未显示的数据列
continue
#new tvcolumn
col = gtk.TreeViewColumn(desc [0])#title
col.set_resizable(True)
#width
if(desc [1] > 0):
col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
col.set_fixed_width(desc [1])$ ​​b
$ b通过单元格循环
用于xrange中的var (2,len(desc)):
cell = desc [var]
#cell renderer
if(cell [2] ==pixbuf):
rend = gtk.CellRendererPixbuf()#img cell
if(cell [1] == str):
cell [3] [stock_id] = datapos#股票图标
expand = False
else:
pix_entry = datapos
cell [3] [pixbuf] = datapos
else:
rend = gtk.CellRendererText()#text cell
cell [3] [text] = datapos
col.set_sort_column_id(datapos)#仅在文本单元上

#将单元格附加到列
col.pack_end(rend ,expand = cell [3] .get(expand,True))
#apply属性
用于attr,val在单元格[3]中.iteritems():
col.add_attribute( rend,attr,val)
#next
datapos + = 1

#将列添加到treeview
widget.append_column(col)
#finalize widget $ b $ widget.set_search_column(2)#??
widget.set_reorderable(True)

#添加数据?
if(entries):
# - expand datamap
vartypes = []#(str,str,bool,str,int,int,gtk.gdk.Pixbuf,str,int)
rowmap = []#[title,desc,bookmarked,name,count,max,img,...]
if(not rowmap) :
用于数据映射中的desc:
用于xrange中的var(2,len(desc)):
vartypes.append(desc [var] [3])#content types
rowmap.append(desc [var] [0])#dict {}列键[]列表
#创建gtk数组存储
ls = gtk.ListStore(* vartypes)#可以是TreeStore ,

#为缺失值和特殊变量类型做准备
defaults = {
str:,
unicode:u,
bool:False,
int:0,
gtk.gdk.Pixbuf:gtk.gdk.pixbuf_new_from_data( \0\0\0\0,gtk.gdk.COLORSPACE_RGB,True,8,1,1,4)
}
如果gtk.gdk.Pixbuf在vartypes中:
pix_entry = vartypes.index(gtk.gdk.Pixbuf)

#将数据排序为gtk liststore数组
用于条目中的行:
#从字典中生成有序列表,使用行映射关联
row = [row.get(skey,defaults [vartypes [i]])for i,skey in enumerate(rowmap)]

#autotransform string - > gtk image object
if(pix_entry and type(row [pix_entry])== str):
row [pix_entry] = gtk.gdk.pixbuf_new_from_file(row [pix_entry])

#add
ls.append(row)#必须适用于真正的TreeStore(需要额外的输入用于分组/级别/父母)

#将数组应用到小部件
widget.set_model(ls)
返回ls

通过


解决方案

试试猕猴桃,也许?尤其是 ObjectList



更新:我认为Kiwi开发已经转移到 PyGTKHelpers


Started my first Python pet project using PyGTK. Though it is a really powerful GUI toolkit and looks excellent, I have some pet peeves. So I thought about transitioning to something else, as it's not yet too extensive. Had a look around on SO and python documentation, but didn't get a good overview.

What's nice about PyGTK:

  • Glade files
  • self.signal_autoconnect({...})
  • self.get_widget() as __getattr__

This is bugging me however:

  • manual gobject.idle_add(lambda: ... and False)
  • no standard functionality to save application/window states
  • TreeView needs array building
  • widget.get_selection().get_selected(), model.get_value(iter, liststore_index)

TreeView: Because this is the main interface element, it's the most distracting. Basically my application builds a list of dictionaries to be displayed name=column+row=>value. To display it using GTK there needs to be a manual conversion process, ordering, typecasts. This seems a lot of overhead, and I wished for something more object-oriented here. PyGtk has many abstractions atop gtk+ but still seems rather low-levelish. I'd prefer to pass my dict as-is and have columns pre-defined somehow. (GtkBuilder can predefine TreeView columns, but this doesn't solve the data representation overhead.)

When I get a mousclick on my TreeView list, I also have to convert everything back into my application data structures. And it's also irksome that PyGTK doesn't wrap gtk+ calls with gobject.idle itself, if run from a non-main thread. Right now there is a lot of GUI code that I believe shouldn't be necessary, or could be rationalized away.

? So, are there maybe additional wrappers on top of PyGTK. Or which other toolkit supports simpler interfaces for displaying a Grid / TreeView. I've read a lot about wxPython being everyones favourite, but it's less mature on Linux. And PyQT seems to be mostly the same abstraction level as PyGTK. Haven't used TkInter much so don't know about if it has simpler interfaces, but it anyway looks unattractive. As does PyFLTK. PyJamas sounds fascinating, but is already too far out (Desktop application).

.

So, GUI toolkit with dict -> Grid display. Which would you pick?

.

Just as exhibit, this is my current TreeView mapping function. Sort of works, but I would rather have something standard:

    #-- fill a treeview
    #
    # Adds treeviewcolumns/cellrenderers and liststore from a data dictionary.
    # Its datamap and the table contents can be supplied in one or two steps.
    # When new data gets applied, the columns aren't recreated.
    #
    # The columns are created according to the datamap, which describes cell
    # mapping and layout. Columns can have multiple cellrenderers, but usually
    # there is a direct mapping to a data source key from entries.
    #
    # datamap = [  #  title   width    dict-key    type,  renderer,  attrs  
    #               ["Name",   150,  ["titlerow",   str,    "text",    {} ]  ],
    #               [False,     0,   ["interndat",  int,     None,     {} ]  ],
    #               ["Desc",   200,  ["descriptn",  str,    "text",    {} ],  ["icon",str,"pixbuf",{}]  ],
    #
    # An according entries list then would contain a dictionary for each row:
    #   entries = [ {"titlerow":"first", "interndat":123}, {"titlerow":"..."}, ]
    # Keys not mentioned in the datamap get ignored, and defaults are applied
    # for missing cols. All values must already be in the correct type however.
    #
    @staticmethod
    def columns(widget, datamap=[], entries=[], pix_entry=False):

        # create treeviewcolumns?
        if (not widget.get_column(0)):
            # loop through titles
            datapos = 0
            for n_col,desc in enumerate(datamap):

                # check for title
                if (type(desc[0]) != str):
                    datapos += 1  # if there is none, this is just an undisplayed data column
                    continue
                # new tvcolumn
                col = gtk.TreeViewColumn(desc[0])  # title
                col.set_resizable(True)
                # width
                if (desc[1] > 0):
                    col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
                    col.set_fixed_width(desc[1])

                # loop through cells
                for var in xrange(2, len(desc)):
                    cell = desc[var]
                    # cell renderer
                    if (cell[2] == "pixbuf"):
                        rend = gtk.CellRendererPixbuf()  # img cell
                        if (cell[1] == str):
                            cell[3]["stock_id"] = datapos  # for stock icons
                            expand = False
                        else:
                            pix_entry = datapos
                            cell[3]["pixbuf"] = datapos
                    else:
                        rend = gtk.CellRendererText()    # text cell
                        cell[3]["text"] = datapos
                        col.set_sort_column_id(datapos)  # only on textual cells

                    # attach cell to column
                    col.pack_end(rend, expand=cell[3].get("expand",True))
                    # apply attributes
                    for attr,val in cell[3].iteritems():
                        col.add_attribute(rend, attr, val)
                    # next
                    datapos += 1

                # add column to treeview
                widget.append_column(col)
            # finalize widget
            widget.set_search_column(2)   #??
            widget.set_reorderable(True)

        # add data?
        if (entries):
            #- expand datamap            
            vartypes = []  #(str, str, bool, str, int, int, gtk.gdk.Pixbuf, str, int)
            rowmap = []    #["title", "desc", "bookmarked", "name", "count", "max", "img", ...]
            if (not rowmap):
                for desc in datamap:
                    for var in xrange(2, len(desc)):
                        vartypes.append(desc[var][3])  # content types
                        rowmap.append(desc[var][0])    # dict{} column keys in entries[] list
            # create gtk array storage
            ls = gtk.ListStore(*vartypes)   # could be a TreeStore, too

            # prepare for missing values, and special variable types
            defaults = {
                str: "",
                unicode: u"",
                bool: False,
                int: 0,
                gtk.gdk.Pixbuf: gtk.gdk.pixbuf_new_from_data("\0\0\0\0",gtk.gdk.COLORSPACE_RGB,True,8,1,1,4)
            }
            if gtk.gdk.Pixbuf in vartypes:
                pix_entry = vartypes.index(gtk.gdk.Pixbuf) 

            # sort data into gtk liststore array
            for row in entries:
                # generate ordered list from dictionary, using rowmap association
                row = [   row.get( skey , defaults[vartypes[i]] )   for i,skey   in enumerate(rowmap)   ]

                # autotransform string -> gtk image object
                if (pix_entry and type(row[pix_entry]) == str):
                    row[pix_entry] = gtk.gdk.pixbuf_new_from_file(row[pix_entry])

                # add
                ls.append(row)   # had to be adapted for real TreeStore (would require additional input for grouping/level/parents)

            # apply array to widget
            widget.set_model(ls)
            return ls

        pass

解决方案

Try Kiwi, maybe? Especially with its ObjectList.

Update: I think Kiwi development has moved to PyGTKHelpers.

这篇关于更高级别的Python GUI工具包,例如为TreeView / Grid传递字典的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆