首页 > 代码库 > python gui之tkinter界面设计pythonic设计

python gui之tkinter界面设计pythonic设计

ui的设计,控件id的记录是一件比较繁琐的事情。

此外,赋值和读取数据也比较繁琐,非常不pythonic。

有没有神马办法优雅一点呢?life is short。

 

鉴于控件有name属性,通过dir(Entry_obj)得知,存放在一个_name的属性里面。于是就有了以下代码:

Entry(frame,name=‘your_id1‘).grid(row=x1,column=y1)Entry(frame,name=‘your_id2‘).grid(row=x2,column=y2)...Entry(frame, name=‘your_idn‘).grid(row=xn,column=yn)

当然还有其他输入控件,此处略。

可以通过 frame.grid_slaves()得到其上面所有的控件。

然后可以通过 __class__来判断具体类型。可以在此基础上判断哪些控件是输入控件,如下:

for ctrl in frame.grid_slaves():    if ctrl.__class__.__name__ in (‘Entry‘,‘Text‘,....):        return Truereturn False

  

此外,我们还需要一个映射表,来关联界面控件和我们的模型。

mapper={‘model_attr1‘:ctrol_id1, ‘model_attr2‘:ctrol_id2,...., ‘model_attrn‘:ctrol_idn}

 

通过这个映射表,我们可以方便的进行表单数据的设置和读取,假设所有输入控件皆为Entry,于是就有了一下读取表单的代码:

    def get_form_data(self):        vals = {}.fromkeys(self.mapper.keys(),False)        ctrls = dict([(x._name,x) for x in self.input_ctrls])        for k,v in self.mapper.items():            ctrl = ctrls.get(v,False)            if ctrl and ctrl.get():                vals.update({k:ctrl.get()})                #print vals        logging.debug(‘product form data:%s‘%vals)        return vals

 

关于input_ctrls的说明,因为控件的从属关系,本质上应该是一个树。

可以采用一个设计:

将控件放入到frame中,所有的frame放入到一个列表中frame_list。

frame中的控件用grid方式布局。于是就有了以下读取界面上所有输入控件的代码:

    def _is_input(self, ctrl_obj):        """        是否为输入控件        :param ctrl_obj:        :return:        """        if ctrl_obj:            name = ctrl_obj._name            matches= [‘txt_‘,‘cb_‘]            if (name.split(‘_‘)[0]+‘_‘) in matches:                return True        return False    def _get_input_ctrls(self, container):        if container:            cs = container.grid_slaves()            cs.extend(container.pack_slaves())            for c in cs:                if self._is_input(c):                    self.input_ctrls.append(c)                else:                    self._get_input_ctrls(c)    def get_input_ctrls(self):        self.input_ctrls=[]        for f in self.frames:            self._get_input_ctrls(f)        return self.input_ctrls

 是否输入控件采用了根据_name属性进行的判断。此处需要有coding规范约束。

实际上可以改写_is_input逻辑,根据__class__来进行枚举判断。

 

相应的设置表单的值逻辑如下:

    def set_data(self, data):        if not isinstance(data,dict):            raise TypeError        if not self.mapper:            raise "set_mapper method must be called before this method being called."        ctrls = dict([(x._name,x) for x in self.get_input_ctrls()])        for k,v in self.mapper.items():            if data.get(k,False):                ctrl_obj = ctrls.get(v)                if ctrl_obj:                    ctrl_obj.configure(state=‘normal‘)                    ctrl_obj.insert(0, data.get(k))                    ctrl_obj.configure(state=‘readonly‘)

  

python gui之tkinter界面设计pythonic设计