class Multicolumn_Listbox(object): _style_index = 0 class List_Of_Rows(object): def __init__(self, multicolumn_listbox): self._multicolumn_listbox = multicolumn_listbox def data(self, index): return self._multicolumn_listbox.row_data(index) def get(self, index): return Row(self._multicolumn_listbox, index) def insert(self, data, index=None): self._multicolumn_listbox.insert_row(data, index) def delete(self, index): self._multicolumn_listbox.delete_row(index) def update(self, index, data): self._multicolumn_listbox.update_row(index, data) def select(self, index): self._multicolumn_listbox.select_row(index) def deselect(self, index): self._multicolumn_listbox.deselect_row(index) def set_selection(self, indices): self._multicolumn_listbox.set_selection(indices) def __getitem__(self, index): return self.get(index) def __setitem__(self, index, value): return self._multicolumn_listbox.update_row(index, value) def __delitem__(self, index): self._multicolumn_listbox.delete_row(index) def __len__(self): return self._multicolumn_listbox.number_of_rows class List_Of_Columns(object): def __init__(self, multicolumn_listbox): self._multicolumn_listbox = multicolumn_listbox def data(self, index): return self._multicolumn_listbox.get_column(index) def get(self, index): return Column(self._multicolumn_listbox, index) def delete(self, index): self._multicolumn_listbox.delete_column(index) def update(self, index, data): self._multicolumn_listbox.update_column(index, data) def __getitem__(self, index): return self.get(index) def __setitem__(self, index, value): return self._multicolumn_listbox.update_column(index, value) def __delitem__(self, index): self._multicolumn_listbox.delete_column(index) def __len__(self): return self._multicolumn_listbox.number_of_columns def __init__(self, master, columns, data=None, command=None, sort=True, select_mode=None, heading_anchor=CENTER, cell_anchor=W, style=None, height=None, padding=None, adjust_heading_to_content=False, stripped_rows=None, selection_background=None, selection_foreground=None, field_background=None, heading_font=None, heading_background=None, heading_foreground=None, cell_pady=2, cell_background=None, cell_foreground=None, cell_font=None, headers=True): self._stripped_rows = stripped_rows self._columns = columns self._number_of_rows = 0 self._number_of_columns = len(columns) self.row = self.List_Of_Rows(self) self.column = self.List_Of_Columns(self) s = Style() if style is None: style_name = "Multicolumn_Listbox%s.Treeview" % self._style_index self._style_index += 1 else: style_name = style style_map = {} if selection_background is not None: style_map["background"] = [('selected', selection_background)] if selection_foreground is not None: style_map["foeground"] = [('selected', selection_foreground)] if style_map: s.map(style_name, **style_map) style_config = {} if cell_background is not None: style_config["background"] = cell_background if cell_foreground is not None: style_config["foreground"] = cell_foreground if cell_font is None: font_name = s.lookup(style_name, "font") cell_font = nametofont(font_name) else: if not isinstance(cell_font, Font): if isinstance(cell_font, basestring): cell_font = nametofont(cell_font) else: if len(font) == 1: cell_font = Font(family=cell_font[0]) elif len(font) == 2: cell_font = Font(family=cell_font[0], size=cell_font[1]) elif len(font) == 3: cell_font = Font(family=cell_font[0], size=cell_font[1], weight=cell_font[2]) else: raise ValueError( "Not possible more than 3 values for font") style_config["font"] = cell_font self._cell_font = cell_font self._rowheight = cell_font.metrics("linespace") + cell_pady style_config["rowheight"] = self._rowheight if field_background is not None: style_config["fieldbackground"] = field_background s.configure(style_name, **style_config) heading_style_config = {} if heading_font is not None: heading_style_config["font"] = heading_font if heading_background is not None: heading_style_config["background"] = heading_background if heading_foreground is not None: heading_style_config["foreground"] = heading_foreground heading_style_name = style_name + ".Heading" s.configure(heading_style_name, **heading_style_config) treeview_kwargs = {"style": style_name} if height is not None: treeview_kwargs["height"] = height if padding is not None: treeview_kwargs["padding"] = padding if headers: treeview_kwargs["show"] = "headings" else: treeview_kwargs["show"] = "" if select_mode is not None: treeview_kwargs["selectmode"] = select_mode self.interior = Treeview(master, columns=columns, **treeview_kwargs) if command is not None: self._command = command self.interior.bind("<<TreeviewSelect>>", self._on_select) for i in range(0, self._number_of_columns): if sort: self.interior.heading( i, text=columns[i], anchor=heading_anchor, command=lambda col=i: self.sort_by(col, descending=False)) else: self.interior.heading(i, text=columns[i], anchor=heading_anchor) if adjust_heading_to_content: self.interior.column(i, width=Font().measure(columns[i])) self.interior.column(i, anchor=cell_anchor) if data is not None: for row in data: self.insert_row(row) @property def row_height(self): return self._rowheight @property def font(self): return self._cell_font def configure_column(self, index, width=None, minwidth=None, anchor=None, stretch=None): kwargs = {} for config_name in ("width", "anchor", "stretch", "minwidth"): config_value = locals()[config_name] if config_value is not None: kwargs[config_name] = config_value self.interior.column('#%s' % (index + 1), **kwargs) def row_data(self, index): try: item_ID = self.interior.get_children()[index] except IndexError: raise ValueError("Row index out of range: %d" % index) return self.item_ID_to_row_data(item_ID) def update_row(self, index, data): try: item_ID = self.interior.get_children()[index] except IndexError: raise ValueError("Row index out of range: %d" % index) if len(data) == len(self._columns): self.interior.item(item_ID, values=data) else: raise ValueError("The multicolumn listbox has only %d columns" % self._number_of_columns) def delete_row(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d" % index) self.interior.delete(item_ID) self._number_of_rows -= 1 if self._stripped_rows: for i in range(index, self._number_of_rows): self.interior.tag_configure(list_of_items[i + 1], background=self._stripped_rows[i % 2]) def insert_row(self, data, index=None): if len(data) != self._number_of_columns: raise ValueError("The multicolumn listbox has only %d columns" % self._number_of_columns) if index is None: index = self._number_of_rows - 1 item_ID = self.interior.insert('', index, values=data) self.interior.item(item_ID, tags=item_ID) self._number_of_rows += 1 if self._stripped_rows: list_of_items = self.interior.get_children() self.interior.tag_configure(item_ID, background=self._stripped_rows[index % 2]) for i in range(index + 1, self._number_of_rows): self.interior.tag_configure(list_of_items[i], background=self._stripped_rows[i % 2]) def column_data(self, index): return [ self.interior.set(child_ID, index) for child_ID in self.interior.get_children('') ] def update_column(self, index, data): for i, item_ID in enumerate(self.interior.get_children()): data_row = self.item_ID_to_row_data(item_ID) data_row[index] = data[i] self.interior.item(item_ID, values=data_row) return data def clear(self): # Another possibility: # self.interior.delete(*self.interior.get_children()) for row in self.interior.get_children(): self.interior.delete(row) self._number_of_rows = 0 def update(self, data): self.clear() for row in data: self.insert_row(row) def focus(self, index=None): if index is None: return self.interior.item(self.interior.focus()) else: item = self.interior.get_children()[index] self.interior.focus(item) def state(self, state=None): if stateSpec is None: return self.interior.state() else: self.interior.state(state) @property def number_of_rows(self): return self._number_of_rows @property def number_of_columns(self): return self._number_of_columns def toogle_selection(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d" % index) self.interior.selection_toggle(item_ID) def select_row(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d" % index) self.interior.selection_add(item_ID) def deselect_row(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d" % index) self.interior.selection_remove(item_ID) def deselect_all(self): self.interior.selection_remove(self.interior.selection()) def set_selection(self, indices): list_of_items = self.interior.get_children() self.interior.selection_set(" ".join(list_of_items[row_index] for row_index in indices)) @property def selected_rows(self): data = [] for item_ID in self.interior.selection(): data_row = self.item_ID_to_row_data(item_ID) data.append(data_row) return data @property def indices_of_selected_rows(self): list_of_indices = [] for index, item_ID in enumerate(self.interior.get_children()): if item_ID in self.interior.selection(): list_of_indices.append(index) return list_of_indices def delete_all_selected_rows(self): selected_items = self.interior.selection() for item_ID in selected_items: self.interior.delete(item_ID) number_of_deleted_rows = len(selected_items) self._number_of_rows -= number_of_deleted_rows return number_of_deleted_rows def _on_select(self, event): for item_ID in event.widget.selection(): data_row = self.item_ID_to_row_data(item_ID) self._command(data_row) def item_ID_to_row_data(self, item_ID): item = self.interior.item(item_ID) return item["values"] @property def table_data(self): data = [] for item_ID in self.interior.get_children(): data_row = self.item_ID_to_row_data(item_ID) data.append(data_row) return data @table_data.setter def table_data(self, data): self.update(data) def cell_data(self, row, column): """Get the value of a table cell""" try: item = self.interior.get_children()[row] except IndexError: raise ValueError("Row index out of range: %d" % row) return self.interior.set(item, column) def update_cell(self, row, column, value): """Set the value of a table cell""" item_ID = self.interior.get_children()[row] data = self.item_ID_to_row_data(item_ID) data[column] = value self.interior.item(item_ID, values=data) def __getitem__(self, index): if isinstance(index, tuple): row, column = index return self.cell_data(row, column) else: raise Exception("Row and column indices are required") def __setitem__(self, index, value): if isinstance(index, tuple): row, column = index self.update_cell(row, column, value) else: raise Exception("Row and column indices are required") def bind(self, event, handler): self.interior.bind(event, handler) def sort_by(self, col, descending): """ sort tree contents when a column header is clicked """ # grab values to sort data = [(self.interior.set(child_ID, col), child_ID) for child_ID in self.interior.get_children('')] # if the Demo_programs to be sorted is numeric change to float try: data = [(float(number), child_ID) for number, child_ID in data] except ValueError: pass # now sort the Demo_programs in place data.sort(reverse=descending) for idx, item in enumerate(data): self.interior.move(item[1], '', idx) # switch the heading so that it will sort in the opposite direction self.interior.heading( col, command=lambda col=col: self.sort_by(col, not descending)) if self._stripped_rows: list_of_items = self.interior.get_children('') for i in range(len(list_of_items)): self.interior.tag_configure(list_of_items[i], background=self._stripped_rows[i % 2]) def destroy(self): self.interior.destroy() def item_ID(self, index): return self.interior.get_children()[index]
class Multicolumn_Listbox(object): _style_index = 0 class List_Of_Rows(object): def __init__(self, multicolumn_listbox): self._multicolumn_listbox = multicolumn_listbox def data(self, index): return self._multicolumn_listbox.row_data(index) def get(self, index): return Row(self._multicolumn_listbox, index) def insert(self, data, index=None): self._multicolumn_listbox.insert_row(data, index) def delete(self, index): self._multicolumn_listbox.delete_row(index) def update(self, index, data): self._multicolumn_listbox.update_row(index, data) def select(self, index): self._multicolumn_listbox.select_row(index) def deselect(self, index): self._multicolumn_listbox.deselect_row(index) def set_selection(self, indices): self._multicolumn_listbox.set_selection(indices) def __getitem__(self, index): return self.get(index) def __setitem__(self, index, value): return self._multicolumn_listbox.update_row(index, value) def __delitem__(self, index): self._multicolumn_listbox.delete_row(index) def __len__(self): return self._multicolumn_listbox.number_of_rows class List_Of_Columns(object): def __init__(self, multicolumn_listbox): self._multicolumn_listbox = multicolumn_listbox def data(self, index): return self._multicolumn_listbox.get_column(index) def get(self, index): return Column(self._multicolumn_listbox, index) def delete(self, index): self._multicolumn_listbox.delete_column(index) def update(self, index, data): self._multicolumn_listbox.update_column(index, data) def __getitem__(self, index): return self.get(index) def __setitem__(self, index, value): return self._multicolumn_listbox.update_column(index, value) def __delitem__(self, index): self._multicolumn_listbox.delete_column(index) def __len__(self): return self._multicolumn_listbox.number_of_columns def __init__(self, master, columns, data=None, command=None, sort=True, select_mode=None, heading_anchor = CENTER, cell_anchor=W, style=None, height=None, padding=None, adjust_heading_to_content=False, stripped_rows=None, selection_background=None, selection_foreground=None, field_background=None, heading_font= None, heading_background=None, heading_foreground=None, cell_pady=2, cell_background=None, cell_foreground=None, cell_font=None, headers=True): self._stripped_rows = stripped_rows self._columns = columns self._number_of_rows = 0 self._number_of_columns = len(columns) self.row = self.List_Of_Rows(self) self.column = self.List_Of_Columns(self) s = Style() if style is None: style_name = "Multicolumn_Listbox%s.Treeview"%self._style_index self._style_index += 1 else: style_name = style style_map = {} if selection_background is not None: style_map["background"] = [('selected', selection_background)] if selection_foreground is not None: style_map["foeground"] = [('selected', selection_foreground)] if style_map: s.map(style_name, **style_map) style_config = {} if cell_background is not None: style_config["background"] = cell_background if cell_foreground is not None: style_config["foreground"] = cell_foreground if cell_font is None: font_name = s.lookup(style_name, "font") cell_font = nametofont(font_name) else: if not isinstance(cell_font, Font): if isinstance(cell_font, basestring): cell_font = nametofont(cell_font) else: if len(font) == 1: cell_font = Font(family=cell_font[0]) elif len(font) == 2: cell_font = Font(family=cell_font[0], size=cell_font[1]) elif len(font) == 3: cell_font = Font(family=cell_font[0], size=cell_font[1], weight=cell_font[2]) else: raise ValueError("Not possible more than 3 values for font") style_config["font"] = cell_font self._cell_font = cell_font self._rowheight = cell_font.metrics("linespace")+cell_pady style_config["rowheight"]=self._rowheight if field_background is not None: style_config["fieldbackground"] = field_background s.configure(style_name, **style_config) heading_style_config = {} if heading_font is not None: heading_style_config["font"] = heading_font if heading_background is not None: heading_style_config["background"] = heading_background if heading_foreground is not None: heading_style_config["foreground"] = heading_foreground heading_style_name = style_name + ".Heading" s.configure(heading_style_name, **heading_style_config) treeview_kwargs = {"style": style_name} if height is not None: treeview_kwargs["height"] = height if padding is not None: treeview_kwargs["padding"] = padding if headers: treeview_kwargs["show"] = "headings" else: treeview_kwargs["show"] = "" if select_mode is not None: treeview_kwargs["selectmode"] = select_mode self.interior = Treeview(master, columns=columns, **treeview_kwargs) if command is not None: self._command = command self.interior.bind("<<TreeviewSelect>>", self._on_select) for i in range(0, self._number_of_columns): if sort: self.interior.heading(i, text=columns[i], anchor=heading_anchor, command=lambda col=i: self.sort_by(col, descending=False)) else: self.interior.heading(i, text=columns[i], anchor=heading_anchor) if adjust_heading_to_content: self.interior.column(i, width=Font().measure(columns[i])) self.interior.column(i, anchor=cell_anchor) if data is not None: for row in data: self.insert_row(row) @property def row_height(self): return self._rowheight @property def font(self): return self._cell_font def configure_column(self, index, width=None, minwidth=None, anchor=None, stretch=None): kwargs = {} for config_name in ("width", "anchor", "stretch", "minwidth"): config_value = locals()[config_name] if config_value is not None: kwargs[config_name] = config_value self.interior.column('#%s'%(index+1), **kwargs) def row_data(self, index): try: item_ID = self.interior.get_children()[index] except IndexError: raise ValueError("Row index out of range: %d"%index) return self.item_ID_to_row_data(item_ID) def update_row(self, index, data): try: item_ID = self.interior.get_children()[index] except IndexError: raise ValueError("Row index out of range: %d"%index) if len(data) == len(self._columns): self.interior.item(item_ID, values=data) else: raise ValueError("The multicolumn listbox has only %d columns"%self._number_of_columns) def delete_row(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d"%index) self.interior.delete(item_ID) self._number_of_rows -= 1 if self._stripped_rows: for i in range(index, self._number_of_rows): self.interior.tag_configure(list_of_items[i+1], background=self._stripped_rows[i%2]) def insert_row(self, data, index=None): if len(data) != self._number_of_columns: raise ValueError("The multicolumn listbox has only %d columns"%self._number_of_columns) if index is None: index = self._number_of_rows-1 item_ID = self.interior.insert('', index, values=data) self.interior.item(item_ID, tags=item_ID) self._number_of_rows += 1 if self._stripped_rows: list_of_items = self.interior.get_children() self.interior.tag_configure(item_ID, background=self._stripped_rows[index%2]) for i in range(index+1, self._number_of_rows): self.interior.tag_configure(list_of_items[i], background=self._stripped_rows[i%2]) def column_data(self, index): return [self.interior.set(child_ID, index) for child_ID in self.interior.get_children('')] def update_column(self, index, data): for i, item_ID in enumerate(self.interior.get_children()): data_row = self.item_ID_to_row_data(item_ID) data_row[index] = data[i] self.interior.item(item_ID, values=data_row) return data def clear(self): # Another possibility: # self.interior.delete(*self.interior.get_children()) for row in self.interior.get_children(): self.interior.delete(row) self._number_of_rows = 0 def update(self, data): self.clear() for row in data: self.insert_row(row) def focus(self, index=None): if index is None: return self.interior.item(self.interior.focus()) else: item = self.interior.get_children()[index] self.interior.focus(item) def state(self, state=None): if stateSpec is None: return self.interior.state() else: self.interior.state(state) @property def number_of_rows(self): return self._number_of_rows @property def number_of_columns(self): return self._number_of_columns def toogle_selection(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d"%index) self.interior.selection_toggle(item_ID) def select_row(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d"%index) self.interior.selection_add(item_ID) def deselect_row(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d"%index) self.interior.selection_remove(item_ID) def deselect_all(self): self.interior.selection_remove(self.interior.selection()) def set_selection(self, indices): list_of_items = self.interior.get_children() self.interior.selection_set(" ".join(list_of_items[row_index] for row_index in indices)) @property def selected_rows(self): data = [] for item_ID in self.interior.selection(): data_row = self.item_ID_to_row_data(item_ID) data.append(data_row) return data @property def indices_of_selected_rows(self): list_of_indices = [] for index, item_ID in enumerate(self.interior.get_children()): if item_ID in self.interior.selection(): list_of_indices.append(index) return list_of_indices def delete_all_selected_rows(self): selected_items = self.interior.selection() for item_ID in selected_items: self.interior.delete(item_ID) number_of_deleted_rows = len(selected_items) self._number_of_rows -= number_of_deleted_rows return number_of_deleted_rows def _on_select(self, event): for item_ID in event.widget.selection(): data_row = self.item_ID_to_row_data(item_ID) self._command(data_row) def item_ID_to_row_data(self, item_ID): item = self.interior.item(item_ID) return item["values"] @property def table_data(self): data = [] for item_ID in self.interior.get_children(): data_row = self.item_ID_to_row_data(item_ID) data.append(data_row) return data @table_data.setter def table_data(self, data): self.update(data) def cell_data(self, row, column): """Get the value of a table cell""" try: item = self.interior.get_children()[row] except IndexError: raise ValueError("Row index out of range: %d"%row) return self.interior.set(item, column) def update_cell(self, row, column, value): """Set the value of a table cell""" item_ID = self.interior.get_children()[row] data = self.item_ID_to_row_data(item_ID) data[column] = value self.interior.item(item_ID, values=data) def __getitem__(self, index): if isinstance(index, tuple): row, column = index return self.cell_data(row, column) else: raise Exception("Row and column indices are required") def __setitem__(self, index, value): if isinstance(index, tuple): row, column = index self.update_cell(row, column, value) else: raise Exception("Row and column indices are required") def bind(self, event, handler): self.interior.bind(event, handler) def sort_by(self, col, descending): """ sort tree contents when a column header is clicked """ # grab values to sort data = [(self.interior.set(child_ID, col), child_ID) for child_ID in self.interior.get_children('')] # if the data to be sorted is numeric change to float try: data = [(float(number), child_ID) for number, child_ID in data] except ValueError: pass # now sort the data in place data.sort(reverse=descending) for idx, item in enumerate(data): self.interior.move(item[1], '', idx) # switch the heading so that it will sort in the opposite direction self.interior.heading(col, command=lambda col=col: self.sort_by(col, not descending)) if self._stripped_rows: list_of_items = self.interior.get_children('') for i in range(len(list_of_items)): self.interior.tag_configure(list_of_items[i], background=self._stripped_rows[i%2]) def destroy(self): self.interior.destroy() def item_ID(self, index): return self.interior.get_children()[index]
class XML_Viwer(Frame): def __init__(self, master, xml=None, heading_text=None, heading_anchor=None, padding=None, cursor=None, takefocus=None, style=None): Frame.__init__(self, master, class_="XML_Viwer") self._vsb = Scrollbar(self, orient=VERTICAL) self._hsb = Scrollbar(self, orient=HORIZONTAL) kwargs = {} kwargs["yscrollcommand"] = lambda f, l: autoscroll(self._vsb, f, l) kwargs["xscrollcommand"] = lambda f, l: autoscroll(self._hsb, f, l) if style is not None: kwargs["style"] = style if padding is not None: kwargs["padding"] = padding if cursor is not None: kwargs["cursor"] = cursor if takefocus is not None: kwargs["takefocus"] = takefocus self._treeview = Treeview(self, **kwargs) if heading_text is not None: if heading_anchor is not None: self._treeview.heading("#0", text=heading_text, anchor=heading_anchor) else: self._treeview.heading("#0", text=heading_text) self._treeview.bind("<<TreeviewOpen>>", self._on_open) self._treeview.bind("<<TreeviewClose>>", self._on_close) # Without this line, horizontal scrolling doesn't work properly. self._treeview.column("#0", stretch=False) self._vsb['command'] = self._treeview.yview self._hsb['command'] = self._treeview.xview self._treeview.grid(column=0, row=0, sticky=N + S + W + E) self._vsb.grid(column=1, row=0, sticky=N + S) self._hsb.grid(column=0, row=1, sticky=E + W) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self._element_tree = None self._item_ID_to_element = {} if xml is not None: self.parse_xml(xml) def _on_open(self, event): item_ID = self._treeview.focus() if item_ID not in self._item_ID_to_element: return node = self._item_ID_to_element[item_ID] self._treeview.item(item_ID, text=self._repr_of_openning_tag(node)) def _on_close(self, event): item_ID = self._treeview.focus() if item_ID not in self._item_ID_to_element: return node = self._item_ID_to_element[item_ID] text = self._repr_of_openning_tag(node) + self._repr_of_closing_tag( node) self._treeview.item(item_ID, text=text) def parse_xml(self, xml): self._element_tree = ET.ElementTree(ET.fromstring(xml)) self.clear() self._walk_xml(self._element_tree.getroot()) @property def element_tree(self): return self._element_tree @element_tree.setter def element_tree(self, element_tree): self._element_tree = element_tree self.clear() self._walk_xml(element_tree.getroot()) def clear(self): self._item_ID_to_element = {} self._treeview.delete(*self._treeview.get_children()) def _repr_of_openning_tag(self, node): text = "<" + node.tag attrs = node.attrib # list function is here necessary to provide support to Python 3 a_names = list(attrs.keys()) a_names.sort() for a_name in a_names: text += ' %s="' % a_name text += attrs[a_name] text += '"' text += ">" return text def _repr_of_closing_tag(self, node): return "</%s>" % node.tag def _walk_xml(self, node, depth=0, parent=""): text = self._repr_of_openning_tag(node) + self._repr_of_closing_tag( node) item = self._treeview.insert(parent, END, text=text) self._item_ID_to_element[item] = node if node.text: text = node.text.strip() if text != "": for line in text.splitlines(): self._treeview.insert(item, END, text=line) child_nodes = sorted(list(node), key=attrgetter('tag')) for child_node in node: self._walk_xml(child_node, depth + 1, parent=item) if node.tail: tail = node.tail.strip() if tail != "": for line in tail.splitlines(): self._treeview.insert(parent, END, text=line)
class App(object): def __init__(self, root, cursor, db): self.frame = Frame(root) self.frame.configure(background='white') self.list_toplevel = {} self.cursor = cursor self.db = db self.child_toplevel = None self.frame.pack() image = Image.open("photo.jpg") image = image.resize((250, 250), Image.ANTIALIAS) photo = ImageTk.PhotoImage(image) label = Label(self.frame, image=photo) label.grid(row=0, column=0, sticky=W) label.image = photo # keep a reference! nou_registre = LabelFrame(self.frame, text="Nou registre", fg="Blue", padx=5, pady=5) nou_registre.configure(background='white') nou_registre.grid(row=0, column=1, padx=15, sticky=W) text_nom = Label(nou_registre, text="Nom:", fg="Blue") text_nom.configure(background='white') text_nom.grid(row=0, column=0) self.entry_nom = Entry(nou_registre) self.entry_nom.grid(row=0, column=1, sticky=W) text_telefon = Label(nou_registre, text="Telèfon: ", fg="Blue") text_telefon.configure(background='white') text_telefon.grid(row=1, column=0) self.entry_telefon = Entry(nou_registre) self.entry_telefon.grid(row=1, column=1) text_email = Label(nou_registre, text="Email: ", fg="Blue") text_email.configure(background='white') text_email.grid(row=2, column=0) self.entry_email = Entry(nou_registre) self.entry_email.grid(row=2, column=1) button_afegir_contacte = Button(nou_registre, text="Afegir contacte", fg="Blue", command=self.afegeix_contacte) button_afegir_contacte.grid(row=3, column=1, sticky=E) button_mostra_historic = Button(nou_registre, text="Mostra historic", fg="Blue", command=self.mostra_historic) button_mostra_historic.grid(row=4, column=0, sticky=W) mostrar_contactes = Button(self.frame, text="Mostrar contactes", fg="Blue", command=self.insert_contacts_treeview) mostrar_contactes.grid(sticky=W, row=3) self.missatge_error_confirmacio = StringVar() self.label_error_confirmacio = Label( self.frame, textvariable=self.missatge_error_confirmacio, fg="Red") self.label_error_confirmacio.configure(background='white') self.label_error_confirmacio.grid(sticky=W, row=3, column=1) self.agenda_contactes = Treeview(self.frame, columns=["nom", "tel"], show="headings") self.agenda_contactes.heading("nom", text="Nom") self.agenda_contactes.heading("tel", text="Telefon") self.agenda_contactes.column("nom", minwidth=0, width=200, stretch=NO, anchor="c") self.agenda_contactes.column("tel", minwidth=0, width=200, stretch=NO, anchor="c") self.agenda_contactes.grid(row=4, column=0, padx=0, columnspan=2) self.insert_contacts_treeview() elimina_seleccionat = Button(self.frame, text="Eliminar seleccionat", command=self.elimina_contacte, fg="Blue") elimina_seleccionat.grid(row=5, column=0, sticky=W) self.modificar_seleccionat = Button(self.frame, text="Modificar seleccionat", fg="Blue", command=self.modifica_contacte) self.modificar_seleccionat.grid(row=5, column=1, sticky=W) sortir = Button(self.frame, text="Sortir", fg="Blue", command=self.frame.quit) sortir.grid(row=5, column=2, sticky=E) def mostra_historic(self): popup = Toplevel() agenda_historic = Treeview( popup, columns=["nom", "tel", "email", "path", "accio", "data"], show="headings") agenda_historic.heading("nom", text="Nom") agenda_historic.heading("tel", text="Telefon") agenda_historic.heading("email", text="Email") agenda_historic.heading("path", text="Path") agenda_historic.heading("accio", text="Acció") agenda_historic.heading("data", text="Data") agenda_historic.column("nom", minwidth=0, width=150, stretch=True, anchor="c") agenda_historic.column("tel", minwidth=0, width=100, stretch=True, anchor="c") agenda_historic.column("email", minwidth=0, width=150, stretch=True, anchor="c") agenda_historic.column("path", minwidth=0, width=200, stretch=True, anchor="c") agenda_historic.column("accio", minwidth=0, width=100, stretch=True, anchor="c") agenda_historic.column("data", minwidth=0, width=150, stretch=True, anchor="c") agenda_historic.grid(row=0, column=0, padx=5, pady=5) self.cursor.execute("select * from HISTORIC ORDER BY data DESC;") dades = self.cursor.fetchall() for data_usuari in dades: agenda_historic.insert('', 'end', values=data_usuari) def insert_contacts_treeview(self): self.cursor.execute("select * from CONTACTES order by nom ASC;") self.agenda_contactes.delete(*self.agenda_contactes.get_children()) for i in self.cursor.fetchall(): self.agenda_contactes.insert('', 'end', values=i[:2]) def show_image(self, imatge_label, path_imatge=''): file_per_default = 'avatar.jpeg' if path_imatge == '': image = Image.open(file_per_default) else: if os.path.exists(path_imatge): try: image = Image.open(path_imatge) except: print "Error al mostrar imatge!" return False else: image = Image.open(file_per_default) image = image.resize((120, 120), Image.ANTIALIAS) photo = ImageTk.PhotoImage(image) imatge_label.configure(image=photo) imatge_label.image = photo return True def edit_image(self, imatge_label, path_imatge, nom, telefon): if os.path.isfile(path_imatge): try: image = Image.open(path_imatge) except: self.missatge_error_confirmacio.set("Imatge incorrecte!") else: try: self.cursor.execute( "UPDATE CONTACTES SET foto=:pathfoto where nom=:nom and telf=:telf", { 'pathfoto': path_imatge, 'nom': nom, 'telf': str(telefon) }) self.db.commit() except: self.missatge_error_confirmacio.set( "Error actualitzant la imatge!") return False self.show_image(imatge_label, path_imatge) def demana_imatge(self, imatge_label, nom, telefon): t = tkFileDialog.askopenfilename(title="Selecciona foto", filetypes=(("jpg files", "*.jpg"), ("jpeg files", "*.jpeg"), ("all files", "*.*"))) if t: self.edit_image(imatge_label, t, nom, telefon) def modificar_contacte(self, entries_fixed, entries_variable, treeview_seleccionat): #print dades_usuari nom_fixed = entries_fixed[0] telefon_fixed = entries_fixed[1] email_fixed = entries_fixed[2] telefon_variable = entries_variable[0] email_variable = entries_variable[1] valor_text_telefon_antic = entries_fixed[3] valor_text_email_antic = entries_fixed[4] changed_email = False changed_tel = False if email_variable.get() != '': try: self.check_email(email_variable.get()) except: self.missatge_error_confirmacio.set("El mail no és correcte!") else: self.cursor.execute( "UPDATE CONTACTES SET email=:email where nom=:nom and telf=:telf", { 'email': email_variable.get(), 'nom': nom_fixed.get(), 'telf': str(telefon_fixed.get()) }) valor_text_email_antic.set(email_variable.get()) changed_email = True if telefon_variable.get() != '': try: assert int(telefon_variable.get()) >= 600000000 except: self.missatge_error_confirmacio.set("Error en el telefon!") else: try: self.cursor.execute( "UPDATE CONTACTES SET telf=:nou_telf where nom=:nom and telf=:telf", { 'nou_telf': telefon_variable.get(), 'nom': nom_fixed.get(), 'telf': str(telefon_fixed.get()) }) except sqlite3.IntegrityError: self.missatge_error_confirmacio.set( "El telèfon ja està registrat!") else: changed_tel = True self.agenda_contactes.item(treeview_seleccionat, values=(nom_fixed.get(), telefon_variable.get())) valor_text_telefon_antic.set(telefon_variable.get()) self.db.commit() if changed_email & changed_tel: self.missatge_error_confirmacio.set( "Dades modificades correctament!") elif changed_email: self.missatge_error_confirmacio.set( "Email modificat correctament!") elif changed_tel: self.missatge_error_confirmacio.set( "Telefon modificat correctament!") def modifica_contacte(self): if self.child_toplevel is not None: self.child_toplevel.destroy() element_a_modificar = self.agenda_contactes.focus() valor_usuari = self.agenda_contactes.item( element_a_modificar)['values'] self.cursor.execute("select * from CONTACTES where nom=? and telf=?;", tuple(valor_usuari)) dades = self.cursor.fetchone() t = Toplevel() self.child_toplevel = t label_imatge = Label(t) label_imatge.configure(background='white') label_imatge.pack(side="left", fill="both", expand=True) self.show_image(label_imatge, dades[3]) frame_info = Frame(t) frame_info.pack(side="right", fill="both", expand=False) frame_info.configure(background='white') label_nom = Label(frame_info, text="Nom: ") label_nom.configure(background='white') label_nom.grid(row=0, column=0) entry_nom = Entry(frame_info, textvariable=StringVar(frame_info, value=dades[0]), width=20, state='disabled') entry_nom.grid(row=0, column=1) label_telefon = Label(frame_info, text="Telefon antic: ") label_telefon.configure(background='white') label_telefon.grid(row=1, column=0) text_telefon = StringVar(frame_info, value=dades[1]) entry_telefon = Entry(frame_info, textvariable=text_telefon, width=20, state='disabled') entry_telefon.grid(row=1, column=1) label_telefon_nou = Label(frame_info, text="Telefon nou: ") label_telefon_nou.configure(background='white') label_telefon_nou.grid(row=2, column=0) entry_telefon_nou = Entry(frame_info, width=20) entry_telefon_nou.grid(row=2, column=1) label_email = Label(frame_info, text="Email: ") label_email.configure(background='white') label_email.grid(row=3, column=0) text_email = StringVar(frame_info, value=dades[2]) #----- entry_email = Entry(frame_info, width=20, textvariable=text_email, state='disabled') entry_email.grid(row=3, column=1) label_email_nou = Label(frame_info, text="Email nou:") label_email_nou.configure(background='white') label_email_nou.grid(row=4, column=0) entry_email_nou = Entry(frame_info, width=20) entry_email_nou.grid(row=4, column=1) selecciona_imatge = Button( frame_info, text="Edita foto", command=lambda: self.demana_imatge(label_imatge, dades[0], text_telefon.get())) selecciona_imatge.grid(row=5) button_modifica_contacte = Button( frame_info, text="Modificar contacte", fg="Blue", command=lambda: self.modificar_contacte([ entry_nom, entry_telefon, entry_email, text_telefon, text_email ], [entry_telefon_nou, entry_email_nou], element_a_modificar)) button_modifica_contacte.grid(row=6, column=1, sticky=E) def check_email(self, email): if re.match("(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", email): return True else: raise "Mail no vàlid!" def elimina_contacte(self): element_seleccionat = self.agenda_contactes.focus() if element_seleccionat != '': informacio_contacte = self.agenda_contactes.item( element_seleccionat)['values'] self.cursor.execute("DELETE from CONTACTES where nom=? and telf=?", tuple(informacio_contacte)) self.db.commit() self.agenda_contactes.delete(element_seleccionat) self.missatge_error_confirmacio.set("Borrat correctament") if self.child_toplevel is not None: self.child_toplevel.destroy() #print self.agenda_contactes.focus() #print self.agenda_contactes.selection() else: self.missatge_error_confirmacio.set("Selecciona un usuari!") print "Selecciona element" def afegeix_contacte(self): try: Nom = self.entry_nom.get() assert Nom != '' Telef = int(self.entry_telefon.get()) assert Telef > 600000000 Email = self.check_email(self.entry_email.get()) except: self.missatge_error_confirmacio.set( "Introdueix les dades correctament!") else: try: self.cursor.execute( """INSERT INTO CONTACTES values (?,?,?,'');""", (Nom.title(), Telef, self.entry_email.get())) self.db.commit() except sqlite3.IntegrityError: self.missatge_error_confirmacio.set("Contacte ja existent!") else: self.insert_contacts_treeview() self.missatge_error_confirmacio.set( "Afegit contacte correctament")
class Example(Frame): def __init__(self): Frame.__init__(self) self.style = Style() self.style.theme_use("default") self.master.title("Log viewer") self.pack(fill=BOTH, expand=True) self.used = [] # List of currently plotted series ([str]) self.series = {} # List of all series ({str -> [number]}) self.names = [] # List of all nodes in tree view ([str]) self.queues = [] # List of all queues ([str]) self.logs = {} # List of all text logs ({str -> [str]}) self.rowconfigure(1, weight=1) self.columnconfigure(6, weight=3) self.columnconfigure(11, weight=1) # Series selection takes row 1-2, col 0-2 self.series_ui = Treeview(self) self.series_ui.grid(row=1, column=0, columnspan=2, rowspan=2, sticky=N+S) self.series_ui.configure(show="tree") self.series_ui.bind("<Double-Button-1>", self.onselect) self.series_ui.tag_configure("graphall", foreground="#070") self.series_ui.tag_configure("graphnone", foreground="#000") self.series_ui.tag_configure("graphsome", foreground="#007") series_ui_scroll = Scrollbar(self, command=self.series_ui.yview, orient=VERTICAL) series_ui_scroll.grid(row=1, column=2, rowspan=2, sticky=N+S) self.series_ui["yscrollcommand"] = series_ui_scroll.set # The plot takes row 1-2, col 3-6 move_mode = StringVar() move_mode.set("pan") show_path = IntVar() show_path.set(0) event_bars = IntVar() event_bars.set(1) show_debug = IntVar() show_debug.set(1) show_error = IntVar() show_error.set(1) show_warning = IntVar() show_warning.set(1) show_info = IntVar() show_info.set(1) self.plot = HackPlot(self, move_mode, show_path, event_bars, [(show_debug, "[DEBUG]"), (show_error, "[ERROR]"), (show_warning, "[WARNING]"), (show_info, "[INFO]")]) self.plot.canvas.grid(row=1, column=3, columnspan=4, rowspan=2, sticky=N+S+E+W) # Text logs take row 1-2, col 7-12 self.plot.listbox.grid(row=1, column=7, columnspan=5, sticky=N+S+E+W) listbox_yscroll = Scrollbar(self, command=self.plot.listbox.yview, orient=VERTICAL) listbox_yscroll.grid(row=1, column=12, sticky=N+S) self.plot.listbox["yscrollcommand"] = listbox_yscroll.set listbox_xscroll = Scrollbar(self, command=self.plot.listbox.xview, orient=HORIZONTAL) listbox_xscroll.grid(row=2, column=7, columnspan=5, sticky=E+W) self.plot.listbox["xscrollcommand"] = listbox_xscroll.set # Controls take row 0, col 0-12 Button(self, text="Load Directory", command=self.loaddir).grid(row=0, column=0) Button(self, text="Load File", command=self.loadfile).grid(row=0, column=1) Button(self, text="Fit X", command=self.plot.fit_x).grid(row=0, column=3, sticky=W) Button(self, text="Fit Y", command=self.plot.fit_y).grid(row=0, column=4, sticky=W) Button(self, text="Fit Auto", command=self.plot.fit_auto).grid(row=0, column=5, sticky=W) Button(self, text="Fit Tele", command=self.plot.fit_tele).grid(row=0, column=6, sticky=W) # Plot controls in a subframe to manage padding so it doesn't look awful move_mode_control = Frame(self, padx=10) Radiobutton(move_mode_control, text="Pan", value="pan", variable=move_mode).grid(row=0, column=0, sticky=W) Radiobutton(move_mode_control, text="Zoom In", value="zoomin", variable=move_mode).grid(row=0, column=1, sticky=W) Radiobutton(move_mode_control, text="Zoom Out", value="zoomout", variable=move_mode).grid(row=0, column=2, sticky=W) move_mode_control.grid(row=0, column=7, sticky=W) Checkbutton(self, text="Event Bars", variable=event_bars, command=self.plot.show_textlogs).grid(row=0, column=8, sticky=W) Checkbutton(self, text="Debug", variable=show_debug, command=self.plot.show_textlogs).grid(row=0, column=9, sticky=W) Checkbutton(self, text="Error", variable=show_error, command=self.plot.show_textlogs).grid(row=0, column=10, sticky=W) Checkbutton(self, text="Warning", variable=show_warning, command=self.plot.show_textlogs).grid(row=0, column=11, sticky=W) Checkbutton(self, text="Info", variable=show_info, command=self.plot.show_textlogs).grid(row=0, column=12, sticky=W) Checkbutton(self, text="Directories", variable=show_path, command=self.plot.show_textlogs).grid(row=0, column=13, sticky=E) # Open Directory button clicked def loaddir(self): dirname = tkFileDialog.askdirectory(initialdir=log_dir) if dirname != "" and dirname != (): # Cancel and (x) not pressed # Empty the data self.used = [] self.series = {} self.names = [] self.queues = [] self.logs = {} self.plot.reset() for node in self.series_ui.get_children(): self.series_ui.delete(node) # For every csv file in the directory, checking recursively and alphabetically for subdirname, subsubdirnames, filenames in os.walk(dirname): subsubdirnames.sort() filenames.sort() for filename in filenames: if filename.endswith(".csv") or filename.endswith(".log"): # The name of the directory without the name of the directory selected, # and the name of the file without the extension, separated by "."s # For example if directory selected is /tmp/logs, subdirname is /tmp/logs/beta/666, # and filename is foo.csv, nodeprefix is "beta.666.foo". nodeprefix = ".".join(subdirname[len(dirname)+1:].split("/") + [filename[:-4]]) if nodeprefix.startswith("."): nodeprefix = nodeprefix[1:] # Add the file's data self.readfile(subdirname + "/" + filename, nodeprefix) for name in self.names: # Add name to (name with everything after last dot removed), as the last child, # with text (everything after last dot of name) and tags graphnone and (whether name represents data) self.series_ui.insert(".".join(name.split(".")[0:-1]), "end", name, text=name.split(".")[-1], tags=["graphnone"]) # Open File button clicked def loadfile(self): filename = tkFileDialog.askopenfilename(filetypes=[("CSV Files", "*.csv"), ("Text log file", "*.log")], initialdir=log_dir) if filename != "" and filename != (): # Cancel and (x) not pressed # Empty the data self.used = [] self.series = {} self.names = [] self.queues = [] self.logs = {} self.plot.reset() for node in self.series_ui.get_children(): self.series_ui.delete(node) # Add the file's data self.readfile(filename, "") for name in self.names: # Add name to (name with everything after last dot removed), as the last child, # with text (everything after last dot of name) and tags graphnone and (whether name represents data) self.series_ui.insert(".".join(name.split(".")[0:-1]), "end", name, text=name.split(".")[-1], tags=["graphnone"]) # Add a file's data # nodeprefix is a string to add before every name in the file, represents file's name in the tree def readfile(self, filename, nodeprefix): try: if filename.endswith(".csv"): # For csv files this will always be concatenated with something if nodeprefix != "": nodeprefix += "." csvfile = open(filename, "rb") reader = csv.DictReader(csvfile) series = {} self.queues.append(nodeprefix[:-1]) for name in reader.fieldnames: # Add ancestor_names to names, without creating duplicates self.names = list(OrderedDict.fromkeys(self.names + ancestor_names(nodeprefix + name))) # Create a series for this field series[nodeprefix + name] = [] for row in reader: for name in reader.fieldnames: try: # Add cell to series if it represents a number series[nodeprefix + name].append(float(row[name])) except ValueError: # Not a number, no problem, could be game_specific_string or something pass self.series.update(series) else: self.names.append(nodeprefix) self.logs[nodeprefix] = open(filename, "r").readlines() except IOError: tkMessageBox.showerror(message="Could not open file: " + str(filename)) # Tree element was double clicked def onselect(self, _): series = self.series_ui.focus() # Set it to graph if no children are graphed, and not to graph if all or some are self.setgraphed(series, self.series_ui.tag_has("graphnone", series)) self.checkgraphed(series) # Set a node and its children to be either all or none graphed def setgraphed(self, node, shouldgraph): if shouldgraph: self.series_ui.item(node, tags=["graphall"]) # If the node represents data and it isn't already graphed, graph it if node in self.series and node not in self.used: self.used.append(node) # Timestamp is queue that contains node + ".timestamp" timestamp_name = [queue for queue in self.queues if node.startswith(queue)][0] + ".timestamp" self.plot.add_plot(self.series[timestamp_name], self.series[node], node) if node in self.logs and node not in self.used: self.used.append(node) self.plot.add_textlog(self.logs[node], node) # If nothing else is plotted, fit the plot to this if len(self.used) == 1: self.plot.fit_x() self.plot.fit_y() for child in self.series_ui.get_children(node): self.setgraphed(child, True) else: # Set tags to be (whether node represents data) and graphnone self.series_ui.item(node, tags=["graphnone"]) if node in self.used: self.used.remove(node) if node in self.logs: self.plot.remove_textlog(node) if node in self.series: self.plot.remove_plot(node) for child in self.series_ui.get_children(node): self.setgraphed(child, False) # Update the tags (and color) on a node and its ancestors, should always be called after setgraphed def checkgraphed(self, node): # Top level nodes are children of "" if node == "": return # True unless a child doesn't share this tag or there are no children graphall = True graphnone = True for child in self.series_ui.get_children(node): if not self.series_ui.tag_has("graphall", child): graphall = False if not self.series_ui.tag_has("graphnone", child): graphnone = False graphtag = "" if graphall and graphnone: # There are no children, check the used list instead graphtag = "graphall" if node in self.used else "graphnone" elif graphall: graphtag = "graphall" elif graphnone: graphtag = "graphnone" else: graphtag = "graphsome" # Set tags to be (whether node represents data) and the computed status self.series_ui.item(node, tags=[graphtag]) # Now that the status of this node is known, check the parent self.checkgraphed(self.series_ui.parent(node))
class WaitingRoom(cll.ClientListener, object): #Note: extending cll.ClientListener if Gui does not extend WaitingRoom def __init__(self): self.Names = [] self.tree_headers = ['Player','Status','Address','Game','Color'] self.quit = False #quit program after wroom has been closed. it will be passed to Gui.quit def startWaitingRoomUI(self, pumpit): self.pumpit = True if 'pumpit' in locals(): self.pumpit = pumpit cfg.wroom = Tk() cfg.wroom.protocol("WM_DELETE_WINDOW", self.quitWaitingRoom) """State variables - By using textvariable=var in definition widget is tied to this variable""" statusmsg_sv = StringVar() #needed entry_sv = StringVar(value = cfg.name) #entry_sv.trace("w", lambda name, index, mode, sv=entry_sv: self.changeName(sv)) chatentry_sv = StringVar(value = "Press enter to chat") """Create and grid the outer content frame""" content = ttk.Frame(cfg.wroom) #, padding=(5, 5, 12, 0)) #Frame in cfg.wroom content.grid(column = 0, row = 0, sticky = (N,W,E,S)) cfg.wroom.grid_columnconfigure(0, weight = 1) cfg.wroom.grid_rowconfigure(0, weight = 1) """Create the different widgets; note the variables that some widgets are bound to""" self.tree = Treeview(content, show="headings", columns=cfg.wroominstance.tree_headers, name = "treeview") self.tree.column("#1", minwidth = 100, width = 120, stretch = NO) self.tree.column("#2", minwidth = 30, width = 60, stretch = NO) self.tree.column("#3", minwidth = 30, width = 50, stretch = YES) self.tree.column("#4", minwidth = 30, width = 50, stretch = YES) self.tree.column("#5", minwidth = 30, width = 50, stretch = YES) namelbl = ttk.Label(content, text="Player name") self.nameentry = ttk.Entry(content, bg = 'white', textvariable = entry_sv, name = "nameentry")#, validatecommand=validateIt) colorlbl = ttk.Label(content, text="Player color") self.colorframe = ttk.Frame(content, name = "colorframe", borderwidth = 1, relief='sunken') lbl = ttk.Label(content, text="Send to player:") #Label on the right self.log = Listbox(content, height = 5, bg = 'white', name = "logbox")#, listvariable=cmessagelog #Listbox with messages self.chatAll = ttk.Button(content, text = 'Chat to All', command = self.chatToAll, default = 'active', width = '6',name = "chat") self.chatentry = ttk.Entry(content, bg = 'white', foreground = 'gray', textvariable = chatentry_sv, name = "chatentry", selectforeground = 'blue') testbtn = ttk.Button(content, text = 'Connections', command = self.test, default = 'active', width = '6', name = "testbtn") ready = ttk.Button(content, text = 'Ready', command = self.toggleReadyForGame, default = 'active', width = '6', name = "readybtn") solitaire = ttk.Button(content, text = 'Solitaire', command = self.solitaire, default = 'active', width = '6', name = "solitairebtn") quit = ttk.Button(content, text = 'Quit', command = self.quitWaitingRoom, default = 'active', width = '6', name = "quitbtn") status = ttk.Label(content, textvariable = statusmsg_sv, anchor = W, name = "statuslbl") #Label on the bottom def get_tree(): """Get from the self.tree an item when clicked""" idxs = self.tree.item(self.tree.focus()) vals = idxs['values'] if len(idxs['values'])==0: return None return vals """def sortby(tree, col, descending): Sort tree contents when a column header is clicked on # grab values to sort data = [(tree.set(child, col), child) \ for child in tree.get_children('')] # now sort the data in place data.sort(reverse=descending) for ix, item in enumerate(data): tree.move(item[1], '', ix) # switch the heading so it will sort in the opposite direction tree.heading(col, command=lambda col=col: sortby(tree, col, int(not descending))) """ def showstatus(*args): """Called when the selection in the listbox changes; Update the status message on the bottom with the new information""" list = get_tree() if list is None: return statusmsg_sv.set("Player %s has this status: %s" % (list[0], list[1])) # Grid all the widgets self.tree.grid(row = 0, column = 0, rowspan = 9, sticky = (N,S,E,W)) namelbl.grid(row = 0, column = 1, columnspan = 2, sticky = (N,W), padx = 5) self.nameentry.grid(row = 1, column = 1, columnspan = 2, sticky = (N,E,W), pady = 5, padx = 5) colorlbl.grid(row = 0, column = 3, columnspan = 1, sticky = (N,W), padx = 5) self.colorframe.grid(row = 1, column = 3, columnspan = 1, sticky = (N,E,W), pady = 5, padx = 5) #testbtn.grid(row = 3, column = 3, columnspan = 1, sticky = E, padx = 5) #Test Button self.log.grid(row = 5, column = 1, columnspan = 3, sticky = (N,S,E,W), padx = 5, pady = 5) #Listbox with all messages self.chatentry.grid(row = 6, column = 1, columnspan = 2, sticky = (N,E), padx = 5, pady = 5) self.chatAll.grid(row = 6, column = 3, columnspan = 1, sticky = (N,E), padx = 5, pady = 5) ready.grid(row = 7, column = 1, sticky = (W,S), padx = 5, pady = 5) # solitaire.grid(row = 7, column = 2, sticky = (W,S), padx = 5, pady = 5) quit.grid(row = 7, column = 3, sticky = (W,S), padx = 5, pady = 5) status.grid(row = 9, column = 0, columnspan = 2, sticky = (W,E)) """Configure content Frame and color Frame""" content.grid_columnconfigure(0, weight = 1) content.grid_rowconfigure(5, weight = 1) h = self.nameentry.winfo_reqheight() self.colorframe.configure(height = h, bg = 'red') """Set event bindings""" self.tree.bind('<<TreeviewSelect>>', showstatus) self.nameentry.bind('<Return>', (lambda _: self.askChangeName(self.nameentry))) self.nameentry.bind('<FocusOut>', (lambda _: self.askChangeName(self.nameentry))) cfg.wroom.bind('<Control-Key-w>', self.quitWaitingRoom) cfg.wroom.bind('<Control-Key-q>', self.quitWaitingRoom) cfg.wroom.bind('<Control-Key-r>', self.toggleReadyForGame) cfg.wroom.bind('<Control-Key-s>', self.solitaire) self.chatentry.bind("<Return>",self.chatToAll) def chatEntryActive(e = None): self.chatentry.config(foreground = 'black') self.chatentry.delete(0, 'end') def chatEntryInactive(e = None): print(self) chatentry_sv.set("Press enter to chat") self.chatentry.config(foreground = 'gray') self.chatentry.bind("<FocusIn>", lambda e: chatEntryActive(e)) self.chatentry.bind("<FocusOut>", lambda e: chatEntryInactive(e)) self.colorframe.bind("<ButtonRelease-1>", self.changeColor) """Set tooltips on widgets""" hover.createToolTip(namelbl, "Type in your name") hover.createToolTip(self.nameentry, "Type in your name") hover.createToolTip(ready, "Toggle ready state to play tantrix with other players") hover.createToolTip(solitaire, "Start a two player game on this computer") hover.createToolTip(quit, "Quit Tantrix") hover.createToolTip(self.chatentry, "Press enter to send to chat") hover.createToolTip(self.chatAll, "Press enter to send to chat") hover.createToolTip(self.colorframe, "Click to select your color") hover.createToolTip(colorlbl, "Your color") """Set the starting state of the interface""" statusmsg_sv.set('') showstatus() """Start main loop for tkinter and Sixpodnet""" self.keepLooping = True if self.pumpit: self.mainLoopWithPump() else: self.mainLoopWithoutPump() return self.quit def test(self): if self.pumpit: self.send_to_server("test") def chatToAll(self, e = None): """Chat to every player in the wroom""" """Get the chat entry and add it to the local log""" msgList = [self.chatentry.get()] if len(msgList[0]) is 0: return """Send message to server""" self.sendChatToAll(msgList = msgList) """Clear chat entry""" self.chatentry.delete(0, 'end') self.chatentry.focus_set() def buildTree(self, tree_list): def sortby(tree, col, descending): """Sort tree contents when a column header is clicked on""" # grab values to sort data = [(tree.set(child, col), child) \ for child in tree.get_children('')] # now sort the data in place data.sort(reverse=descending) for ix, item in enumerate(data): tree.move(item[1], '', ix) # switch the heading so it will sort in the opposite direction tree.heading(col, command=lambda col=col: sortby(tree, col, int(not descending))) for ind, col in enumerate(self.tree_headers): self.tree.heading(ind, text=col.title(),command=lambda c=col: sortby(self.tree, c, 0))# # adjust the column's width to the header string #self.tree.column(col, width=tkFont.Font().measure(col.title())) """Convert Status and Game to a better format, then insert in Treeview""" convert_status = {0: "Idle", 1: "Ready", -1: "Playing", -2: "Solitaire"} for item in tree_list: item[1] = convert_status[item[1]] if item[3] is None: item[3] = "" self.tree.insert('', 'end', values=item) # adjust column's width if necessary to fit each value #import Tkinter.font as tkFont #for ix, val in enumerate(item): #col_w = tkFont.Font().measure(val) #if self.tree.column(selfcfg.wroominstance.tree_headers[ix],width=None)<col_w: #self.tree.column(selfcfg.wroominstance.tree_headers[ix], width=col_w) def addToMessageLog(self, listToLog, fg = 'black'): """Add a line to the log listbox""" for item in listToLog: self.log.insert(END, item) self.log.itemconfig(END, {'fg': fg}) self.log.select_set(END) self.log.yview(END) def searchTreeByHeader(self, val, header = 'Player'): """Return item in Treeview by player name""" val = str(val) items = self.tree.get_children() headerIndToSearchInto = cfg.wroominstance.tree_headers.index(header) # ['Player','Status','Address'] for item in items: itemval = str(self.tree.item(item, 'values')[headerIndToSearchInto]) if itemval.startswith(val): return item return None def editItemInTree(self, item, valList, headerList = ['Player']): """Edit an item of TreeView by its header(s)""" #Get the current (old) values as a list old_vals = self.tree.item(item)['values'] #Create a list with the new values newvalues = list(old_vals) for ind, header in enumerate(headerList): #Get from headerList which index should be changed headerIndex = cfg.wroominstance.tree_headers.index(header) newvalues[headerIndex] = valList[ind] #Finally change the old values self.tree.item(item, values=newvalues) def removeFromTree(self, name = ''): """remove an item of TreeView by its name filed""" item = self.searchTreeByHeader(name, header = 'Player') if item is not None: self.tree.delete(item) def askChangeName(self, sv): """User wants to change name. Ask server if ok""" name = sv.get() self.sendChangedName(name) def changeName(self, name): """Server sends the name of this player""" self.nameentry.delete(0, END) self.nameentry.insert(0, name) cfg.name = name cfg.wroom.title(name + ": waiting room") cfg.wroom.update() def changeColor(self, e = None): current = self.colorframe.cget('bg') color_ind = cfg.PLAYERCOLORS.index(current) + 1 color = cfg.PLAYERCOLORS[color_ind % 4] self.colorframe.configure(bg = color) cfg.playercolor = color self.sendChangedColor(color) def toggleReadyForGame(self, e = None): if self.pumpit: self.sendToggleReady() #Change button layout when clicked frame = cfg.wroom.winfo_children()[0] readybtn = frame.children['readybtn'] """Configure the button""" if readybtn.config('relief')[4]=='raised': readybtn.configure(relief='sunken') readybtn.configure(bg = 'green') elif readybtn.config('relief')[4]=='sunken': readybtn.configure(relief='raised') readybtn.configure(bg = '#d6d6d6') sleep(0.1) cfg.wroom.update() def quitWaitingRoom(self, e = None): print("Quitting the waiting room") self.keepLooping = False self.quit = True #used to quit everything after wroom has been closed if self.pumpit: self.send_to_server("quit") def solitaire(self, e = None): print("Starting a game on one client (solitaire)") cfg.solitaire = True self.keepLooping = False if self.pumpit: self.sendSolitaire() #cfg.wroominstance.tree = None def mainLoopWithoutPump(self): """Start main loop in waiting room. Do not use Sixpodnet to connect with server""" while self.keepLooping: #self.keepLooping changed by callbacks below """Update the boards""" cfg.wroom.update() cfg.wroom.update_idletasks() cfg.wroom.destroy() def mainLoopWithPump(self): """Start main loop in waiting room""" while self.keepLooping: #self.keepLooping changed by callbacks below """Polling loop for the client. asks the connection singleton for any new messages from the network""" connection.Pump() """Server""" self.Pump() """Check if there is a connection. If so start the waiting room, else go to preSolitaire""" if cfg.connected: """Update the boards""" cfg.wroom.update() cfg.wroom.update_idletasks() else: global attempt2connect attempt2connect += 1 if attempt2connect == 20: self.solitaire() cfg.wroom.destroy()
class XML_Viwer(Frame): def __init__(self, master, xml=None, heading_text=None, heading_anchor=None, padding=None, cursor=None, takefocus=None, style=None): Frame.__init__(self, master, class_="XML_Viwer") self._vsb = Scrollbar(self, orient=VERTICAL) self._hsb = Scrollbar(self, orient=HORIZONTAL) kwargs = {} kwargs["yscrollcommand"] = lambda f, l: autoscroll(self._vsb, f, l) kwargs["xscrollcommand"] = lambda f, l: autoscroll(self._hsb, f, l) if style is not None: kwargs["style"] = style if padding is not None: kwargs["padding"] = padding if cursor is not None: kwargs["cursor"] = cursor if takefocus is not None: kwargs["takefocus"] = takefocus self._treeview = Treeview(self, **kwargs) if heading_text is not None: if heading_anchor is not None: self._treeview.heading("#0", text=heading_text, anchor=heading_anchor) else: self._treeview.heading("#0", text=heading_text) self._treeview.bind("<<TreeviewOpen>>", self._on_open) self._treeview.bind("<<TreeviewClose>>", self._on_close) # Without this line, horizontal scrolling doesn't work properly. self._treeview.column("#0", stretch= False) self._vsb['command'] = self._treeview.yview self._hsb['command'] = self._treeview.xview self._treeview.grid(column=0, row=0, sticky=N+S+W+E) self._vsb.grid(column=1, row=0, sticky=N+S) self._hsb.grid(column=0, row=1, sticky=E+W) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self._element_tree = None self._item_ID_to_element = {} if xml is not None: self.parse_xml(xml) def _on_open(self, event): item_ID = self._treeview.focus() if item_ID not in self._item_ID_to_element: return node = self._item_ID_to_element[item_ID] self._treeview.item(item_ID, text = self._repr_of_openning_tag(node)) def _on_close(self, event): item_ID = self._treeview.focus() if item_ID not in self._item_ID_to_element: return node = self._item_ID_to_element[item_ID] text = self._repr_of_openning_tag(node) + self._repr_of_closing_tag(node) self._treeview.item(item_ID, text = text) def parse_xml(self, xml): self._element_tree = ET.ElementTree(ET.fromstring(xml)) self.clear() self._walk_xml(self._element_tree.getroot()) @property def element_tree(self): return self._element_tree @element_tree.setter def element_tree(self, element_tree): self._element_tree = element_tree self.clear() self._walk_xml(element_tree.getroot()) def clear(self): self._item_ID_to_element = {} self._treeview.delete(*self._treeview.get_children()) def _repr_of_openning_tag(self, node): text = "<" + node.tag attrs = node.attrib # list function is here necessary to provide support to Python 3 a_names = list(attrs.keys()) a_names.sort() for a_name in a_names: text += ' %s="' % a_name text += attrs[a_name] text += '"' text += ">" return text def _repr_of_closing_tag(self, node): return "</%s>"%node.tag def _walk_xml(self, node, depth=0, parent=""): text = self._repr_of_openning_tag(node) + self._repr_of_closing_tag(node) item = self._treeview.insert(parent, END, text = text) self._item_ID_to_element[item] = node if node.text: text = node.text.strip() if text != "": for line in text.splitlines(): self._treeview.insert(item, END, text = line) child_nodes = sorted(list(node), key=attrgetter('tag')) for child_node in node: self._walk_xml(child_node, depth+1, parent=item) if node.tail: tail = node.tail.strip() if tail != "": for line in tail.splitlines(): self._treeview.insert(parent, END, text = line)
class LobbyUI(Frame): """ Sudoku multiplayer lobby UI class. In case of incorrect inputs error messages are shown. """ action = None def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.row, self.col = -1, -1 self.__initUI() def __initUI(self): """ Initialize UI with a list and required entry fields and submit buttons.""" self.parent.title('Multiplayer Game') self.pack(fill=BOTH, expand=1) self.lobby_list = Treeview(self, columns=('room', 'players')) self.lobby_list['show'] = 'headings' self.lobby_list.heading('room', text='Room ID') self.lobby_list.column('room', width=250, anchor=CENTER) self.lobby_list.heading('players', text='Players') self.lobby_list.column('players', width=100, anchor=CENTER) self.lobby_list.grid(row=1, column=0, columnspan=2, rowspan=2, padx=20, pady=(10, 0)) self.connect_lobby = Button(self, text='Joining Sudoku\n Solving Session', command=self.__connect_lobby) self.connect_lobby.grid(row=3, column=1, pady=(0, 10)) Label(self, text='Creating new Sudoku\n solving session:').grid(row=4, column=0) self.max_players = Entry(self) self.max_players.grid(row=4, column=1) self.create_game = Button(self, text='Join new game', command=self.__create_game) self.create_game.grid(row=5, column=1) def __connect_lobby(self): """ Handle lobby connection button.""" LOG.debug('Lobby connect button has been pressed.') current_item = self.lobby_list.focus() selected_id = None if current_item is not None and current_item.strip() != '': # Select game column value from item values dictionary. selected_id = self.lobby_list.item(current_item)['values'][0] LOG.debug('Player wishes to join game ' + str(selected_id)) if selected_id is not None: self.action = ('select', selected_id) else: tkMessageBox.showwarning( "Connection error", "Please select a game from the lobby to join.") def __create_game(self): """ Create game with some number of max players.""" max_ok = False try: max_count = int(self.max_players.get()) except (ValueError, TypeError): max_count = -1 tkMessageBox.showwarning("Input error", "Max player count has to be an integer.") if isinstance(max_count, int): if max_count >= 2: max_ok = True LOG.debug('Ok max player count.') else: tkMessageBox.showwarning( "Input error", "Max player count has to be larger than 2.") LOG.error('Bad max count.') if max_ok: self.action = ('create', max_count) def populate_list(self, games): """ Method to re-populate the lobby list every poll. Additionally retains the focused line during polling. :param games: """ previous_selection = self.lobby_list.selection() prev_item = None if len(previous_selection) > 0: prev_item = self.lobby_list.item(previous_selection[0]) self.lobby_list.delete(*self.lobby_list.get_children()) for game in games: self.lobby_list.insert('', 'end', values=(str(game[0]), str(game[1]) + '/' + str(game[2]))) if prev_item is not None: for item in self.lobby_list.get_children(): if self.lobby_list.item(item) == prev_item: self.lobby_list.selection_set(item) self.lobby_list.focus(item)
class pylasticGUI(Frame): def __init__(self): self.__fileName = 'POSCAR' self.__NoP = 11 self.__strain = 0.05 self.__executable = '/home/t.dengg/bin/vasp/vasp.5.3/vasp' self.__status = None self.__finished = None self.__paths = None self.__structuresinst = None self.__p1 = None self.__p2 = None self.__workdir = os.getcwd() Frame.__init__(self, name = 'pylastic') self.grid(row=0, column=0, sticky=NSEW) #self.pack(expand=Y, fill=BOTH) self._create_panel() def _create_panel(self): panel = Frame(self, name='elastic') #panel.pack(side=TOP, fill=BOTH, expand=Y) panel.grid(row=0, column=0, sticky=NSEW) nb = Notebook(panel, name='notebook') nb.enable_traversal() #nb.pack(fill=BOTH, expand=Y, padx=2, pady=3) nb.grid(row=0, column=0, sticky=NSEW) self._create_setup_tab(nb) self._create_analyze_tab(nb) def _create_setup_tab(self, nb): frame = Frame(nb, name='setup') self.e1 = Entry(frame, width=7) self.e1.bind() self.e1.grid(row=0, column=1) self.e1.delete(0, END) self.e1.insert(0, '21') self.label1 = Label(frame, text='Number of points:') self.label1.grid(row=0, column=0, sticky=W) self.e2 = Entry(frame, width=7) self.e2.bind() self.e2.grid(row=1, column=1) self.e2.delete(0, END) self.e2.insert(0, '0.05') self.label2 = Label(frame, text='Max. Lagrangian strain:') self.label2.grid(row=1, column=0, sticky=W) #Choose inputfile (Button) b2 = Button(frame, text="Inputfile", width=15, command=self.select_file) b2.grid(row=3, column=0, columnspan=2) b = Button(frame, text="set values", width=15, command=self.read_val) b.grid(row=4, column=0, columnspan=2) #Read structure (Button) b1 = Button(frame, text="Read structure", width=15, command=self.read_POS) b1.grid(row=5, column=0, columnspan=2) #Write structures (Button) b3 = Button(frame, text="Setup calculation", width=15, command=self.setup_calc) b3.grid(row=6, column=0, columnspan=2) #Strart calculations b4 = Button(frame, text="Calculation status", width=15, command=self.check_calc) b4.grid(row=7, column=0, columnspan=2) v = IntVar() r11 = Radiobutton(frame, text="Energy", variable=v, value=1) r12 = Radiobutton(frame, text="Strain", variable=v, value=2, state=DISABLED) r11.select() r11.grid(row=8, column=0, sticky=W) r12.grid(row=9, column=0, sticky=W) w = IntVar() r21 = Radiobutton(frame, text="2nd", variable=w, value=1) r22 = Radiobutton(frame, text="3rd", variable=w, value=2) r21.select() r21.grid(row=10, column=0, sticky=W) r22.grid(row=11, column=0, sticky=W) nb.add(frame, text='Setup', underline=0, padding=2) return def _create_analyze_tab(self, nb): frame = Frame(nb, name='analyze') self._create_treeview(frame, ) root = self.tree.insert('', END, text = 'calc', values=['text1','text2']) #self._populate_tree(root) # b1 = Button(frame, text="Refresh", width=15, command=lambda: self._populate_tree(root)) b1.grid(row=2, column=0) b2 = Button(frame, text="Analyze", width=15, command=lambda: self.analyze(frame)) b2.grid(row=2, column=1) b2 = Button(frame, text="Result", width=15, command=lambda: self.create_window()) b2.grid(row=2, column=2) if self.__status and '--------' in self.__status: self.__finished = False else: self.__finished = True if self.__status and self.__finished: ECs.set_analytics() nb.add(frame, text='Analyze', underline=0, padding=2) return def _populate_tree(self, root, lock=None): if lock: lock.acquire() if len(self.tree.get_children(self.tree.get_children())) > 1: for i in self.tree.get_children(self.tree.get_children()): self.tree.delete(i) #self.tree.delete(self.tree.get_children()) status, paths = self.check_calc() for key in status.keys(): #print paths[key].lstrip(self.__workdir).split('/') self.tree.insert(root, END, text = status[key], values=['text3','text4', paths[key]]) if lock: lock.release() def _create_treeview(self, parent): f = Frame(parent) #f.pack(side=TOP, fill=BOTH, expand=Y) f.grid(row=0, column=0, sticky=NSEW, columnspan=3) # create the tree and scrollbars self.dataCols = ('fullpath', 'type', 'status') self.tree = Treeview(columns=self.dataCols, displaycolumns='status') ysb = Scrollbar(orient=VERTICAL, command= self.tree.yview) xsb = Scrollbar(orient=HORIZONTAL, command= self.tree.xview) self.tree['yscroll'] = ysb.set self.tree['xscroll'] = xsb.set # setup column headings self.tree.heading('#0', text='Directory Structure', anchor=W) self.tree.heading('status', text='Status', anchor=W) self.tree.column('status', stretch=0, width=100) # add tree and scrollbars to frame self.tree.grid(in_=f, row=0, column=0, sticky=NSEW) ysb.grid(in_=f, row=0, column=1, sticky=NS) xsb.grid(in_=f, row=1, column=0, sticky=EW) # set frame resizing priorities f.rowconfigure(0, weight=1) f.columnconfigure(0, weight=1) # action to perform when a node is expanded self.tree.bind('<<TreeviewOpen>>', self._update_tree) self.tree.bind("<Double-1>", self.OnDoubleClick) def OnDoubleClick(self, event): item = self.tree.identify('item',event.x,event.y) if self.tree.item(item,"text") == 'calc': self.create_window() def _update_tree(self, event): # user expanded a node - build the related directory nodeId = self.tree.focus() # the id of the expanded node if self.tree.parent(nodeId): # not at root topChild = self.tree.get_children(nodeId)[0] # if the node only has a 'dummy' child, remove it and # build new directory; skip if the node is already # populated if self.tree.item(topChild, option='text') == 'dummy': self.tree.delete(topChild) path = self.tree.set(nodeId, 'fullpath') self._populate_tree(nodeId, path, os.listdir(path)) def create_window(self): t = Toplevel(self) t.wm_title("Elastic constants") l = Label(t, text="Elastic constants:") l.grid(row=0, column=0) textf = Text(t) try: textf.insert(INSERT, self.ec.get_C()) except: textf.insert(INSERT, '') textf.grid(row=1, column=0) def read_val(self): self.__NoP = float(self.e1.get()) self.__strain = float(self.e2.get()) def read_POS(self): self.__poscar = POS(self.__fileName).read_pos() #print self.__poscar def read_strain(self): self.__strain = self.e2.get() def select_file(self): self.__fileName = askopenfilename() print self.__fileName self.__workdir = self.__fileName.rstrip('POSCAR') print self.__workdir def setup_calc(self): ###################### Create Structures instance: ################### self.__structuresinst = Structures() ## Generate distorted structures and add them to structures object: ## atom = ElAtoms() print self.__poscar atom.poscarToAtoms(self.__poscar) for etan in np.linspace(-self.__strain, self.__strain, self.__NoP): for strains in range(len(atom.strainList)): atom = ElAtoms() atom.poscarToAtoms(self.__poscar) atom.distort(eta=etan, strainType_index = strains) self.__structuresinst.append_structure(atom) ####################### Write vasp input files: ####################### self.__structuresinst.workdir = self.__workdir self.__structuresinst.write_structures(self.__structuresinst) #################### Start local vasp calculation: #################### if self.__executable: lock = thread.allocate_lock() self.__structuresinst.executable = self.__executable thread.start_new_thread(self.__structuresinst.calc_vasp, (lock,)) def check_calc(self): self.__status = {} self.__paths = {} if not self.__structuresinst: try: with open(self.__workdir+'/structures.pkl', 'rb') as input: structures = pickle.load(input) atoms = structures.get_structures() except: raise Exception("Please do setup first!") else: atoms = self.__structuresinst.get_structures() #print self.__structuresinst for stype, eta in atoms: #print stype, eta, atoms[(stype,eta)].path try: et.parse(atoms[(stype,eta)].path+'/vasprun.xml') self.__status[(stype,eta)] = 'finished' except: self.__status[(stype,eta)] = '--------' self.__paths[(stype,eta)] = atoms[(stype,eta)].path return self.__status, self.__paths def analyze(self, frame): if self.__status and '--------' in self.__status: self.__finished = False else: self.__finished = True if self.__status and self.__finished: self.ec = ECs() self.ec.set_structures() self.ec.set_gsenergy() self.ec.set_analytics() self.__p1 = self.ec.plot_cvs() self.__p2 = self.ec.plot_2nd() canvas = FigureCanvasTkAgg(self.__p1, master=frame) canvas.show() canvas.get_tk_widget().grid(row=3, column=0) canvas = FigureCanvasTkAgg(self.__p2, master=frame) canvas.show() canvas.get_tk_widget().grid(row=3, column=1) canvas._tkcanvas.grid(row=3, column=2)
class GUIMainMenu(Frame): """Main menu for test of Genesi i.MX53 systems""" def __init__(self,master=None): """Initialize the base class""" Frame.__init__(self,master) """Set window title""" self.master.title("Select System Test") """System Tests""" self.createTestEntries() """Constants""" self.TEST_COL=0 self.STATUS_COL=1 self.TEXT_ROW=0 self.TREEVIEW_ROW=1 self.BUTTON_ROW=2 """Display main window with padding""" self.grid() self.createWidgets() def createTestEntries(self): #TODO must be a better way. Pickle? self.tests = [TestInfo("Audio", AudioGUI), TestInfo("Clock", Dummy1), TestInfo("Display", Dummy1), TestInfo("Keyboard", Dummy1), TestInfo("Network", Dummy1), TestInfo("SSD", Dummy2), TestInfo("Video", VideoGUI)] self.testsLookup = {} for te in self.tests: self.testsLookup.update({te.name : te}) def createWidgets(self): """Create all the initial widgets for this menu""" """Labels""" lbl = Label(self, text="Select test below", justify=LEFT) lbl.grid(row=self.TEXT_ROW, column=self.TEST_COL) """Tests""" self.trv = Treeview(self, columns=("Status"), displaycolumns='#all') for test in self.tests: treeviewInsertTest(self.trv, test) self.trv.column('#0', width=100) self.trv.heading('#0', text="Test") self.trv.heading('Status', text='Status') self.trv.grid(column=self.TEST_COL, row=self.TREEVIEW_ROW, columnspan=2) """Buttons""" self.btnOK = Button(self, text="OK", command=self.launchTest) self.btnOK.grid(row=self.BUTTON_ROW, column=0) self.btnQuit = Button(self, text="Quit", command=self.quit) self.btnQuit.grid(row=self.BUTTON_ROW, column=1) def launchTest(self): # get the item in focus testItem = self.trv.item(self.trv.focus()) if not testItem['text'] == '': testInfo = self.testsLookup[testItem['text']] testInfo.launchTest(self) def processResults(self, testInfo): self.trv.item(testInfo.name, values=(testInfo.status), tags=(testInfo.status)) # update color notifications self.trv.tag_configure('Success', foreground='green') self.trv.tag_configure('Failure', foreground='red') self.deiconify() def withdraw(self): """Helpful function to hide window""" self.master.withdraw() def deiconify(self): """Helpful function to restore window""" self.master.deiconify()