def test_get(self): v = IntVar(self.root, 123, "name") self.assertEqual(123, v.get()) self.root.globalsetvar("name", "345") self.assertEqual(345, v.get()) self.root.globalsetvar("name", "876.5") self.assertEqual(876, v.get())
def test_invalid_value(self): v = IntVar(self.root, name="name") self.root.globalsetvar("name", "value") with self.assertRaises(ValueError): v.get() self.root.globalsetvar("name", "345.0") with self.assertRaises(ValueError): v.get()
class FrameKSPObject(Frame): def __init__(self, master=None): Frame.__init__(self, master) self.pack() frame = Frame(self) frame.pack() self.string_var0 = StringVar() self.string_var1 = StringVar() self.int_var = IntVar() self.entry0 = Entry(frame, textvariable=self.string_var0) self.entry0.pack(side='left') Entry(frame, textvariable=self.string_var1).pack(side='left') frame = Frame(self) frame.pack() Button(frame, width=8, text='Accept', command=self.accept).pack(side='left') Button(frame, width=8, text='Cancel', command=self.cancel).pack(side='left') Button(frame, width=8, text='Delete', command=self.delete).pack(side='left') def populate(self, kspobject): self._kspobject = kspobject self.string_var0.set(kspobject.name) self.string_var1.set(kspobject.value) self.int_var.set(kspobject.id_) def accept(self): name = self.string_var0.get() value = self.string_var1.get() id_ = self.int_var.get() self.master.master.update_kspobject(name, value, id_) self.master.destroy() def cancel(self): self.master.destroy() def delete(self): id_ = self.int_var.get() self.master.master.delete_kspobject(id_) self.master.destroy()
class ProgressCheckButton(Frame, Observable): def __init__(self, parent, model, index, status_model): Frame.__init__(self, parent) Observable.__init__(self) self.model = model self.index = index self.status_model = status_model self.var = IntVar() self.var.set(model.get_checked()) self.progress_var = IntVar() self.progress_status = ProgressStatus.undefined self.check_button = Checkbutton(self, text=model.get_label, variable=self.var, command=self._check_changed) self.progress_bar = Progressbar(self, orient='horizontal', mode='indeterminate', variable=self.progress_var) self.check_button.pack(side=LEFT, fill="both", expand=True) self.model.add_listener(self._model_changed) def _model_changed(self, new_status): model_state = self.model.get_checked() gui_state = self.var.get() if model_state is not gui_state: self.model.set_checked(gui_state) def refresh_check(self): if self.status_model.is_checked_force_reload(): self.check_button.select() else: self.check_button.deselect() def is_checked(self): return self.var.get() def _progress_status_changed(self, new_status): self._refresh_progress() def _refresh_progress(self): status = self.status_model.get_status() if not status == self.progress_status: if status == ProgressStatus.in_progress: self.progress_bar.pack(side=RIGHT, fill="both", expand=True) else: self.progress_bar.pack_forget() def _check_changed(self): new_checked = self.var.get() if new_checked is not self.model.get_checked(): self.model.set_checked(new_checked) if new_checked is not self.status_model.is_checked(): self._notify(self.index, new_checked)
class DlgLogin(Dialog): def body(self, master, cfg={}): "place user dialog widgets" self.config = cfg self.config["OK button"] = False self.site = StringVar() self.site.set(cfg.get("site", "")) self.login = StringVar() self.login.set(cfg.get("user", "")) self.password = StringVar() self.password.set(str(cfg.get("password", ""))) site = Entry(master, width=15, textvariable=self.site) site.grid(column=1, row=0, sticky="e") Label(master, text=_("Site:")).grid(column=0, row=0, sticky="w") loge = Entry(master, width=15, textvariable=self.login) loge.grid(column=1, row=1, sticky="e") Label(master, text=_("Username:"******"w") pase = Entry(master, width=15, textvariable=self.password, show="*") pase.grid(column=1, row=2, sticky="e") Label(master, text=_("Password:"******"w") self.to_remember = IntVar() self.to_remember.set(cfg.get("remember_passwd", 1)) chk1 = Checkbutton(master, text="Remember", variable=self.to_remember) chk1.grid(column=0, row=3, sticky="w", columnspan=2) self.resizable(width=0, height=0) return loge def apply(self): "On ok button pressed" self.config["remember_passwd"] = self.to_remember.get() self.config["site"] = self.site.get() self.config["user"] = self.login.get() self.config["password"].set_password(self.password.get()) self.config["OK button"] = True
class PasswordDialog(Dialog): def __init__(self, title, prompt, parent): self.prompt = prompt Dialog.__init__(self, parent, title) def body(self, master): from tkinter import Label from tkinter import Entry from tkinter import Checkbutton from tkinter import IntVar from tkinter import W self.checkVar = IntVar() Label(master, text=self.prompt).grid(row=0, sticky=W) self.e1 = Entry(master) self.e1.grid(row=0, column=1) self.cb = Checkbutton(master, text="Save to keychain", variable=self.checkVar) self.cb.pack() self.cb.grid(row=1, columnspan=2, sticky=W) self.e1.configure(show='*') def apply(self): self.result = (self.e1.get(), self.checkVar.get() == 1)
class Example(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() def initUI(self): self.parent.title("Checkbutton") self.pack(fill=BOTH, expand=1) self.var = IntVar() cb = Checkbutton(self, text="Show title", variable=self.var, command=self.onClick) cb.select() cb.place(x=50, y=50) def onClick(self): if self.var.get() == 1: self.master.title("Checkbutton") else: self.master.title("-")
class MainMenu(): def main(self): '''Function to run on game start''' self.mainMenu=Tk() self.mainMenu.geometry('200x300+200+200') self.mainMenu.title("Minesweeper") playButton=Button(self.mainMenu,text='Play',command=lambda:self.startPlay(None)) self.height= IntVar() self.width= IntVar() self.minesAmount= IntVar() self.height.set(10) self.width.set(10) self.minesAmount.set(10) playButton.pack() xSlider=Scale(self.mainMenu,orient='horizontal',length=150,width=15,label='Height',sliderlength=20,from_=1,to=15,tickinterval=0,variable=self.height).pack() ySlider=Scale(self.mainMenu,orient='horizontal',length=150,width=15,label='Width',sliderlength=20,from_=1,to=15,tickinterval=0,variable=self.width).pack() minesSlider=Scale(self.mainMenu,orient='horizontal',length=150,width=15,label='Mines',sliderlength=20,from_=0,to=15*15-1,tickinterval=0,variable=self.minesAmount).pack() aboutButton=Button(self.mainMenu,text='About',command=self.about) quitButton=Button(self.mainMenu,text='Quit',command=self.quitApp) aboutButton.pack() quitButton.pack() def startPlay(self,event): play=Play() minesAmount=self.minesAmount.get() height=self.height.get() width=self.width.get() if minesAmount>width*height-1: messagebox.showerror(title='Error',message="Amount of mines can't be bigger than total size of the field. Plese try again.") return self.mainMenu.destroy() play.StartGame(minesAmount,height,width) def about(self): messagebox.showinfo(title='About',message='Author:Marcel Salmič.') def quitApp(self): self.mainMenu.destroy()
def highlight_pattern(self, pattern, tag, start="1.0", end="end", regexp=False): start = self.index(start) end = self.index(end) self.mark_set("matchStart", start) self.mark_set("matchEnd", start) self.mark_set("searchLimit", end) count = IntVar() while True: index = self.search(pattern, "matchEnd","searchLimit", count=count, regexp=regexp) if index == "": break if count.get() == 0: break self.mark_set("matchStart", index) self.mark_set("matchEnd", "%s+%sc" % (index, count.get())) self.tag_add(tag, "matchStart", "matchEnd")
class Checkbox(Checkbutton): def __init__(self, master, text, default=None, **args): self.var = IntVar() Checkbutton.__init__(self, master, text=text, variable=self.var, **args) if default is not None: self.var.set(default) def get(self): return self.var.get()
class ValCheckbutton(Checkbutton): def __init__(self, master, **kw): self.intVal = IntVar() Checkbutton.__init__(self, master, var=self.intVal, **kw) def setVal(self, val): if bool(val): self.select() else: self.deselect() def getVal(self): return bool(self.intVal.get())
class ConfigDialog(Toplevel): '''Every instance of the TkTimer needs a Tk widget to call the after method. If no widget is provided, the TkTimer will create this ConfigDialog, and use its Toplevel's after method. ''' def __init__(self, *args, **kwargs): timer = kwargs.pop('timer') self.__timer = timer super().__init__(*args, **kwargs) interval = LabeledEntry(self) interval.label_text = 'Interval (ms)' interval.entry_text = str(timer.interval) interval.entry_width = 5 interval.pack(side='top') self.interval = interval self.active = IntVar(timer.active) Checkbutton(self, text='Activate', variable=self.active, command=self._on_active_button_click).pack(side='top') Button(self, text='OK', command=self._on_ok_button_click).pack(side='top') def hide(): self.visible = False self.protocol('WM_DELETE_WINDOW', hide) self.__visible = True self.visible = False def _on_active_button_click(self): self.__timer.active = self.active.get() def _on_ok_button_click(self): self.__timer.interval = self.interval.get_int() @property def visible(self): return self.__visible @visible.setter def visible(self, val): self.__visible = val if val: self.update() self.deiconify() else: self.withdraw()
class ProgressListBoxItem(Frame, Observable): def __init__(self, parent, model): Frame.__init__(self, parent) Observable.__init__(self) self._model = model # Create variables and initialise to zero self._checked_var = IntVar() self._progress_var = IntVar() self._checked_var.set(0) self._progress_var.set(0) self._current_gui_checked_state = CheckStatus.undefined self._current_gui_progress_state = ProgressStatus.undefined self.check_button = Checkbutton(self, text=model.get_label(), variable=self._checked_var, command=self._user_check_changed) self.progress_bar = Progressbar(self, orient='horizontal', mode='indeterminate', variable=self._progress_var) self.check_button.pack(side=LEFT, fill="both", expand=True) self._update() self._model.add_listener(self._model_changed) def _model_changed(self): self.update() def _update(self): # Update check status model_check_state = self._model.get_check_status() if model_check_state is not self._current_gui_checked_state: self._current_gui_checked_state = model_check_state # if self.status_model.is_checked_force_reload(): if model_check_state: self.check_button.select() else: self.check_button.deselect() # Update progress status model_progress_state = self._model.get_progress_status if not model_progress_state == self._current_gui_progress_state: self._current_gui_progress_state = model_progress_state if model_progress_state == ProgressStatus.in_progress: self.progress_bar.pack(side=RIGHT, fill="both", expand=True) else: self.progress_bar.pack_forget() def _user_check_changed(self): new_checked = self._checked_var.get() if new_checked is not self._model.get_check_status(): self._model.manual_set_checked(new_checked)
def highlight_pattern(self, pattern, tag, start="1.0", end="end", regexp=False): '''Apply the given tag to all text that matches the given pattern If 'regexp' is set to True, pattern will be treated as a regular expression ''' start = self.index(start) end = self.index(end) self.mark_set("matchStart",start) self.mark_set("matchEnd",start) self.mark_set("searchLimit", end) count = IntVar() while True: index = self.search(pattern, "matchEnd","searchLimit", count=count, regexp=regexp) if index == "": break self.mark_set("matchStart", index) self.mark_set("matchEnd", "%s+%sc" % (index,count.get())) self.tag_add(tag, "matchStart","matchEnd")
class ShiftReduceApp(object): """ A graphical tool for exploring the shift-reduce parser. The tool displays the parser's stack and the remaining text, and allows the user to control the parser's operation. In particular, the user can shift tokens onto the stack, and can perform reductions on the top elements of the stack. A "step" button simply steps through the parsing process, performing the operations that ``nltk.parse.ShiftReduceParser`` would use. """ def __init__(self, grammar, sent, trace=0): self._sent = sent self._parser = SteppingShiftReduceParser(grammar, trace) # Set up the main window. self._top = Tk() self._top.title('Shift Reduce Parser Application') # Animations. animating_lock is a lock to prevent the demo # from performing new operations while it's animating. self._animating_lock = 0 self._animate = IntVar(self._top) self._animate.set(10) # = medium # The user can hide the grammar. self._show_grammar = IntVar(self._top) self._show_grammar.set(1) # Initialize fonts. self._init_fonts(self._top) # Set up key bindings. self._init_bindings() # Create the basic frames. self._init_menubar(self._top) self._init_buttons(self._top) self._init_feedback(self._top) self._init_grammar(self._top) self._init_canvas(self._top) # A popup menu for reducing. self._reduce_menu = Menu(self._canvas, tearoff=0) # Reset the demo, and set the feedback frame to empty. self.reset() self._lastoper1['text'] = '' ######################################### ## Initialization Helpers ######################################### def _init_fonts(self, root): # See: <http://www.astro.washington.edu/owen/ROTKFolklore.html> self._sysfont = tkinter.font.Font(font=Button()["font"]) root.option_add("*Font", self._sysfont) # TWhat's our font size (default=same as sysfont) self._size = IntVar(root) self._size.set(self._sysfont.cget('size')) self._boldfont = tkinter.font.Font(family='helvetica', weight='bold', size=self._size.get()) self._font = tkinter.font.Font(family='helvetica', size=self._size.get()) def _init_grammar(self, parent): # Grammar view. self._prodframe = listframe = Frame(parent) self._prodframe.pack(fill='both', side='left', padx=2) self._prodlist_label = Label(self._prodframe, font=self._boldfont, text='Available Reductions') self._prodlist_label.pack() self._prodlist = Listbox(self._prodframe, selectmode='single', relief='groove', background='white', foreground='#909090', font=self._font, selectforeground='#004040', selectbackground='#c0f0c0') self._prodlist.pack(side='right', fill='both', expand=1) self._productions = list(self._parser.grammar().productions()) for production in self._productions: self._prodlist.insert('end', (' %s' % production)) self._prodlist.config(height=min(len(self._productions), 25)) # Add a scrollbar if there are more than 25 productions. if 1:#len(self._productions) > 25: listscroll = Scrollbar(self._prodframe, orient='vertical') self._prodlist.config(yscrollcommand = listscroll.set) listscroll.config(command=self._prodlist.yview) listscroll.pack(side='left', fill='y') # If they select a production, apply it. self._prodlist.bind('<<ListboxSelect>>', self._prodlist_select) # When they hover over a production, highlight it. self._hover = -1 self._prodlist.bind('<Motion>', self._highlight_hover) self._prodlist.bind('<Leave>', self._clear_hover) def _init_bindings(self): # Quit self._top.bind('<Control-q>', self.destroy) self._top.bind('<Control-x>', self.destroy) self._top.bind('<Alt-q>', self.destroy) self._top.bind('<Alt-x>', self.destroy) # Ops (step, shift, reduce, undo) self._top.bind('<space>', self.step) self._top.bind('<s>', self.shift) self._top.bind('<Alt-s>', self.shift) self._top.bind('<Control-s>', self.shift) self._top.bind('<r>', self.reduce) self._top.bind('<Alt-r>', self.reduce) self._top.bind('<Control-r>', self.reduce) self._top.bind('<Delete>', self.reset) self._top.bind('<u>', self.undo) self._top.bind('<Alt-u>', self.undo) self._top.bind('<Control-u>', self.undo) self._top.bind('<Control-z>', self.undo) self._top.bind('<BackSpace>', self.undo) # Misc self._top.bind('<Control-p>', self.postscript) self._top.bind('<Control-h>', self.help) self._top.bind('<F1>', self.help) self._top.bind('<Control-g>', self.edit_grammar) self._top.bind('<Control-t>', self.edit_sentence) # Animation speed control self._top.bind('-', lambda e,a=self._animate:a.set(20)) self._top.bind('=', lambda e,a=self._animate:a.set(10)) self._top.bind('+', lambda e,a=self._animate:a.set(4)) def _init_buttons(self, parent): # Set up the frames. self._buttonframe = buttonframe = Frame(parent) buttonframe.pack(fill='none', side='bottom') Button(buttonframe, text='Step', background='#90c0d0', foreground='black', command=self.step,).pack(side='left') Button(buttonframe, text='Shift', underline=0, background='#90f090', foreground='black', command=self.shift).pack(side='left') Button(buttonframe, text='Reduce', underline=0, background='#90f090', foreground='black', command=self.reduce).pack(side='left') Button(buttonframe, text='Undo', underline=0, background='#f0a0a0', foreground='black', command=self.undo).pack(side='left') def _init_menubar(self, parent): menubar = Menu(parent) filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label='Reset Parser', underline=0, command=self.reset, accelerator='Del') filemenu.add_command(label='Print to Postscript', underline=0, command=self.postscript, accelerator='Ctrl-p') filemenu.add_command(label='Exit', underline=1, command=self.destroy, accelerator='Ctrl-x') menubar.add_cascade(label='File', underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) editmenu.add_command(label='Edit Grammar', underline=5, command=self.edit_grammar, accelerator='Ctrl-g') editmenu.add_command(label='Edit Text', underline=5, command=self.edit_sentence, accelerator='Ctrl-t') menubar.add_cascade(label='Edit', underline=0, menu=editmenu) rulemenu = Menu(menubar, tearoff=0) rulemenu.add_command(label='Step', underline=1, command=self.step, accelerator='Space') rulemenu.add_separator() rulemenu.add_command(label='Shift', underline=0, command=self.shift, accelerator='Ctrl-s') rulemenu.add_command(label='Reduce', underline=0, command=self.reduce, accelerator='Ctrl-r') rulemenu.add_separator() rulemenu.add_command(label='Undo', underline=0, command=self.undo, accelerator='Ctrl-u') menubar.add_cascade(label='Apply', underline=0, menu=rulemenu) viewmenu = Menu(menubar, tearoff=0) viewmenu.add_checkbutton(label="Show Grammar", underline=0, variable=self._show_grammar, command=self._toggle_grammar) viewmenu.add_separator() viewmenu.add_radiobutton(label='Tiny', variable=self._size, underline=0, value=10, command=self.resize) viewmenu.add_radiobutton(label='Small', variable=self._size, underline=0, value=12, command=self.resize) viewmenu.add_radiobutton(label='Medium', variable=self._size, underline=0, value=14, command=self.resize) viewmenu.add_radiobutton(label='Large', variable=self._size, underline=0, value=18, command=self.resize) viewmenu.add_radiobutton(label='Huge', variable=self._size, underline=0, value=24, command=self.resize) menubar.add_cascade(label='View', underline=0, menu=viewmenu) animatemenu = Menu(menubar, tearoff=0) animatemenu.add_radiobutton(label="No Animation", underline=0, variable=self._animate, value=0) animatemenu.add_radiobutton(label="Slow Animation", underline=0, variable=self._animate, value=20, accelerator='-') animatemenu.add_radiobutton(label="Normal Animation", underline=0, variable=self._animate, value=10, accelerator='=') animatemenu.add_radiobutton(label="Fast Animation", underline=0, variable=self._animate, value=4, accelerator='+') menubar.add_cascade(label="Animate", underline=1, menu=animatemenu) helpmenu = Menu(menubar, tearoff=0) helpmenu.add_command(label='About', underline=0, command=self.about) helpmenu.add_command(label='Instructions', underline=0, command=self.help, accelerator='F1') menubar.add_cascade(label='Help', underline=0, menu=helpmenu) parent.config(menu=menubar) def _init_feedback(self, parent): self._feedbackframe = feedbackframe = Frame(parent) feedbackframe.pack(fill='x', side='bottom', padx=3, pady=3) self._lastoper_label = Label(feedbackframe, text='Last Operation:', font=self._font) self._lastoper_label.pack(side='left') lastoperframe = Frame(feedbackframe, relief='sunken', border=1) lastoperframe.pack(fill='x', side='right', expand=1, padx=5) self._lastoper1 = Label(lastoperframe, foreground='#007070', background='#f0f0f0', font=self._font) self._lastoper2 = Label(lastoperframe, anchor='w', width=30, foreground='#004040', background='#f0f0f0', font=self._font) self._lastoper1.pack(side='left') self._lastoper2.pack(side='left', fill='x', expand=1) def _init_canvas(self, parent): self._cframe = CanvasFrame(parent, background='white', width=525, closeenough=10, border=2, relief='sunken') self._cframe.pack(expand=1, fill='both', side='top', pady=2) canvas = self._canvas = self._cframe.canvas() self._stackwidgets = [] self._rtextwidgets = [] self._titlebar = canvas.create_rectangle(0,0,0,0, fill='#c0f0f0', outline='black') self._exprline = canvas.create_line(0,0,0,0, dash='.') self._stacktop = canvas.create_line(0,0,0,0, fill='#408080') size = self._size.get()+4 self._stacklabel = TextWidget(canvas, 'Stack', color='#004040', font=self._boldfont) self._rtextlabel = TextWidget(canvas, 'Remaining Text', color='#004040', font=self._boldfont) self._cframe.add_widget(self._stacklabel) self._cframe.add_widget(self._rtextlabel) ######################################### ## Main draw procedure ######################################### def _redraw(self): scrollregion = self._canvas['scrollregion'].split() (cx1, cy1, cx2, cy2) = [int(c) for c in scrollregion] # Delete the old stack & rtext widgets. for stackwidget in self._stackwidgets: self._cframe.destroy_widget(stackwidget) self._stackwidgets = [] for rtextwidget in self._rtextwidgets: self._cframe.destroy_widget(rtextwidget) self._rtextwidgets = [] # Position the titlebar & exprline (x1, y1, x2, y2) = self._stacklabel.bbox() y = y2-y1+10 self._canvas.coords(self._titlebar, -5000, 0, 5000, y-4) self._canvas.coords(self._exprline, 0, y*2-10, 5000, y*2-10) # Position the titlebar labels.. (x1, y1, x2, y2) = self._stacklabel.bbox() self._stacklabel.move(5-x1, 3-y1) (x1, y1, x2, y2) = self._rtextlabel.bbox() self._rtextlabel.move(cx2-x2-5, 3-y1) # Draw the stack. stackx = 5 for tok in self._parser.stack(): if isinstance(tok, Tree): attribs = {'tree_color': '#4080a0', 'tree_width': 2, 'node_font': self._boldfont, 'node_color': '#006060', 'leaf_color': '#006060', 'leaf_font':self._font} widget = tree_to_treesegment(self._canvas, tok, **attribs) widget.label()['color'] = '#000000' else: widget = TextWidget(self._canvas, tok, color='#000000', font=self._font) widget.bind_click(self._popup_reduce) self._stackwidgets.append(widget) self._cframe.add_widget(widget, stackx, y) stackx = widget.bbox()[2] + 10 # Draw the remaining text. rtextwidth = 0 for tok in self._parser.remaining_text(): widget = TextWidget(self._canvas, tok, color='#000000', font=self._font) self._rtextwidgets.append(widget) self._cframe.add_widget(widget, rtextwidth, y) rtextwidth = widget.bbox()[2] + 4 # Allow enough room to shift the next token (for animations) if len(self._rtextwidgets) > 0: stackx += self._rtextwidgets[0].width() # Move the remaining text to the correct location (keep it # right-justified, when possible); and move the remaining text # label, if necessary. stackx = max(stackx, self._stacklabel.width()+25) rlabelwidth = self._rtextlabel.width()+10 if stackx >= cx2-max(rtextwidth, rlabelwidth): cx2 = stackx + max(rtextwidth, rlabelwidth) for rtextwidget in self._rtextwidgets: rtextwidget.move(4+cx2-rtextwidth, 0) self._rtextlabel.move(cx2-self._rtextlabel.bbox()[2]-5, 0) midx = (stackx + cx2-max(rtextwidth, rlabelwidth))/2 self._canvas.coords(self._stacktop, midx, 0, midx, 5000) (x1, y1, x2, y2) = self._stacklabel.bbox() # Set up binding to allow them to shift a token by dragging it. if len(self._rtextwidgets) > 0: def drag_shift(widget, midx=midx, self=self): if widget.bbox()[0] < midx: self.shift() else: self._redraw() self._rtextwidgets[0].bind_drag(drag_shift) self._rtextwidgets[0].bind_click(self.shift) # Draw the stack top. self._highlight_productions() def _draw_stack_top(self, widget): # hack.. midx = widget.bbox()[2]+50 self._canvas.coords(self._stacktop, midx, 0, midx, 5000) def _highlight_productions(self): # Highlight the productions that can be reduced. self._prodlist.selection_clear(0, 'end') for prod in self._parser.reducible_productions(): index = self._productions.index(prod) self._prodlist.selection_set(index) ######################################### ## Button Callbacks ######################################### def destroy(self, *e): if self._top is None: return self._top.destroy() self._top = None def reset(self, *e): self._parser.initialize(self._sent) self._lastoper1['text'] = 'Reset App' self._lastoper2['text'] = '' self._redraw() def step(self, *e): if self.reduce(): return True elif self.shift(): return True else: if list(self._parser.parses()): self._lastoper1['text'] = 'Finished:' self._lastoper2['text'] = 'Success' else: self._lastoper1['text'] = 'Finished:' self._lastoper2['text'] = 'Failure' def shift(self, *e): if self._animating_lock: return if self._parser.shift(): tok = self._parser.stack()[-1] self._lastoper1['text'] = 'Shift:' self._lastoper2['text'] = '%r' % tok if self._animate.get(): self._animate_shift() else: self._redraw() return True return False def reduce(self, *e): if self._animating_lock: return production = self._parser.reduce() if production: self._lastoper1['text'] = 'Reduce:' self._lastoper2['text'] = '%s' % production if self._animate.get(): self._animate_reduce() else: self._redraw() return production def undo(self, *e): if self._animating_lock: return if self._parser.undo(): self._redraw() def postscript(self, *e): self._cframe.print_to_file() def mainloop(self, *args, **kwargs): """ Enter the Tkinter mainloop. This function must be called if this demo is created from a non-interactive program (e.g. from a secript); otherwise, the demo will close as soon as the script completes. """ if in_idle(): return self._top.mainloop(*args, **kwargs) ######################################### ## Menubar callbacks ######################################### def resize(self, size=None): if size is not None: self._size.set(size) size = self._size.get() self._font.configure(size=-(abs(size))) self._boldfont.configure(size=-(abs(size))) self._sysfont.configure(size=-(abs(size))) #self._stacklabel['font'] = ('helvetica', -size-4, 'bold') #self._rtextlabel['font'] = ('helvetica', -size-4, 'bold') #self._lastoper_label['font'] = ('helvetica', -size) #self._lastoper1['font'] = ('helvetica', -size) #self._lastoper2['font'] = ('helvetica', -size) #self._prodlist['font'] = ('helvetica', -size) #self._prodlist_label['font'] = ('helvetica', -size-2, 'bold') self._redraw() def help(self, *e): # The default font's not very legible; try using 'fixed' instead. try: ShowText(self._top, 'Help: Shift-Reduce Parser Application', (__doc__ or '').strip(), width=75, font='fixed') except: ShowText(self._top, 'Help: Shift-Reduce Parser Application', (__doc__ or '').strip(), width=75) def about(self, *e): ABOUT = ("NLTK Shift-Reduce Parser Application\n"+ "Written by Edward Loper") TITLE = 'About: Shift-Reduce Parser Application' try: from tkinter.messagebox import Message Message(message=ABOUT, title=TITLE).show() except: ShowText(self._top, TITLE, ABOUT) def edit_grammar(self, *e): CFGEditor(self._top, self._parser.grammar(), self.set_grammar) def set_grammar(self, grammar): self._parser.set_grammar(grammar) self._productions = list(grammar.productions()) self._prodlist.delete(0, 'end') for production in self._productions: self._prodlist.insert('end', (' %s' % production)) def edit_sentence(self, *e): sentence = " ".join(self._sent) title = 'Edit Text' instr = 'Enter a new sentence to parse.' EntryDialog(self._top, sentence, instr, self.set_sentence, title) def set_sentence(self, sent): self._sent = sent.split() #[XX] use tagged? self.reset() ######################################### ## Reduce Production Selection ######################################### def _toggle_grammar(self, *e): if self._show_grammar.get(): self._prodframe.pack(fill='both', side='left', padx=2, after=self._feedbackframe) self._lastoper1['text'] = 'Show Grammar' else: self._prodframe.pack_forget() self._lastoper1['text'] = 'Hide Grammar' self._lastoper2['text'] = '' def _prodlist_select(self, event): selection = self._prodlist.curselection() if len(selection) != 1: return index = int(selection[0]) production = self._parser.reduce(self._productions[index]) if production: self._lastoper1['text'] = 'Reduce:' self._lastoper2['text'] = '%s' % production if self._animate.get(): self._animate_reduce() else: self._redraw() else: # Reset the production selections. self._prodlist.selection_clear(0, 'end') for prod in self._parser.reducible_productions(): index = self._productions.index(prod) self._prodlist.selection_set(index) def _popup_reduce(self, widget): # Remove old commands. productions = self._parser.reducible_productions() if len(productions) == 0: return self._reduce_menu.delete(0, 'end') for production in productions: self._reduce_menu.add_command(label=str(production), command=self.reduce) self._reduce_menu.post(self._canvas.winfo_pointerx(), self._canvas.winfo_pointery()) ######################################### ## Animations ######################################### def _animate_shift(self): # What widget are we shifting? widget = self._rtextwidgets[0] # Where are we shifting from & to? right = widget.bbox()[0] if len(self._stackwidgets) == 0: left = 5 else: left = self._stackwidgets[-1].bbox()[2]+10 # Start animating. dt = self._animate.get() dx = (left-right)*1.0/dt self._animate_shift_frame(dt, widget, dx) def _animate_shift_frame(self, frame, widget, dx): if frame > 0: self._animating_lock = 1 widget.move(dx, 0) self._top.after(10, self._animate_shift_frame, frame-1, widget, dx) else: # but: stacktop?? # Shift the widget to the stack. del self._rtextwidgets[0] self._stackwidgets.append(widget) self._animating_lock = 0 # Display the available productions. self._draw_stack_top(widget) self._highlight_productions() def _animate_reduce(self): # What widgets are we shifting? numwidgets = len(self._parser.stack()[-1]) # number of children widgets = self._stackwidgets[-numwidgets:] # How far are we moving? if isinstance(widgets[0], TreeSegmentWidget): ydist = 15 + widgets[0].label().height() else: ydist = 15 + widgets[0].height() # Start animating. dt = self._animate.get() dy = ydist*2.0/dt self._animate_reduce_frame(dt/2, widgets, dy) def _animate_reduce_frame(self, frame, widgets, dy): if frame > 0: self._animating_lock = 1 for widget in widgets: widget.move(0, dy) self._top.after(10, self._animate_reduce_frame, frame-1, widgets, dy) else: del self._stackwidgets[-len(widgets):] for widget in widgets: self._cframe.remove_widget(widget) tok = self._parser.stack()[-1] if not isinstance(tok, Tree): raise ValueError() label = TextWidget(self._canvas, str(tok.label()), color='#006060', font=self._boldfont) widget = TreeSegmentWidget(self._canvas, label, widgets, width=2) (x1, y1, x2, y2) = self._stacklabel.bbox() y = y2-y1+10 if not self._stackwidgets: x = 5 else: x = self._stackwidgets[-1].bbox()[2] + 10 self._cframe.add_widget(widget, x, y) self._stackwidgets.append(widget) # Display the available productions. self._draw_stack_top(widget) self._highlight_productions() # # Delete the old widgets.. # del self._stackwidgets[-len(widgets):] # for widget in widgets: # self._cframe.destroy_widget(widget) # # # Make a new one. # tok = self._parser.stack()[-1] # if isinstance(tok, Tree): # attribs = {'tree_color': '#4080a0', 'tree_width': 2, # 'node_font': bold, 'node_color': '#006060', # 'leaf_color': '#006060', 'leaf_font':self._font} # widget = tree_to_treesegment(self._canvas, tok.type(), # **attribs) # widget.node()['color'] = '#000000' # else: # widget = TextWidget(self._canvas, tok.type(), # color='#000000', font=self._font) # widget.bind_click(self._popup_reduce) # (x1, y1, x2, y2) = self._stacklabel.bbox() # y = y2-y1+10 # if not self._stackwidgets: x = 5 # else: x = self._stackwidgets[-1].bbox()[2] + 10 # self._cframe.add_widget(widget, x, y) # self._stackwidgets.append(widget) #self._redraw() self._animating_lock = 0 ######################################### ## Hovering. ######################################### def _highlight_hover(self, event): # What production are we hovering over? index = self._prodlist.nearest(event.y) if self._hover == index: return # Clear any previous hover highlighting. self._clear_hover() # If the production corresponds to an available reduction, # highlight the stack. selection = [int(s) for s in self._prodlist.curselection()] if index in selection: rhslen = len(self._productions[index].rhs()) for stackwidget in self._stackwidgets[-rhslen:]: if isinstance(stackwidget, TreeSegmentWidget): stackwidget.label()['color'] = '#00a000' else: stackwidget['color'] = '#00a000' # Remember what production we're hovering over. self._hover = index def _clear_hover(self, *event): # Clear any previous hover highlighting. if self._hover == -1: return self._hover = -1 for stackwidget in self._stackwidgets: if isinstance(stackwidget, TreeSegmentWidget): stackwidget.label()['color'] = 'black' else: stackwidget['color'] = 'black'
class Gui(Frame): def __init__(self, control, *args, **kwargs): Frame.__init__(self, *args, **kwargs) self.config(padx=2) self.queue = Queue() self.control = control self.disabledWhileRunning = [] self.formulae = list(map(lambda t: StringVar(self, t), ["x/22.5+4", "50-x*50/180"])) self.executionTime = DoubleVar(self, "360") self.programSpeed = IntVar(self, "292") self.maxTravel = IntVar(self, "-200000") self.loadSettings() self.createWidgets() self.thread = None def compileFormulae(self): rv = [] for f in self.formulae: body = "def formula5480750923(x):\n return " + f.get() l = {} try: exec(body, {}, l) except: rv.append(None) continue compiled = l["formula5480750923"] compiled(0) rv.append(compiled) return rv def plotFormulae(self): try: compiled = self.compileFormulae() except: return for g in self.graphs: g.points = [] self.canvas.x.end = self.executionTime.get() self.canvas.clear() for x in range(self.canvas.x.start, int(self.canvas.x.end)): point = [] for c in range(len(compiled)): v = None if compiled[c]: v = compiled[c](x) assert isinstance(v, float) point.append(v) self.__addPoint__(x, point) self.canvas.update() def __start__(self): self.canvas.x.end = self.executionTime.get() pumps = self.compileFormulae() self.setValues() self.control.mover.setSpeed(abs(int(self.programSpeed.get()))) start_time = float(self.current_time.get()) def calcPumpValues(time): values = list(map(lambda x: x(time), pumps)) self.__addPoint__(time, values) self.current_time.set(time) return values def thFunc(): try: for g in self.graphs: g.points = [] self.control.executeProgram(start_time, calcPumpValues) finally: self.invoke(self.__enableControls__) self.__disableControls__() self.canvas.clear() self.thread = Thread(target=thFunc, name="Control") self.thread.start() def __enableControls__(self): for e in self.disabledWhileRunning: e.config(state=NORMAL) def __disableControls__(self): for e in self.disabledWhileRunning: e.config(state="disabled") def __addPoint__(self, x, values): for v in values: assert isinstance(v, float) def c(): for i in range(len(self.canvas.graphs)): self.canvas.graphs[i].addPoint(x, values[i]) self.invoke(c) def invoke(self, callable): self.after_idle(callable) def __stop__(self): self.control.stop() def __quit__(self): def quitting(): self.__stop__() if self.thread and self.thread.is_alive(): print("Thread is active") return False self.quit() return True run_repeating(self, quitting) def __move__(self, steps): speed = int(self.speed.get()) if speed < 0: speed *= -1 self.speed.set(speed) self.control.mover.setSpeed(speed) self.control.mover.go(steps) def __up__(self): steps = int(self.steps.get()) self.__move__(steps) def __down__(self): steps = int(self.steps.get()) self.__move__(-steps) def showValues(self): self.maxTravel.set(self.control.mover.maxTravel) self.executionTime.set(self.control.fullTime) self.programSpeed.set(self.control.mover.getSpeed()) def setValues(self): self.control.mover.maxTravel = int(self.maxTravel.get()) self.control.fullTime = float(self.executionTime.get()) self.control.mover.setSpeed(abs(int(self.programSpeed.get()))) def loadSettings(self): config = Config() try: config.read() except KeyError: pass config.configureControl(self.control) for i in range(len(self.formulae)): self.formulae[i].set(config.formulae[i]) self.showValues() def saveSettings(self): self.setValues() config = Config() config.getFromControl(self.control) for i in range(len(self.formulae)): config.formulae[i] = self.formulae[i].get() config.write() def createWidgets(self): panel = Frame(self, name="mainMenu") panel.grid(sticky=W) Button(panel, name="quit", text="Выход", command=self.__quit__).grid(row=0, column=0) Button(panel, name="reconnect", text="Пересоединение", command=self.control.reconnect).grid(row=0, column=1) b = Button(panel, text="Загрузить", command=self.loadSettings) b.grid(row=0, column=2) self.disabledWhileRunning.append(b) b = Button(panel, text="Сохранить", command=self.saveSettings) b.grid(row=0, column=3) self.disabledWhileRunning.append(b) panel = LabelFrame(self, text="Прямое управление стаканом", name="motor") panel.grid(sticky=W) b = Button(panel, text="Вверх", command=self.__up__, name="up") b.grid(row=0, column=0) self.disabledWhileRunning.append(b) b = Button(panel, text="Вниз", command=self.__down__, name="down") b.grid(row=1, column=0) self.disabledWhileRunning.append(b) Label(panel, text="Шаг:").grid(sticky=E, row=0, column=1) self.steps = IntVar(self, "10000") Entry(panel, textvariable=self.steps, width=6).grid(sticky=W, row=0, column=2) Label(panel, text="Скорость:").grid(sticky=E, row=1, column=1) self.speed = IntVar(self, "2000") Entry(panel, textvariable=self.speed, width=6).grid(sticky=W, row=1, column=2) self.position = IntVar(self, "1000") def readPosition(): try: self.position.set(self.control.mover.getPosition()) except (ConnectionResetError, Timeout): pass run_repeating(self, readPosition, 10000) b = Button(panel, text="Прочитать положение", command=readPosition) b.grid(row=0, column=3, columnspan=2) self.disabledWhileRunning.append(b) Label(panel, text="Положение:").grid(sticky=E, row=1, column=3) Entry(panel, textvariable=self.position, width=8, state="disabled").grid(sticky=W, row=1, column=4) panel = LabelFrame(self, text="Программа", name="program") program = panel panel.grid(sticky=W + E) panel.columnconfigure(1, weight=1) row = 0 for f in self.formulae: columns, rows = self.grid_size() Label(panel, text="Насос %d:" % (row + 1)).grid(row=row, column=0, sticky=E) e = Entry(panel, textvariable=f) e.grid(sticky=E + W, row=row, column=1) self.disabledWhileRunning.append(e) f.trace("w", lambda *x: self.after_idle(self.plotFormulae)) row += 1 panel = Frame(program, name="mover") panel.grid(columnspan=2, sticky=W) Label(panel, text="Максимальное смещение:").grid(sticky=E) Entry(panel, textvariable=self.maxTravel).grid(sticky=W, row=0, column=1) Label(panel, text="Скорость:").grid(sticky=E) Entry(panel, textvariable=self.programSpeed).grid(sticky=W, row=1, column=1) Label(panel, text="Время выполнения (в секундах):").grid(sticky=E) e = Entry(panel, textvariable=self.executionTime) e.grid(sticky=W, row=2, column=1) self.current_time = DoubleVar(self, "0") Label(panel, text="Текущее время:").grid(sticky=E) e = Entry(panel, textvariable=self.current_time) e.grid(sticky=W, row=3, column=1) self.disabledWhileRunning.append(e) self.executionTime.trace("w", lambda *x: self.plotFormulae()) panel = Frame(program, name="bottom") panel.grid(columnspan=2, sticky=W) row = 0 startButton = Button(panel, name="start", text="Старт", command=self.__start__) startButton.grid(row=row, column=0) self.disabledWhileRunning.append(startButton) Button(panel, text="Стоп", command=self.__stop__).grid(row=row, column=1) self.canvas = GraphCanvas(self) self.graphs = (Graph(self.canvas), Graph(self.canvas)) self.canvas.x.end = 100 self.canvas.y.end = 24 self.plotFormulae() self.canvas.grid(sticky=E + W + S + N) columns, rows = self.grid_size() self.columnconfigure(columns - 1, weight=1) self.rowconfigure(rows - 1, weight=1)
class CollocationsView: _BACKGROUND_COLOUR='#FFF' #white def __init__(self): self.queue = q.Queue() self.model = CollocationsModel(self.queue) self.top = Tk() self._init_top(self.top) self._init_menubar() self._init_widgets(self.top) self.load_corpus(self.model.DEFAULT_CORPUS) self.after = self.top.after(POLL_INTERVAL, self._poll) def _init_top(self, top): top.geometry('550x650+50+50') top.title('NLTK Collocations List') top.bind('<Control-q>', self.destroy) top.protocol('WM_DELETE_WINDOW', self.destroy) top.minsize(550,650) def _init_widgets(self, parent): self.main_frame = Frame(parent, dict(background=self._BACKGROUND_COLOUR, padx=1, pady=1, border=1)) self._init_corpus_select(self.main_frame) self._init_results_box(self.main_frame) self._init_paging(self.main_frame) self._init_status(self.main_frame) self.main_frame.pack(fill='both', expand=True) def _init_corpus_select(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) self.var = StringVar(innerframe) self.var.set(self.model.DEFAULT_CORPUS) Label(innerframe, justify=LEFT, text=' Corpus: ', background=self._BACKGROUND_COLOUR, padx = 2, pady = 1, border = 0).pack(side='left') other_corpora = list(self.model.CORPORA.keys()).remove(self.model.DEFAULT_CORPUS) om = OptionMenu(innerframe, self.var, self.model.DEFAULT_CORPUS, command=self.corpus_selected, *self.model.non_default_corpora()) om['borderwidth'] = 0 om['highlightthickness'] = 1 om.pack(side='left') innerframe.pack(side='top', fill='x', anchor='n') def _init_status(self, parent): self.status = Label(parent, justify=LEFT, relief=SUNKEN, background=self._BACKGROUND_COLOUR, border=0, padx = 1, pady = 0) self.status.pack(side='top', anchor='sw') def _init_menubar(self): self._result_size = IntVar(self.top) menubar = Menu(self.top) filemenu = Menu(menubar, tearoff=0, borderwidth=0) filemenu.add_command(label='Exit', underline=1, command=self.destroy, accelerator='Ctrl-q') menubar.add_cascade(label='File', underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) rescntmenu = Menu(editmenu, tearoff=0) rescntmenu.add_radiobutton(label='20', variable=self._result_size, underline=0, value=20, command=self.set_result_size) rescntmenu.add_radiobutton(label='50', variable=self._result_size, underline=0, value=50, command=self.set_result_size) rescntmenu.add_radiobutton(label='100', variable=self._result_size, underline=0, value=100, command=self.set_result_size) rescntmenu.invoke(1) editmenu.add_cascade(label='Result Count', underline=0, menu=rescntmenu) menubar.add_cascade(label='Edit', underline=0, menu=editmenu) self.top.config(menu=menubar) def set_result_size(self, **kwargs): self.model.result_count = self._result_size.get() def _init_results_box(self, parent): innerframe = Frame(parent) i1 = Frame(innerframe) i2 = Frame(innerframe) vscrollbar = Scrollbar(i1, borderwidth=1) hscrollbar = Scrollbar(i2, borderwidth=1, orient='horiz') self.results_box = Text(i1, font=tkinter.font.Font(family='courier', size='16'), state='disabled', borderwidth=1, yscrollcommand=vscrollbar.set, xscrollcommand=hscrollbar.set, wrap='none', width='40', height = '20', exportselection=1) self.results_box.pack(side='left', fill='both', expand=True) vscrollbar.pack(side='left', fill='y', anchor='e') vscrollbar.config(command=self.results_box.yview) hscrollbar.pack(side='left', fill='x', expand=True, anchor='w') hscrollbar.config(command=self.results_box.xview) #there is no other way of avoiding the overlap of scrollbars while using pack layout manager!!! Label(i2, text=' ', background=self._BACKGROUND_COLOUR).pack(side='left', anchor='e') i1.pack(side='top', fill='both', expand=True, anchor='n') i2.pack(side='bottom', fill='x', anchor='s') innerframe.pack(side='top', fill='both', expand=True) def _init_paging(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) self.prev = prev = Button(innerframe, text='Previous', command=self.previous, width='10', borderwidth=1, highlightthickness=1, state='disabled') prev.pack(side='left', anchor='center') self.next = next = Button(innerframe, text='Next', command=self.__next__, width='10', borderwidth=1, highlightthickness=1, state='disabled') next.pack(side='right', anchor='center') innerframe.pack(side='top', fill='y') self.reset_current_page() def reset_current_page(self): self.current_page = -1 def _poll(self): try: event = self.queue.get(block=False) except q.Empty: pass else: if event == CORPUS_LOADED_EVENT: self.handle_corpus_loaded(event) elif event == ERROR_LOADING_CORPUS_EVENT: self.handle_error_loading_corpus(event) self.after = self.top.after(POLL_INTERVAL, self._poll) def handle_error_loading_corpus(self, event): self.status['text'] = 'Error in loading ' + self.var.get() self.unfreeze_editable() self.clear_results_box() self.freeze_editable() self.reset_current_page() def handle_corpus_loaded(self, event): self.status['text'] = self.var.get() + ' is loaded' self.unfreeze_editable() self.clear_results_box() self.reset_current_page() #self.next() collocations = self.model.next(self.current_page + 1) self.write_results(collocations) self.current_page += 1 def corpus_selected(self, *args): new_selection = self.var.get() self.load_corpus(new_selection) def previous(self): self.freeze_editable() collocations = self.model.prev(self.current_page - 1) self.current_page= self.current_page - 1 self.clear_results_box() self.write_results(collocations) self.unfreeze_editable() def __next__(self): self.freeze_editable() collocations = self.model.next(self.current_page + 1) self.clear_results_box() self.write_results(collocations) self.current_page += 1 self.unfreeze_editable() def load_corpus(self, selection): if self.model.selected_corpus != selection: self.status['text'] = 'Loading ' + selection + '...' self.freeze_editable() self.model.load_corpus(selection) def freeze_editable(self): self.prev['state'] = 'disabled' self.next['state'] = 'disabled' def clear_results_box(self): self.results_box['state'] = 'normal' self.results_box.delete("1.0", END) self.results_box['state'] = 'disabled' def fire_event(self, event): #Firing an event so that rendering of widgets happen in the mainloop thread self.top.event_generate(event, when='tail') def destroy(self, *e): if self.top is None: return self.top.after_cancel(self.after) self.top.destroy() self.top = None def mainloop(self, *args, **kwargs): if in_idle(): return self.top.mainloop(*args, **kwargs) def unfreeze_editable(self): self.set_paging_button_states() def set_paging_button_states(self): if self.current_page == -1 or self.current_page == 0: self.prev['state'] = 'disabled' else: self.prev['state'] = 'normal' if self.model.is_last_page(self.current_page): self.next['state'] = 'disabled' else: self.next['state'] = 'normal' def write_results(self, results): self.results_box['state'] = 'normal' row = 1 for each in results: self.results_box.insert(str(row) + '.0', each[0] + " " + each[1] + "\n") row += 1 self.results_box['state'] = 'disabled'
class IntegerEntry(StringEntry): """Integer class for entry Parameters ---------- parent : str parent handle lf_text : str text on LabelFrame mess_text : str message l_limit : int lower limit u_limit : int upper limit def_inp : str default text colour : str frame colour mod : str enable or disable state switch Returns ------- integer """ def __init__(self, parent, lf_text, mess_text, l_limit, u_limit, def_inp="", colour='brown', mod=False): self.parent = parent self.lf_text = lf_text self.mess_text = mess_text self.mod = mod self.colour = colour StringEntry.__init__(self, parent, lf_text, mess_text, def_inp, colour, mod) self.l_limit = l_limit self.u_limit = u_limit self.out_var = IntVar() self.out_var.set(def_inp) self.farbe = farbe = { 'blue': 'light blue', 'brown': '#EDEF77', 'green': 'light green', 'pink': '#EAAFBF' } colour = colour if colour in farbe else 'brown' self.colour = colour st1 = Style() st1.theme_use('default') st1.configure(colour + '.TLabelframe', background='#C9B99B') st1.configure(colour + '.TLabelframe.Label', background=farbe[colour]) st1.configure(colour + '.TCheckbutton', background=farbe[colour]) st1.configure('brownn.TLabel', background='#EDEF77') st1.configure('lowr.TLabel', background='lightblue') st1.configure('upr.TLabel', background='red') self.construct() self.limits() def limits(self): """limit logic Parameters ---------- None Returns ------- None """ self.ulab = Label(self.lf1, text=str(self.u_limit) + " upper limit", style='brown.TLabel') self.ulab.grid(row=0, column=1, padx=10) self.llab = Label(self.lf1, text=str(self.l_limit) + " lower limit", style='brown.TLabel') self.llab.grid(row=2, column=1, padx=10) self.make_entry() def end_input(self, _evt): """limit on integer Parameters ---------- evt : str bind handle Returns ------- None """ self.ulab['style'] = 'brown.TLabel' self.llab['style'] = 'brown.TLabel' if self.l_limit < int(self.out_var.get()) < self.u_limit: self.messlbl['text'] = "That's OK" elif self.l_limit >= int(self.out_var.get()): self.messlbl['text'] = "Input below or at lower limit" self.llab['style'] = 'lowr.TLabel' else: self.messlbl['text'] = "Input above or at upper limit" self.ulab['style'] = 'upr.TLabel' def is_okay(self, text, inp, ind): """ validation function Parameters ---------- text : str text if allowed inp : str current input Returns ------- boolean """ if text in ("", "-"): return True try: int(text) except ValueError: return False return True
class IpdSubOptionsForm(VerticalScrolledFrame): # Initialize the GUI def __init__(self, root): VerticalScrolledFrame.__init__(self, root) #Frame.__init__(self, root) #super(500, 500) root.title("Choose IPD-IMGT/HLA Submission Options") self.parent = root #button_opt = {'fill': Tkconstants.BOTH, 'padx': 35, 'pady': 5} # This window should not be resizeable. I guess. self.parent.resizable(width=False, height=False) #self.parent.resizable(width=True, height=True) # To define the exit behavior. Save and exit. self.parent.protocol('WM_DELETE_WINDOW', self.saveOptions) # Define the return behavior. Same as "close window" etc root.bind('<Return>', self.returnFunction) self.instructionsFrame = Frame(self.interior) self.instructionText = StringVar() self.instructionText.set('\nThese options are required for an IPD allele submission.\n' + 'Login Credentials will not be stored, but they will be sent to IPD via\n' + 'secure https connection.\n') Label(self.instructionsFrame, width=85, height=6, textvariable=self.instructionText).pack() self.instructionsFrame.pack() #Standard Inputs widths for the form elements formInputWidth = 35 labelInputWidth = 35 # Make a frame to contain the input variables # self.interior is defined in the ScrolledWindow class self.submissionDetailsInputFrame = Frame(self.interior) self.usernameInstrText = StringVar() self.usernameInstrText.set('IPD Username:'******'IPD Password:'******'Cell/Sample ID:') self.sampleIDinstrLabel = Label(self.submissionDetailsInputFrame, width=labelInputWidth, height=1, textvariable=self.sampleIDInstrText).grid(row=2, column=0) self.inputSampleID = StringVar() self.inputSampleIDEntry = Entry(self.submissionDetailsInputFrame, width=formInputWidth, textvariable=self.inputSampleID).grid(row=2, column=1) self.geneInstrStringVar = StringVar() self.geneInstrStringVar.set('Gene:') self.geneInstrLabel = Label(self.submissionDetailsInputFrame, width=labelInputWidth, height=1, textvariable=self.geneInstrStringVar).grid(row=3, column=0) self.inputGene = StringVar() self.inputGeneEntry = Entry(self.submissionDetailsInputFrame, width=formInputWidth, textvariable=self.inputGene).grid(row=3, column=1) self.chooseClassIntVar = IntVar() self.chooseClassIntVar.set(1) Radiobutton(self.submissionDetailsInputFrame, text="HLA Class I ", variable=self.chooseClassIntVar, value=1).grid(row=4, column=0) Radiobutton(self.submissionDetailsInputFrame, text="HLA Class II", variable=self.chooseClassIntVar, value=2).grid(row=4, column=1) self.alleleInstrText = StringVar() self.alleleInstrText.set('Allele Local Name:') self.alleleInstrLabel = Label(self.submissionDetailsInputFrame, width=labelInputWidth, height=1, textvariable=self.alleleInstrText).grid(row=5, column=0) self.inputAllele = StringVar() self.inputAlleleEntry = Entry(self.submissionDetailsInputFrame, width=formInputWidth, textvariable=self.inputAllele).grid(row=5, column=1) # New form stuff # Gotta add this to the load/save config nonsense below. # TODO: Can I just load an ENA accession? I think that is possible. Easier than filling it in here # TODO: When ENA Sequence Accession # Is provided, I can probably lookup an annotated sequence. # Should I put a button next to this field # Button: "Lookup This ENA Sequence Accession #" # If it is found, then i already know the sequence with exon boundaries. # TODO: Do I need to specify if it is ENA / Genbank / The other one? Probably not. # I can require an ENA code and disregard Genbank. # Radio Buttons? # ENA / Genbank Accession # # No, this tool is for ENA submission. But this is a question for James Robinson. # Should i choose between which intermediate databse they use? self.enaAccInstrText = StringVar() self.enaAccInstrText.set('ENA Sequence Accession #:') self.enaAccInstrLabel = Label(self.submissionDetailsInputFrame, width=labelInputWidth, height=1, textvariable=self.enaAccInstrText).grid(row=6, column=0) self.inputEnaAcc = StringVar() self.inputEnaAccEntry = Entry(self.submissionDetailsInputFrame, width=formInputWidth, textvariable=self.inputEnaAcc).grid(row=6, column=1) # Release Date self.releaseDateInstrText = StringVar() self.releaseDateInstrText.set('IPD Release Date:') self.releaseDateInstrLabel = Label(self.submissionDetailsInputFrame, width=labelInputWidth, height=1, textvariable=self.releaseDateInstrText).grid(row=7, column=0) self.inputReleaseDate = StringVar() self.inputReleaseDateEntry = Entry(self.submissionDetailsInputFrame, width=formInputWidth, textvariable=self.inputReleaseDate).grid(row=7, column=1) # Reference Details # Is this allele in a published paper or not? # 0=unpublished, 1=published self.publishedReferenceIntVar = IntVar() self.publishedReferenceIntVar.set(0) self.submissionDetailsInputFrame.pack() self.unpublishedReferenceFrame = Frame(self.interior) self.referenceInstrText = StringVar() self.referenceInstrText.set('\nPlease provide some information about a\npublished paper relevant to this sequence.\n') self.referenceInstrLabel = Label(self.unpublishedReferenceFrame, width=70, height=4, textvariable=self.referenceInstrText).pack()#.grid(row=2, column=0) Radiobutton(self.unpublishedReferenceFrame, text="No Published Reference.", variable=self.publishedReferenceIntVar, value=0).pack() self.unpublishedReferenceFrame.pack() self.publishedReferenceFrame = Frame(self.interior) # Radio Button: Published Radiobutton(self.unpublishedReferenceFrame, text="Use This Reference:", variable=self.publishedReferenceIntVar, value=1).pack() # Reference Title self.referenceTitleInstrText = StringVar() self.referenceTitleInstrText.set('Reference Title:') self.referenceTitleInstrLabel = Label(self.publishedReferenceFrame, width=labelInputWidth, height=1, textvariable=self.referenceTitleInstrText).grid(row=1, column=0) self.inputReferenceTitle = StringVar() self.inputReferenceTitleEntry = Entry(self.publishedReferenceFrame, width=formInputWidth, textvariable=self.inputReferenceTitle).grid(row=1, column=1) # Authors self.referenceAuthorsInstrText = StringVar() self.referenceAuthorsInstrText.set('Reference Authors:') self.referenceAuthorsInstrLabel = Label(self.publishedReferenceFrame, width=labelInputWidth, height=1, textvariable=self.referenceAuthorsInstrText).grid(row=2, column=0) self.inputReferenceAuthors = StringVar() self.inputReferenceAuthorsEntry = Entry(self.publishedReferenceFrame, width=formInputWidth, textvariable=self.inputReferenceAuthors).grid(row=2, column=1) # Journal self.referenceJournalInstrText = StringVar() self.referenceJournalInstrText.set('Reference Journal:') self.referenceJournalInstrLabel = Label(self.publishedReferenceFrame, width=labelInputWidth, height=1, textvariable=self.referenceJournalInstrText).grid(row=3, column=0) self.inputReferenceJournal = StringVar() self.inputReferenceJournalEntry = Entry(self.publishedReferenceFrame, width=formInputWidth, textvariable=self.inputReferenceJournal).grid(row=3, column=1) self.publishedReferenceFrame.pack() # Make a frame to contain the input variables. # I had to make 2 of them to organize my gui, maybe I can name this better. self.submissionDetailsInputFrame2 = Frame(self.interior) # /alignment -> defined by IPD sequence alignment service # In this case, it is the closest known allele. self.closestAlleleInstrText = StringVar() self.closestAlleleInstrText.set('Closest Known HLA Allele:') self.closestAlleleInstrLabel = Label(self.submissionDetailsInputFrame2, width=labelInputWidth, height=1, textvariable=self.closestAlleleInstrText).grid(row=1, column=0) self.inputClosestAllele = StringVar() self.inputClosestAlleleEntry = Entry(self.submissionDetailsInputFrame2, width=formInputWidth, textvariable=self.inputClosestAllele).grid(row=1, column=1) # Written Description # Looks like this is a description of how the sequence differes from closest knnown allele self.closestAlleleWrittenDescriptionInstrText = StringVar() self.closestAlleleWrittenDescriptionInstrText.set('Differences from Closest Allele:') self.closestAlleleWrittenDescriptionInstrLabel = Label(self.submissionDetailsInputFrame2, width=labelInputWidth, height=1, textvariable=self.closestAlleleWrittenDescriptionInstrText).grid(row=2, column=0) self.inputClosestAlleleWrittenDescription = StringVar() self.inputClosestAlleleWrittenDescriptionEntry = Entry(self.submissionDetailsInputFrame2, width=formInputWidth, textvariable=self.inputClosestAlleleWrittenDescription).grid(row=2, column=1) # DONOR INFORMATION # Cell ID (cellnum) # Wait, is this the same as the sample ID? Should I move the sample ID field down here? # No. I am disregarding this sample ID. # Ethnic Origin - Text self.ethnicOriginInstrText = StringVar() self.ethnicOriginInstrText.set('Ethnic Origin:') self.ethnicOriginInstrLabel = Label(self.submissionDetailsInputFrame2, width=labelInputWidth, height=1, textvariable=self.ethnicOriginInstrText).grid(row=3, column=0) self.inputEthnicOrigin = StringVar() self.inputEthnicOriginEntry = Entry(self.submissionDetailsInputFrame2, width=formInputWidth, textvariable=self.inputEthnicOrigin).grid(row=3, column=1) # Sex - Text self.sexInstrText = StringVar() self.sexInstrText.set('Sex:') self.sexInstrLabel = Label(self.submissionDetailsInputFrame2, width=labelInputWidth, height=1, textvariable=self.sexInstrText).grid(row=4, column=0) self.inputSex = StringVar() self.inputSexEntry = Entry(self.submissionDetailsInputFrame2, width=formInputWidth, textvariable=self.inputSex).grid(row=4, column=1) # TODO Make a boolean # Consanguineous (T/F) self.consanguineousInstrText = StringVar() self.consanguineousInstrText.set('Sample is Consanguineous:') self.consanguineousInstrLabel = Label(self.submissionDetailsInputFrame2, width=labelInputWidth, height=1, textvariable=self.consanguineousInstrText).grid(row=5, column=0) self.inputConsanguineous = StringVar() self.inputConsanguineousEntry = Entry(self.submissionDetailsInputFrame2, width=formInputWidth, textvariable=self.inputConsanguineous).grid(row=5, column=1) # TODO Make a boolean # Homozygous (T/F) # TODO: Accepted values are 'Yes', 'No', 'Unknown' # Make dropdown for this, or radio buttons. self.homozygousInstrText = StringVar() self.homozygousInstrText.set('Sample is Homozygous:') self.homozygousInstrLabel = Label(self.submissionDetailsInputFrame2, width=labelInputWidth, height=1, textvariable=self.homozygousInstrText).grid(row=6, column=0) self.inputHomozygous = StringVar() self.inputHomozygousEntry = Entry(self.submissionDetailsInputFrame2, width=formInputWidth, textvariable=self.inputHomozygous).grid(row=6, column=1) # Lab of Origin (text) self.labOriginInstrText = StringVar() self.labOriginInstrText.set('Lab of Origin:') self.labOriginInstrLabel = Label(self.submissionDetailsInputFrame2, width=labelInputWidth, height=1, textvariable=self.labOriginInstrText).grid(row=7, column=0) self.inputLabOrigin = StringVar() self.inputLabOriginEntry = Entry(self.submissionDetailsInputFrame2, width=formInputWidth, textvariable=self.inputLabOrigin).grid(row=7, column=1) # Lab Contact self.labContactInstrText = StringVar() self.labContactInstrText.set('Lab Contact:') self.labContactInstrLabel = Label(self.submissionDetailsInputFrame2, width=labelInputWidth, height=1, textvariable=self.labContactInstrText).grid(row=8, column=0) self.inputLabContact = StringVar() self.inputLabContactEntry = Entry(self.submissionDetailsInputFrame2, width=formInputWidth, textvariable=self.inputLabContact).grid(row=8, column=1) # Cell Availability # Material Available (T/F) self.materialAvailableInstrText = StringVar() self.materialAvailableInstrText.set('Material Availability:') self.materialAvailableInstrLabel = Label(self.submissionDetailsInputFrame2, width=labelInputWidth, height=1, textvariable=self.materialAvailableInstrText).grid(row=9, column=0) self.inputMaterialAvailable = StringVar() self.inputMaterialAvailableEntry = Entry(self.submissionDetailsInputFrame2, width=formInputWidth, textvariable=self.inputMaterialAvailable).grid(row=9, column=1) # Cell Bank (Text) self.cellBankInstrText = StringVar() self.cellBankInstrText.set('Cell Bank:') self.cellBankInstrLabel = Label(self.submissionDetailsInputFrame2, width=labelInputWidth, height=1, textvariable=self.cellBankInstrText).grid(row=10, column=0) self.inputCellBank = StringVar() self.inputCellBankEntry = Entry(self.submissionDetailsInputFrame2, width=formInputWidth, textvariable=self.inputCellBank).grid(row=10, column=1) # Cell Workshop Details # I think Cell Workshop Details is just a header. there isn't new information here, just a header. # TODO: Compare this with the IPD Submission website, im not missing something? self.submissionDetailsInputFrame2.pack() # numbering these input frames are not informative. Oh well. This frame has HLA Allele calls on it. self.submissionDetailsInputFrame3 = Frame(self.interior) # Alternative HLA DNA Typing # Dropdown Box with another Entry Field? # I need: # Label self.sourceHLAInstrText = StringVar() self.sourceHLAInstrText.set('Source HLA Types (Sequenced):') self.sourceHLAInstrLabel = Label(self.submissionDetailsInputFrame3, width=labelInputWidth, height=1, textvariable=self.sourceHLAInstrText).grid(row=1, column=0) # Combo Box, with source_hla dictionary keys. Sorted. # Text input, with the gene specified. # "Clear" button. clear out all allele calls. # Configuration should be assigned whenever text changes. # I Think i need a new panel for this. Yeah. # Source Serology Typing # Maybe the same as DNA typing? # Ignore for now. # Sequencing Methods # Primers # This is probably a Dropdown with Entry field also. # TODO: Comments. Where does this stuff go? This is details about the lab of origin. I haven't tried specifying this one yet, ask James how to do it. # Comments self.submissionDetailsInputFrame3.pack() # Make a frame for the save options button. self.saveOptionsFrame = Frame(self.interior) Button(self.saveOptionsFrame, text='Save Options', command=self.saveOptions).grid(row=0, column=0) self.saveOptionsFrame.pack() self.loadOptions() # I needed a function for the return keypress to latch onto. # It is just a wrapper for the saveOptions method. def returnFunction(self, event): self.saveOptions() # submissionOptions is a dictionary, passed by the parent. def loadOptions(self): if getConfigurationValue('ipd_username') is not None: self.inputUsername.set(getConfigurationValue('ipd_username')) if getConfigurationValue('ipd_password') is not None: self.inputPassword.set(getConfigurationValue('ipd_password')) if getConfigurationValue('sample_id') is not None: self.inputSampleID.set(getConfigurationValue('sample_id')) if getConfigurationValue('gene') is not None: self.inputGene.set(getConfigurationValue('gene')) if getConfigurationValue('class') is not None: if (str(getConfigurationValue('class')) == '1'): self.chooseClassIntVar.set(1) elif (str(getConfigurationValue('class')) == '2'): self.chooseClassIntVar.set(2) else: raise Exception('Error loading IPD submission options. Invalid class:' + str(getConfigurationValue('class'))) if getConfigurationValue('allele_name') is not None: self.inputAllele.set(getConfigurationValue('allele_name')) if getConfigurationValue('ena_sequence_accession') is not None: self.inputEnaAcc.set(getConfigurationValue('ena_sequence_accession')) if getConfigurationValue('ena_release_date') is not None: self.inputReleaseDate.set(getConfigurationValue('ena_release_date')) # 0=unpublished, 1=published #print('1Setting is_published value to:' + getConfigurationValue('is_published')) if (getConfigurationValue('is_published') is None or getConfigurationValue('is_published') == 'None'): self.publishedReferenceIntVar.set(0) #print('2Setting is_published value to:' + getConfigurationValue('is_published')) else: self.publishedReferenceIntVar.set(getConfigurationValue('is_published')) if getConfigurationValue('reference_title') is not None: self.inputReferenceTitle.set(getConfigurationValue('reference_title')) if getConfigurationValue('reference_authors') is not None: self.inputReferenceAuthors.set(getConfigurationValue('reference_authors')) if getConfigurationValue('reference_journal') is not None: self.inputReferenceJournal.set(getConfigurationValue('reference_journal')) if getConfigurationValue('reference_journal') is not None: self.inputReferenceJournal.set(getConfigurationValue('reference_journal')) if getConfigurationValue('closest_known_allele') is not None: self.inputClosestAllele.set(getConfigurationValue('closest_known_allele')) if getConfigurationValue('closest_allele_written_description') is not None: self.inputClosestAlleleWrittenDescription.set(getConfigurationValue('closest_allele_written_description')) if getConfigurationValue('ethnic_origin') is not None: self.inputEthnicOrigin.set(getConfigurationValue('ethnic_origin')) if getConfigurationValue('sex') is not None: self.inputSex.set(getConfigurationValue('sex')) if getConfigurationValue('consanguineous') is not None: self.inputConsanguineous.set(getConfigurationValue('consanguineous')) if getConfigurationValue('homozygous') is not None: self.inputHomozygous.set(getConfigurationValue('homozygous')) if getConfigurationValue('lab_of_origin') is not None: self.inputLabOrigin.set(getConfigurationValue('lab_of_origin')) if getConfigurationValue('lab_contact') is not None: self.inputLabContact.set(getConfigurationValue('lab_contact')) if getConfigurationValue('material_availability') is not None: self.inputMaterialAvailable.set(getConfigurationValue('material_availability')) if getConfigurationValue('cell_bank') is not None: self.inputCellBank.set(getConfigurationValue('cell_bank')) # TODO: # Load options for HLA allele calls. # Clear the combo-box, and fill it with the keys of my hla allele call dictionary. def saveOptions(self): # Close the window # TODO: If i force the user to fill in all the options, this form is really obnoxious. # Instead they should be allowed to close it and I will still warn them. # I can re-think this plan if people are trying to submit bad data. #if (self.checkOptions()): #Don't force user to fill in all the options: self.checkOptions() if(True): logging.info ('Saving Options....') assignConfigurationValue('ipd_username', self.inputUsername.get()) # I store this password so I can use it in the submission # I don't ever want to save the password. Make sure it isn't being saved in the config, in AlleleSubCommon.py assignConfigurationValue('ipd_password', self.inputPassword.get()) assignConfigurationValue('sample_id', self.inputSampleID.get()) assignConfigurationValue('gene', self.inputGene.get()) assignConfigurationValue('class', str(self.chooseClassIntVar.get())) assignConfigurationValue('allele_name', self.inputAllele.get()) assignConfigurationValue('ena_sequence_accession', self.inputEnaAcc.get()) assignConfigurationValue('ena_release_date', self.inputReleaseDate.get()) assignConfigurationValue('is_published', str(self.publishedReferenceIntVar.get())) #print('Saving is_published configuration as :' + str(self.publishedReferenceIntVar.get())) assignConfigurationValue('reference_title',self.inputReferenceTitle.get()) assignConfigurationValue('reference_authors',self.inputReferenceAuthors.get()) assignConfigurationValue('reference_journal',self.inputReferenceJournal.get()) assignConfigurationValue('closest_known_allele', self.inputClosestAllele.get()) assignConfigurationValue('closest_allele_written_description', self.inputClosestAlleleWrittenDescription.get()) assignConfigurationValue('ethnic_origin', self.inputEthnicOrigin.get()) assignConfigurationValue('sex', self.inputSex.get()) # TODO: Accepted values are 'Yes', 'No', 'Unknown' # Make dropdown for these assignConfigurationValue('consanguineous', self.inputConsanguineous.get()) assignConfigurationValue('homozygous', self.inputHomozygous.get()) assignConfigurationValue('lab_of_origin', self.inputLabOrigin.get()) assignConfigurationValue('lab_contact', self.inputLabContact.get()) assignConfigurationValue('material_availability', self.inputMaterialAvailable.get()) assignConfigurationValue('cell_bank', self.inputCellBank.get()) # I have saved hla calls in a dictionary. They should have been saved individually. self.parent.destroy() else: #logging.info('Not ready to save, you are missing options.') pass def checkOptions(self): # TODO this method logging.info ('Checking options.') # Don't check the IPD Username # Don't check the IPD Password if (not self.inputSampleID.get()): messagebox.showwarning('Missing Form Value', 'You are missing a Sample ID. Please try again.') return False if (not self.inputGene.get()): messagebox.showwarning('Missing Form Value', 'You are missing a Gene. Please try again.') return False if (not self.inputAllele.get()): messagebox.showwarning('Missing Form Value', 'You are missing an Allele Name. Please try again.') return False if (not self.inputEnaAcc.get()): messagebox.showwarning('Missing Form Value', 'You are missing an ENA Accession Number. Please try again.') return False if (not self.inputReleaseDate.get()): messagebox.showwarning('Missing Form Value', 'You are missing an IPD Submission Release Date. Please try again.') return False # This is NOne if nothing is selected. if (self.publishedReferenceIntVar.get() == 0): # unpublished, nothing to check pass else: if ((not self.inputReferenceTitle.get()) or (not self.inputReferenceAuthors.get()) or (not self.inputReferenceJournal.get()) ): messagebox.showwarning('Missing Form Value', 'You are must supply information about the published Reference. Please try again.') return False if (not self.inputClosestAllele.get()): messagebox.showwarning('Missing Form Value', 'You are missing the closest known reference allele to this sequence. Please provide this information.') return False if (not self.inputEthnicOrigin.get()): messagebox.showwarning('Missing Form Value', 'Please provide a description of an ethnic origin for this sample.') return False if (not self.inputSex.get()): messagebox.showwarning('Missing Form Value', 'Please identify the sex for this sample.') return False # TODO: Accepted values are 'Yes', 'No', 'Unknown' I think if (not self.inputConsanguineous.get()): messagebox.showwarning('Missing Form Value', 'Please indicate if the sample is consanguineous or not.') return False if (not self.inputHomozygous.get()): messagebox.showwarning('Missing Form Value', 'Please indicate if the sample is homozygous or not.') return False if (not self.inputLabOrigin.get()): messagebox.showwarning('Missing Form Value', 'Please provide the name of the submitting laboratory.') return False if (not self.inputLabContact.get()): messagebox.showwarning('Missing Form Value', 'Please provide the name of the laboratory contact.') return False if (not self.inputMaterialAvailable.get()): messagebox.showwarning('Missing Form Value', 'Please indicate if the cell material is available.') return False if (not self.inputCellBank.get()): messagebox.showwarning('Missing Form Value', 'Please provide the name of the cell bank where the sample can be found.') return False # TODO Validate the HLA ALlele calls. I won't do IMGT/HLA validation, I will leave that validation up to IMGT/HLA # Validate A, B, DRB1. The rest, I don't care. # All options look good, right? return True def closeWindow(self): #writeConfigurationFile() self.parent.destroy()
class interface(Frame): def __init__(self, sets): super().__init__() self.initUI(sets) self.mainloop() def initUI(self, sets): self.current_palette = sns.cubehelix_palette(len(sets), start=2, rot=0, dark=.2, light=.85, reverse=True) self.sets = sets outer_options_frame = Frame(self.master) outer_options_frame.pack(side=LEFT, expand=True, fill='both') self.fig = plt.figure() self.fig.patch.set_alpha(1) self.fig.set_facecolor((.95, .95, .95)) matplotlib.style.use('seaborn-darkgrid') self.ax = self.fig.add_subplot(1, 1, 1) self.ax.set_facecolor((210 / 255, 210 / 255, 210 / 255)) self.ax.set_alpha(0.0) self.ax.spines['left'].set_visible(True) # w, h = self.master.winfo_screenwidth(), self.master.winfo_screenheight() # if self.master.winfo_screenwidth() != w or self.master.winfo_screenheight() options_frame = Frame(outer_options_frame) options_frame.pack(side=LEFT) self.canvas_frame = Frame(outer_options_frame, bg='') self.canvas_frame.pack(side=LEFT, expand=True, fill='both') self.canvas = FigureCanvasTkAgg(self.fig, self.canvas_frame) self.toolbar = CustomToolbar(self.canvas, self.canvas_frame) self.canvas.get_tk_widget().pack(side=LEFT, expand=True, fill='both') self.drop = Notebook(options_frame) self.drop.pack(expand=True, fill='x') title_frame = Frame(options_frame) title_frame.pack(expand=True, fill='x') title_label = Label(title_frame, text='Title', fg='#009999', bg='#C0C0C0') title_label.pack(expand=True, fill='x') self.title_box = Entry(title_frame, fg='#009999') self.title_box.pack(side=LEFT, expand=True, fill='both') x_ax_frame = Frame(options_frame) x_ax_frame.pack(expand=True, fill='x') x_axlabel = Label(x_ax_frame, text='X Axis Label', fg='#009999', bg='#C0C0C0') x_axlabel.pack(expand=True, fill='x') self.x_ax_box = Entry(x_ax_frame, fg='#009999') self.x_ax_box.pack(side=LEFT, expand=True, fill='x') y_ax_frame = Frame(options_frame) y_ax_frame.pack(expand=True, fill='x') y_axlabel = Label(y_ax_frame, text='Y Axis Label', fg='#009999', bg='#C0C0C0') y_axlabel.pack(expand=True, fill='x') self.y_ax_box = Entry(y_ax_frame, fg='#009999') self.y_ax_box.pack(side=LEFT, expand=True, fill='x') self.integrate_onoffs = [] self.max_points = [] self.min_points = [] self.min_boxes = [] self.max_boxes = [] self.max_texts = [] self.min_texts = [] self.max_lower_boxes = [] self.min_lower_boxes = [] self.max_higher_boxes = [] self.min_higher_boxes = [] self.min_onoffs = [] self.max_onoffs = [] self.lines = [] self.fills = [] self.area_boxes = [] self.data_titles = [] self.lines = [] self.x_maxmax = -999999999 self.x_minmin = 99999999999 self.y_maxmax = -999999999 self.y_minmin = 99999999999 self.data_checks = [] self.data_check_onoffs = [] self.lines_onoffs = [] self.linewidths = [] for set in sets: current_frame = Frame(self.drop) max_point = 0 self.fills.append(0) self.linewidths.append(3) min_point = 0 max_text = '' min_text = '' self.max_texts.append(max_text) self.min_texts.append(min_text) self.max_points.append(max_point) self.min_points.append(min_point) x = set[0] y = set[1] if max(x) > self.x_maxmax: self.x_maxmax = max(x) if min(x) < self.x_minmin: self.x_minmin = min(x) if max(y) > self.y_maxmax: self.y_maxmax = max(y) if min(y) < self.y_minmin: self.y_minmin = min(y) line, = self.ax.plot(x, y, linewidth=3, color=self.current_palette[sets.index(set)]) self.lines.append(line) self.lines_onoffs.append(1) # self.ax.scatter(x, y, linewidth=3, color=self.current_palette[sets.index(set)]) dataset_frame = Frame(current_frame) dataset_frame.pack() data_check_onoff = IntVar() data_check = Checkbutton(dataset_frame, bg='#C0C0C0', fg='#009999', variable=data_check_onoff, command=self.toggle_line, activebackground='#C0C0C0', activeforeground='#009999') data_check.pack(side=LEFT, expand=True, fill='x') self.data_checks.append(data_check) self.data_check_onoffs.append(data_check_onoff) dataset_box = Entry(dataset_frame, fg='#009999', bg='#C0C0C0', justify='center') dataset_box.insert(0, 'Dataset ' + str(sets.index(set) + 1)) self.data_titles.append(dataset_box) dataset_box.pack(expand=True, fill='both', side=LEFT) max_frame = Frame(current_frame, bg='#C0C0C0') max_frame.pack(expand=True, fill='x') max_OnOff = IntVar() max_checkbox = Checkbutton(max_frame, text='Max:', variable=max_OnOff, command=self.maximum, fg='#009999', bg='#C0C0C0', activebackground='#C0C0C0', activeforeground='#009999') self.max_onoffs.append(max_OnOff) max_checkbox.pack(side=LEFT) self.max_boxes.append(max_checkbox) max_lower_label = Label(max_frame, text='Between', fg='#009999', bg='#C0C0C0') max_lower_label.pack(side=LEFT) max_lower_box = Entry(max_frame, width=7, fg='#009999') max_lower_box.insert(0, str(float(min(x)))) max_lower_box.pack(side=LEFT, expand=True, fill='x') max_higher_label = Label(max_frame, text='and', fg='#009999', bg='#C0C0C0') max_higher_label.pack(side=LEFT) max_higher_box = Entry(max_frame, width=7, fg='#009999') max_higher_box.insert(0, str(float(max(x)))) max_higher_box.pack(side=LEFT, expand=True, fill='x') self.max_higher_boxes.append(max_higher_box) self.max_lower_boxes.append(max_lower_box) min_frame = Frame(current_frame, bg='#C0C0C0') min_frame.pack(expand=True, fill='x') min_OnOff = IntVar() min_checkbox = Checkbutton(min_frame, text='Min:', variable=min_OnOff, command=self.minimum, fg='#009999', bg='#C0C0C0', activebackground='#C0C0C0', activeforeground='#009999') self.min_onoffs.append(min_OnOff) min_checkbox.pack(side=LEFT) self.min_boxes.append(min_checkbox) min_lower_label = Label(min_frame, text='Between', fg='#009999', bg='#C0C0C0') min_lower_label.pack(side=LEFT) min_lower_box = Entry(min_frame, width=7, fg='#009999') min_lower_box.insert(0, str(float(min(x)))) min_lower_box.pack(side=LEFT, expand=True, fill='x') min_higher_label = Label(min_frame, text='and', fg='#009999', bg='#C0C0C0') min_higher_label.pack(side=LEFT) min_higher_box = Entry(min_frame, width=7, fg='#009999') min_higher_box.insert(0, str(float(max(x)))) min_higher_box.pack(side=LEFT, expand=True, fill='x') self.min_higher_boxes.append(min_higher_box) self.min_lower_boxes.append(min_lower_box) integrate_frame = Frame(current_frame) integrate_frame.pack(expand=True, fill='x') integrate_ofonn = IntVar() self.integrate_check = Checkbutton(integrate_frame, bg='#C0C0C0', variable=integrate_ofonn, fg='#009999', activebackground='#C0C0C0', activeforeground='#009999', text='Integrate, Area = ', command=self.integral) self.integrate_check.pack(expand=True, fill='x', side=LEFT) area_box = Entry(integrate_frame, fg='#009999') area_box.pack(side=LEFT, expand=True, fill='x') self.area_boxes.append(area_box) self.integrate_onoffs.append(integrate_ofonn) # line_width_frame = Frame(current_frame) # line_width_frame.pack(expand=True, fill = 'x') # line_width_box = Entry(line_width_frame, width=7, fg='#009999', text ='Linewidth') # line_width_box.insert('3') # line_width_box.pack(expand=True, fill = 'x') # linear_frame = Frame(current_frame) # linear_frame.pack(expand=True, fill='x') # linear_ofonn = IntVar() # linear_checkbox = Checkbutton(linear_frame, text='Linear Regression', variable=linear_ofonn, fg='#009999', activebackground='#C0C0C0', activeforeground='#009999', command=self.lin_reg, bg = '#C0C0C0') # linear_checkbox.pack(expand=True, fill='x') # equation_box = Entry(linear_frame) self.drop.add(current_frame, text=str(1 + sets.index(set))) self.xlow, self.xhigh, self.ylow, self.yhigh = plt.axis() xlimit_frame = Frame(options_frame) xlimit_frame.pack(expand=True, fill='x') xlim_label = Label(xlimit_frame, text='X Limit', fg='#009999', bg='#C0C0C0') xlim_label.pack(side=LEFT) self.xlim_lower_box = Entry(xlimit_frame, width=7, fg='#009999') self.xlim_lower_box.insert(0, self.xlow) self.xlim_lower_box.pack(side=LEFT, expand=True, fill='x') xlim_higher_label = Label(xlimit_frame, text='to', fg='#009999', bg='#C0C0C0') xlim_higher_label.pack(side=LEFT) self.xlim_higher_box = Entry(xlimit_frame, width=7, fg='#009999') self.xlim_higher_box.insert(0, self.xhigh) self.xlim_higher_box.pack(side=LEFT, expand=True, fill='x') ylimit_frame = Frame(options_frame) ylimit_frame.pack(expand=True, fill='x') ylim_label = Label(ylimit_frame, text='Y Limit', fg='#009999', bg='#C0C0C0') ylim_label.pack(side=LEFT) self.ylim_lower_box = Entry(ylimit_frame, width=7, fg='#009999') self.ylim_lower_box.insert(0, self.ylow) self.ylim_lower_box.pack(side=LEFT, expand=True, fill='x') ylim_higher_label = Label(ylimit_frame, text='to', fg='#009999', bg='#C0C0C0') ylim_higher_label.pack(side=LEFT) self.ylim_higher_box = Entry(ylimit_frame, width=7, fg='#009999') self.ylim_higher_box.insert(0, self.yhigh) self.ylim_higher_box.pack(side=LEFT, expand=True, fill='x') bg_slider_frame = Frame(options_frame) bg_slider_frame.pack(expand=True, fill='x') bg_slider_label = Label(bg_slider_frame, text='Background Color', fg='#009999', bg='#C0C0C0') bg_slider_label.pack(expand=True, fill='x') self.bg_slider = Scale(bg_slider_frame, from_=0, to=255, orient='horizontal', bg='#C0C0C0') self.bg_slider.set(210) self.bg_slider.pack(expand=True, fill='x') legend_frame = Frame(options_frame) legend_frame.pack(expand=True, fill='x') self.legend_onoff = IntVar() self.legend_check = Checkbutton(legend_frame, bg='#C0C0C0', fg='#009999', variable=self.legend_onoff, command=self.add_legend, text='Legend', activebackground='#C0C0C0', activeforeground='#009999') self.legend_check.pack(expand=True, fill='x') apply_button_frame = Frame(options_frame, bg='#C0C0C0') apply_button_frame.pack() self.apply_button = Button(apply_button_frame, text='Apply', command=self.apply, bg='#C0C0C0') self.apply_button.grid(row=0, column=0) for chk in self.data_checks: chk.toggle() def close(self): self.master.destroy() self.master.quit() self.master.protocol("WM_DELETE_WINDOW", lambda: close(self)) def xlimit(self): if self.xlim_lower_box.get() != self.xlow: lower_text = self.xlim_lower_box.get() self.ax.set_xlim(xmin=float(lower_text)) self.ax.set_xticks( linspace(float(lower_text), self.ax.get_xlim()[1], 20)) self.canvas.get_tk_widget().update() self.canvas.draw() if self.xlim_higher_box.get() != self.xhigh: higher_text = self.xlim_higher_box.get() self.ax.set_xlim(xmax=float(higher_text)) self.ax.set_xticks( linspace(self.ax.get_xlim()[0], float(higher_text), 20)) self.canvas.get_tk_widget().update() self.canvas.draw() def ylimit(self): if self.ylim_lower_box.get() != self.ylow: lower_text = self.ylim_lower_box.get() self.ax.set_ylim(ymin=float(lower_text)) self.ax.set_yticks( linspace(float(lower_text), self.ax.get_ylim()[1], 20)) self.canvas.get_tk_widget().update() self.canvas.draw() if self.ylim_higher_box.get() != self.yhigh: higher_text = self.ylim_higher_box.get() self.ax.set_ylim(ymax=float(higher_text)) self.ax.set_yticks( linspace(self.ax.get_ylim()[0], float(higher_text), 20)) self.canvas.get_tk_widget().update() self.canvas.draw() # def linewidth(self): # def title(self): title_text = self.title_box.get() self.title_box.delete(0, len(title_text)) self.ax.set_title(title_text) self.canvas.get_tk_widget().update() self.canvas.draw() def background(self): color = self.bg_slider.get() self.ax.set_facecolor((color / 255, color / 255, color / 255)) self.canvas.get_tk_widget().update() self.canvas.draw() def x_ax(self): x_ax_text = self.x_ax_box.get() self.x_ax_box.delete(0, len(x_ax_text)) self.ax.set_xlabel(x_ax_text) self.canvas.get_tk_widget().update() self.canvas.draw() def y_ax(self): y_ax_text = self.y_ax_box.get() self.y_ax_box.delete(0, len(y_ax_text)) self.ax.set_ylabel(y_ax_text) self.canvas.get_tk_widget().update() self.canvas.draw() def maximum(self): for box in self.max_boxes: x = self.sets[self.max_boxes.index(box)][0] y = self.sets[self.max_boxes.index(box)][1] if self.max_onoffs[self.max_boxes.index(box)].get( ) == 0 and self.max_points[self.max_boxes.index(box)] != 0: try: self.max_points[self.max_boxes.index(box)].remove() self.max_texts[self.max_boxes.index(box)].remove() self.canvas.get_tk_widget().update() self.canvas.draw() except: pass if self.max_onoffs[self.max_boxes.index(box)].get() == 1: try: self.max_points[self.max_boxes.index(box)].remove() self.max_texts[self.max_boxes.index(box)].remove() except: pass try: lower_val = float( self.max_lower_boxes[self.max_boxes.index(box)].get()) except: lower_val = min(x) self.max_lower_boxes[self.max_boxes.index(box)].insert( 0, str(min(x))) try: higher_val = float( self.max_higher_boxes[self.max_boxes.index(box)].get()) except: higher_val = max(x) self.max_higher_boxes[self.max_boxes.index(box)].insert( 0, str(max(x))) if lower_val not in x: closest = x[0] for val in x: if abs(lower_val - val) < abs(lower_val - closest): closest = val lower_val = closest if higher_val not in x: closest = x[0] for val in x: if abs(higher_val - val) < abs(higher_val - closest): closest = val higher_val = closest if lower_val != min(x) or higher_val != max(x): try: self.max_points[self.max_boxes.index(box)].remove() self.max_texts[self.max_boxes.index(box)].remove() self.canvas.get_tk_widget().update() self.canvas.draw() except: pass self.max_higher_boxes[self.max_boxes.index(box)].delete( 0, len(self.max_higher_boxes[self.max_boxes.index( box)].get())) self.max_lower_boxes[self.max_boxes.index(box)].delete( 0, len(self.max_lower_boxes[self.max_boxes.index(box)].get())) self.max_lower_boxes[self.max_boxes.index(box)].insert( 0, str(lower_val)) self.max_higher_boxes[self.max_boxes.index(box)].insert( 0, str(higher_val)) max_y_range = y[x.index(lower_val):x.index(higher_val) + 1] ymax = max(max_y_range) xmax = x[y.index(ymax)] max_point, = self.ax.plot(xmax, ymax, 'ko') self.max_points[self.max_boxes.index(box)] = max_point max_str = 'Max: (' + str(round(xmax, 2)) + ',' + str( round(ymax, 2)) + ')' max_text = self.ax.annotate(max_str, (xmax, ymax + ymax / 100), annotation_clip=False) self.max_texts[self.max_boxes.index(box)] = max_text self.canvas.get_tk_widget().update() self.canvas.draw() def minimum(self): for box in self.min_boxes: x = self.sets[self.min_boxes.index(box)][0] y = self.sets[self.min_boxes.index(box)][1] if self.min_onoffs[self.min_boxes.index(box)].get( ) == 0 and self.min_points[self.min_boxes.index(box)] != 0: try: self.min_points[self.min_boxes.index(box)].remove() self.min_texts[self.min_boxes.index(box)].remove() self.canvas.get_tk_widget().update() self.canvas.draw() except: pass if self.min_onoffs[self.min_boxes.index(box)].get() == 1: try: self.min_points[self.min_boxes.index(box)].remove() self.min_texts[self.min_boxes.index(box)].remove() except: pass try: lower_val = float( self.min_lower_boxes[self.min_boxes.index(box)].get()) except: lower_val = min(x) self.min_lower_boxes[self.min_boxes.index(box)].insert( 0, str(min(x))) try: higher_val = float( self.min_higher_boxes[self.min_boxes.index(box)].get()) except: higher_val = max(x) self.min_higher_boxes[self.min_boxes.index(box)].insert( 0, str(max(x))) if lower_val not in x: closest = x[0] for val in x: if abs(lower_val - val) < abs(lower_val - closest): closest = val lower_val = closest if higher_val not in x: closest = x[0] for val in x: if abs(higher_val - val) < abs(higher_val - closest): closest = val higher_val = closest if lower_val != min(x) or higher_val != max(x): try: self.min_points[self.min_boxes.index(box)].remove() self.min_texts[self.min_boxes.index(box)].remove() self.canvas.get_tk_widget().update() self.canvas.draw() except: pass self.min_higher_boxes[self.min_boxes.index(box)].delete( 0, len(self.min_higher_boxes[self.min_boxes.index( box)].get())) self.min_lower_boxes[self.min_boxes.index(box)].delete( 0, len(self.min_lower_boxes[self.min_boxes.index(box)].get())) self.min_lower_boxes[self.min_boxes.index(box)].insert( 0, str(lower_val)) self.min_higher_boxes[self.min_boxes.index(box)].insert( 0, str(higher_val)) min_y_range = y[x.index(lower_val):x.index(higher_val) + 1] ymin = min(min_y_range) xmin = x[y.index(ymin)] min_point, = self.ax.plot(xmin, ymin, 'ko') self.min_points[self.min_boxes.index(box)] = min_point min_str = 'Min: (' + str(round(xmin, 2)) + ',' + str( round(ymin, 2)) + ')' min_text = self.ax.annotate(min_str, (xmin, ymin + ymin / 100), annotation_clip=False) self.min_texts[self.min_boxes.index(box)] = min_text self.canvas.get_tk_widget().update() self.canvas.draw() def apply(self): if self.title_box.get() != '': self.title() if (self.x_ax_box.get() != ''): self.x_ax() if (self.y_ax_box.get() != ''): self.y_ax() self.xlimit() self.ylimit() self.maximum() self.minimum() self.background() self.integral() self.add_legend() def integral(self): for box in self.integrate_onoffs: ind = self.integrate_onoffs.index(box) if box.get() == 1 and self.fills[ind] == 0: area_box = self.area_boxes[ind] set = self.sets[ind] x = set[0] y = set[1] color = self.current_palette[ind] fill = self.ax.fill_between(x, 0, y, alpha=.35, color=color) self.fills[ind] = fill self.canvas.get_tk_widget().update() self.canvas.draw() area = 0 x = self.sets[ind][0] y = self.sets[ind][1] last_x = x[0] last_y = y[0] for i in range(len(x)): x_val = x[i] y_val = y[i] low_da = (x_val - last_x) * last_y high_da = (x_val - last_x) * y_val da = (low_da + high_da) / 2 area += da last_x = x_val last_y = y_val area_box.insert(0, str(round(area, 4))) area_box.update() if box.get() == 0: area_box = self.area_boxes[ind] try: area_box.delete(0, len(area_box.get())) area_box.update() self.fills[ind].remove() self.fills[ind] = 0 self.canvas.get_tk_widget().update() self.canvas.draw() except: pass def add_legend(self): if self.legend_onoff.get() == 1: labels = () lines = () for i in range(len(self.sets)): label = self.data_titles[i].get() labels += (label, ) line = self.ax.lines[i] lines += (line, ) self.leg = self.ax.legend(lines, labels, frameon=True, loc=4) self.canvas.get_tk_widget().update() self.canvas.draw() if self.legend_onoff.get() == 0: try: self.leg.remove() self.canvas.get_tk_widget().update() self.canvas.draw() except: pass def toggle_line(self): for chk in self.data_check_onoffs: if chk.get() == 0: if self.lines_onoffs[self.data_check_onoffs.index(chk)] == 1: self.lines_onoffs[self.data_check_onoffs.index(chk)] = 0 self.lines[self.data_check_onoffs.index(chk)].remove() self.canvas.get_tk_widget().update() self.canvas.draw() try: self.min_points[self.data_check_onoffs.index( chk)].remove() self.min_texts[self.data_check_onoffs.index( chk)].remove() self.canvas.get_tk_widget().update() self.canvas.draw() except: pass try: self.max_points[self.data_check_onoffs.index( chk)].remove() self.max_texts[self.data_check_onoffs.index( chk)].remove() self.canvas.get_tk_widget().update() self.canvas.draw() except: pass try: ind = self.data_check_onoffs.index(chk) area_box = self.area_boxes[ind] area_box.delete(0, len(area_box.get())) area_box.update() self.fills[ind].remove() self.fills[ind] = 0 self.canvas.get_tk_widget().update() self.canvas.draw() except: pass if chk.get() == 1: if self.lines_onoffs[self.data_check_onoffs.index(chk)] == 0: x = self.sets[self.data_check_onoffs.index(chk)][0] y = self.sets[self.data_check_onoffs.index(chk)][1] line, = self.ax.plot( x, y, linewidth=3, color=self.current_palette[ self.data_check_onoffs.index(chk)]) self.lines[self.data_check_onoffs.index(chk)] = line self.canvas.get_tk_widget().update() self.canvas.draw() self.lines_onoffs[self.data_check_onoffs.index(chk)] = 1 if self.integrate_onoffs[self.data_check_onoffs.index( chk)].get() == 1: try: ind = self.data_check_onoffs.index(chk) area_box = self.area_boxes[ind] set = self.sets[ind] x = set[0] y = set[1] color = self.current_palette[ind] fill = self.ax.fill_between(x, 0, y, alpha=.35, color=color) self.fills[ind] = fill self.canvas.get_tk_widget().update() self.canvas.draw() area = 0 x = self.sets[ind][0] y = self.sets[ind][1] last_x = x[0] last_y = y[0] for i in range(len(x)): x_val = x[i] y_val = y[i] low_da = (x_val - last_x) * last_y high_da = (x_val - last_x) * y_val da = (low_da + high_da) / 2 area += da last_x = x_val last_y = y_val area_box.insert(0, str(round(area, 4))) area_box.update() except: pass if self.min_onoffs[self.data_check_onoffs.index( chk)].get() == 1: try: try: self.min_points[self.data_check_onoffs.index( chk)].remove() self.min_texts[self.data_check_onoffs.index( chk)].remove() except: pass try: lower_val = float(self.min_lower_boxes[ self.data_check_onoffs.index(chk)].get()) except: lower_val = min(x) self.min_lower_boxes[ self.data_check_onoffs.index(chk)].insert( 0, str(min(x))) try: higher_val = float(self.min_higher_boxes[ self.data_check_onoffs.index(chk)].get()) except: higher_val = max(x) self.min_higher_boxes[ self.data_check_onoffs.index(chk)].insert( 0, str(max(x))) if lower_val not in x: closest = x[0] for val in x: if abs(lower_val - val) < abs(lower_val - closest): closest = val lower_val = closest if higher_val not in x: closest = x[0] for val in x: if abs(higher_val - val) < abs(higher_val - closest): closest = val higher_val = closest if lower_val != min(x) or higher_val != max(x): try: self.min_points[self.data_check_onoffs. index(chk)].remove() self.min_texts[self.data_check_onoffs. index(chk)].remove() self.canvas.get_tk_widget().update() self.canvas.draw() except: pass self.min_higher_boxes[self.data_check_onoffs.index( chk)].delete( 0, len(self.min_higher_boxes[ self.data_check_onoffs.index( chk)].get())) self.min_lower_boxes[self.data_check_onoffs.index( chk)].delete( 0, len(self.min_lower_boxes[ self.data_check_onoffs.index( chk)].get())) self.min_lower_boxes[self.data_check_onoffs.index( chk)].insert(0, str(lower_val)) self.min_higher_boxes[self.data_check_onoffs.index( chk)].insert(0, str(higher_val)) min_y_range = y[x.index(lower_val ):x.index(higher_val) + 1] ymin = min(min_y_range) xmin = x[y.index(ymin)] min_point, = self.ax.plot(xmin, ymin, 'ko') self.min_points[self.data_check_onoffs.index( chk)] = min_point min_str = 'Min: (' + str(round( xmin, 2)) + ',' + str(round(ymin, 2)) + ')' min_text = self.ax.annotate( min_str, (xmin, ymin + ymin / 100), annotation_clip=False) self.min_texts[self.data_check_onoffs.index( chk)] = min_text self.canvas.get_tk_widget().update() self.canvas.draw() except: pass if self.max_onoffs[self.data_check_onoffs.index( chk)].get() == 1: try: self.max_points[self.data_check_onoffs.index( chk)].remove() self.max_texts[self.data_check_onoffs.index( chk)].remove() except: pass try: lower_val = float(self.max_lower_boxes[ self.data_check_onoffs.index(chk)].get()) except: lower_val = min(x) self.max_lower_boxes[self.data_check_onoffs.index( chk)].insert(0, str(min(x))) try: higher_val = float(self.max_higher_boxes[ self.data_check_onoffs.index(chk)].get()) except: higher_val = max(x) self.max_higher_boxes[self.data_check_onoffs.index( chk)].insert(0, str(max(x))) if lower_val not in x: closest = x[0] for val in x: if abs(lower_val - val) < abs(lower_val - closest): closest = val lower_val = closest if higher_val not in x: closest = x[0] for val in x: if abs(higher_val - val) < abs(higher_val - closest): closest = val higher_val = closest if lower_val != min(x) or higher_val != max(x): try: self.max_points[self.data_check_onoffs.index( chk)].remove() self.max_texts[self.data_check_onoffs.index( chk)].remove() self.canvas.get_tk_widget().update() self.canvas.draw() except: pass self.max_higher_boxes[self.data_check_onoffs.index( chk)].delete( 0, len(self.max_higher_boxes[ self.data_check_onoffs.index(chk)].get())) self.max_lower_boxes[self.data_check_onoffs.index( chk)].delete( 0, len(self.max_lower_boxes[ self.data_check_onoffs.index(chk)].get())) self.max_lower_boxes[self.data_check_onoffs.index( chk)].insert(0, str(lower_val)) self.max_higher_boxes[self.data_check_onoffs.index( chk)].insert(0, str(higher_val)) max_y_range = y[x.index(lower_val ):x.index(higher_val) + 1] ymax = max(max_y_range) xmax = x[y.index(ymax)] max_point, = self.ax.plot(xmax, ymax, 'ko') self.max_points[self.data_check_onoffs.index( chk)] = max_point max_str = 'Max: (' + str(round(xmax, 2)) + ',' + str( round(ymax, 2)) + ')' max_text = self.ax.annotate(max_str, (xmax, ymax + ymax / 100), annotation_clip=False) self.max_texts[self.data_check_onoffs.index( chk)] = max_text self.canvas.get_tk_widget().update() self.canvas.draw() def lin_reg(self): ...
class Counseling(Tk): def __init__(self, *args, **kwargs): Tk.__init__(self) self.title("Counseling App") self.iconbitmap(position + "/Requirements/AU.ico") self.wm_state('zoomed') self.minsize(width=1300, height=649) self.width1 = self.winfo_screenwidth() self.height1 = self.winfo_screenheight() self.frame = Frame(self, background="white", width=self.width1, height=self.height1) self.frame.place(width=self.width1, height=self.height1) self.width_change = self.frame['width'] self.height_change = self.frame['height'] self.insideOfCounse() self.bind("<Configure>", self.on_resize) def on_resize(self, event): self.config(width=event.width, height=event.height) self.width_change = event.width self.height_change = event.height if self.width_change >= 1300 and self.height_change >= 649: self.gvt.place_configure(x=float(self.width_change / 13), y=float(self.height_change / 20)) self.myname.place_configure(x=float(self.width_change / 6), y=float(self.height_change / 10)) self.fromRankEn.place_configure(x=float(self.width_change / 2), y=float(self.height_change / 10)) x_axis = float( self.width_change / 2) - (self.fromLabel.winfo_reqwidth() - self.fromRankEn.winfo_reqwidth()) / 2 self.fromLabel.place_configure(x=x_axis, y=float(self.height_change / 17)) self.TORankEn.place_configure(x=float(self.width_change / 2) + (self.fromLabel.winfo_reqwidth() + self.fromRankEn.winfo_reqwidth()), y=float(self.height_change / 10)) x_axis2 = float(self.width_change / 2) + (self.fromLabel.winfo_reqwidth() + self.fromRankEn.winfo_reqwidth() ) - (self.TOLabel.winfo_reqwidth() - self.TORankEn.winfo_reqwidth()) / 2 self.TOLabel.place_configure(x=x_axis2, y=float(self.height_change / 17)) self.CollEn.place_configure(x=x_axis2 + (2 * self.TOLabel.winfo_reqwidth()), y=float(self.height_change / 10)) self.CollLabel.place_configure( x=x_axis2 + (2 * self.TOLabel.winfo_reqwidth()) - ((self.CollLabel.winfo_reqwidth() - self.CollEn.winfo_reqwidth()) / 2), y=float(self.height_change / 17)) x_axis3 = x_axis2+(2*self.TOLabel.winfo_reqwidth()) - \ ((self.CollLabel.winfo_reqwidth()-self.CollEn.winfo_reqwidth())/2) self.label.place_configure(x=x_axis3 + 2 * self.CollLabel.winfo_reqwidth(), y=float(self.height_change / 11)) small_width = int((self.width_change / 11) + (2 * ((self.width_change / 11) / 3)) / 11) self.WholeView.column("#0", stretch=YES, minwidth=int((self.width_change / 11) / 2), width=int((self.width_change / 11) / 2), anchor='w') self.WholeView.column("#1", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.column("#2", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.column("#3", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.column("#4", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.column("#5", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.column("#6", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.column("#7", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.column("#8", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.column("#9", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.column("#10", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) else: pass def insideOfCounse(self): self.INTVARFR = IntVar() self.INTVARTO = IntVar() self.COLCODE = StringVar() self.gvt = ttk.Label(self.frame, text="TNEA 2018 Cutoff details", font=("Times 20"), background="white", foreground="brown") self.gvt.place(x=float(self.width_change / 13), y=float(self.height_change / 20)) self.myname = ttk.Label(self.frame, text="Created by,\n\tKiruban Kamaraj", font=("Times 16"), background="white", foreground="brown") self.myname.place(x=float(self.width_change / 6), y=float(self.height_change / 11)) self.fromRankEn = ttk.Entry(self.frame, textvar=self.INTVARFR, font=("Times 16"), width=6) self.fromRankEn.place(x=float(self.width_change / 2), y=float(self.height_change / 10)) self.fromRankEn.focus() self.fromLabel = ttk.Label(self.frame, text="From Rank", font=("Times 16"), background="white") x_axis = float( self.width_change / 2) - (self.fromLabel.winfo_reqwidth() - self.fromRankEn.winfo_reqwidth()) / 2 self.fromLabel.place(x=x_axis, y=float(self.height_change / 17)) self.TORankEn = ttk.Entry(self.frame, textvar=self.INTVARTO, font=("Times 16"), width=6) self.TORankEn.place(x=float(self.width_change / 2) + (self.fromLabel.winfo_reqwidth() + self.fromRankEn.winfo_reqwidth()), y=float(self.height_change / 10)) self.TOLabel = ttk.Label(self.frame, text="To Rank", font=("Times 16"), background="white") x_axis2 = float(self.width_change / 2) + ( self.fromLabel.winfo_reqwidth() + self.fromRankEn.winfo_reqwidth() ) - (self.TOLabel.winfo_reqwidth() - self.TORankEn.winfo_reqwidth()) / 2 self.TOLabel.place(x=x_axis2, y=float(self.height_change / 17)) self.CollEn = ttk.Entry(self.frame, textvar=self.COLCODE, font=("Times 16"), width=6) self.CollEn.place(x=x_axis2 + (2 * self.TOLabel.winfo_reqwidth()), y=float(self.height_change / 10)) self.CollLabel = ttk.Label(self.frame, text="Community", font=("Times 16"), background="white") self.CollLabel.place( x=x_axis2 + (2 * self.TOLabel.winfo_reqwidth()) - ((self.CollLabel.winfo_reqwidth() - self.CollEn.winfo_reqwidth()) / 2), y=float(self.height_change / 17)) x_axis3 = x_axis2+(2*self.TOLabel.winfo_reqwidth()) - \ ((self.CollLabel.winfo_reqwidth()-self.CollEn.winfo_reqwidth())/2) def fch(event): if str(event)[1:6] == "Enter": ImageName = "/Requirements/findup.png" elif str(event)[1:6] == "Leave": ImageName = "/Requirements/find.png" self.findImageChange = ImageTk.PhotoImage( Image.open(position + ImageName)) self.label.configure(image=self.findImageChange) self.label.image = self.findImageChange photo = ImageTk.PhotoImage( Image.open(position + "/Requirements/find.png")) self.label = ttk.Label(self.frame, image=photo, background="#FDFEFE") self.label.image = photo self.label.place(x=x_axis3 + 2 * self.CollLabel.winfo_reqwidth(), y=float(self.height_change / 11)) self.label.bind("<Enter>", fch) self.label.bind("<Leave>", fch) self.label.bind("<Button-1>", self.fetching) self.label.bind("<Return>", self.fetching) def upchange(event): self.label.event_generate("<Enter>") self.label.focus() self.fromRankEn.bind("<Return>", lambda a: self.TORankEn.focus()) self.TORankEn.bind("<Return>", lambda a: self.CollEn.focus()) self.fromRankEn.bind("<FocusIn>", lambda a: self.fromRankEn.select_range(0, END)) self.TORankEn.bind("<FocusIn>", lambda a: self.TORankEn.select_range(0, END)) self.CollEn.bind("<FocusIn>", lambda a: self.CollEn.select_range(0, END)) self.CollEn.bind("<Return>", upchange) style = ttk.Style() style.configure("Treeview", font=("Times", 12), background="brown", foreground="white", rowheight=30) style.configure("Treeview.Heading", font=("Times", 12), background="brown") self.WholeView = ttk.Treeview(self.frame, selectmode='browse') self.WholeView["columns"] = ("SL.NO.", "College Code", "Branch Code", "Round No", "APP.NO.", "Community", "Overall Rank", "Community Rank", "MARK", "Choice No", "Category Allotted") self.Scroll = ttk.Scrollbar(self.frame, orient="vertical", command=self.WholeView.yview) small_width = int((self.width_change / 11) + (2 * ((self.width_change / 11) / 3)) / 11) self.WholeView.column("#0", stretch=YES, minwidth=int((self.width_change / 11) / 2), width=int((self.width_change / 11) / 2), anchor='w') self.WholeView.column("#1", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.column("#2", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.column("#3", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.column("#4", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.column("#5", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.column("#6", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.column("#7", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.column("#8", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.column("#9", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.column("#10", stretch=NO, minwidth=small_width, width=small_width, anchor=CENTER) self.WholeView.heading("#0", text="SL.NO.") self.WholeView.heading("#1", text="College Code") self.WholeView.heading("#2", text="Branch Code") self.WholeView.heading("#3", text="Round No") self.WholeView.heading("#4", text="APP.NO.") self.WholeView.heading("#5", text="Community") self.WholeView.heading("#6", text="Overall Rank") self.WholeView.heading("#7", text="Community Rank") self.WholeView.heading("#8", text="MARK") self.WholeView.heading("#9", text="Choice No") self.WholeView.heading("#10", text="Category Allotted") negheight = (self.height_change - float(self.height_change / 5.5)) / 28.276363636363634 self.WholeView.place(x=0, y=float(self.height_change / 5.5), width=self.width_change - 20, height=self.height_change - float(self.height_change / 5.5) - negheight) self.WholeView.configure(yscrollcommand=self.Scroll.set) self.Scroll.place(x=self.width_change - 20, y=float(self.height_change / 5.5), height=self.height_change - float(self.height_change / 5.5) - negheight) def fetching(self, event=None): start = self.INTVARFR.get() end = self.INTVARTO.get() colco = self.COLCODE.get() self.WholeView.delete(*self.WholeView.get_children()) if len(str(start)) >= 1 and len(str(end)) >= 1: with sql.connect(position + "/Counseling.db") as db: data = db.cursor() data.execute( '''SELECT * FROM Counseling WHERE OverallRank >= %s AND OverallRank <= %s ORDER BY OverallRank ASC''' % (start, end)) details = data.fetchall() db.commit() if len(colco) >= 1: hole_out = [] for i in details: if i[4] == str(colco).upper(): hole_out.append(i) else: pass for insert in range(0, len(hole_out)): self.WholeView.insert( "", "end", text=insert + 1, values=(hole_out[insert][0], hole_out[insert][1], hole_out[insert][2], hole_out[insert][3], hole_out[insert][4], hole_out[insert][5], hole_out[insert][6], hole_out[insert][7], hole_out[insert][8], hole_out[insert][9])) else: for insert in range(0, len(details)): self.WholeView.insert( "", "end", text=insert + 1, values=(details[insert][0], details[insert][1], details[insert][2], details[insert][3], details[insert][4], details[insert][5], details[insert][6], details[insert][7], details[insert][8], details[insert][9])) else: pass try: if event.keysym == "Return": sleep(0.5) self.label.event_generate("<Leave>") self.fromRankEn.focus() else: pass except: pass
class Application(tkinter.Tk): def __init__(self): tkinter.Tk.__init__(self) # Menu Setup menuBar = Menu(self) fileMenu = Menu(menuBar, tearoff=False) fileMenu.add_command(label="Open...", command=self.loadSequence) fileMenu.add_command(label="Close", command=self.closeSequence) fileMenu.add_separator() fileMenu.add_command(label="Exit", command=self.destroy) aboutMenu = Menu(menuBar, tearoff=False) aboutMenu.add_command(label="Help", command=self.showHelp) aboutMenu.add_command(label="About...", command=self.showAbout) menuBar.add_cascade(label="File", menu=fileMenu) menuBar.add_cascade(label="About", menu=aboutMenu) # Window Setup self.title("Rotostitch " + __version__) self.config(menu=menuBar) self.iconbitmap(default=os.path.join(RESOURCE_DIR, "rotostitch-icon.ico")) masterFrame = Frame(self) masterFrame.pack(expand=1, fill=Tkc.BOTH, padx=2, pady=2) self.status = StatusBar(self) self.status.pack(anchor=Tkc.W, fill=Tkc.X, side=Tkc.BOTTOM) # Image review panels frame imgFrame = Frame(masterFrame, borderwidth=2, relief=Tkc.GROOVE) imgFrame.pack(expand=1, fill=Tkc.BOTH) imgFrame.columnconfigure(0, weight=1) imgFrame.columnconfigure(1, weight=0) imgFrame.columnconfigure(2, weight=1) imgFrame.rowconfigure(0, weight=1) imgFrame.rowconfigure(1, weight=0, pad=3) # Creation options frame settingsFrame = Frame(masterFrame, borderwidth=2, relief=Tkc.GROOVE) settingsFrame.pack(fill=Tkc.X) settingsFrame.columnconfigure(1, weight=1, pad=4) create = Button(masterFrame, text="Create", command=self.merge) create.pack(anchor='se', pady=2) self.previewStart = ZoomImage(imgFrame, width=200, height=200, borderwidth=2, relief=Tkc.RIDGE, cursor="crosshair") self.previewStart.grid(row=0, column=0, sticky=Tkc.NSEW) self.previewEnd = ZoomImage(imgFrame, width=200, height=200, borderwidth=2, relief=Tkc.RIDGE) self.previewEnd.grid(row=0, column=2, sticky=Tkc.NSEW) self.previewStart.bind("<Button>", self._startPreviewClicked) self.previewStart.bind("<<Dragged>>", self._previewDragged) self.previewEnd.bind("<<Dragged>>", self._previewDragged) # Binding just the previews to the MouseWheel event should work but doesn't. # The workaround is to bind everything to the mousewheel event # and filter it for just our previews in our callback... self.bind_all("<MouseWheel>", self.previewsScrollZoom) zoomFrame = Frame(imgFrame) zoomFrame.grid(row=0, column=1) self.zoomInImg = PhotoImage(file=os.path.join(RESOURCE_DIR, "plus.gif")) zoomIn = Button(zoomFrame, image=self.zoomInImg, command=self.previewsZoomIn) zoomIn.pack() self.zoomResetImg = PhotoImage(file=os.path.join(RESOURCE_DIR, "refresh.gif")) zoomReset = Button(zoomFrame, image=self.zoomResetImg, command=self.previewsResetZoom) zoomReset.pack() self.zoomOutImg = PhotoImage(file=os.path.join(RESOURCE_DIR, "minus.gif")) zoomOut = Button(zoomFrame, image=self.zoomOutImg, command=self.previewsZoomOut) zoomOut.pack() self.differenceImg = PhotoImage(file=os.path.join(RESOURCE_DIR, "difference.gif")) self.differenceBtn = ToggleButton(imgFrame, image=self.differenceImg) self.differenceBtn.grid(row=1, column=1) self.differenceBtn.bind("<Button1-ButtonRelease>", self.toggleDifference) startSpinFrame = Frame(imgFrame) startSpinFrame.grid(row=1, column=0) endSpinFrame = Frame(imgFrame) endSpinFrame.grid(row=1, column=2) startLabel = Label(startSpinFrame, text="Start Frame:") startLabel.pack(side=Tkc.LEFT) self.startSpin = Spinbox(startSpinFrame) self.startSpin.pack() self.startSpin.changedCallback = self.updateStartPreview endLabel = Label(endSpinFrame, text="End Frame:") endLabel.pack(side=Tkc.LEFT) self.endSpin = Spinbox(endSpinFrame) self.endSpin.pack() self.endSpin.changedCallback = self.updateEndPreview widthHeightFrame = Frame(settingsFrame) widthHeightFrame.grid(row=0, column=1, columnspan=2, sticky=Tkc.E+Tkc.W) widthLabel = Label(settingsFrame, text="Width:") widthLabel.grid(row=0, column=0, sticky=Tkc.W) self.activePic = PhotoImage(file=os.path.join(RESOURCE_DIR, "go.gif")) self.widthSetButton = Button(widthHeightFrame, text="Set", command=self.activateSetWidth, image=self.activePic, compound=Tkc.LEFT) self.widthSetButton.grid(row=0, column=1, sticky=Tkc.W) heightLabel = Label(widthHeightFrame, text="Height:") heightLabel.grid(row=0, column=2, padx=10, sticky=Tkc.E) self.unactivePic = PhotoImage(file=os.path.join(RESOURCE_DIR, "stop.gif")) self.heightSetButton = Button(widthHeightFrame, text="Set", command=self.activateSetHeight, image=self.unactivePic, compound=Tkc.LEFT) self.heightSetButton.grid(row=0, column=3, sticky=Tkc.W) rotationLabel = Label(settingsFrame, text="Rotation:") rotationLabel.grid(row=1, column=0, sticky=Tkc.W) rotFrame = Frame(settingsFrame) rotFrame.grid(row=1, column=1, sticky=Tkc.W) self.rotVar = IntVar() self.rotVar.set(1) rotLeft = Radiobutton(rotFrame, text="Counter Clockwise", value=1, variable=self.rotVar) rotLeft.pack(side=Tkc.LEFT, padx=4) rotRight = Radiobutton(rotFrame, text="Clockwise", value=2, variable=self.rotVar) rotRight.pack(padx=4) outputLabel = Label(settingsFrame, text="Save As:") outputLabel.grid(row=2, column=0, sticky=Tkc.W) self.outputPathVar = StringVar() outputEntry = Entry(settingsFrame, textvariable=self.outputPathVar) outputEntry.grid(row=2, column=1, sticky=Tkc.EW) self.outputImg = PhotoImage(file=os.path.join(RESOURCE_DIR, "folder.gif")) outputSearch = Button(settingsFrame, image=self.outputImg, command=self.setSavePath) outputSearch.grid(row=2, column=2, sticky=Tkc.W) # Object variables self.sequenceLoaded = False self.currentSequence = None self.startImage = None self.endImage = None self.differenceOn = False self.overlayTag = "OverlayItems" self.settingWidth = True self.settingHeight = False self.width = {'start': Coord(), 'end': Coord()} self.height = {'start1': Coord(), 'end1': Coord(), 'start2': Coord(), 'end2': Coord()} def showAbout(self): pass def showHelp(self): pass def loadSequence(self): path = filedialog.askopenfilename(title="Select image from image sequence...") if path and os.path.isfile(path): self.status.showText("Loading sequence: '{}'".format(path)) s = self.currentSequence = FrameSequence(path) self.sequenceLoaded = True self.setupForSequence() self.status.showText("Finished loading: '{}'".format(''.join([s.name, "#" * s.frameDigits, s.ext]))) else: self.status.showText("No sequence at: '{}'".format(path)) def closeSequence(self): self.currentSequence = None self.sequenceLoaded = False self.previewStart.delete(self.overlayTag) self.width = {'start': Coord(), 'end': Coord()} self.height = {'start1': Coord(), 'end1': Coord(), 'start2': Coord(), 'end2': Coord()} self.previewStart.reset() self.previewEnd.reset() self.startSpin.reset() self.endSpin.reset() def setSavePath(self): path = filedialog.asksaveasfilename(title="Select save location...") if path: self.outputPathVar.set(path) def setupForSequence(self): s = self.currentSequence if self.differenceOn: self.differenceBtn.setSelected(False) self.differenceOn = False start = s.start end = s.end self.setStartPreview(start) self.setEndPreview(end) self.startSpin.min(start) self.startSpin.set(start) self.endSpin.max(end) self.endSpin.set(end) self.startSpin.max(end) self.endSpin.min(start) def setStartPreview(self, frame): self.startImage = self.currentSequence.image(frame) if self.startImage: if self.startImage.mode != "RGBA": self.startImage = self.startImage.convert("RGBA") self._refreshStartPreview() def _refreshStartPreview(self): im = self.startImage.copy() if self.differenceOn: endIm = self.previewEnd.getImage() im = ImageChops.difference(im, endIm) im.putalpha(255) self.previewStart.setImage(im) def setEndPreview(self, frame): self.endImage = self.currentSequence.image(frame) if self.endImage: if self.endImage.mode != "RGBA": self.endImage = self.endImage.convert("RGBA") self._refreshEndPreview() def _refreshEndPreview(self): im = self.endImage if self.differenceOn: dif = ImageChops.difference(self.startImage, im) dif.putalpha(255) self.previewStart.setImage(dif) self.previewEnd.setImage(im) def updateStartPreview(self): i = self.startSpin.get() self.endSpin.min(i) if self.sequenceLoaded: self.setStartPreview(i) def updateEndPreview(self): i = self.endSpin.get() self.startSpin.max(i) if self.sequenceLoaded: self.setEndPreview(i) def previewsScrollZoom(self, event): w = self.winfo_containing(event.x_root, event.y_root) if w == self.previewStart or w == self.previewEnd: center = (event.x_root - w.winfo_rootx(), event.y_root - w.winfo_rooty()) if event.delta < 0: self.adjustZoom("out", center) else: self.adjustZoom("in", center) def previewsZoomIn(self): self.adjustZoom("in") def previewsZoomOut(self): self.adjustZoom("out") def adjustZoom(self, direction, center=None): if self.sequenceLoaded: x, y = center if center else (self.previewStart.size[0] / 2, self.previewStart.size[1] / 2) if direction == "in": self.previewStart.zoomIn(center) self.previewEnd.zoomIn(center) self.previewStart.scale(self.overlayTag, x, y, 2.0, 2.0) elif direction == "out": self.previewStart.zoomOut(center) self.previewEnd.zoomOut(center) self.previewStart.scale(self.overlayTag, x, y, .5, .5) self.drawOverlay() def previewsResetZoom(self): self.previewStart.resetZoom() self.previewEnd.resetZoom() self.drawOverlay() def _previewDragged(self, event): if event.widget == self.previewStart: self.previewEnd.moveImage(event.x, event.y) else: self.previewStart.moveImage(event.x, event.y) self.previewStart.move(self.overlayTag, -event.x, -event.y) def toggleDifference(self, event): if not self.differenceBtn.selected(): self.differenceOn = True else: self.differenceOn = False self.setDifference() def setDifference(self): if self.sequenceLoaded: if self.differenceOn: startIm = self.previewStart.getImage() endIm = self.previewEnd.getImage() dif = ImageChops.difference(startIm, endIm) dif.putalpha(255) self.previewStart.setImage(dif) self.differenceOn = True else: self.previewStart.setImage(self.startImage) self.differenceOn = False def activateSetWidth(self): self.widthSetButton.configure(image=self.activePic) self.heightSetButton.configure(image=self.unactivePic) self.settingWidth = True self.settingHeight = False def activateSetHeight(self): self.widthSetButton.configure(image=self.unactivePic) self.heightSetButton.configure(image=self.activePic) self.settingWidth = False self.settingHeight = True def _startPreviewClicked(self, event): if self.sequenceLoaded and (event.num == 1 or event.num == 3): x, y = self.previewStart.screenToWorld((event.x, event.y)) if self.settingWidth: self._setWidth(event.num, x, y) elif self.settingHeight: self._setHeight(event.num, x, y, event.state) def _setWidth(self, button, x, y): if button == 1: self.width['start'].set(x, y) else: self.width['end'].set(x, y) self.drawOverlay() def _setHeight(self, button, x, y, mod): shift = 0x0001 if button == 1: if mod & shift == shift: self.height['start2'].set(x, y) else: self.height['start1'].set(x, y) else: if mod & shift == shift: self.height['end2'].set(x, y) else: self.height['end1'].set(x, y) self.drawOverlay() def drawOverlay(self): prev = self.previewStart # Draw the width line and center line x, y = prev.worldToScreen(self.width['start'].get()) # Width line and dot start point x2, y2 = prev.worldToScreen(self.width['end'].get()) # Width line and dot end point x3 = (x + x2) / 2 # Rotation center line x __, y3 = prev.worldToScreen((0, 0)) # Rotation center line top y __, y4 = prev.worldToScreen(prev.getImage().size) # Rotation center line bottom y prev.delete(self.overlayTag) prev.create_line(x3, y3, x3, y4, tags=self.overlayTag, fill="blue") prev.create_line(x, y, x2, y2, tags=self.overlayTag, fill="red") prev.create_oval(x - 2, y - 2, x + 3, y + 3, tags=self.overlayTag, fill="green") prev.create_oval(x2 - 2, y2 - 2, x2 + 3, y2 + 3, tags=self.overlayTag, fill="green") # Draw the height lines x, y = prev.worldToScreen(self.height['start1'].get()) x2, y2 = prev.worldToScreen(self.height['end1'].get()) prev.create_line(x, y, x2, y2, tags=self.overlayTag, fill="violet") prev.create_oval(x - 2, y - 2, x + 3, y + 3, tags=self.overlayTag, fill="green") prev.create_oval(x2 - 2, y2 - 2, x2 + 3, y2 + 3, tags=self.overlayTag, fill="green") x, y = prev.worldToScreen(self.height['start2'].get()) x2, y2 = prev.worldToScreen(self.height['end2'].get()) prev.create_line(x, y, x2, y2, tags=self.overlayTag, fill="cyan") prev.create_oval(x - 2, y - 2, x + 3, y + 3, tags=self.overlayTag, fill="green") prev.create_oval(x2 - 2, y2 - 2, x2 + 3, y2 + 3, tags=self.overlayTag, fill="green") def merge(self): path = self.outputPathVar.get() if self.sequenceLoaded and path != "": self.status.showProgress() start = self.startSpin.get() end = self.endSpin.get() s = self.currentSequence rotationCenter = int((self.width['start'].x + self.width['end'].x) / 2) height = s.frameSize[1] frameCount = end - start self.status.setProgressMax(frameCount) h = self.height len1 = abs(h['start1'].y - h['end1'].y) len2 = abs(h['start2'].y - h['end2'].y) if len1 > len2: adjustmentRatio = len1/len2 else: adjustmentRatio = len2/len1 crossSection = abs(self.width['start'].x - self.width['end'].x) idealWidth = crossSection * math.pi * adjustmentRatio arcLen = (1.0 / frameCount) * idealWidth stripWidth = int(round(arcLen)) width = stripWidth * frameCount mergeIm = Image.new("RGB", (width, height), None) if self.rotVar.get() == 1: x = width - stripWidth dx = -1 else: x = 0 dx = 1 self.status.setProgress(0) for fnum in range(start, end): frame = s.image(fnum) if frame: frameStrip = frame.crop((rotationCenter, 0, rotationCenter + stripWidth, height)) mergeIm.paste(frameStrip, (x, 0)) x += (dx * stripWidth) self.status.setProgress(fnum) mergeIm = mergeIm.resize((int(idealWidth), height), Image.ANTIALIAS) try: mergeIm.save(path) except IOError: messagebox.showerror("Sorry...", message="Unable to save the final image.") self.status.showText("Finished merging. Unable to save to '{}'".format(path)) self.status.showText("Finished merging. Saved to '{}'".format(path))
class Fenetre(Tk): """ À completer !. """ def __init__(self): """ À completer !. """ super().__init__() # Nom de la fenêtre. self.title("Ultimate Tic-Tac-Toe") # La partie de ultimate Tic-Tac-Toe self.partie = Partie() # Un ditionnaire contenant les 9 canvas des 9 plateaux du jeu self.canvas_uplateau = {} Button(self.canvas_uplateau, text ='Débuter la partie', command =self.demande_confirmation).\ grid(row =0, column =4) self.var = IntVar() Checkbutton(self, text= 'VS ordinateur', variable=self.var, onvalue =1, offvalue =0).grid(row =0, column =2) # L'entrée du joueur1 est automatiquement demandé Label(self.canvas_uplateau, text ="Nom du Joueur 1:").\ grid(row =0, column =0, sticky=E) self.joueur1 = Entry(self.canvas_uplateau, width =14) self.joueur1.grid(row =0, column =1, padx=5, pady=5, sticky=E+W) # Label (self.canvas_uplateau, text="Le tour: {}".format(self.partie.joueur_courant.nom)).grid(row=3, column=3) # L'entrée du joueur2 est selon la checkbox (peut etre l'ordinateur Label(self.canvas_uplateau, text ="Nom du Joueur 2:").\ grid(row =1, column =0, sticky=E) self.joueur2 = Entry(self.canvas_uplateau, width =14) self.joueur2.grid(row =1, column =1, padx=5, pady=5, sticky=E+W) Button(self.canvas_uplateau, text = 'Quitter', command = self.quit).\ grid (row = 5, column = 4, sticky = E) # Création des frames et des canvas du jeu for i in range(0, 3): for j in range(0, 3): cadre = Frame(self, borderwidth=5, relief=GROOVE, background = '#e1e1e1') cadre.grid(row=i+3, column=j, padx=5, pady=5) cadre.bind('<Enter>', self.entrer_frame) cadre.bind('<Leave>', self.sortir_frame) self.canvas_uplateau[i,j] = CanvasPlateau(cadre, self.partie.uplateau[i,j]) self.canvas_uplateau[i,j].grid() # On lie un clic sur le Canvas à une méthode. self.canvas_uplateau[i,j].bind('<Button-1>', self.selectionner) # Ajout d'une étiquette d'information. self.messages = Label(self) self.messages.grid(columnspan=3) # Création de deux joueurs. Ce code doit être bien sûr modifié, # car il faut chercher ces infos dans les widgets de la fenêtre. # Vous pouvez également déplacer ce code dans une autre méthode selon votre propre solution. # p1 = Joueur("VotreNom", "Personne", 'X') # p2 = Joueur("Colosse", "Ordinateur", 'O') # self.partie.joueurs = [p1,p2] # self.partie.joueur_courant = p1 def selectionner(self, event): """ À completer !. """ print (self.partie.joueur_courant.nom) try: # On trouve le numéro de ligne/colonne en divisant par le nombre de pixels par case. # event.widget représente ici un des 9 canvas ! ligne = event.y // event.widget.taille_case colonne = event.x // event.widget.taille_case if not self.partie.uplateau[event.widget.plateau.cordonnees_parent].cases[ligne, colonne].est_vide(): raise ErreurChoixCase ("La case est déjà sélectionné !") self.afficher_message("Case sélectionnée à la position (({},{}),({},{}))." .format(event.widget.plateau.cordonnees_parent[0], event.widget.plateau.cordonnees_parent[1], ligne, colonne)) self.desactiver_plateau(ligne, colonne) # On dessine le pion dans le canvas, au centre de la case. # On utilise l'attribut "tags" pour être en mesure de récupérer # les éléments dans le canvas afin de les effacer par exemple. coordonnee_y = ligne * event.widget.taille_case + event.widget.taille_case // 2 coordonnee_x = colonne * event.widget.taille_case + event.widget.taille_case // 2 event.widget.create_text(coordonnee_x, coordonnee_y, text=self.partie.joueur_courant.pion, font=('Helvetica', event.widget.taille_case//2), tags='pion') # Mettre à jour la case sélectionnée self.partie.uplateau[event.widget.plateau.cordonnees_parent]\ .selectionner_case(ligne, colonne, self.partie.joueur_courant.pion) try: #Eric # On vérifie si le joueur courant est gagnant if event.widget.plateau.est_gagnant(self.partie.joueur_courant.pion): raise EstGagnant (" Bravo {}, Vous avez gagné un plateau !!!".format (self.partie.joueur_courant.nom)) except EstGagnant as e: messagebox.showwarning("Terminé", str(e)) # Changer le joueur courant. # Vous pouvez modifier ou déplacer ce code dans une autre méthode selon votre propre solution. if self.partie.joueur_courant == self.partie.joueurs[0]: self.partie.joueur_courant = self.partie.joueurs[1] else: self.partie.joueur_courant = self.partie.joueurs[0] # Effacer le contenu du widget (canvas) et du plateau (dictionnaire) quand ce dernier devient plein. # Vous pouvez modifier ou déplacer ce code dans une autre méthode selon votre propre solution. if not event.widget.plateau.non_plein(): event.widget.delete('pion') event.widget.plateau.initialiser() except ErreurChoixCase as e: messagebox.showerror ("Erreur", str(e)) def desactiver_plateau(self, ligne, colonne): for i in range(0, 3): for j in range(0, 3): if i != ligne or j != colonne: self.canvas_uplateau[i,j]['borderwidth'] = 2 self.canvas_uplateau[i,j]['background'] = '#e1e1e1' self.canvas_uplateau[i,j].unbind('<Button-1>') else: self.canvas_uplateau[i,j]['borderwidth'] = 2 self.canvas_uplateau[i,j]['background'] = 'blue' self.canvas_uplateau[ligne, colonne].bind('<Button-1>', self.selectionner) def activer_plateau(self): self.canvas_uplateau[0,0].bind('<Button-1>'.self.selectionner) def afficher_message(self, message): """ À completer !. """ self.messages['foreground'] = 'black' self.messages['text'] = message def entrer_frame(self, event): event.widget['background'] = 'red' def sortir_frame(self, event): event.widget['background'] = '#e1e1e1' def demande_confirmation(self): """ À compléter !. """ print ('self.var:', self.var.get()) # en provenance du checkbutton (VS ordinateur) if self.var.get(): # la case est cochée pour jouer contre l'ordinateur deuxieme_joueur = "Le Gros Colosse" type_deuxieme_joueur = "Ordinateur" else: # jouer contre un autre joueur deuxieme_joueur = self.joueur2.get() type_deuxieme_joueur = "Personne" # Création de deux joueurs. Ce code doit être bien sûr modifié, # car il faut chercher ces infos dans les widgets de la fenêtre. # Vous pouvez également déplacer ce code dans une autre méthode selon votre propre solution. p1 = Joueur(self.joueur1.get(), "Personne", 'X') p2 = Joueur(deuxieme_joueur, type_deuxieme_joueur, 'O') self.partie.joueurs = [p1,p2] self.partie.joueur_courant = p1 self.joueur1['state'] = 'disabled' self.joueur2['state'] = 'disabled'
class DeleteDialog(Toplevel): def __init__(self, root, file, delMethod): Toplevel.__init__(self, root) self.wm_title("Confirm Delete") self.file = file self.delMethod = delMethod self.grid_columnconfigure(0, weight=1) self.grid_columnconfigure(1, weight=1) self.mainLbl = Label(self, text="Permanently delete file?") self.dataFrame = Frame(self, bg="#ffffff", bd=2, relief="groove") self.dataFrame.grid_columnconfigure(1, weight=1) self.nameLbl = Label(self.dataFrame, text="Name", bg="#ffffff") self.sizeLbl = Label(self.dataFrame, text="Size", bg="#ffffff") self.modLbl = Label(self.dataFrame, text="Modified", bg="#ffffff") self.nameVal = Label(self.dataFrame, text=self.file["name"], bg="#ffffff") self.sizeVal = Label(self.dataFrame, text=self.file["size"], bg="#ffffff") self.modVal = Label(self.dataFrame, text=ctime(self.file["modified"]), bg="#ffffff") self.trimVar = IntVar() self.trimVar.set(1) btnText = "Delete empty path" self.trimButton = Checkbutton(self, text=btnText, variable=self.trimVar) self.yesBtn = Button(self, text="Yes", width=10, command=self.yes) self.noBtn = Button(self, text="No", width=10, command=self.destroy) self.nameLbl.grid(row=0, column=0, padx=5, pady=10, sticky="w") self.sizeLbl.grid(row=1, column=0, padx=5, pady=5, sticky="w") self.modLbl.grid(row=2, column=0, padx=5, pady=5, sticky="w") self.nameVal.grid(row=0, column=1, padx=5, pady=5, sticky="e") self.sizeVal.grid(row=1, column=1, padx=5, pady=5, sticky="e") self.modVal.grid(row=2, column=1, padx=5, pady=5, sticky="e") self.mainLbl.grid(row=0, column=0, columnspan=2, padx=5, pady=5, sticky="w") self.dataFrame.grid(row=1, column=0, columnspan=2, padx=5, pady=5, sticky="ew") self.trimButton.grid(row=2, column=0, padx=5, pady=5, sticky="w") self.yesBtn.grid(row=3, column=0, pady=10) self.noBtn.grid(row=3, column=1, pady=10) self.geometry("300x225") self.resizable(False, False) self.grab_set() self.transient() # executed on yes click def yes(self, event=None): p = dirname(self.file["path"]) self.delMethod(self.file) if self.trimVar.get() == 1: trimPath(p) self.destroy()
class LoginFrame(Frame): def __init__(self, master): super().__init__(master) master.title("Login") master.resizable(False, False) master.configure(background=backgroundColor) self.configure(background=backgroundColor) textFont2 = Font(size=12, weight="bold") textFont = Font(size=12, weight="normal") self.duco = ImageTk.PhotoImage(Image.open(resources + "duco.png")) self.duco.image = self.duco self.ducoLabel = Label(self, background="#ff7f50", image=self.duco) self.ducoLabel2 = Label( self, background="#ff7f50", foreground="#FAFAFA", text="Welcome to the\nDuino-Coin\nTkinter GUI Wallet", font=textFont2) self.spacer = Label(self, background=backgroundColor) self.label_username = Label(self, text="USERNAME", background=backgroundColor, foreground=foregroundColor, font=textFont2) self.label_password = Label(self, text="PASSWORD", background=backgroundColor, foreground=foregroundColor, font=textFont2) self.entry_username = Entry(self, background=backgroundColor, foreground=foregroundColor, font=textFont) self.entry_password = Entry(self, show="*", background=backgroundColor, foreground=foregroundColor, font=textFont) self.ducoLabel.grid(row=0, sticky="nswe", pady=(5, 0), padx=(5)) self.ducoLabel2.grid(row=1, sticky="nswe", padx=(5)) self.spacer.grid(row=3, sticky="nswe", padx=(5)) self.label_username.grid(row=4, sticky=W, pady=(5)) self.entry_username.grid(row=5, sticky=N, padx=(5)) self.label_password.grid(row=6, sticky=W, pady=(5)) self.entry_password.grid(row=7, sticky=N, pady=(5)) self.var = IntVar() self.checkbox = Checkbutton(self, text="Keep me logged in", variable=self.var, background=backgroundColor, foreground=foregroundColor, font=textFont, borderwidth="0", highlightthickness="0") self.checkbox.grid(columnspan=2) self.logbtn = Button(self, text="LOGIN", command=self._login_btn_clicked, background=backgroundColor, foreground=foregroundColor, font=textFont2) self.logbtn.grid(columnspan=2, sticky="nswe", padx=(5), pady=(0, 3)) self.regbtn = Button(self, text="REGISTER", command=self._register_btn_clicked, background=backgroundColor, foreground=foregroundColor, font=textFont2) self.regbtn.grid(columnspan=2, sticky="nswe", padx=(5), pady=(0, 5)) self.pack() def _login_btn_clicked(self): global username, password username = self.entry_username.get() password = self.entry_password.get() keeplogedin = self.var.get() if username and password: soc = socket.socket() soc.connect((pool_address, int(pool_port))) soc.recv(3) soc.send( bytes(f"LOGI,{str(username)},{str(password)}", encoding="utf8")) response = soc.recv(64).decode("utf8") response = response.split(",") if response[0] == "OK": if keeplogedin >= 1: passwordEnc = b64encode(bytes(password, encoding="utf8")) with sqlite3.connect(f"{resources}/wallet.db") as con: cur = con.cursor() cur.execute( '''INSERT INTO UserData(username, password) VALUES(?, ?)''', (username, passwordEnc)) con.commit() root.destroy() else: messagebox.showerror(title="Error loging-in", message=response[1]) else: messagebox.showerror(title="Error loging-in", message="Fill in the blanks first") def _registerprotocol(self): emailS = email.get() usernameS = username.get() passwordS = password.get() confpasswordS = confpassword.get() if emailS and usernameS and passwordS and confpasswordS: if passwordS == confpasswordS: soc = socket.socket() soc.connect((pool_address, int(pool_port))) soc.recv(3) soc.send( bytes( f"REGI,{str(usernameS)},{str(passwordS)},{str(emailS)}", encoding="utf8")) response = soc.recv(128).decode("utf8") response = response.split(",") if response[0] == "OK": messagebox.showinfo( title="Registration successfull", message= "New user has been registered sucessfully. You can now login" ) register.destroy() execl(sys.executable, sys.executable, *sys.argv) else: messagebox.showerror(title="Error registering user", message=response[1]) else: messagebox.showerror(title="Error registering user", message="Passwords don't match") else: messagebox.showerror(title="Error registering user", message="Fill in the blanks first") def _register_btn_clicked(self): global username, password, confpassword, email, register root.destroy() register = Tk() register.title("Register") register.resizable(False, False) #register.geometry("220x350") register.configure(background=backgroundColor) textFont2 = Font(register, size=12, weight="bold") # textFont3 = Font(register, size=14,weight="bold") textFont = Font(register, size=12, weight="normal") duco = ImageTk.PhotoImage(Image.open(resources + "duco.png")) duco.image = duco ducoLabel = Label(register, background="#ff7f50", image=duco) ducoLabel2 = Label(register, background="#ff7f50", foreground="#FAFAFA", text="Register on network", font=textFont2) ducoLabel.grid(row=0, padx=5, pady=(5, 0), sticky="nswe") ducoLabel2.grid(row=1, padx=5, sticky="nswe") Label(register, background=backgroundColor).grid(row=2, padx=5) Label(register, text="USERNAME", background=backgroundColor, foreground=foregroundColor, font=textFont2).grid(row=3, sticky=W) username = Entry(register, background=backgroundColor, foreground=foregroundColor, font=textFont) username.grid(row=4, padx=5) Label(register, text="PASSWORD", background=backgroundColor, foreground=foregroundColor, font=textFont2).grid(row=5, sticky=W) password = Entry(register, background=backgroundColor, show="*", foreground=foregroundColor, font=textFont) password.grid(row=6, padx=5) Label(register, text="CONFIRM PASSWORD", background=backgroundColor, foreground=foregroundColor, font=textFont2).grid(row=7, sticky=W) confpassword = Entry(register, background=backgroundColor, show="*", foreground=foregroundColor, font=textFont) confpassword.grid(row=8, padx=5) Label(register, text="E-MAIL", background=backgroundColor, foreground=foregroundColor, font=textFont2).grid(row=9, sticky=W) email = Entry(register, background=backgroundColor, foreground=foregroundColor, font=textFont) email.grid(row=10, padx=5) self.logbtn = Button(register, text="REGISTER", command=self._registerprotocol, background=backgroundColor, foreground=foregroundColor, font=textFont2) self.logbtn.grid(columnspan=2, sticky="nswe", padx=(5, 5), pady=(5, 5))
class Window(object): """"This class creates a GUI using the built in python libary tkinter""" def __init__(self, window): self.window = window self.check = False self.animateval = False titlel = Label(window, text="Evolutionary Spatial Games", height=3) titlel.grid(row=0, column=0, rowspan=2) self.cellularAutomata = Canvas(window, height=600, width=600, background="blue") self.cellularAutomata.grid(row=2, column=0, rowspan="20") l2 = Label(window, text="Payoff matrix:", width=16) l2.grid(row=3, column=1) l3 = Label(window, text="Cell size: ", width=16) l3.grid(row=6, column=1) l8 = Label(window, text="Moore Neighbourhood: ", width=22) l8.grid(row=7, column=1) l9 = Label(window, text="Von Nuemann Neighbourhood: ", width=26) l9.grid(row=8, column=1) l4 = Label(window, text="Initial Distribution: ", width=16) l4.grid(row=10, column=1) l9 = Label(window, text="Fixed boundary (A): ", width=26) l9.grid(row=11, column=1) l9 = Label(window, text="Reflective boundary: ", width=26) l9.grid(row=12, column=1) l9 = Label(window, text="Periodic boundary: ", width=26) l9.grid(row=13, column=1) la = Label(window, text="Count (A|B|C): ", width=16) la.grid(row=16, column=1) l5 = Label(window, text="Iterations: ", width=16) l5.grid(row=17, column=1) b1 = Button(window, text="Draw", command=self.draw_command) b1.grid(row=19, column=1) self.b2 = Button(window, text="Start", command=self.begin_command) self.b2.grid(row=19, column=2) self.e1 = Scale( window, width=8, orient=HORIZONTAL, from_=2, to=3, label="Strategies" ) self.e1.grid(row=0, column=1) self.e1.bind("<ButtonRelease-1>", self.change_entry) self.li = Label(window, text="B invades A: ", width=16) self.li.grid(row=14, column=1) self.ival = IntVar() self.iv = Checkbutton(window, variable=self.ival) self.iv.grid(row=14, column=2) self.ld = Label(window, text="Dynamic", width=16) self.ld.grid(row=15, column=1) self.dyval = IntVar() self.dyval.set(1) self.dy = Checkbutton(window, variable=self.dyval) self.dy.grid(row=15, column=2) self.e2 = IntVar() self.e2 = Entry(window, textvariable=self.e2, width=6) self.e2.grid(row=3, column=2) self.e3 = IntVar() self.e3 = Entry(window, textvariable=self.e3, width=6) self.e3.grid(row=3, column=3) self.e4 = IntVar() self.e4 = Entry(window, textvariable=self.e4, width=6) self.e4.grid(row=4, column=2) self.e5 = IntVar() self.e5 = Entry(window, textvariable=self.e5, width=6) self.e5.grid(row=4, column=3) self.cellsize = IntVar() self.cellsize.set(8) self.cellsize = Entry(window, textvariable=self.cellsize, width=6) self.cellsize.grid(row=6, column=2) self.p1 = DoubleVar() self.p1 = Entry(window, textvariable=self.p1, width=6) self.p1.grid(row=10, column=2) self.p2 = DoubleVar() self.p2 = Entry(window, textvariable=self.p2, width=6) self.p2.grid(row=10, column=3) self.neighbourE = IntVar() self.neighbourE.set(1) self.moore = Radiobutton(window, variable=self.neighbourE, value=1) self.moore.grid(row=7, column=2) self.nuemann = Radiobutton(window, variable=self.neighbourE, value=2) self.nuemann.grid(row=8, column=2) self.boundaryvar = IntVar() self.boundaryvar.set(2) self.fixed = Radiobutton(window, variable=self.boundaryvar, value=1) self.fixed.grid(row=11, column=2) self.reflective = Radiobutton(window, variable=self.boundaryvar, value=2) self.reflective.grid(row=12, column=2) self.periodic = Radiobutton(window, variable=self.boundaryvar, value=3) self.periodic.grid(row=13, column=2) self.a1 = Listbox(window, width=4, height=1) self.a1.grid(row=16, column=2) self.a2 = Listbox(window, width=4, height=1) self.a2.grid(row=16, column=3) self.i1 = Listbox(window, width=4, height=1) self.i1.grid(row=17, column=2) def draw_command(self): self.cellularAutomata.delete("all") self.count = 0 self.i1.delete(0, END) self.i1.insert(END, self.count) try: self.b3.destroy() self.b2 = Button(window, text="Start", command=self.begin_command) self.b2.grid(row=19, column=2) except AttributeError: pass try: if self.e1.get() == 2: matrix = [ [self.e2.get(), self.e3.get()], [self.e4.get(), self.e5.get()], ] self.SpatialGame = spatialGame( 600, 600, self.cellsize.get(), [self.p1.get(), self.p2.get()], self.e1.get(), matrix, self.ival.get(), self.neighbourE.get(), self.boundaryvar.get(), self.dyval.get(), ) if self.e1.get() == 3: matrix = [ [self.e2.get(), self.e3.get(), self.e6.get()], [self.e4.get(), self.e5.get(), self.e7.get()], [self.e8.get(), self.e9.get(), self.e10.get()], ] self.SpatialGame = spatialGame( 600, 600, self.cellsize.get(), [self.p1.get(), self.p2.get(), self.p3.get()], self.e1.get(), matrix, self.ival.get(), self.neighbourE.get(), self.boundaryvar.get(), self.dyval.get(), ) self.cells = self.SpatialGame.cells for x in range(0, self.SpatialGame.width): for y in range(0, self.SpatialGame.height): if self.cells[x][y] == 2: square_coords = ( x * self.SpatialGame.cell_size, y * self.SpatialGame.cell_size, x * self.SpatialGame.cell_size + self.SpatialGame.cell_size, y * self.SpatialGame.cell_size + self.SpatialGame.cell_size, ) self.cellularAutomata.create_rectangle( square_coords, fill="red", outline="red" ) if self.SpatialGame.cells[x][y] == 3: square_coords = ( x * self.SpatialGame.cell_size, y * self.SpatialGame.cell_size, x * self.SpatialGame.cell_size + self.SpatialGame.cell_size, y * self.SpatialGame.cell_size + self.SpatialGame.cell_size, ) self.cellularAutomata.create_rectangle( square_coords, fill="pink", outline="pink" ) except ValueError: self.cellularAutomata.create_text( 300, 300, fill="White", font="Times 20 bold", text="Your probability distribution must add to 1.", ) def begin_command(self): self.animateval = True self.animate() def next(self): self.cellularAutomata.delete("all") self.SpatialGame.run_rules() self.cells = self.SpatialGame.cells self.count = self.count + 1 self.i1.delete(0, END) self.i1.insert(END, self.count) self.b2.destroy() self.b3 = Button(window, text="Stop", command=self.stop_command) self.b3.grid(row=19, column=2) self.animateval = True for x in range(0, self.SpatialGame.width): for y in range(0, self.SpatialGame.height): if self.cells[x][y] == 2: square_coords = ( x * self.SpatialGame.cell_size, y * self.SpatialGame.cell_size, x * self.SpatialGame.cell_size + self.SpatialGame.cell_size, y * self.SpatialGame.cell_size + self.SpatialGame.cell_size, ) self.cellularAutomata.create_rectangle( square_coords, fill="red", outline="red" ) if self.cells[x][y] == 4: square_coords = ( x * self.SpatialGame.cell_size, y * self.SpatialGame.cell_size, x * self.SpatialGame.cell_size + self.SpatialGame.cell_size, y * self.SpatialGame.cell_size + self.SpatialGame.cell_size, ) self.cellularAutomata.create_rectangle( square_coords, fill="green", outline="green" ) if self.cells[x][y] == 5: square_coords = ( x * self.SpatialGame.cell_size, y * self.SpatialGame.cell_size, x * self.SpatialGame.cell_size + self.SpatialGame.cell_size, y * self.SpatialGame.cell_size + self.SpatialGame.cell_size, ) self.cellularAutomata.create_rectangle( square_coords, fill="yellow", outline="yellow" ) if self.cells[x][y] == 3: square_coords = ( x * self.SpatialGame.cell_size, y * self.SpatialGame.cell_size, x * self.SpatialGame.cell_size + self.SpatialGame.cell_size, y * self.SpatialGame.cell_size + self.SpatialGame.cell_size, ) self.cellularAutomata.create_rectangle( square_coords, fill="pink", outline="pink" ) if self.cells[x][y] == 6: square_coords = ( x * self.SpatialGame.cell_size, y * self.SpatialGame.cell_size, x * self.SpatialGame.cell_size + self.SpatialGame.cell_size, y * self.SpatialGame.cell_size + self.SpatialGame.cell_size, ) self.cellularAutomata.create_rectangle( square_coords, fill="purple", outline="purple" ) self.a1.delete(0, END) self.a1.insert(END, self.SpatialGame.stratA) self.a2.delete(0, END) self.a2.insert(END, self.SpatialGame.stratB) try: self.a3.delete(0, END) self.a3.insert(END, self.SpatialGame.stratC) except: pass def change_entry(self, event): if self.e1.get() == 3 and self.check == False: self.check = True self.e6 = IntVar() self.e6 = Entry(window, textvariable=self.e6, width=6) self.e6.grid(row=3, column=4) self.e7 = IntVar() self.e7 = Entry(window, textvariable=self.e7, width=6) self.e7.grid(row=4, column=4) self.e8 = IntVar() self.e8 = Entry(window, textvariable=self.e8, width=6) self.e8.grid(row=5, column=2) self.e9 = IntVar() self.e9 = Entry(window, textvariable=self.e9, width=6) self.e9.grid(row=5, column=3) self.e10 = IntVar() self.e10 = Entry(window, textvariable=self.e10, width=6) self.e10.grid(row=5, column=4) self.p3 = DoubleVar() self.p3 = Entry(window, textvariable=self.p3, width=6) self.p3.grid(row=10, column=4) self.li.destroy() self.iv.destroy() self.ival = IntVar() self.ival.set(0) self.a3 = Listbox(window, width=4, height=1) self.a3.grid(row=16, column=4) elif self.e1.get() == 2 and self.check == True: self.li = Label(window, text="B invades A: ", width=16) self.li.grid(row=14, column=1) self.ival = IntVar() self.iv = Checkbutton(window, variable=self.ival) self.iv.grid(row=14, column=2) self.check = False self.e6.destroy() self.e7.destroy() self.e8.destroy() self.e9.destroy() self.e10.destroy() self.p3.destroy() self.a3.destroy() def stop_command(self): self.animateval = False self.b3.destroy() self.b2 = Button(window, text="Start", command=self.begin_command) self.b2.grid(row=19, column=2) def animate(self): while self.animateval == True: self.next() self.window.update() time.sleep(0.5)
class pwordGUI(): def __init__(self, master): self.master = master master.title("Password Generator") self.lbl1 = Label(master, text="Include:").grid(row=0, sticky=W) self.incLower = IntVar() self.incLower.set(1) self.chk1 = Checkbutton(master, text="lower case", variable=self.incLower).grid(row=1, sticky=W) self.incUpper = IntVar() self.incUpper.set(1) self.chk2 = Checkbutton(master, text="UPPER CASE", variable=self.incUpper).grid(row=2, sticky=W) self.incNumeric = IntVar() self.incNumeric.set(1) self.chk3 = Checkbutton(master, text="numeric", variable=self.incNumeric).grid(row=3, sticky=W) self.incPunc = IntVar() self.chk4 = Checkbutton(master, text="punctuation", variable=self.incPunc).grid(row=4, sticky=W) self.b1 = Button(master, text="Generate password", width=20, command=self.genPwd).grid(row=5, sticky=W) self.b2 = Button(master, text="Quit", width=20, command=self.exitApp).grid(row=5, column=1, sticky=W) self.label_text = StringVar() self.lbl2 = Label(master, textvariable=self.label_text).grid(row=6, column=0, columnspan=2, sticky=W + E) self.label_text.set("") self.numDigits = IntVar() self.sc1 = Scale(master, from_=6, to=40, variable=self.numDigits).grid(row=0, rowspan=5, column=1, sticky=E) def genPwd(self): if not (self.incLower.get() or self.incUpper.get() or self.incNumeric.get() or self.incPunc.get()): self.label_text.set("Select at least one character type") else: password = '' if self.incLower.get(): password += string.ascii_lowercase if self.incUpper.get(): password += string.ascii_uppercase if self.incNumeric.get(): password += string.digits if self.incPunc.get(): password += string.punctuation myrg = random.SystemRandom() # Get password and make sure it contains at least one of each desired character type goodPwd = False while not goodPwd: pword = ''.join(myrg.choice(password) for i in range(self.numDigits.get())) # Now need to assume password is good and then set it to bad if any test fails goodPwd = True if self.incLower.get(): goodPwd = self.contains_n(string.ascii_lowercase, pword) if self.incUpper.get() and goodPwd: # if password was bad for previous test want to leave it bad goodPwd = self.contains_n(string.ascii_uppercase, pword) if self.incNumeric.get() and goodPwd: # if password was bad for previous test want to leave it bad goodPwd = self.contains_n(string.digits, pword) if self.incPunc.get() and goodPwd: # if password was bad for previous test want to leave it bad goodPwd = self.contains_n(string.punctuation, pword) self.label_text.set(pword) self.master.clipboard_clear() self.master.clipboard_append(pword) def contains_n(self, search, password): for i in password: for j in search: if j == i : return True return False def exitApp(self): self.master.clipboard_clear() # It appears the clipboard doesn't actually clear until you write something new to it. # So write a blank line. self.master.clipboard_append('') self.master.quit()
class TrainFrame(Frame): def __init__(self, master): super().__init__(master) self.l = None self.load_image = PhotoImage(file="images/load.png") self.meta_image = PhotoImage(file="images/recurse.png") self.folder_path = StringVar() self.meta_path = StringVar() self.k_control = IntVar(value=0) self.prog_control = IntVar(value=0) self.construct() self.pack(expand=True) def construct(self): self.construct_load_box() self.construct_input_boxes() def load_routine(self): filename = filedialog.askopenfilename() self.folder_path.set(filename) try: fd = FileData.file_to_data(self.folder_path.get()) self.l = Learner(int(self.chrom_entry.get()), int(self.head_entry.get()), int(self.gene_entry.get()), fd) except FileNotFoundError: messagebox.showerror("Error", "Invalid data file. Use the LOAD command.") def set_text(self, box, text): box.delete(0, END) box.insert(0, text) def meta_routine(self): filename = filedialog.askopenfilename() self.meta_path.set(filename) messagebox.showinfo( "Finished", "Loaded parameters from {}".format(self.meta_path.get())) try: fd = FileData.file_to_data(self.folder_path.get()) with open(self.meta_path.get(), "rb") as file: params = pickle.load(file) self.set_text(self.chrom_entry, math.floor(params[MetaLearner.N_CHROM])) self.set_text(self.head_entry, math.floor(params[MetaLearner.HEAD_LEN])) self.set_text(self.gene_entry, math.floor(params[MetaLearner.N_GENE])) self.l = Learner(int(self.chrom_entry.get()), int(self.head_entry.get()), int(self.gene_entry.get()), fd) self.l.set_params(params) except: messagebox.showerror("Error", "Invalid data file. Use the LOAD command.") def construct_load_box(self): top_frame = Frame(self) path_entry = Label(top_frame, textvariable=self.folder_path) path_entry.grid(row=0, column=0, padx=10) load_button = Button(top_frame, image=self.load_image, command=self.load_routine) load_button.grid(row=0, column=1, padx=10) recurse_button = Button(top_frame, image=self.meta_image, command=self.meta_routine) recurse_button.grid(row=0, column=2, padx=10) top_frame.pack(side="top", pady=45) def start_training(self): if len(self.folder_path.get()) < 1 or self.l is None: messagebox.showerror("Error", "File path not provided. Use LOAD " "command") return try: max_cycles = int(self.cycle_entry.get()) if self.k_control.get() == 1: fd = FileData.file_to_data(self.folder_path.get()) self.l.k_fold_validation(fd, cycles=max_cycles, k=int(self.k_fold_entry.get())) else: self.l.learn(max_cycles=max_cycles) f_name = "fittest.p" with open(f_name, "wb") as out: best_chrom = self.l.best_pop.best dill.dump(best_chrom, out) messagebox.showinfo("Finished", "Best population saved to fittest.p") self.update() except FileNotFoundError: messagebox.showerror("Error", "File not found.") def construct_input_boxes(self): bottom_frame = Frame(self) chrom_title = Label(bottom_frame, text="Chromosomes:") self.chrom_entry = Entry(bottom_frame, width=10) self.chrom_entry.insert(0, "30") chrom_title.grid(row=0, column=0, padx=10) self.chrom_entry.grid(row=0, column=1, padx=10) head_title = Label(bottom_frame, text="Head length:") self.head_entry = Entry(bottom_frame, width=10) self.head_entry.insert(0, "8") head_title.grid(row=0, column=2, padx=10) self.head_entry.grid(row=0, column=3, padx=10) gene_title = Label(bottom_frame, text="Number of Genes:") self.gene_entry = Entry(bottom_frame, width=10) self.gene_entry.insert(0, "4") gene_title.grid(row=0, column=4, padx=10) self.gene_entry.grid(row=0, column=5, padx=10) cycle_title = Label(bottom_frame, text="Number of Cycles:") self.cycle_entry = Entry(bottom_frame, width=10) self.cycle_entry.insert(0, "500") cycle_title.grid(row=1, column=0, padx=10, pady=10) self.cycle_entry.grid(row=1, column=1, padx=10, pady=10) k_fold_title = Checkbutton(bottom_frame, text="K-fold Validation:", variable=self.k_control) self.k_fold_entry = Entry(bottom_frame, width=10) self.k_fold_entry.insert(0, "10") k_fold_title.grid(row=1, column=2, padx=10, pady=10) self.k_fold_entry.grid(row=1, column=3, padx=10, pady=10) start_button = Button(bottom_frame, text="START", bg="#98fb98", width=12, command=self.start_training) cancel_button = Button(bottom_frame, text="CANCEL", bg="#ff9292", width=12) start_button.grid(row=1, column=4, padx=2, pady=10) cancel_button.grid(row=1, column=5, padx=2, pady=10) bottom_frame.pack(side="bottom", pady=40)
class EnaSubOptionsForm(VerticalScrolledFrame): # Initialize the GUI def __init__(self, root): #Frame.__init__(self, root) VerticalScrolledFrame.__init__(self, root) root.title("Choose EMBL-ENA Submission Options") self.parent = root # Assign the icon of this sub-window. assignIcon(self.parent) #button_opt = {'fill': Tkconstants.BOTH, 'padx': 35, 'pady': 5} # To define the exit behavior. Save and exit. self.parent.protocol('WM_DELETE_WINDOW', self.saveOptions) # Define the return behavior. Same as "close window" etc root.bind('<Return>', self.returnFunction) # This window should not be resizeable. I guess. self.parent.resizable(width=False, height=False) #Standard Inputs widths for the form elements formInputWidth = 30 labelInputWidth = 30 self.instructionsFrame = Frame(self.interior) self.instructionText = StringVar() self.instructionText.set('\nProvide this required sequence metadata, please.\n' + 'The Allele Local Name is provided by the submitting laboratory.\n' + 'You may name it similar to the closest known allele,\n' + 'if you wish.') Label(self.instructionsFrame, width=85, height=6, textvariable=self.instructionText).pack() self.instructionsFrame.pack() self.submissionDetailsInputFrame2 = Frame(self.interior) self.sampleIDInstrText = StringVar() self.sampleIDInstrText.set('Sample ID:') self.sampleIDinstrLabel = Label(self.submissionDetailsInputFrame2, width=labelInputWidth, height=1, textvariable=self.sampleIDInstrText).grid(row=0, column=0) self.inputSampleID = StringVar() self.inputSampleIDEntry = Entry(self.submissionDetailsInputFrame2, width=formInputWidth, textvariable=self.inputSampleID).grid(row=0, column=1) self.geneInstrStringVar = StringVar() self.geneInstrStringVar.set('Gene:') self.geneInstrLabel = Label(self.submissionDetailsInputFrame2, width=labelInputWidth, height=1, textvariable=self.geneInstrStringVar).grid(row=1, column=0) self.inputGene = StringVar() self.inputGeneEntry = Entry(self.submissionDetailsInputFrame2, width=formInputWidth, textvariable=self.inputGene).grid(row=1, column=1) self.chooseClassIntVar = IntVar() self.chooseClassIntVar.set(1) Radiobutton(self.submissionDetailsInputFrame2, text="HLA Class I ", variable=self.chooseClassIntVar, value=1).grid(row=2, column=0) Radiobutton(self.submissionDetailsInputFrame2, text="HLA Class II", variable=self.chooseClassIntVar, value=2).grid(row=2, column=1) self.alleleInstrText = StringVar() self.alleleInstrText.set('Allele Local Name:') self.alleleInstrLabel = Label(self.submissionDetailsInputFrame2, width=labelInputWidth, height=1, textvariable=self.alleleInstrText).grid(row=3, column=0) self.inputAllele = StringVar() self.inputAlleleEntry = Entry(self.submissionDetailsInputFrame2, width=formInputWidth, textvariable=self.inputAllele).grid(row=3, column=1) self.submissionDetailsInputFrame2.pack() # Make a frame to contain the Test/Production radio buttons. self.testProductionFrame = Frame(self.interior) self.testProductionInstrText = StringVar() self.testProductionInstrText.set('\nBy default, you submit to the EMBL-ENA test servers,\n' + 'where submissions are regularly deleted.\n' + 'change this option if you want to submit to the live environment.\n' + 'Login Credentials will not be stored, but they will be sent\n' + 'to EMBL-ENA via REST during allele submission.\n' ) self.alleleInstrLabel = Label(self.testProductionFrame, width=70, height=7, textvariable=self.testProductionInstrText).pack()#.grid(row=2, column=0) # 1 = Test. 0 = Production/live server self.chooseTestServersIntVar = IntVar() # a short check in case the config value has not been implemented yet. if(getConfigurationValue('test_submission') is not None): self.chooseTestServersIntVar.set(int(getConfigurationValue('test_submission'))) else: self.chooseTestServersIntVar.set(1) Radiobutton(self.testProductionFrame, text="Submit to EMBL-ENA TEST / DEMO environment.", variable=self.chooseTestServersIntVar, value=1).pack() Radiobutton(self.testProductionFrame, text="Submit to EMBL-ENA LIVE / PROD environment.", variable=self.chooseTestServersIntVar, value=0).pack() self.testProductionFrame.pack() # Make a frame to contain the input variables self.submissionDetailsInputFrame = Frame(self.interior) self.usernameInstrText = StringVar() self.usernameInstrText.set('EMBL-ENA Username:'******'EMBL-ENA Password:'******'\nEMBL-ENA will store the sequence in an "Analysis" object.\n' + 'You must specify an analysis Alias, Title, and\n' + 'Description for every submitted sequence.\n' + 'The Alias must be unique.\n' ) self.analysisMetadataLabel = Label(self.analysisOptionsInputFrame, width=70, height=5, textvariable=self.analysisMetadataInstrText).pack()#.grid(row=2, column=0) self.analysisOptionsInputFrame.pack() # Frame to specify Analysis Information self.newAnalysisFrame = Frame(self.interior) self.analysisAliasInstrText = StringVar() self.analysisAliasInstrText.set('Analysis Alias:') self.analysisAliasInstrLabel = Label(self.newAnalysisFrame, width=labelInputWidth, height=1, textvariable=self.analysisAliasInstrText).grid(row=0, column=0) self.inputAnalysisAlias = StringVar() self.inputStudyIdEntry = Entry(self.newAnalysisFrame, width=formInputWidth, textvariable=self.inputAnalysisAlias).grid(row=0, column=1) self.analysisTitleInstrText = StringVar() self.analysisTitleInstrText.set('Analysis Title:') self.analysisTitleInstrLabel = Label(self.newAnalysisFrame, width=labelInputWidth, height=1, textvariable=self.analysisTitleInstrText).grid(row=1, column=0) self.inputAnalysisTitle = StringVar() self.inputAnalysisTitleEntry = Entry(self.newAnalysisFrame, width=formInputWidth, textvariable=self.inputAnalysisTitle).grid(row=1, column=1) self.analysisDescriptionInstrText = StringVar() self.analysisDescriptionInstrText.set('Analysis Description:') self.analysisDescriptionInstrLabel = Label(self.newAnalysisFrame, width=labelInputWidth, height=1, textvariable=self.analysisDescriptionInstrText).grid(row=2, column=0) self.inputAnalysisDescription = StringVar() self.inputAnalysisDescriptionEntry = Entry(self.newAnalysisFrame, width=formInputWidth, textvariable=self.inputAnalysisDescription).grid(row=2, column=1) self.newAnalysisFrame.pack() # A Frame for specifing the details of the Study / Project self.projectDetailsFrame = Frame(self.interior) self.alleleInstrText = StringVar() self.alleleInstrText.set('\nEMBL-ENA requires that submissions are assigned to a Study/Project.\n' + 'You must either:\n\n' + '1.) Provide an existing EMBL-ENA study/project accession #.\n' + 'This was provided in a previous submission, or you can see a list of\n' + 'your projects by logging into EMBL-ENA Webin. (ex. \'PRJEB01234\')\n' + '\n' + '2.) Specify metadata for a new study at EMBL-ENA.\n' + 'Provide an Identifier, Title, and short Abstract for the new Study,\n' + 'and I will create it automatically.\n' + 'Study Identifier must be Unique.' ) self.alleleInstrLabel = Label(self.projectDetailsFrame, width=70, height=12, textvariable=self.alleleInstrText).pack()#.grid(row=2, column=0) self.chooseProjectIntVar = IntVar() self.chooseProjectIntVar.set(2) # A frame for the "new study" radio button self.existingProjectFrame = Frame(self.projectDetailsFrame) Radiobutton(self.existingProjectFrame, text="Use this study accession:", variable=self.chooseProjectIntVar, value=1).grid(row=0,column=0) self.inputStudyAccession = StringVar() self.inputStudyIdEntry = Entry(self.existingProjectFrame, width=formInputWidth, textvariable=self.inputStudyAccession).grid(row=0, column=1) self.existingProjectFrame.pack() # Filler Label Label(self.projectDetailsFrame, width=labelInputWidth, height=1, text=' ').pack() # This radio button is on the project details frame, but not # on one of it's sub-frames (existingProjectFrame or newProjectFrame) # That's so i can pack it, and not use a grid Radiobutton(self.projectDetailsFrame, text="Create a new study with this information:", variable=self.chooseProjectIntVar, value=2).pack() self.newProjectFrame = Frame(self.projectDetailsFrame) self.studyIdInstrText = StringVar() self.studyIdInstrText.set('Short Study Identifier:') self.studyIdInstrLabel = Label(self.newProjectFrame, width=labelInputWidth, height=1, textvariable=self.studyIdInstrText).grid(row=0, column=0) self.inputStudyId = StringVar() self.inputStudyIdEntry = Entry(self.newProjectFrame, width=formInputWidth, textvariable=self.inputStudyId).grid(row=0, column=1) self.studyShortTitleInstrText = StringVar() self.studyShortTitleInstrText.set('Descriptive Study Title:') self.studyShortTitleInstrLabel = Label(self.newProjectFrame, width=labelInputWidth, height=1, textvariable=self.studyShortTitleInstrText).grid(row=1, column=0) self.inputStudyShortTitle = StringVar() self.inputStudyShortTitleEntry = Entry(self.newProjectFrame, width=formInputWidth, textvariable=self.inputStudyShortTitle).grid(row=1, column=1) self.studyAbstractInstrText = StringVar() self.studyAbstractInstrText.set('Study Description / Abstract:') self.studyAbstractInstrLabel = Label(self.newProjectFrame, width=labelInputWidth, height=1, textvariable=self.studyAbstractInstrText).grid(row=2, column=0) self.inputStudyAbstract = StringVar() self.inputStudyAbstractEntry = Entry(self.newProjectFrame, width=formInputWidth, textvariable=self.inputStudyAbstract).grid(row=2, column=1) self.newProjectFrame.pack() self.projectDetailsFrame.pack() # Make a frame for the save options button. self.saveOptionsFrame = Frame(self.interior) Button(self.saveOptionsFrame, text='Save Options', command=self.saveOptions).grid(row=0, column=0) self.saveOptionsFrame.pack() # TODO: Should there be a cancel button, to close this window without saving? self.loadOptions() # I needed a function for the return keypress to latch onto. # It is just a wrapper for the saveOptions method. def returnFunction(self, event): self.saveOptions() # submissionOptions is a dictionary, passed by the parent. def loadOptions(self): if getConfigurationValue('ena_username') is not None: self.inputUsername.set(getConfigurationValue('ena_username')) if getConfigurationValue('ena_password') is not None: self.inputPassword.set(getConfigurationValue('ena_password')) if getConfigurationValue('sample_id') is not None: self.inputSampleID.set(getConfigurationValue('sample_id')) if getConfigurationValue('gene') is not None: self.inputGene.set(getConfigurationValue('gene')) if getConfigurationValue('class') is not None: if (str(getConfigurationValue('class')) == '1'): self.chooseClassIntVar.set(1) elif (str(getConfigurationValue('class')) == '2'): self.chooseClassIntVar.set(2) else: raise Exception('Error loading EMBL-ENA submission options. Invalid class:' + str(getConfigurationValue('class'))) if getConfigurationValue('allele_name') is not None: self.inputAllele.set(getConfigurationValue('allele_name')) if getConfigurationValue('choose_project') is not None: if (str(getConfigurationValue('choose_project')) == '1'): self.chooseProjectIntVar.set(1) elif (str(getConfigurationValue('choose_project')) == '2'): self.chooseProjectIntVar.set(2) else: raise Exception('Error loading EMBL-ENA submission options. Invalid Project choice:' + str(getConfigurationValue('choose_project'))) if getConfigurationValue('study_accession') is not None: self.inputStudyAccession.set(getConfigurationValue('study_accession')) if getConfigurationValue('study_identifier') is not None: self.inputStudyId.set(getConfigurationValue('study_identifier')) if getConfigurationValue('study_short_title') is not None: self.inputStudyShortTitle.set(getConfigurationValue('study_short_title')) if getConfigurationValue('study_abstract') is not None: self.inputStudyAbstract.set(getConfigurationValue('study_abstract')) if getConfigurationValue('test_submission') is not None: # 1 = Test. 0 = Production/live server self.chooseTestServersIntVar.set(int(getConfigurationValue('test_submission'))) if getConfigurationValue('analysis_alias') is not None: self.inputAnalysisAlias.set(getConfigurationValue('analysis_alias')) if getConfigurationValue('analysis_title') is not None: self.inputAnalysisTitle.set(getConfigurationValue('analysis_title')) if getConfigurationValue('analysis_description') is not None: self.inputAnalysisDescription.set(getConfigurationValue('analysis_description')) def saveOptions(self): # Close the window if (self.checkOptions()): logging.info ('Saving Options....') assignConfigurationValue('ena_username', self.inputUsername.get()) # I store this password so I can use it in the submission # I don't ever want to save the password. Make sure it isn't being saved in the config, in AlleleSubCommon.py assignConfigurationValue('ena_password', self.inputPassword.get()) assignConfigurationValue('sample_id', self.inputSampleID.get()) assignConfigurationValue('gene', self.inputGene.get()) assignConfigurationValue('class', str(self.chooseClassIntVar.get())) assignConfigurationValue('allele_name', self.inputAllele.get()) assignConfigurationValue('choose_project', str(self.chooseProjectIntVar.get())) assignConfigurationValue('study_accession', self.inputStudyAccession.get()) assignConfigurationValue('study_identifier', self.inputStudyId.get()) assignConfigurationValue('study_short_title', self.inputStudyShortTitle.get()) assignConfigurationValue('study_abstract', self.inputStudyAbstract.get()) assignConfigurationValue('test_submission', str(self.chooseTestServersIntVar.get())) assignConfigurationValue('analysis_alias', str(self.inputAnalysisAlias.get())) assignConfigurationValue('analysis_title', str(self.inputAnalysisTitle.get())) assignConfigurationValue('analysis_description', str(self.inputAnalysisDescription.get())) self.parent.destroy() else: #logging.info('Not ready to save, you are missing options.') pass def checkOptions(self): # TODO: THis is really annoying. I should allow them to close this screen without providing all the information # Im sure a user will complain about this. #logging.info ('Checking options.') # Don't check the ena Username # Don't check the ena Password # TODO: I should be more strict with this enforcement. I got rid of the False returns because it was too darn annoying. if (not self.inputSampleID.get()): messagebox.showwarning('Missing Form Value', 'You are missing a Sample ID. Please try again.') #return False return True if (not self.inputGene.get()): messagebox.showwarning('Missing Form Value', 'You are missing a Gene. Please try again.') #return False return True # Don't check the class boolean if (not self.inputAllele.get()): messagebox.showwarning('Missing Form Value', 'You are missing an Allele Name. Please try again.') #return False return True if (str(self.chooseProjectIntVar.get()) == '1'): # Use Existing Project if (not self.inputStudyAccession.get()): messagebox.showwarning('Missing Form Value', 'You are missing a Study Accession number. Please try again.') #return False return True elif(str(self.chooseProjectIntVar.get()) == '2'): # Use New Project if (not self.inputStudyId.get()): messagebox.showwarning('Missing Form Value', 'You are missing a Study Name. Please try again.') #return False return True if (not self.inputStudyShortTitle.get()): messagebox.showwarning('Missing Form Value', 'You are missing a Study Description. Please try again.') #return False return True if (not self.inputStudyAbstract.get()): messagebox.showwarning('Missing Form Value', 'You are missing a Study Accession number. Please try again.') #return False return True else: raise Exception ('Unknown value of self.chooseProjectIntVar. I expect 1 or 2. Observed:' + str(self.chooseProjectIntVar)) if (not self.inputAnalysisAlias.get()): messagebox.showwarning('Missing Form Value', 'You are missing an Analysis Alias. Please try again.') #return False return True if (not self.inputAnalysisTitle.get()): messagebox.showwarning('Missing Form Value', 'You are missing an Analysis Title. Please try again.') #return False return True if (not self.inputAnalysisDescription.get()): messagebox.showwarning('Missing Form Value', 'You are missing an Analysis Description. Please try again.') #return False return True # All options look good, right? return True def closeWindow(self): self.parent.destroy()
def test_default(self): v = IntVar(self.root) self.assertEqual(0, v.get())
class ShiftReduceApp: """ A graphical tool for exploring the shift-reduce parser. The tool displays the parser's stack and the remaining text, and allows the user to control the parser's operation. In particular, the user can shift tokens onto the stack, and can perform reductions on the top elements of the stack. A "step" button simply steps through the parsing process, performing the operations that ``nltk.parse.ShiftReduceParser`` would use. """ def __init__(self, grammar, sent, trace=0): self._sent = sent self._parser = SteppingShiftReduceParser(grammar, trace) # Set up the main window. self._top = Tk() self._top.title("Shift Reduce Parser Application") # Animations. animating_lock is a lock to prevent the demo # from performing new operations while it's animating. self._animating_lock = 0 self._animate = IntVar(self._top) self._animate.set(10) # = medium # The user can hide the grammar. self._show_grammar = IntVar(self._top) self._show_grammar.set(1) # Initialize fonts. self._init_fonts(self._top) # Set up key bindings. self._init_bindings() # Create the basic frames. self._init_menubar(self._top) self._init_buttons(self._top) self._init_feedback(self._top) self._init_grammar(self._top) self._init_canvas(self._top) # A popup menu for reducing. self._reduce_menu = Menu(self._canvas, tearoff=0) # Reset the demo, and set the feedback frame to empty. self.reset() self._lastoper1["text"] = "" ######################################### ## Initialization Helpers ######################################### def _init_fonts(self, root): # See: <http://www.astro.washington.edu/owen/ROTKFolklore.html> self._sysfont = Font(font=Button()["font"]) root.option_add("*Font", self._sysfont) # TWhat's our font size (default=same as sysfont) self._size = IntVar(root) self._size.set(self._sysfont.cget("size")) self._boldfont = Font(family="helvetica", weight="bold", size=self._size.get()) self._font = Font(family="helvetica", size=self._size.get()) def _init_grammar(self, parent): # Grammar view. self._prodframe = listframe = Frame(parent) self._prodframe.pack(fill="both", side="left", padx=2) self._prodlist_label = Label(self._prodframe, font=self._boldfont, text="Available Reductions") self._prodlist_label.pack() self._prodlist = Listbox( self._prodframe, selectmode="single", relief="groove", background="white", foreground="#909090", font=self._font, selectforeground="#004040", selectbackground="#c0f0c0", ) self._prodlist.pack(side="right", fill="both", expand=1) self._productions = list(self._parser.grammar().productions()) for production in self._productions: self._prodlist.insert("end", (" %s" % production)) self._prodlist.config(height=min(len(self._productions), 25)) # Add a scrollbar if there are more than 25 productions. if 1: # len(self._productions) > 25: listscroll = Scrollbar(self._prodframe, orient="vertical") self._prodlist.config(yscrollcommand=listscroll.set) listscroll.config(command=self._prodlist.yview) listscroll.pack(side="left", fill="y") # If they select a production, apply it. self._prodlist.bind("<<ListboxSelect>>", self._prodlist_select) # When they hover over a production, highlight it. self._hover = -1 self._prodlist.bind("<Motion>", self._highlight_hover) self._prodlist.bind("<Leave>", self._clear_hover) def _init_bindings(self): # Quit self._top.bind("<Control-q>", self.destroy) self._top.bind("<Control-x>", self.destroy) self._top.bind("<Alt-q>", self.destroy) self._top.bind("<Alt-x>", self.destroy) # Ops (step, shift, reduce, undo) self._top.bind("<space>", self.step) self._top.bind("<s>", self.shift) self._top.bind("<Alt-s>", self.shift) self._top.bind("<Control-s>", self.shift) self._top.bind("<r>", self.reduce) self._top.bind("<Alt-r>", self.reduce) self._top.bind("<Control-r>", self.reduce) self._top.bind("<Delete>", self.reset) self._top.bind("<u>", self.undo) self._top.bind("<Alt-u>", self.undo) self._top.bind("<Control-u>", self.undo) self._top.bind("<Control-z>", self.undo) self._top.bind("<BackSpace>", self.undo) # Misc self._top.bind("<Control-p>", self.postscript) self._top.bind("<Control-h>", self.help) self._top.bind("<F1>", self.help) self._top.bind("<Control-g>", self.edit_grammar) self._top.bind("<Control-t>", self.edit_sentence) # Animation speed control self._top.bind("-", lambda e, a=self._animate: a.set(20)) self._top.bind("=", lambda e, a=self._animate: a.set(10)) self._top.bind("+", lambda e, a=self._animate: a.set(4)) def _init_buttons(self, parent): # Set up the frames. self._buttonframe = buttonframe = Frame(parent) buttonframe.pack(fill="none", side="bottom") Button( buttonframe, text="Step", background="#90c0d0", foreground="black", command=self.step, ).pack(side="left") Button( buttonframe, text="Shift", underline=0, background="#90f090", foreground="black", command=self.shift, ).pack(side="left") Button( buttonframe, text="Reduce", underline=0, background="#90f090", foreground="black", command=self.reduce, ).pack(side="left") Button( buttonframe, text="Undo", underline=0, background="#f0a0a0", foreground="black", command=self.undo, ).pack(side="left") def _init_menubar(self, parent): menubar = Menu(parent) filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label="Reset Parser", underline=0, command=self.reset, accelerator="Del") filemenu.add_command( label="Print to Postscript", underline=0, command=self.postscript, accelerator="Ctrl-p", ) filemenu.add_command(label="Exit", underline=1, command=self.destroy, accelerator="Ctrl-x") menubar.add_cascade(label="File", underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) editmenu.add_command( label="Edit Grammar", underline=5, command=self.edit_grammar, accelerator="Ctrl-g", ) editmenu.add_command( label="Edit Text", underline=5, command=self.edit_sentence, accelerator="Ctrl-t", ) menubar.add_cascade(label="Edit", underline=0, menu=editmenu) rulemenu = Menu(menubar, tearoff=0) rulemenu.add_command(label="Step", underline=1, command=self.step, accelerator="Space") rulemenu.add_separator() rulemenu.add_command(label="Shift", underline=0, command=self.shift, accelerator="Ctrl-s") rulemenu.add_command(label="Reduce", underline=0, command=self.reduce, accelerator="Ctrl-r") rulemenu.add_separator() rulemenu.add_command(label="Undo", underline=0, command=self.undo, accelerator="Ctrl-u") menubar.add_cascade(label="Apply", underline=0, menu=rulemenu) viewmenu = Menu(menubar, tearoff=0) viewmenu.add_checkbutton( label="Show Grammar", underline=0, variable=self._show_grammar, command=self._toggle_grammar, ) viewmenu.add_separator() viewmenu.add_radiobutton( label="Tiny", variable=self._size, underline=0, value=10, command=self.resize, ) viewmenu.add_radiobutton( label="Small", variable=self._size, underline=0, value=12, command=self.resize, ) viewmenu.add_radiobutton( label="Medium", variable=self._size, underline=0, value=14, command=self.resize, ) viewmenu.add_radiobutton( label="Large", variable=self._size, underline=0, value=18, command=self.resize, ) viewmenu.add_radiobutton( label="Huge", variable=self._size, underline=0, value=24, command=self.resize, ) menubar.add_cascade(label="View", underline=0, menu=viewmenu) animatemenu = Menu(menubar, tearoff=0) animatemenu.add_radiobutton(label="No Animation", underline=0, variable=self._animate, value=0) animatemenu.add_radiobutton( label="Slow Animation", underline=0, variable=self._animate, value=20, accelerator="-", ) animatemenu.add_radiobutton( label="Normal Animation", underline=0, variable=self._animate, value=10, accelerator="=", ) animatemenu.add_radiobutton( label="Fast Animation", underline=0, variable=self._animate, value=4, accelerator="+", ) menubar.add_cascade(label="Animate", underline=1, menu=animatemenu) helpmenu = Menu(menubar, tearoff=0) helpmenu.add_command(label="About", underline=0, command=self.about) helpmenu.add_command(label="Instructions", underline=0, command=self.help, accelerator="F1") menubar.add_cascade(label="Help", underline=0, menu=helpmenu) parent.config(menu=menubar) def _init_feedback(self, parent): self._feedbackframe = feedbackframe = Frame(parent) feedbackframe.pack(fill="x", side="bottom", padx=3, pady=3) self._lastoper_label = Label(feedbackframe, text="Last Operation:", font=self._font) self._lastoper_label.pack(side="left") lastoperframe = Frame(feedbackframe, relief="sunken", border=1) lastoperframe.pack(fill="x", side="right", expand=1, padx=5) self._lastoper1 = Label(lastoperframe, foreground="#007070", background="#f0f0f0", font=self._font) self._lastoper2 = Label( lastoperframe, anchor="w", width=30, foreground="#004040", background="#f0f0f0", font=self._font, ) self._lastoper1.pack(side="left") self._lastoper2.pack(side="left", fill="x", expand=1) def _init_canvas(self, parent): self._cframe = CanvasFrame( parent, background="white", width=525, closeenough=10, border=2, relief="sunken", ) self._cframe.pack(expand=1, fill="both", side="top", pady=2) canvas = self._canvas = self._cframe.canvas() self._stackwidgets = [] self._rtextwidgets = [] self._titlebar = canvas.create_rectangle(0, 0, 0, 0, fill="#c0f0f0", outline="black") self._exprline = canvas.create_line(0, 0, 0, 0, dash=".") self._stacktop = canvas.create_line(0, 0, 0, 0, fill="#408080") size = self._size.get() + 4 self._stacklabel = TextWidget(canvas, "Stack", color="#004040", font=self._boldfont) self._rtextlabel = TextWidget(canvas, "Remaining Text", color="#004040", font=self._boldfont) self._cframe.add_widget(self._stacklabel) self._cframe.add_widget(self._rtextlabel) ######################################### ## Main draw procedure ######################################### def _redraw(self): scrollregion = self._canvas["scrollregion"].split() (cx1, cy1, cx2, cy2) = (int(c) for c in scrollregion) # Delete the old stack & rtext widgets. for stackwidget in self._stackwidgets: self._cframe.destroy_widget(stackwidget) self._stackwidgets = [] for rtextwidget in self._rtextwidgets: self._cframe.destroy_widget(rtextwidget) self._rtextwidgets = [] # Position the titlebar & exprline (x1, y1, x2, y2) = self._stacklabel.bbox() y = y2 - y1 + 10 self._canvas.coords(self._titlebar, -5000, 0, 5000, y - 4) self._canvas.coords(self._exprline, 0, y * 2 - 10, 5000, y * 2 - 10) # Position the titlebar labels.. (x1, y1, x2, y2) = self._stacklabel.bbox() self._stacklabel.move(5 - x1, 3 - y1) (x1, y1, x2, y2) = self._rtextlabel.bbox() self._rtextlabel.move(cx2 - x2 - 5, 3 - y1) # Draw the stack. stackx = 5 for tok in self._parser.stack(): if isinstance(tok, Tree): attribs = { "tree_color": "#4080a0", "tree_width": 2, "node_font": self._boldfont, "node_color": "#006060", "leaf_color": "#006060", "leaf_font": self._font, } widget = tree_to_treesegment(self._canvas, tok, **attribs) widget.label()["color"] = "#000000" else: widget = TextWidget(self._canvas, tok, color="#000000", font=self._font) widget.bind_click(self._popup_reduce) self._stackwidgets.append(widget) self._cframe.add_widget(widget, stackx, y) stackx = widget.bbox()[2] + 10 # Draw the remaining text. rtextwidth = 0 for tok in self._parser.remaining_text(): widget = TextWidget(self._canvas, tok, color="#000000", font=self._font) self._rtextwidgets.append(widget) self._cframe.add_widget(widget, rtextwidth, y) rtextwidth = widget.bbox()[2] + 4 # Allow enough room to shift the next token (for animations) if len(self._rtextwidgets) > 0: stackx += self._rtextwidgets[0].width() # Move the remaining text to the correct location (keep it # right-justified, when possible); and move the remaining text # label, if necessary. stackx = max(stackx, self._stacklabel.width() + 25) rlabelwidth = self._rtextlabel.width() + 10 if stackx >= cx2 - max(rtextwidth, rlabelwidth): cx2 = stackx + max(rtextwidth, rlabelwidth) for rtextwidget in self._rtextwidgets: rtextwidget.move(4 + cx2 - rtextwidth, 0) self._rtextlabel.move(cx2 - self._rtextlabel.bbox()[2] - 5, 0) midx = (stackx + cx2 - max(rtextwidth, rlabelwidth)) / 2 self._canvas.coords(self._stacktop, midx, 0, midx, 5000) (x1, y1, x2, y2) = self._stacklabel.bbox() # Set up binding to allow them to shift a token by dragging it. if len(self._rtextwidgets) > 0: def drag_shift(widget, midx=midx, self=self): if widget.bbox()[0] < midx: self.shift() else: self._redraw() self._rtextwidgets[0].bind_drag(drag_shift) self._rtextwidgets[0].bind_click(self.shift) # Draw the stack top. self._highlight_productions() def _draw_stack_top(self, widget): # hack.. midx = widget.bbox()[2] + 50 self._canvas.coords(self._stacktop, midx, 0, midx, 5000) def _highlight_productions(self): # Highlight the productions that can be reduced. self._prodlist.selection_clear(0, "end") for prod in self._parser.reducible_productions(): index = self._productions.index(prod) self._prodlist.selection_set(index) ######################################### ## Button Callbacks ######################################### def destroy(self, *e): if self._top is None: return self._top.destroy() self._top = None def reset(self, *e): self._parser.initialize(self._sent) self._lastoper1["text"] = "Reset App" self._lastoper2["text"] = "" self._redraw() def step(self, *e): if self.reduce(): return True elif self.shift(): return True else: if list(self._parser.parses()): self._lastoper1["text"] = "Finished:" self._lastoper2["text"] = "Success" else: self._lastoper1["text"] = "Finished:" self._lastoper2["text"] = "Failure" def shift(self, *e): if self._animating_lock: return if self._parser.shift(): tok = self._parser.stack()[-1] self._lastoper1["text"] = "Shift:" self._lastoper2["text"] = "%r" % tok if self._animate.get(): self._animate_shift() else: self._redraw() return True return False def reduce(self, *e): if self._animating_lock: return production = self._parser.reduce() if production: self._lastoper1["text"] = "Reduce:" self._lastoper2["text"] = "%s" % production if self._animate.get(): self._animate_reduce() else: self._redraw() return production def undo(self, *e): if self._animating_lock: return if self._parser.undo(): self._redraw() def postscript(self, *e): self._cframe.print_to_file() def mainloop(self, *args, **kwargs): """ Enter the Tkinter mainloop. This function must be called if this demo is created from a non-interactive program (e.g. from a secript); otherwise, the demo will close as soon as the script completes. """ if in_idle(): return self._top.mainloop(*args, **kwargs) ######################################### ## Menubar callbacks ######################################### def resize(self, size=None): if size is not None: self._size.set(size) size = self._size.get() self._font.configure(size=-(abs(size))) self._boldfont.configure(size=-(abs(size))) self._sysfont.configure(size=-(abs(size))) # self._stacklabel['font'] = ('helvetica', -size-4, 'bold') # self._rtextlabel['font'] = ('helvetica', -size-4, 'bold') # self._lastoper_label['font'] = ('helvetica', -size) # self._lastoper1['font'] = ('helvetica', -size) # self._lastoper2['font'] = ('helvetica', -size) # self._prodlist['font'] = ('helvetica', -size) # self._prodlist_label['font'] = ('helvetica', -size-2, 'bold') self._redraw() def help(self, *e): # The default font's not very legible; try using 'fixed' instead. try: ShowText( self._top, "Help: Shift-Reduce Parser Application", (__doc__ or "").strip(), width=75, font="fixed", ) except: ShowText( self._top, "Help: Shift-Reduce Parser Application", (__doc__ or "").strip(), width=75, ) def about(self, *e): ABOUT = "NLTK Shift-Reduce Parser Application\n" + "Written by Edward Loper" TITLE = "About: Shift-Reduce Parser Application" try: from tkinter.messagebox import Message Message(message=ABOUT, title=TITLE).show() except: ShowText(self._top, TITLE, ABOUT) def edit_grammar(self, *e): CFGEditor(self._top, self._parser.grammar(), self.set_grammar) def set_grammar(self, grammar): self._parser.set_grammar(grammar) self._productions = list(grammar.productions()) self._prodlist.delete(0, "end") for production in self._productions: self._prodlist.insert("end", (" %s" % production)) def edit_sentence(self, *e): sentence = " ".join(self._sent) title = "Edit Text" instr = "Enter a new sentence to parse." EntryDialog(self._top, sentence, instr, self.set_sentence, title) def set_sentence(self, sent): self._sent = sent.split() # [XX] use tagged? self.reset() ######################################### ## Reduce Production Selection ######################################### def _toggle_grammar(self, *e): if self._show_grammar.get(): self._prodframe.pack(fill="both", side="left", padx=2, after=self._feedbackframe) self._lastoper1["text"] = "Show Grammar" else: self._prodframe.pack_forget() self._lastoper1["text"] = "Hide Grammar" self._lastoper2["text"] = "" def _prodlist_select(self, event): selection = self._prodlist.curselection() if len(selection) != 1: return index = int(selection[0]) production = self._parser.reduce(self._productions[index]) if production: self._lastoper1["text"] = "Reduce:" self._lastoper2["text"] = "%s" % production if self._animate.get(): self._animate_reduce() else: self._redraw() else: # Reset the production selections. self._prodlist.selection_clear(0, "end") for prod in self._parser.reducible_productions(): index = self._productions.index(prod) self._prodlist.selection_set(index) def _popup_reduce(self, widget): # Remove old commands. productions = self._parser.reducible_productions() if len(productions) == 0: return self._reduce_menu.delete(0, "end") for production in productions: self._reduce_menu.add_command(label=str(production), command=self.reduce) self._reduce_menu.post(self._canvas.winfo_pointerx(), self._canvas.winfo_pointery()) ######################################### ## Animations ######################################### def _animate_shift(self): # What widget are we shifting? widget = self._rtextwidgets[0] # Where are we shifting from & to? right = widget.bbox()[0] if len(self._stackwidgets) == 0: left = 5 else: left = self._stackwidgets[-1].bbox()[2] + 10 # Start animating. dt = self._animate.get() dx = (left - right) * 1.0 / dt self._animate_shift_frame(dt, widget, dx) def _animate_shift_frame(self, frame, widget, dx): if frame > 0: self._animating_lock = 1 widget.move(dx, 0) self._top.after(10, self._animate_shift_frame, frame - 1, widget, dx) else: # but: stacktop?? # Shift the widget to the stack. del self._rtextwidgets[0] self._stackwidgets.append(widget) self._animating_lock = 0 # Display the available productions. self._draw_stack_top(widget) self._highlight_productions() def _animate_reduce(self): # What widgets are we shifting? numwidgets = len(self._parser.stack()[-1]) # number of children widgets = self._stackwidgets[-numwidgets:] # How far are we moving? if isinstance(widgets[0], TreeSegmentWidget): ydist = 15 + widgets[0].label().height() else: ydist = 15 + widgets[0].height() # Start animating. dt = self._animate.get() dy = ydist * 2.0 / dt self._animate_reduce_frame(dt / 2, widgets, dy) def _animate_reduce_frame(self, frame, widgets, dy): if frame > 0: self._animating_lock = 1 for widget in widgets: widget.move(0, dy) self._top.after(10, self._animate_reduce_frame, frame - 1, widgets, dy) else: del self._stackwidgets[-len(widgets):] for widget in widgets: self._cframe.remove_widget(widget) tok = self._parser.stack()[-1] if not isinstance(tok, Tree): raise ValueError() label = TextWidget(self._canvas, str(tok.label()), color="#006060", font=self._boldfont) widget = TreeSegmentWidget(self._canvas, label, widgets, width=2) (x1, y1, x2, y2) = self._stacklabel.bbox() y = y2 - y1 + 10 if not self._stackwidgets: x = 5 else: x = self._stackwidgets[-1].bbox()[2] + 10 self._cframe.add_widget(widget, x, y) self._stackwidgets.append(widget) # Display the available productions. self._draw_stack_top(widget) self._highlight_productions() # # Delete the old widgets.. # del self._stackwidgets[-len(widgets):] # for widget in widgets: # self._cframe.destroy_widget(widget) # # # Make a new one. # tok = self._parser.stack()[-1] # if isinstance(tok, Tree): # attribs = {'tree_color': '#4080a0', 'tree_width': 2, # 'node_font': bold, 'node_color': '#006060', # 'leaf_color': '#006060', 'leaf_font':self._font} # widget = tree_to_treesegment(self._canvas, tok.type(), # **attribs) # widget.node()['color'] = '#000000' # else: # widget = TextWidget(self._canvas, tok.type(), # color='#000000', font=self._font) # widget.bind_click(self._popup_reduce) # (x1, y1, x2, y2) = self._stacklabel.bbox() # y = y2-y1+10 # if not self._stackwidgets: x = 5 # else: x = self._stackwidgets[-1].bbox()[2] + 10 # self._cframe.add_widget(widget, x, y) # self._stackwidgets.append(widget) # self._redraw() self._animating_lock = 0 ######################################### ## Hovering. ######################################### def _highlight_hover(self, event): # What production are we hovering over? index = self._prodlist.nearest(event.y) if self._hover == index: return # Clear any previous hover highlighting. self._clear_hover() # If the production corresponds to an available reduction, # highlight the stack. selection = [int(s) for s in self._prodlist.curselection()] if index in selection: rhslen = len(self._productions[index].rhs()) for stackwidget in self._stackwidgets[-rhslen:]: if isinstance(stackwidget, TreeSegmentWidget): stackwidget.label()["color"] = "#00a000" else: stackwidget["color"] = "#00a000" # Remember what production we're hovering over. self._hover = index def _clear_hover(self, *event): # Clear any previous hover highlighting. if self._hover == -1: return self._hover = -1 for stackwidget in self._stackwidgets: if isinstance(stackwidget, TreeSegmentWidget): stackwidget.label()["color"] = "black" else: stackwidget["color"] = "black"
class FensterRS(GuiTemplate): def __init__(self, master): super().__init__(master) self.grid() self.str_Ay = StringVar() self.str_Ax = StringVar() self.str_By = StringVar() self.str_Bx = StringVar() self.str_My = StringVar() self.str_Mx = StringVar() self.str_TNA = StringVar() self.str_TNB = StringVar() self.str_TNM = StringVar() self.int_radioBSelect = IntVar(value=1) self.str_Alpha = StringVar() self.str_Beta = StringVar() self.str_Ny = StringVar() self.str_Nx = StringVar() Label(self, text="Y").grid(row=1, column=0, padx=3, pady=3, columnspan=2) Label(self, text="X").grid(row=2, column=0, padx=3, pady=3, columnspan=2) Label(self, text="Punkt A").grid(row=0, column=2, padx=3, pady=3, columnspan=2) Label(self, text="Punkt M").grid(row=0, column=4, padx=3, pady=3, columnspan=2) Label(self, text="Punkt B").grid(row=0, column=6, padx=3, pady=3, columnspan=2) Label(self, text="Richtung / gon").grid(row=3, column=0, padx=3, pady=3) Label(self, text="Alpha").grid(row=4, column=3, padx=3, pady=3, columnspan=2) Label(self, text="Beta").grid(row=4, column=5, padx=3, pady=3, columnspan=2) Label(self, text="Winkel / gon").grid(row=5, column=0, padx=3, pady=3, columnspan=1) Label(self, text="Y").grid(row=8, column=2, padx=3, pady=3, columnspan=2) Label(self, text="X").grid(row=9, column=2, padx=3, pady=3, columnspan=2) Label(self, text="Punkt N").grid(row=7, column=4, padx=3, pady=3, columnspan=2) self.RB_dir = Radiobutton(self, value=0, variable=self.int_radioBSelect, command=self.toggleEntry) self.RB_dir.grid(row=3, column=1, padx=3, pady=3) self.RB_angle = Radiobutton(self, value=1, variable=self.int_radioBSelect, command=self.toggleEntry) self.RB_angle.grid(row=5, column=1, padx=3, pady=3) Entry(self, textvariable=self.str_Ay).grid(row=1, column=2, padx=3, pady=3, columnspan=2) Entry(self, textvariable=self.str_Ax).grid(row=2, column=2, padx=3, pady=3, columnspan=2) Entry(self, textvariable=self.str_My).grid(row=1, column=4, padx=3, pady=3, columnspan=2) Entry(self, textvariable=self.str_Mx).grid(row=2, column=4, padx=3, pady=3, columnspan=2) Entry(self, textvariable=self.str_By).grid(row=1, column=6, padx=3, pady=3, columnspan=2) Entry(self, textvariable=self.str_Bx).grid(row=2, column=6, padx=3, pady=3, columnspan=2) self.e_TNA = Entry(self, textvariable=self.str_TNA, state="readonly") self.e_TNA.grid(row=3, column=2, padx=3, pady=3, columnspan=2) self.e_TNM = Entry(self, textvariable=self.str_TNM, state="readonly") self.e_TNM.grid(row=3, column=4, padx=3, pady=3, columnspan=2) self.e_TNB = Entry(self, textvariable=self.str_TNB, state="readonly") self.e_TNB.grid(row=3, column=6, padx=3, pady=3, columnspan=2) self.e_Alpha = Entry(self, textvariable=self.str_Alpha) self.e_Alpha.grid(row=5, column=3, padx=3, pady=3, columnspan=2) self.e_Beta = Entry(self, textvariable=self.str_Beta) self.e_Beta.grid(row=5, column=5, padx=3, pady=3, columnspan=2) Button(self, text="Berechnen", command=self.BtnPressedCalc).grid(row=6, column=4, padx=3, pady=3, columnspan=2) Entry(self, textvariable=self.str_Ny, state="readonly").grid(row=8, column=4, padx=3, pady=3, columnspan=2) Entry(self, textvariable=self.str_Nx, state="readonly").grid(row=9, column=4, padx=3, pady=3, columnspan=2) def BtnPressedCalc(self): A_y = float(self.str_Ay.get().replace(",", ".")) A_x = float(self.str_Ax.get().replace(",", ".")) B_y = float(self.str_By.get().replace(",", ".")) B_x = float(self.str_Bx.get().replace(",", ".")) M_y = float(self.str_My.get().replace(",", ".")) M_x = float(self.str_Mx.get().replace(",", ".")) pA = Punkt(A_y, A_x) pB = Punkt(B_y, B_x) pM = Punkt(M_y, M_x) if self.int_radioBSelect.get() == 0: t_NA = Winkel(float(self.str_TNA.get().replace(",", ".")), "gon") t_NM = Winkel(float(self.str_TNM.get().replace(",", ".")), "gon") t_NB = Winkel(float(self.str_TNB.get().replace(",", ".")), "gon") self.str_Alpha.set("") self.str_Beta.set("") pN = Rückwärtsschnitt.init_dir(pA, pB, pM, t_NA, t_NB, t_NM).schneiden() else: aAlpha = Winkel(float(self.str_Alpha.get().replace(",", ".")), "gon") aBeta = Winkel(float(self.str_Beta.get().replace(",", ".")), "gon") self.str_TNA.set("") self.str_TNM.set("") self.str_TNB.set("") pN = Rückwärtsschnitt(pA, pB, pM, aAlpha, aBeta).schneiden() self.str_Ny.set(self.runde(pN.get_y())) self.str_Nx.set(self.runde(pN.get_x())) def toggleEntry(self): if self.int_radioBSelect.get() == 1: self.e_Alpha.config(state="normal") self.e_Beta.config(state="normal") self.e_TNA.config(state="readonly") self.e_TNM.config(state="readonly") self.e_TNB.config(state="readonly") else: self.e_Alpha.config(state="readonly") self.e_Beta.config(state="readonly") self.e_TNA.config(state="normal") self.e_TNM.config(state="normal") self.e_TNB.config(state="normal")
class fen_info(Tk): """ Fenêtre permettant de saisir les informations sur les joueurs """ def __init__(self): super().__init__() # Initialisation des pions à la valeur initiale. self.pion1 = "X" self.pion2 = "O" # Titre de la fenêtre self.title("Ultimate TIC-TAC-TOE") # Pour changer taille minimum de fenêtre et taille centrer, # changer variable self.width_fen, self.height_fen. self.width_fen, self.height_fen = 430, 500 # Taille minimum de la fenêtre self.minsize(self.width_fen, self.height_fen) # Centrer la fenêtre. centreFen(self, self.width_fen, self.height_fen) # Création d'un canvas avec l'image "logo.gif" canvas = Canvas(self, width=280, height=100) self.img = PhotoImage(file="logo.gif") canvas.create_image(280, 100, anchor=SE, image=self.img) canvas.grid(row=0, columnspan=5, pady=10) # Libellé - Nouvelle Partie Label(self, text="Nouvelle partie", font=("Arial", 16), fg="#0080FF", justify=CENTER).grid( row=1, columnspan=5, padx = 20, pady = 5) separateur(20).grid(row=10,columnspan=5) # Sélection du type de partie avec bouton radio self.choixJoueur = IntVar() r1 = Radiobutton(self, text="Jouer avec l'ordinateur", variable = self.choixJoueur, value = 1, command=self.define_choix) r1.select() r1.grid(row=20, column=0) r2 = Radiobutton(self, text="Jouer avec un autre joueur", variable = self.choixJoueur, value = 2, command=self.define_choix) r2.grid(row=20, column=1) # Saisie du nom du joueur 1. f_j1 = Frame(self, borderwidth=1, padx=5, pady=5, relief=SUNKEN) f_j1.grid(row=30, columnspan=5, padx=5, pady=5) Label(f_j1, text="Nom joueur 1:").grid(row=1, column=0, sticky=E, padx = 5, pady = 5) self.nom_joueur1 = Entry(f_j1) self.nom_joueur1.grid(row=1,column=1) # Sélection du pion joueur 1. Le pion restant est automatiquement attribué au joueur 2. Label(f_j1, text="Choix de pion:").grid(row=1, column=2, padx=5) self.sel_pion=IntVar() p1 = Radiobutton(f_j1, indicatoron=0, width=5, text="X", variable=self.sel_pion, value=1, command=self.choix_pion) p1.grid(row=1, column=3, padx=2) p1.select() Radiobutton(f_j1, indicatoron=0, width=5, text="O", variable=self.sel_pion, value=2, command=self.choix_pion).grid(row=1, column=4, padx=2) # Saisie du nom du joueur 2. Apparaît seulement si on sélection 2 joueurs. Voir define_choix self.f_j2 = Frame(self, width=420, borderwidth=1, padx=5, pady=5, relief=SUNKEN) Label(self.f_j2, text="Nom joueur 2").grid(row=1, column=0, sticky=E, padx = 5, pady = 5) self.nom_joueur2 = Entry(self.f_j2, state="disabled") self.nom_joueur2.grid(row=1, column=1) self.label_pion2 = Label(self.f_j2, text="Pion Joueur 2 = O") self.label_pion2.grid(row=1, column=2, padx=5) # Information sur l'ordinateur. Disparaît si on choisi 2 joueurs. self.f_ordi = Frame(self, width=420, borderwidth=1, padx=5, pady=5, relief=SUNKEN) self.f_ordi.grid(row=40, columnspan=5, padx=5, pady=5) Label(self.f_ordi, text="Ordinateur = Colosse", font=("Arial", 12), fg="#0080FF")\ .grid(row=1, column=0, sticky=E, padx = 5, pady = 5) self.pion_ordi = Label(self.f_ordi, text="| Pion de l'ordinateur = O", font=("Arial", 12), fg="#0080FF") self.pion_ordi.grid(row=1, column=2) separateur(20).grid(row=50,columnspan=5) # Sélection de la force de l'ordinateur self.choixForce = IntVar() self.f1 = Radiobutton(self, indicatoron=0, width = 20, padx = 20, text="Facile", variable=self.choixForce, value=1, command=self.define_choix) self.f1.select() self.f1.grid(row=60, columnspan=5) self.f2 = Radiobutton(self, indicatoron=0, width = 20, padx = 20, text="Moyen", variable=self.choixForce, value=2, command=self.define_choix) self.f2.grid(row=61, columnspan=5) self.f3 = Radiobutton(self, indicatoron=0, width = 20, padx = 20, text="Difficile", variable=self.choixForce, value=3, command=self.define_choix) self.f3.grid(row=62, columnspan=5) separateur(40).grid(row=70, column=0) #Button pour démarrer la partie self.bt_start = Button(text="Démarrer", font=("Arial", 12), fg="green", command=self.demarrer_jeu) self.bt_start.grid(row=80, columnspan=5) def define_choix(self): """ Fonction qui active ou désactive le nom du joueur 2 selon si on joue contre l'ordinateur ou contre un autre joueur """ if self.choixJoueur.get()==1: self.nom_joueur2.delete(0, END) self.nom_joueur2["state"]="disabled" self.f1["state"]="normal" self.f2["state"]="normal" self.f3["state"]="normal" self.f_j2.grid_remove() self.f_ordi.grid(row=40, columnspan=5, padx=5, pady=5) elif self.choixJoueur.get()==2: self.nom_joueur2["state"]="normal" self.f1["state"]="disabled" self.f2["state"]="disabled" self.f3["state"]="disabled" self.f_j2.grid(row=40, columnspan=5, padx=5, pady=5) self.f_ordi.grid_remove() def choix_pion(self): # Définition des pions if self.sel_pion.get()==1: self.pion1="X" self.pion2="O" self.label_pion2["text"]="Pion Joueur 2 = {}".format(self.pion2) self.pion_ordi["text"]="| Pion de l'ordinateur = {}".format(self.pion2) else: self.pion1="O" self.pion2="X" self.label_pion2["text"]="Pion Joueur 2 = {}".format(self.pion2) self.pion_ordi["text"]="| Pion de l'ordinateur = {}".format(self.pion2) def demarrer_jeu(self): """ Démarrer la partie avec les informations saisie. Afficher le plateau """ if self.choixJoueur.get()==1: type2 = "Ordinateur" if self.nom_joueur1.get()!='': j1 = self.nom_joueur1.get() j2 = "Colosse" else: j1 = "Joueur 1" j2 = "Colosse" elif self.choixJoueur.get()==2: type2 = "Personne" if self.nom_joueur1.get()!='' and self.nom_joueur2.get()!='': j1 = self.nom_joueur1.get() j2 = self.nom_joueur2.get() elif self.nom_joueur1.get()=='': j1 = "Joueur 1" if self.nom_joueur2.get()=='': j2 = "Joueur 2" else: j2 = self.nom_joueur2.get() else: j1 = self.nom_joueur1.get() if self.nom_joueur2.get()=='': j2 = "Joueur 2" else: j2 = self.nom_joueur2.get() p1 = self.pion1 p2 = self.pion2 force = self.choixForce.get() self.destroy() ma_fenetre = Fenetre(j1, j2, type2, p1, p2, force) ma_fenetre.mainloop()
class RouteAttemptsEntry(Frame): def __init__(self, parent, num, *args, **kwargs): Frame.__init__(self, parent, *args, **kwargs) self.num = num self.parent = parent self.isActive = False self.font = ['Arial', -0.02] self.font[1] = round(self.font[1] * self.parent.parent.parent.SCREEN_HEIGHT) self.numFont = ['Arial', -0.02, 'bold'] self.numFont[1] = round(self.numFont[1] * self.parent.parent.parent.SCREEN_HEIGHT) self.config(bg=LBLUE) self.labelbg = LBLUE self.labelfg = 'white' self.buttonbg = BLUE self.buttonfg = 'white' self.plusIcon = '+' self.minusIcon = '-' # im expecting these will be replaced with images in the future self.attemptsAmt = IntVar() self.attemptsAmt.set(0) self.numLabel = Label(self, text='#{}'.format(num), width=3, fg=self.labelfg, bg=self.labelbg, font=self.numFont) self.minusButton = Button(self, text=self.minusIcon, fg=self.buttonfg, bg=self.buttonbg, width=2, command=self.minus, font=self.numFont) self.attemptsAmtLabel = Label(self, width=2, fg=self.labelfg, bg=self.labelbg, textvariable=self.attemptsAmt, font=self.numFont) self.plusButton = Button(self, text=self.plusIcon, width=2, bg=self.buttonbg, fg=self.buttonfg, command=self.plus, font=self.numFont) self.numLabel.grid(row=0, column=0, sticky='nsew') self.minusButton.grid(row=0, column=1, sticky='nsew') self.attemptsAmtLabel.grid(row=0, column=2, sticky='nsew') self.plusButton.grid(row=0, column=3, sticky='nsew') for i in range(0, 4): self.columnconfigure(i, weight=1) self.rowconfigure(0, weight=1) def plus(self): if self.attemptsAmt.get() > 0: self.attemptsAmt.set(self.attemptsAmt.get() + 1) elif self.parent.not_five_routes_selected(): self.attemptsAmt.set(self.attemptsAmt.get() + 1) self.activate() self.parent.parent.competitorInfoFrame.update_from_route_buttons() def minus(self): if self.attemptsAmt.get() != 0: self.attemptsAmt.set(self.attemptsAmt.get() - 1) if self.attemptsAmt.get() == 0: self.deactivate() self.parent.parent.competitorInfoFrame.update_from_route_buttons() def activate(self): self.isActive = True self.numLabel.configure(bg=DDBLUE, fg='white') def deactivate(self): self.isActive = False self.numLabel.configure(bg=self.labelbg, fg=self.labelfg)
def scale_callback(self, var: tk.IntVar, color_var: tk.IntVar) -> None: color_var.set(var.get()) self.focus = "rgb" self.update_color()
class TipCalulator(): def __init__(self): window = Tk() window.title("Tip Calculator Application") window.configure(background="SkyBlue") window.geometry("370x350") window.resizable(width=False, height=False) #variables for class self.meal_cost = StringVar() self.tip_percent = IntVar() self.tip = StringVar() self.total_cost = StringVar() #Some lable for it tip_percents = Label(window, text="Tip Percentages", bg="Purple", fg="White") tip_percents.grid(column=0, row=0, padx=15) bill_amount = Label(window, text="Bill Amount", bg="Black", fg="White") bill_amount.grid(column=1, row=0, padx=15) bill_amount_entry = Entry(window, textvariable=self.meal_cost, width=14) bill_amount_entry.grid(column=2, row=0) #somw radio button create for percent five_percent_tip = Radiobutton(window, text="0.5%", variable=self.tip_percent, value=5) five_percent_tip.grid(column=0, row=1) ten_percent_tip = Radiobutton(window, text="10%", variable=self.tip_percent, value=10) ten_percent_tip.grid(column=0, row=2) fifteen_percent_tip = Radiobutton(window, text="15%", variable=self.tip_percent, value=15) fifteen_percent_tip.grid(column=0, row=3) twenty_percent_tip = Radiobutton(window, text="20%", variable=self.tip_percent, value=20) twenty_percent_tip.grid(column=0, row=4) twentyfive_percent_tip = Radiobutton(window, text="25%", variable=self.tip_percent, value=25) twentyfive_percent_tip.grid(column=0, row=5) thirty_percent_tip = Radiobutton(window, text="30%", variable=self.tip_percent, value=30) thirty_percent_tip.grid(column=0, row=6) tip_amount_lbl = Label(window, text="Tip Amount", bg="Black", fg="White") tip_amount_lbl.grid(column=1, row=3, padx=15) tip_amount_entry = Entry(window, textvariable=self.tip, width=14) tip_amount_entry.grid(column=2, row=3) bill_total_lbl = Label(window, text="Bill Total", bg="Black", fg="white") bill_total_lbl.grid(column=1, row=5, padx=15) bill_total_entry = Entry(window, textvariable=self.total_cost, width=14) bill_total_entry.grid(column=2, row=5) #include some buttons calculate_btn = Button(window, text="Calculate", bg="green", fg="white", command="self.calculate") calculate_btn.grid(column=1, row=7, padx=15) clear_btn = Button(window, text="Clear", bg="Black", fg="White", command="") clear_btn.grid(column=2, row=7) window.mainloop() def calculate(self): pre_tip = float(self.meal_cost.get()) percentage = self.tip_percent.get() / 100 tip_amount_entry = pre_tip * percentage self.tip.set(tip_amount_entry) final_bill = pre_tip + tip_amount_entry self.total_cost.set(final_bill) def clear(self): self.total_cost.set("") self.meal_cost.set("") self.tip.set("")
class Gui(Frame): counter = 0 def __init__(self, master): Frame.__init__(self, master) self.pack() global buienradarAPI #define master variables (geometry and background) master.geometry('{}x{}'.format(1600, 900)) master.resizable(width=False, height=False) master.filename = PhotoImage(file="achtergrond.png") master.background_label = Label(master, image=master.filename) master.background_label.place(x=0, y=0, relwidth=1, relheight=1) #define variables needed to get information from checkboxes in the gui self.IntVarWaterHeight = IntVar() self.IntVarRainLevel = IntVar() self.IntVarWindDirection = IntVar() self.IntVarWindSpeed = IntVar() #define graph dimensions self.graphHeight = 178 self.graphWidth = 698 self.startYvar = self.graphHeight + 2 self.startYvar = self.graphHeight + 2 self.waterLevelCoords = [0, 0, 0, 0, 0, 0, 0, 0] self.rainLevelCoords = [0, 0, 0, 0, 0, 0, 0, 0] self.windDirectionCoords = [0, 0, 0, 0, 0, 0, 0, 0] self.windSpeedCoords = [0, 0, 0, 0, 0, 0, 0, 0] self.keringStatus = 'OPEN' #define frame for gui box = Frame(master, relief=SUNKEN, borderwidth=2).pack() #define gui elements (graphs, buttons, checkboxes, sliders) self.waterLevelGraph = Canvas(box, height=self.graphHeight, width=self.graphWidth, relief=SUNKEN, borderwidth=1) self.waterLevelGraph.place(x=10, y=30) self.rainLevelGraph = Canvas(box, height=self.graphHeight, width=self.graphWidth, relief=SUNKEN, borderwidth=1) self.rainLevelGraph.place(x=10, y=250) self.windDirectionGraph = Canvas(box, height=self.graphHeight, width=self.graphWidth, relief=SUNKEN, borderwidth=1) self.windDirectionGraph.place(x=10, y=470) self.windSpeedGraph = Canvas(box, height=self.graphHeight, width=self.graphWidth, relief=SUNKEN, borderwidth=1) self.windSpeedGraph.place(x=10, y=690) self.statusLabel = Label(box, text=self.keringStatus, font=('Helvetica', 16), relief=SUNKEN, borderwidth=5) self.statusLabel.place(x=890, y=50, width=700, height=100) self.exitButton = Button(box, text='Afsluiten', font=('Helvetica', 16), command=exit, borderwidth=2) self.exitButton.place(x=1245, y=800, height=90, width=345) self.historyButton = Button(box, text='Historie', font=('Helvetica', 16), borderwidth=2, command=lambda: self.showHistoryWindow()) self.historyButton.place(x=890, y=800, height=40, width=345) self.historyStartEntry = Entry(box, borderwidth=2) self.historyStartEntry.insert(0, 'jjjj-mm-dd uu:mm') self.historyStartEntry.place(x=890, y=850, height=40, width=170) self.historyEndEntry = Entry(box, borderwidth=2) self.historyEndEntry.insert(0, 'jjjj-mm-dd uu:mm') self.historyEndEntry.place(x=1065, y=850, height=40, width=170) self.waterLevelSlider = Scale(box, from_=0, to=75, resolution=25, relief=RAISED) self.waterLevelSlider.place(x=910, y=230, height=265) self.waterLevelCheck = Checkbutton(box, variable=self.IntVarWaterHeight) self.waterLevelCheck.place(x=1120, y=350) self.rainLevelSlider = Scale(box, from_=0, to=250, resolution=10, relief=RAISED) self.rainLevelSlider.place(x=910, y=505, height=265) self.rainLevelCheck = Checkbutton(box, variable=self.IntVarRainLevel) self.rainLevelCheck.place(x=1140, y=626) self.windDirectionSlider = Scale(box, from_=0, to=350, resolution=10, relief=RAISED) self.windDirectionSlider.place(x=1245, y=230, height=265) self.windSpeedSlider = Scale(box, from_=0, to=35, relief=RAISED) self.windSpeedSlider.place(x=1245, y=505, height=265) self.windSpeedCheck = Checkbutton(box, variable=self.IntVarWindSpeed) self.windSpeedCheck.place(x=1505, y=485) self.applyConfigButton = Button(box, text='toepassen', font=('Helvetica', 16), command=self.updateConfig) self.applyConfigButton.place(x=1462, y=180, height=30, width=117) #function used to test checkboxes def getConfig(self): waterHeightConfigCheck = self.IntVarWaterHeight.get() rainLevelConfigCheck = self.IntVarRainLevel.get() windDirectionConfigCheck = self.IntVarWindDirection.get() windSpeedConfigCheck = self.IntVarWindSpeed.get() checksList = [] checksList.append(waterHeightConfigCheck) checksList.append(rainLevelConfigCheck) checksList.append(windDirectionConfigCheck) checksList.append(windSpeedConfigCheck) return checksList def create_window(self, title, text): t = Toplevel(self) t.wm_title(title) i = Text(t, relief="flat", height=50, width=70) i.insert(1.0, text) i.config(state='disabled') print(text) i.pack() def showHistoryWindow(self): string = self.getHistoryString() self.create_window('Historie', string) def getHistoryString(self): self.startEntryString = self.historyStartEntry.get() self.endEntryString = self.historyEndEntry.get() returnValue = 'beginwaarde' if validDateString(self.startEntryString) == True: if validDateString(self.endEntryString) == True: if time.mktime( time.strptime(self.startEntryString, '%Y-%m-%d %H:%M')) <= time.mktime( time.strptime( self.endEntryString, '%Y-%m-%d %H:%M')): returnValue = (self.startEntryString, self.endEntryString) else: returnValue = 'allemaal problemen' print('functie doorlopen') print(returnValue) return returnValue #function used to read config from the GUI and write to file def updateConfig(self): print('config updated') if self.IntVarWaterHeight.get() == 0: waterheightParameter = '-' else: waterheightParameter = self.waterLevelSlider.get() if self.IntVarWindSpeed.get() == 0: windSpeedParameter = '-' else: windSpeedParameter = self.windSpeedSlider.get() if self.IntVarRainLevel.get() == 0: rainLevelParameter = '-' else: rainLevelParameter = self.rainLevelSlider.get() windDirectionParameter = self.windDirectionSlider.get() writeParameters('params.json', windDirectionParameter, windSpeedParameter, waterheightParameter, rainLevelParameter) #function used to def updateYCoordList(self, list, type): if type == 'rainLevel': list.append(self.getRainLevelYCoord()) list.remove(list[0]) elif type == 'waterLevel': list.append(self.getWaterLevelYCoord()) list.remove(list[0]) elif type == 'windDirection': list.append(self.getWindDirectionYCoord()) list.remove(list[0]) elif type == 'windSpeed': list.append(self.getWindSpeedYCoord()) list.remove(list[0]) else: list.append(36) list.remove(list[0]) return list def drawGraph(self, list, canvas): canvas.delete('all') startX = 0 for index in range(len(list) - 1): startY = self.startYvar - list[index] try: endY = self.startYvar - list[index + 1] except: print('error') pass endX = startX + 100 canvas.create_line(startX, startY, endX, endY) startX += 100 def updateGraph(self, list, canvas, type, miliseconds): self.drawGraph(self.updateYCoordList(list, type), canvas) canvas.after(miliseconds, self.updateGraph, list, canvas, type, miliseconds) def updateStatusLabel(self, label): label.configure(text=random.randint(0, 9)) label.after(100, self.updateStatusLabel, label) def getRainLevelYCoord(self): rainLevel = buienradarAPI['regenMMPU'] if rainLevel == '-': rainLevel = 0 rainLevelY = int(float(rainLevel) * 1.388888888888889) return rainLevelY def getWindSpeedYCoord(self): windSpeed = buienradarAPI['windsnelheidMS'] windSpeedY = int(float(windSpeed) * 5) return windSpeedY def getWindDirectionYCoord(self): windDirection = buienradarAPI['windrichtingGR'] windDirectionY = int(float(windDirection) * 0.4) return windDirectionY def getWaterLevelYCoord(self): return 50
class SolutionTabFrame(Frame): ''' This class is responsible for displaying solution on the screen. It extends Frame class. Attributes: parent (Tk object that can contain Frame): parent that can contain Frame, MUST implement method change_solution_tab_name(str). data_from_file_lbl (Label): label that contains file name with data if specified. solution_tab (SolutionFrameWithText): notebook with tabs describing solution. model_solutions (list of Solution): list with one or more solutions that have been generated after running algorithm. param_strs (list of str): list with strings that should appear before printing every solution from model_solutions. ranks (list of list of int): list of ranks corresponding to every solution from model_solutions, ranks are generated by peel-the-onion algorithm. categorical (str): name of the categorical variable used in categorical analysis. progress_bar (Progressbar): progress bar to show how solution is loaded or saved to file. status_lbl (Label): label for displaying solution status. solution_format_var (IntVar): IntVar object that tracks which file format is chosen for solution. ''' def __init__(self, parent, *args, **kw): super().__init__(parent, *args, **kw) self.parent = parent self.data_from_file_lbl = None self.solution_tab = None self.model_solutions = None self.param_strs = None self.ranks = None self.params = None self.categorical = None self.run_date = None self.total_seconds = 0 self.progress_bar = None self.status_lbl = None self.solution_format_var = IntVar() self.create_widgets() def create_widgets(self): ''' Creates appropriate widgets on this frame. ''' self.columnconfigure(0, weight=1) self.rowconfigure(3, weight=1) frame_for_save_btn = Frame(self) frame_for_save_btn.columnconfigure(1, weight=1) self.status_lbl = Label(frame_for_save_btn, text='') self.status_lbl.grid(row=0, column=1, sticky=N + W) save_solution_btn = Button(frame_for_save_btn, text='Save solution', command=self.on_save_solution) save_solution_btn.grid(row=1, column=0, sticky=W + N, padx=5, pady=5) self.progress_bar = Progressbar(frame_for_save_btn, mode='determinate', maximum=100) self.progress_bar.grid(row=1, column=1, sticky=W + E, padx=10, pady=5) frame_for_save_btn.grid(sticky=W + N + E + S, padx=5, pady=5) frame_for_btns = Frame(self) self._create_file_format_btn('*.xlsx', 1, frame_for_btns, 0) self._create_file_format_btn('*.csv', 2, frame_for_btns, 1) self.solution_format_var.set(1) frame_for_btns.grid(row=1, column=0, sticky=W + N + E + S, padx=5, pady=5) self.data_from_file_lbl = Label(self, text=TEXT_FOR_FILE_LBL, anchor=W, justify=LEFT, wraplength=MAX_FILE_PARAMS_LBL_LENGTH) self.data_from_file_lbl.grid(row=2, column=0, padx=5, pady=5, sticky=W + N) self.solution_tab = SolutionFrameWithText(self) self.solution_tab.grid(row=3, column=0, sticky=W + E + S + N, padx=5, pady=5) def _create_file_format_btn(self, btn_text, var_value, parent, column): ''' Creates and grids Radiobutton used for choosing solution file format. Args: btn_text (str): text displayed next to the Radiobutton. var_value (int): value of the IntVar associated with this Radiobutton. parent (Tk object): parent of this Radiobutton. column (int): column index where this Radiobutton should be gridded. ''' sol_format_btn = Radiobutton(parent, text=btn_text, variable=self.solution_format_var, value=var_value) sol_format_btn.grid(row=2, column=column, sticky=W + N, padx=2) def on_save_solution(self): ''' Saves solution to file. This method is called when save solution button is pressed. If there is a solution, this method will ask user to provide a file name where solution should be stored. If a valid name is provided, solution is saved to that file. Allowed file format is .xlsx. If the user checked 'csv' as solution output format, then the user will be asked to choose a directory where all csv files will be written. ''' if self.model_solutions is not None: assert (self.param_strs is not None) if self.solution_format_var.get() == 1: #xlsx file_name = self.ask_file_name_to_save( self.solution_format_var.get()) dir_name = '' else: #csv dir_name = askdirectory() file_name = '' if file_name or dir_name: print(file_name) self.status_lbl.config(text='Saving solution to file...') if file_name.endswith('.xlsx'): work_book = XlsxWorkbook() else: # all not supported formats will be written to csv assert (dir_name) work_book = TxtWriter(dir_name) writer = FileWriter(self.params, work_book, self.run_date, self.total_seconds, ranks=self.ranks, categorical=self.categorical) nb_models = len(self.model_solutions) # +1 for parameters sheet, it is stored separately nb_sheets = len(writer.worksheets) + 1 progress_recorder = GuiProgress(self.progress_bar, nb_models, nb_sheets) try: for count, sol in enumerate(self.model_solutions): writer.write_data(sol, self.param_strs[count], progress_recorder) work_book.save(file_name) except ValueError: # can happen if maximum number of rows is exceeded self.status_lbl.config( text='File is too large for xlsx format,' ' it will be saved to csv instead') work_book = TxtWriter(os.path.splitext(file_name)[0]) writer = FileWriter(self.params, work_book, self.run_date, self.total_seconds, ranks=self.ranks, categorical=self.categorical) progress_recorder.set_position(0) for count, sol in enumerate(self.model_solutions): writer.write_data(sol, self.param_strs[count], progress_recorder) work_book.save(file_name) progress_recorder.set_position(100) self.parent.change_solution_tab_name('Solution') self.status_lbl.config(text='Solution saved') def ask_file_name_to_save(self, ext_code): ''' Calls asksaveasfilename dialogue to ask the user where file should be saved. If file without extension is entered, default extension will be used (.xlsx). This method is used to mock this object for unit tests. Args: ext_code (int): code for file extension 1 - xlsx. ''' if ext_code == 1: filetype = SOLUTION_XLSX_FILE return asksaveasfilename(filetypes=filetype, defaultextension='.xlsx') def show_solution(self, solutions, params, param_strs, run_date, total_seconds, ranks=None, categorical=None): ''' Displays solution on the screen. Args: solutions (list of Solution): list of solutions (might contain just one solution) that have been generated after running algorithm. params (Parameters): object with parameters that will be written to file on the Parameters page. param_strs (list of str): list with strings that should appear before printing every solution from model_solutions. ranks (list of list of int): list of ranks corresponding to every solution from model_solutions, ranks are generated by peel-the-onion algorithm. categorical (str): name of the categorical variable used in categorical analysis. ''' self.status_lbl.config(text='') self.model_solutions = solutions self.param_strs = param_strs self.ranks = ranks self.params = params self.categorical = categorical self.run_date = run_date self.total_seconds = total_seconds self.status_lbl.config(text='Loading solution...') self.solution_tab.show_solution(solutions, params, param_strs, run_date, total_seconds, ranks, categorical) self.parent.change_solution_tab_name('Solution*') self.status_lbl.config(text='Solution loaded') def update_data_file_name(self, new_data_file_name): ''' Updates label with data file name. Args: new_data_file_name (str): new value of the data file name ''' self.data_from_file_lbl.config(text=TEXT_FOR_FILE_LBL + new_data_file_name)
class MenuBoard(Frame): def __init__(self, parent): '''size is the size of a square, in pixels''' Frame.__init__(self, parent) self.setUpMenu() def setUpMenu(self): lbl = Label(self, text="Algorithms", font=("Helvetica", 16)) lbl.grid(row=0, column=0, columnspan=2, sticky="w") Label(self, text=" ").grid(row=1, column=0) self.algorithm = StringVar(self) self.algorithm.set("Backtracking") # default value w = OptionMenu(self, self.algorithm, "DFS", "Backtracking") w.grid(row=1, column=1) Label(self, text=" ", font=("Helvetica", 16)).grid(row=2, column=0, columnspan=2) Label(self, text="Ordering", font=("Helvetica", 16)).grid(row=3, column=0, columnspan=2, sticky="w") self.ordering = IntVar(self) self.ordering.set(1) # initializing the choice, i.e. Python orderOptions = [ ("None", 1), ("MRV", 2), ("MRV with LCV", 3), ] def ShowChoice(): print(self.ordering.get()) row = 5 for nm, val in orderOptions: Radiobutton(self, text=nm, variable=self.ordering, command=ShowChoice, value=val).grid(row=row, column=1, sticky="w") row = row + 1 Label(self, text=" ", font=("Helvetica", 16)).grid(row=row, column=0, columnspan=2) row = row + 1 Label(self, text="Filtering", font=("Helvetica", 16)).grid(row=row, column=0, columnspan=2, sticky="w") row = row + 1 self.filtering = IntVar(self) self.filtering.set(1) filterOptions = [ ("None", 1), ("Forward Checking", 2), ("Arc Consistency", 3), ] def ShowChoiceFiltering(): print(self.filtering.get()) for nm, val in filterOptions: Radiobutton(self, text=nm, variable=self.filtering, command=ShowChoiceFiltering, value=val).grid(row=row, column=1, sticky="w") row = row + 1 Label(self, text=" ", font=("Helvetica", 16)).grid(row=row, column=0, columnspan=2) row = row + 1 Label(self, text="Board Options", font=("Helvetica", 16)).grid(row=row, column=0, columnspan=2, sticky="w") row = row + 1 self.boardType = IntVar(self) self.boardType.set(1) boardOptions = [("Show Board", 1), ("Show Domain", 2)] def ShowChoiceBoard(): print(self.boardType.get()) for nm, val in boardOptions: Radiobutton(self, text=nm, variable=self.boardType, command=ShowChoiceBoard, value=val).grid(row=row, column=1, sticky="w") row = row + 1 Label(self, text="Speed (in seconds)", font=("Helvetica", 12)).grid(row=row, column=0, columnspan=2, sticky="w") row = row + 1 self.speedEntry = Entry(self, text="0.005", width=10) self.speedEntry.insert(0, ".005") self.speedEntry.grid(row=row, column=1)
font_size.set(12) font_size_drop.config(width=2) font_size_drop.grid(row=0, column=5, padx=5, pady=5) option = ['none', 'bold', 'italic'] font_option = StringVar() font_option_drop = tkinter.OptionMenu(menu_frame, font_option, *option, command=change_font) font_option.set('none') font_option_drop.config(width=5) font_option_drop.grid(row=0, column=6, padx=5, pady=5) #Layout for the text frame my_font = font_family.get(), font_size.get() #create the input text as yoy scroll through the text field input_text = tkinter.scrolledtext.ScrolledText(text_frame, width=1000, height=100, bg=text_color, font=my_font) input_text.pack() #run the main loop root.mainloop()
class OptimizeGroup(Group): def __init__(self, *args, **kwargs): self._app = kwargs.pop('wavesyn_root') self.__topwin = kwargs.pop('topwin') super().__init__(*args, **kwargs) parameter_frame = Frame(self) parameter_frame.pack(side='left', expand='yes', fill='y') self.__num = LabeledEntry(parameter_frame) set_attributes(self.__num, label_text = 'num', entry_text = '1', label_width = 5, entry_width = 8, checker_function = self._app.gui.value_checker.check_int ) self.__num.entry.bind('<Return>', lambda event: self._on_solve_click()) self.__num.pack(side='top') self.__pci = LabeledEntry(parameter_frame) set_attributes(self.__pci, label_text = 'PCI', entry_text = '100', label_width = 5, entry_width = 8, checker_function = self._app.gui.value_checker.check_int ) self.__pci.pack(side='top') self.__parallel_checker_variable = IntVar() self.__parallel_checker = Checkbutton(parameter_frame, text="Parallel", variable=self.__parallel_checker_variable, command=self._on_parallel_checker_click) self.__parallel_checker.pack() progfrm = Frame(self) progfrm.pack(side='left', expand='yes', fill='y') self.__genbtn = Button(progfrm, text='Generate', command=self._on_solve_click) self.__genbtn.pack(side='top') Button(progfrm, text='Stop', command=self._on_stop_button_click).pack(side='top') self.__progressbar_variable = IntVar() self.__finishedwav = IntVar() self.__progressbar = Progressbar(progfrm, orient='horizontal', variable=self.__progressbar_variable, maximum=100) self.__progressbar.pack(side='left') self.__progressbar.config(length=55) self.__finishedwavbar = Progressbar(progfrm, orient='horizontal', variable=self.__finishedwav) self.__finishedwavbar.pack(side='left') self.__finishedwavbar.config(length=30) self.name = 'Generate' self.getparams = None self.__stopflag = False def _on_solve_click(self): params = self.__topwin.parameter_group.get_parameters() repeat_times = self.__num.get_int() if self.__parallel_checker_variable.get(): run = self.__topwin.current_algorithm.process_run else: run = self.__topwin.current_algorithm.thread_run with code_printer(): run(on_finished=['store', 'plot'], progress_indicator='progress_dialog', repeat_times=repeat_times, **params) def _on_stop_button_click(self): self.__stopflag = True def _on_parallel_checker_click(self): topwin = self.__topwin if topwin.current_algorithm.need_cuda: self.__parallel_checker_variable.set(0) topwin.root_node.gui.dialogs.report(f'''{topwin.node_path}: Current algorithm "{topwin.current_algorithm.meta.name}" need CUDA worker, which does not support multi-cpu parallel. ''') def _cancel_parallel(self): self.__parallel_checker_variable.set(0)
class RandomExcursionTestItem: def __init__(self, master, title, x_coor, y_coor, data, variant=False, font_size=11): self.__chb_var = IntVar() self.__state = StringVar() self.__count = StringVar() self.__xObs = StringVar() self.__p_value = StringVar() self.__result = StringVar() self.__results = [] self.__variant = variant checkbox = Checkbutton(master, text=title, variable=self.__chb_var) checkbox.config(font=("Calibri", font_size)) checkbox.place(x=x_coor, y=y_coor) state_label = LabelTag(master, 'State', (x_coor + 60), (y_coor + 30), width=100, font_size=font_size, border=2, relief='groove') if variant: self.__state.set('-1.0') else: self.__state.set('+1') state_option = OptionMenu(master, self.__state, *data) state_option.place(x=(x_coor + 60), y=(y_coor + 60), height=25, width=100) if not variant: xObs_label = LabelTag(master, 'CHI-SQUARED', (x_coor + 165), (y_coor + 30), width=350, font_size=font_size, border=2, relief='groove') xObs_Entry = Entry(master, textvariable=self.__xObs) xObs_Entry.place(x=(x_coor + 165), y=(y_coor + 60), width=350, height=25) else: count_label = LabelTag(master, 'Count', (x_coor + 165), (y_coor + 30), width=350, font_size=font_size, border=2, relief='groove') count_Entry = Entry(master, textvariable=self.__count) count_Entry.place(x=(x_coor + 165), y=(y_coor + 60), width=350, height=25) pass p_value_label = LabelTag(master, 'P-Value', (x_coor + 520), (y_coor + 30), width=350, font_size=font_size, border=2, relief='groove') p_value_Entry = Entry(master, textvariable=self.__p_value) p_value_Entry.place(x=(x_coor + 520), y=(y_coor + 60), width=350, height=25) conclusion_label = LabelTag(master, 'Conclusion', (x_coor + 875), (y_coor + 30), width=150, font_size=font_size, border=2, relief='groove') conclusion_Entry = Entry(master, textvariable=self.__result) conclusion_Entry.place(x=(x_coor + 875), y=(y_coor + 60), width=150, height=25) update_button = Button(master, text='Update', command=self.update) update_button.config(font=("Calibri", 10)) update_button.place(x=(x_coor + 1030), y=(y_coor + 60), width=180, height=25) def get_check_box_value(self): return self.__chb_var.get() def set_check_box_value(self, value): self.__chb_var.set(value) def set_results(self, results): self.__results = results self.update() def update(self): match = False for result in self.__results: if result[0] == self.__state.get(): if self.__variant: self.__count.set(result[2]) else: self.__xObs.set(result[2]) self.__p_value.set(result[3]) self.__result.set(self.get_result_string(result[4])) match = True if not match: if self.__variant: self.__count.set('') else: self.__xObs.set('') self.__p_value.set('') self.__result.set('') def get_result_string(self, result): if result == True: return 'Random' else: return 'Non-Random' def reset(self): self.__chb_var.set('0') if self.__variant: self.__state.set('-1.0') self.__count.set('') else: self.__state.set('+1') self.__xObs.set('') self.__p_value.set('') self.__result.set('')
class MLNQueryGUI(object): def __init__(self, master, gconf, directory=None): self.master = master self.initialized = False self.master.bind('<Return>', self.infer) self.master.bind('<Escape>', lambda a: self.master.quit()) self.master.protocol('WM_DELETE_WINDOW', self.quit) self.dir = os.path.abspath(ifnone(directory, ifnone(gconf['prev_query_path'], os.getcwd()))) self.frame = Frame(master) self.frame.pack(fill=BOTH, expand=1) self.frame.columnconfigure(1, weight=1) row = 0 # pracmln project options Label(self.frame, text='PRACMLN Project: ').grid(row=row, column=0, sticky='ES') project_container = Frame(self.frame) project_container.grid(row=row, column=1, sticky="NEWS") # new proj file self.btn_newproj = Button(project_container, text='New Project...', command=self.new_project) self.btn_newproj.grid(row=0, column=1, sticky="WS") # open proj file self.btn_openproj = Button(project_container, text='Open Project...', command=self.ask_load_project) self.btn_openproj.grid(row=0, column=2, sticky="WS") # save proj file self.btn_updateproj = Button(project_container, text='Save Project...', command=self.noask_save_project) self.btn_updateproj.grid(row=0, column=3, sticky="WS") # save proj file as... self.btn_saveproj = Button(project_container, text='Save Project as...', command=self.ask_save_project) self.btn_saveproj.grid(row=0, column=4, sticky="WS") # grammar selection row += 1 Label(self.frame, text='Grammar: ').grid(row=row, column=0, sticky='E') grammars = ['StandardGrammar', 'PRACGrammar'] self.selected_grammar = StringVar() self.selected_grammar.trace('w', self.settings_setdirty) l = OptionMenu(*(self.frame, self.selected_grammar) + tuple(grammars)) l.grid(row=row, column=1, sticky='NWE') # logic selection row += 1 Label(self.frame, text='Logic: ').grid(row=row, column=0, sticky='E') logics = ['FirstOrderLogic', 'FuzzyLogic'] self.selected_logic = StringVar() self.selected_logic.trace('w', self.settings_setdirty) l = OptionMenu(*(self.frame, self.selected_logic) + tuple(logics)) l.grid(row=row, column=1, sticky='NWE') # mln section row += 1 Label(self.frame, text="MLN: ").grid(row=row, column=0, sticky='NE') self.mln_container = FileEditBar(self.frame, directory=self.dir, filesettings={'extension': '.mln', 'ftypes': [('MLN files', '.mln')]}, defaultname='*unknown{}', importhook=self.import_mln, deletehook=self.delete_mln, projecthook=self.save_proj, filecontenthook=self.mlnfilecontent, fileslisthook=self.mlnfiles, updatehook=self.update_mln, onchangehook=self.project_setdirty) self.mln_container.editor.bind("<FocusIn>", self._got_focus) self.mln_container.grid(row=row, column=1, sticky="NEWS") self.mln_container.columnconfigure(1, weight=2) self.frame.rowconfigure(row, weight=1) row += 1 self.use_emln = IntVar() self.use_emln.set(0) self.cb_use_emln = Checkbutton(self.frame, text="use model extension", variable=self.use_emln, command=self.onchange_use_emln) self.cb_use_emln.grid(row=row, column=1, sticky="W") # mln extension section row += 1 self.emlncontainerrow = row self.emln_label = Label(self.frame, text="EMLN: ") self.emln_label.grid(row=self.emlncontainerrow, column=0, sticky='NE') self.emln_container = FileEditBar(self.frame, directory=self.dir, filesettings={'extension': '.emln', 'ftypes': [('MLN extension files','.emln')]}, defaultname='*unknown{}', importhook=self.import_emln, deletehook=self.delete_emln, projecthook=self.save_proj, filecontenthook=self.emlnfilecontent, fileslisthook=self.emlnfiles, updatehook=self.update_emln, onchangehook=self.project_setdirty) self.emln_container.grid(row=self.emlncontainerrow, column=1, sticky="NEWS") self.emln_container.editor.bind("<FocusIn>", self._got_focus) self.emln_container.columnconfigure(1, weight=2) self.onchange_use_emln(dirty=False) self.frame.rowconfigure(row, weight=1) # db section row += 1 Label(self.frame, text="Evidence: ").grid(row=row, column=0, sticky='NE') self.db_container = FileEditBar(self.frame, directory=self.dir, filesettings={'extension': '.db', 'ftypes': [('Database files', '.db')]}, defaultname='*unknown{}', importhook=self.import_db, deletehook=self.delete_db, projecthook=self.save_proj, filecontenthook=self.dbfilecontent, fileslisthook=self.dbfiles, updatehook=self.update_db, onchangehook=self.project_setdirty) self.db_container.grid(row=row, column=1, sticky="NEWS") self.db_container.editor.bind("<FocusIn>", self._got_focus) self.db_container.columnconfigure(1, weight=2) self.frame.rowconfigure(row, weight=1) # inference method selection row += 1 self.list_methods_row = row Label(self.frame, text="Method: ").grid(row=row, column=0, sticky=E) self.selected_method = StringVar() self.selected_method.trace('w', self.select_method) methodnames = sorted(InferenceMethods.names()) self.list_methods = OptionMenu(*(self.frame, self.selected_method) + tuple(methodnames)) self.list_methods.grid(row=self.list_methods_row, column=1, sticky="NWE") # options row += 1 option_container = Frame(self.frame) option_container.grid(row=row, column=1, sticky="NEWS") # Multiprocessing self.multicore = IntVar() self.cb_multicore = Checkbutton(option_container, text="Use all CPUs", variable=self.multicore, command=self.settings_setdirty) self.cb_multicore.grid(row=0, column=2, sticky=W) # profiling self.profile = IntVar() self.cb_profile = Checkbutton(option_container, text='Use Profiler', variable=self.profile, command=self.settings_setdirty) self.cb_profile.grid(row=0, column=3, sticky=W) # verbose self.verbose = IntVar() self.cb_verbose = Checkbutton(option_container, text='verbose', variable=self.verbose, command=self.settings_setdirty) self.cb_verbose.grid(row=0, column=4, sticky=W) # options self.ignore_unknown_preds = IntVar() self.cb_ignore_unknown_preds = Checkbutton(option_container, text='ignore unkown predicates', variable=self.ignore_unknown_preds, command=self.settings_setdirty) self.cb_ignore_unknown_preds.grid(row=0, column=5, sticky="W") # queries row += 1 Label(self.frame, text="Queries: ").grid(row=row, column=0, sticky=E) self.query = StringVar() self.query.trace('w', self.settings_setdirty) Entry(self.frame, textvariable=self.query).grid(row=row, column=1, sticky="NEW") # additional parameters row += 1 Label(self.frame, text="Add. params: ").grid(row=row, column=0, sticky="NE") self.params = StringVar() self.params.trace('w', self.settings_setdirty) self.entry_params = Entry(self.frame, textvariable=self.params) self.entry_params.grid(row=row, column=1, sticky="NEW") # closed-world predicates row += 1 Label(self.frame, text="CW preds: ").grid(row=row, column=0, sticky="E") cw_container = Frame(self.frame) cw_container.grid(row=row, column=1, sticky='NEWS') cw_container.columnconfigure(0, weight=1) self.cwPreds = StringVar() self.cwPreds.trace('w', self.settings_setdirty) self.entry_cw = Entry(cw_container, textvariable=self.cwPreds) self.entry_cw.grid(row=0, column=0, sticky="NEWS") self.closed_world = IntVar() self.cb_closed_world = Checkbutton(cw_container, text="CW Assumption", variable=self.closed_world, command=self.onchange_cw) self.cb_closed_world.grid(row=0, column=1, sticky='W') # output filename row += 1 output_cont = Frame(self.frame) output_cont.grid(row=row, column=1, sticky='NEWS') output_cont.columnconfigure(0, weight=1) # - filename Label(self.frame, text="Output: ").grid(row=row, column=0, sticky="NE") self.output_filename = StringVar() self.entry_output_filename = Entry(output_cont, textvariable=self.output_filename) self.entry_output_filename.grid(row=0, column=0, sticky="NEW") # - save option self.save = IntVar() self.cb_save = Checkbutton(output_cont, text="save", variable=self.save) self.cb_save.grid(row=0, column=1, sticky=W) # start button row += 1 start_button = Button(self.frame, text=">> Start Inference <<", command=self.infer) start_button.grid(row=row, column=1, sticky="NEW") self.settings_dirty = IntVar() self.project_dirty = IntVar() self.gconf = gconf self.project = None self.project_dir = os.path.abspath(ifnone(directory, ifnone(gconf['prev_query_path'], os.getcwd()))) if gconf['prev_query_project': self.project_dir] is not None: self.load_project(os.path.join(self.project_dir, gconf['prev_query_project':self.project_dir])) else: self.new_project() self.config = self.project.queryconf self.project.addlistener(self.project_setdirty) self.mln_container.dirty = False self.emln_container.dirty = False self.db_container.dirty = False self.project_setdirty(dirty=False) self.master.geometry(gconf['window_loc_query']) self.initialized = True def _got_focus(self, *_): if self.master.focus_get() == self.mln_container.editor: if not self.project.mlns and not self.mln_container.file_buffer: self.mln_container.new_file() elif self.master.focus_get() == self.db_container.editor: if not self.project.dbs and not self.db_container.file_buffer: self.db_container.new_file() elif self.master.focus_get() == self.emln_container.editor: if not self.project.emlns and not self.emln_container.file_buffer: self.emln_container.new_file() def quit(self): if self.settings_dirty.get() or self.project_dirty.get(): savechanges = messagebox.askyesnocancel("Save changes", "You have unsaved project changes. Do you want to save them before quitting?") if savechanges is None: return elif savechanges: self.noask_save_project() self.master.destroy() else: # write gui settings and destroy self.write_gconfig() self.master.destroy() ####################### PROJECT FUNCTIONS ################################# def new_project(self): self.project = MLNProject() self.project.addlistener(self.project_setdirty) self.project.name = DEFAULTNAME.format('.pracmln') self.reset_gui() self.set_config(self.project.queryconf) self.mln_container.update_file_choices() self.emln_container.update_file_choices() self.db_container.update_file_choices() self.project_setdirty(dirty=True) def project_setdirty(self, dirty=False, *args): self.project_dirty.set(dirty or self.mln_container.dirty or self.db_container.dirty or self.emln_container.dirty) self.changewindowtitle() def settings_setdirty(self, *args): self.settings_dirty.set(1) self.changewindowtitle() def changewindowtitle(self): title = (WINDOWTITLEEDITED if (self.settings_dirty.get() or self.project_dirty.get()) else WINDOWTITLE).format(self.project_dir, self.project.name) self.master.title(title) def ask_load_project(self): filename = askopenfilename(initialdir=self.dir, filetypes=[('PRACMLN project files', '.pracmln')], defaultextension=".pracmln") if filename and os.path.exists(filename): self.load_project(filename) else: logger.info('No file selected.') return def load_project(self, filename): if filename and os.path.exists(filename): projdir, _ = ntpath.split(filename) self.dir = os.path.abspath(projdir) self.project_dir = os.path.abspath(projdir) self.project = MLNProject.open(filename) self.project.addlistener(self.project_setdirty) self.reset_gui() self.set_config(self.project.queryconf.config) self.mln_container.update_file_choices() self.db_container.update_file_choices() if len(self.project.mlns) > 0: self.mln_container.selected_file.set(self.project.queryconf['mln'] or list(self.project.mlns.keys())[0]) self.mln_container.dirty = False if len(self.project.emlns) > 0: self.emln_container.selected_file.set(self.project.queryconf['emln'] or list(self.project.emlns.keys())[0]) self.emln_container.dirty = False if len(self.project.dbs) > 0: self.db_container.selected_file.set(self.project.queryconf['db'] or list(self.project.dbs.keys())[0]) self.db_container.dirty = False self.write_gconfig(savegeometry=False) self.settings_dirty.set(0) self.project_setdirty(dirty=False) self.changewindowtitle() else: logger.error('File {} does not exist. Creating new project...'.format(filename)) self.new_project() def noask_save_project(self): if self.project.name and not self.project.name == DEFAULTNAME.format('.pracmln'): self.save_project(os.path.join(self.project_dir, self.project.name)) else: self.ask_save_project() def ask_save_project(self): fullfilename = asksaveasfilename(initialdir=self.project_dir, confirmoverwrite=True, filetypes=[('PRACMLN project files','.pracmln')], defaultextension=".pracmln") self.save_project(fullfilename) def save_project(self, fullfilename): if fullfilename: fpath, fname = ntpath.split(fullfilename) fname = fname.split('.')[0] self.project.name = fname self.dir = os.path.abspath(fpath) self.project_dir = os.path.abspath(fpath) self.mln_container.save_all_files() self.emln_container.save_all_files() self.db_container.save_all_files() self.update_config() self.project.save(dirpath=self.project_dir) self.write_gconfig() self.load_project(fullfilename) self.settings_dirty.set(0) def save_proj(self): self.project.save(dirpath=self.project_dir) self.write_gconfig() self.project_setdirty(dirty=False) ####################### MLN FUNCTIONS ##################################### def import_mln(self, name, content): self.project.add_mln(name, content) def delete_mln(self, fname): if fname in self.project.mlns: self.project.rm_mln(fname) fnamestr = fname.strip('*') if fnamestr in self.project.mlns: self.project.rm_mln(fnamestr) def update_mln(self, old=None, new=None, content=None, askoverwrite=True): if old is None: old = self.mln_container.selected_file.get() if new is None: new = self.mln_container.selected_file.get().strip('*') if content is None: content = self.mln_container.editor.get("1.0", END).strip() if old == new and askoverwrite: savechanges = messagebox.askyesno("Save changes", "A file '{}' already exists. Overwrite?".format(new)) if savechanges: self.project.mlns[old] = content else: logger.error('no name specified!') return -1 elif old == new and not askoverwrite: self.project.mlns[old] = content else: if new in self.project.mlns: if askoverwrite: savechanges = messagebox.askyesno("Save changes", "A file '{}' already exists. Overwrite?".format(new)) if savechanges: self.project.mlns[new] = content else: logger.error('no name specified!') return -1 else: self.project.mlns[new] = content return 1 def mlnfiles(self): return list(self.project.mlns.keys()) def mlnfilecontent(self, filename): return self.project.mlns.get(filename, '').strip() # /MLN FUNCTIONS ##################################### ####################### EMLN FUNCTIONS ##################################### def import_emln(self, name, content): self.project.add_emln(name, content) def delete_emln(self, fname): if fname in self.project.emlns: self.project.rm_emln(fname) fnamestr = fname.strip('*') if fnamestr in self.project.emlns: self.project.rm_emln(fnamestr) def update_emln(self, old=None, new=None, content=None, askoverwrite=True): if old is None: old = self.emln_container.selected_file.get() if new is None: new = self.emln_container.selected_file.get().strip('*') if content is None: content = self.emln_container.editor.get("1.0", END).strip() if old == new and askoverwrite: savechanges = messagebox.askyesno("Save changes", "A file '{}' already exists. Overwrite?".format(new)) if savechanges: self.project.emlns[old] = content else: logger.error('no name specified!') return -1 elif old == new and not askoverwrite: self.project.emlns[old] = content else: if new in self.project.emlns: if askoverwrite: savechanges = messagebox.askyesno("Save changes", "A file '{}' already exists. Overwrite?".format(new)) if savechanges: self.project.emlns[new] = content else: logger.error('no name specified!') return -1 else: self.project.emlns[new] = content return 1 def emlnfiles(self): return list(self.project.emlns.keys()) def emlnfilecontent(self, filename): return self.project.emlns.get(filename, '').strip() # /EMLN FUNCTIONS ##################################### # DB FUNCTIONS ##################################### def import_db(self, name, content): self.project.add_db(name, content) def delete_db(self, fname): if fname in self.project.dbs: self.project.rm_db(fname) fnamestr = fname.strip('*') if fnamestr in self.project.dbs: self.project.rm_db(fnamestr) def update_db(self, old=None, new=None, content=None, askoverwrite=True): if old is None: old = self.db_container.selected_file.get() if new is None: new = self.db_container.selected_file.get().strip('*') if content is None: content = self.db_container.editor.get("1.0", END).strip() if old == new and askoverwrite: savechanges = messagebox.askyesno("Save changes", "A file '{}' already exists. Overwrite?".format(new)) if savechanges: self.project.dbs[old] = content else: logger.error('no name specified!') return -1 elif old == new and not askoverwrite: self.project.dbs[old] = content else: if new in self.project.dbs: if askoverwrite: savechanges = messagebox.askyesno("Save changes", "A file '{}' already exists. Overwrite?".format(new)) if savechanges: self.project.dbs[new] = content else: logger.error('no name specified!') return -1 else: self.project.dbs[new] = content return 1 def dbfiles(self): return list(self.project.dbs.keys()) def dbfilecontent(self, filename): return self.project.dbs.get(filename, '').strip() # /DB FUNCTIONS ##################################### # GENERAL FUNCTIONS ################################# def select_method(self, *args): self.set_outputfilename() self.settings_setdirty() def onchange_use_emln(self, dirty=True, *args): if not self.use_emln.get(): self.emln_label.grid_forget() self.emln_container.grid_forget() else: self.emln_label.grid(row=self.emlncontainerrow, column=0, sticky="NE") self.emln_container.grid(row=self.emlncontainerrow, column=1, sticky="NWES") if dirty: self.settings_setdirty() def onchange_cw(self, *args): if self.closed_world.get(): self.entry_cw.configure(state=DISABLED) else: self.entry_cw.configure(state=NORMAL) self.settings_setdirty() def reset_gui(self): self.set_config({}) self.db_container.clear() self.emln_container.clear() self.mln_container.clear() def set_config(self, newconf): self.config = newconf self.selected_grammar.set(ifnone(newconf.get('grammar'), 'PRACGrammar')) self.selected_logic.set(ifnone(newconf.get('logic'), 'FirstOrderLogic')) self.mln_container.selected_file.set(ifnone(newconf.get('mln'), '')) if self.use_emln.get(): self.emln_container.selected_file.set(ifnone(newconf.get('mln'), '')) self.db_container.selected_file.set(ifnone(newconf.get('db'), "")) self.selected_method.set(ifnone(newconf.get("method"), InferenceMethods.name('MCSAT'), transform=InferenceMethods.name)) self.multicore.set(ifnone(newconf.get('multicore'), 0)) self.profile.set(ifnone(newconf.get('profile'), 0)) self.params.set(ifnone(newconf.get('params'), '')) self.use_emln.set(ifnone(newconf.get('use_emln'), 0)) self.verbose.set(ifnone(newconf.get('verbose'), 1)) self.ignore_unknown_preds.set(ifnone(newconf.get('ignore_unknown_preds'), 0)) self.output_filename.set(ifnone(newconf.get('output_filename'), '')) self.cwPreds.set(ifnone(newconf.get('cw_preds'), '')) self.closed_world.set(ifnone(newconf.get('cw'), 0)) self.save.set(ifnone(newconf.get('save'), 0)) self.query.set(ifnone(newconf.get('queries'), '')) self.onchange_cw() def set_outputfilename(self): if not hasattr(self, "output_filename") or not hasattr(self, "db_filename") or not hasattr(self, "mln_filename"): return mln = self.mln_container.selected_file.get() db = self.db_container.selected_file.get() if "" in (mln, db): return if self.selected_method.get(): method = InferenceMethods.clazz(self.selected_method.get()) methodid = InferenceMethods.id(method) filename = config.query_output_filename(mln, methodid, db) self.output_filename.set(filename) def update_config(self): self.config = PRACMLNConfig() self.config["use_emln"] = self.use_emln.get() self.config['mln'] = self.mln_container.selected_file.get().strip().lstrip('*') self.config['emln'] = self.emln_container.selected_file.get().strip().lstrip('*') self.config["db"] = self.db_container.selected_file.get().strip().lstrip('*') self.config["method"] = InferenceMethods.id(self.selected_method.get().strip()) self.config["params"] = self.params.get().strip() self.config["queries"] = self.query.get() self.config["output_filename"] = self.output_filename.get().strip() self.config["cw"] = self.closed_world.get() self.config["cw_preds"] = self.cwPreds.get() self.config['profile'] = self.profile.get() self.config['logic'] = self.selected_logic.get() self.config['grammar'] = self.selected_grammar.get() self.config['multicore'] = self.multicore.get() self.config['save'] = self.save.get() self.config['ignore_unknown_preds'] = self.ignore_unknown_preds.get() self.config['verbose'] = self.verbose.get() self.config['window_loc'] = self.master.winfo_geometry() self.config['dir'] = self.dir self.project.queryconf = PRACMLNConfig() self.project.queryconf.update(self.config.config.copy()) def write_gconfig(self, savegeometry=True): self.gconf['prev_query_path'] = self.dir self.gconf['prev_query_project': self.dir] = self.project.name # save geometry if savegeometry: self.gconf['window_loc_query'] = self.master.geometry() self.gconf.dump() def infer(self, savegeometry=True, options={}, *args): mln_content = self.mln_container.editor.get("1.0", END).strip() db_content = self.db_container.editor.get("1.0", END).strip() # create conf from current gui settings self.update_config() # write gui settings self.write_gconfig(savegeometry=savegeometry) # hide gui self.master.withdraw() try: print((headline('PRACMLN QUERY TOOL'))) print() if options.get('mlnarg') is not None: mlnobj = MLN(mlnfile=os.path.abspath(options.get('mlnarg')), logic=self.config.get('logic', 'FirstOrderLogic'), grammar=self.config.get('grammar', 'PRACGrammar')) else: mlnobj = parse_mln(mln_content, searchpaths=[self.dir], projectpath=os.path.join(self.dir, self.project.name), logic=self.config.get('logic', 'FirstOrderLogic'), grammar=self.config.get('grammar', 'PRACGrammar')) if options.get('emlnarg') is not None: emln_content = mlnpath(options.get('emlnarg')).content else: emln_content = self.emln_container.editor.get("1.0", END).strip() if options.get('dbarg') is not None: dbobj = Database.load(mlnobj, dbfiles=[options.get('dbarg')], ignore_unknown_preds=self.config.get('ignore_unknown_preds', True)) else: out(self.config.get('ignore_unknown_preds', True)) dbobj = parse_db(mlnobj, db_content, ignore_unknown_preds=self.config.get('ignore_unknown_preds', True)) if options.get('queryarg') is not None: self.config["queries"] = options.get('queryarg') infer = MLNQuery(config=self.config, mln=mlnobj, db=dbobj, emln=emln_content) result = infer.run() # write to file if run from commandline, otherwise save result to project results if options.get('outputfile') is not None: output = io.StringIO() result.write(output) with open(os.path.abspath(options.get('outputfile')), 'w') as f: f.write(output.getvalue()) logger.info('saved result to {}'.format(os.path.abspath(options.get('outputfile')))) elif self.save.get(): output = io.StringIO() result.write(output) fname = self.output_filename.get() self.project.add_result(fname, output.getvalue()) self.project.save(dirpath=self.dir) logger.info('saved result to file results/{} in project {}'.format(fname, self.project.name)) else: logger.debug('No output file given - results have not been saved.') except: traceback.print_exc() # restore main window sys.stdout.flush() self.master.deiconify()
class TestItem: def __init__(self, master, title, x_coor, y_coor, serial=False, p_value_x_coor=365, p_value_width=500, result_x_coor=870, result_width=350, font_size=12, two_columns=False): self.__chb_var = IntVar() self.__p_value = StringVar() self.__result = StringVar() self.__p_value_02 = StringVar() self.__result_02 = StringVar() checkbox = Checkbutton(master, text=title, variable=self.__chb_var) checkbox.config(font=("Calibri", font_size)) checkbox.place(x=x_coor, y=y_coor) p_value_entry = Entry(master, textvariable=self.__p_value) p_value_entry.config(state=DISABLED) p_value_entry.place(x=p_value_x_coor, y=y_coor, width=p_value_width, height=25) result_entry = Entry(master, textvariable=self.__result) result_entry.config(state=DISABLED) result_entry.place(x=result_x_coor, y=y_coor, width=result_width, height=25) if serial and two_columns: p_value_entry_02 = Entry(master, textvariable=self.__p_value_02) p_value_entry_02.config(state=DISABLED) p_value_entry_02.place(x=875, y=y_coor, width=235, height=25) result_entry_02 = Entry(master, textvariable=self.__result_02) result_entry_02.config(state=DISABLED) result_entry_02.place(x=1115, y=y_coor, width=110, height=25) elif serial and not two_columns: p_value_entry_02 = Entry(master, textvariable=self.__p_value_02) p_value_entry_02.config(state=DISABLED) p_value_entry_02.place(x=365, y=y_coor + 25, width=500, height=25) result_entry_02 = Entry(master, textvariable=self.__result_02) result_entry_02.config(state=DISABLED) result_entry_02.place(x=870, y=y_coor + 25, width=350, height=25) def get_check_box_value(self): return self.__chb_var.get() def set_check_box_value(self, value): self.__chb_var.set(value) def set_p_value(self, value): self.__p_value.set(value) def set_result_value(self, value): self.__result.set(value) def set_p_value_02(self, value): self.__p_value_02.set(value) def set_result_value_02(self, value): self.__result_02.set(value) def set_values(self, values): self.__p_value.set(values[0]) self.__result.set(self.__get_result_string(values[1])) def set_p_2_values(self, values): self.__p_value_02(values[0]) self.__result_02(self.__get_result_string(values[1])) def reset(self): self.set_check_box_value(0) self.set_p_value('') self.set_result_value('') self.set_p_value_02('') self.set_result_value_02('') def __get_result_string(self, result): if result == True: return 'Random' else: return 'Non-Random'
class EditPlotManager: def __init__(self, controller: utils.ControllerType): self.controller = controller self.tab = None self.tk_format = utils.TkFormat(self.controller.config_info) self.exclude_specular = IntVar() self.edit_plot_dialog = None self.plot_samples_listbox = None self.i_entry = None self.e_entry = None self.az_entry = None self.new_plot_title_entry = None self.exclude_specular_check = None self.spec_tolerance_entry = None def show(self, tab: Tab, existing_sample_indices: List, sample_options: List, existing_geoms: Dict, current_title: str): self.tab = tab buttons = { "ok": { self.select_tab: [], # The lambda sends a list of the currently selected samples back to the tab along with the new title # and selected incidence/emission angles lambda: tab.set_samples( list( map(lambda y: sample_options[y], self.plot_samples_listbox.curselection())), self.new_plot_title_entry.get(), *self.check_angle_lists(self.i_entry.get(), self.e_entry.get(), self.az_entry.get()), self.exclude_specular.get(), self.spec_tolerance_entry.get(), ): [], } } self.edit_plot_dialog = Dialog(self.controller, "Edit Plot", "\nPlot title:", buttons=buttons) self.new_plot_title_entry = Entry( self.edit_plot_dialog.top, width=20, bd=self.tk_format.bd, bg=self.tk_format.entry_background, selectbackground=self.tk_format.selectbackground, selectforeground=self.tk_format.selectforeground, ) self.new_plot_title_entry.insert(0, current_title) self.new_plot_title_entry.pack() sample_label = Label( self.edit_plot_dialog.top, padx=self.tk_format.padx, pady=self.tk_format.pady, bg=self.tk_format.bg, fg=self.tk_format.textcolor, text="\nSamples:", ) sample_label.pack(pady=(0, 10)) self.plot_samples_listbox = utils.ScrollableListbox( self.edit_plot_dialog.top, self.tk_format.bg, self.tk_format.entry_background, self.tk_format.listboxhighlightcolor, selectmode=EXTENDED, ) geom_label = Label( self.edit_plot_dialog.top, padx=self.tk_format.padx, pady=self.tk_format.pady, bg=self.tk_format.bg, fg=self.tk_format.textcolor, text= "\nEnter incidence and emission angles to plot,\nor leave blank to plot all:\n", ) geom_label.pack() geom_frame = Frame(self.edit_plot_dialog.top) geom_frame.pack(padx=(20, 20), pady=(0, 10)) i_label = Label( geom_frame, padx=self.tk_format.padx, pady=self.tk_format.pady, bg=self.tk_format.bg, fg=self.tk_format.textcolor, text="i: ", ) i_label.pack(side=LEFT) self.i_entry = Entry( geom_frame, width=8, bd=self.tk_format.bd, bg=self.tk_format.entry_background, selectbackground=self.tk_format.selectbackground, selectforeground=self.tk_format.selectforeground, ) for i, incidence in enumerate(existing_geoms["i"]): if i == 0: self.i_entry.insert(0, str(incidence)) else: self.i_entry.insert("end", "," + str(incidence)) self.i_entry.pack(side=LEFT) e_label = Label( geom_frame, padx=self.tk_format.padx, pady=self.tk_format.pady, bg=self.tk_format.bg, fg=self.tk_format.textcolor, text=" e: ", ) e_label.pack(side=LEFT) self.e_entry = Entry( geom_frame, width=8, bd=self.tk_format.bd, bg=self.tk_format.entry_background, selectbackground=self.tk_format.selectbackground, selectforeground=self.tk_format.selectforeground, ) for i, emission in enumerate(existing_geoms["e"]): if i == 0: self.e_entry.insert(0, str(emission)) else: self.e_entry.insert("end", "," + str(emission)) self.e_entry.pack(side=LEFT) az_label = Label( geom_frame, padx=self.tk_format.padx, pady=self.tk_format.pady, bg=self.tk_format.bg, fg=self.tk_format.textcolor, text=" az: ", ) az_label.pack(side=LEFT) self.az_entry = Entry( geom_frame, width=8, bd=self.tk_format.bd, bg=self.tk_format.entry_background, selectbackground=self.tk_format.selectbackground, selectforeground=self.tk_format.selectforeground, ) for i, azimuth in enumerate(existing_geoms["az"]): if i == 0: self.az_entry.insert(0, str(azimuth)) else: self.az_entry.insert("end", "," + str(azimuth)) self.az_entry.pack(side=LEFT) exclude_specular_frame = Frame(self.edit_plot_dialog.top, bg=self.tk_format.bg, padx=self.tk_format.padx, pady=self.tk_format.pady) exclude_specular_frame.pack() self.exclude_specular_check = Checkbutton( exclude_specular_frame, selectcolor=self.tk_format.check_bg, fg=self.tk_format.textcolor, text=" Exclude specular angles (+/-", bg=self.tk_format.bg, pady=self.tk_format.pady, highlightthickness=0, variable=self.exclude_specular, ) self.exclude_specular_check.pack(side=LEFT) self.spec_tolerance_entry = Entry( exclude_specular_frame, width=4, bd=self.tk_format.bd, bg=self.tk_format.entry_background, selectbackground=self.tk_format.selectbackground, selectforeground=self.tk_format.selectforeground, ) self.spec_tolerance_entry.pack(side=LEFT) spec_tolerance_label = Label( exclude_specular_frame, padx=self.tk_format.padx, pady=self.tk_format.pady, bg=self.tk_format.bg, fg=self.tk_format.textcolor, text="\u00B0)", ) spec_tolerance_label.pack(side=LEFT) if tab.exclude_specular: self.exclude_specular_check.select() self.spec_tolerance_entry.insert(0, tab.specularity_tolerance) for option in sample_options: self.plot_samples_listbox.insert(END, option) for i in existing_sample_indices: self.plot_samples_listbox.select_set(i) self.plot_samples_listbox.config(height=8) def check_angle_lists(self, incidences: str, emissions: str, azimuths: str) -> Tuple[List, List, List]: def check_list(list_to_check: str) -> Tuple[List, List]: invalid_list = [] list_to_check = list_to_check.split(",") if "None" in list_to_check or "none" in list_to_check: while "None" in list_to_check: list_to_check.remove("None") while "none" in list_to_check: list_to_check.remove("none") list_to_check.append(None) if list_to_check == [""]: list_to_check = [] print(list_to_check) # If e.g. %5 is included in the list, include all angles where angle % 5 == 0 n = 0 while n < len(list_to_check): angle = list_to_check[n] if "%" in str(angle): try: val = int(str(angle).replace("%", "")) except ValueError: invalid_list.append(angle) continue for k in range(-70, 171): if k % val == 0: list_to_check.insert(n, k) n += 1 list_to_check.remove(angle) n -= 1 n += 1 for n, angle in enumerate(list_to_check): if angle is not None: try: list_to_check[n] = int(angle) except ValueError: invalid_list.append(angle) return list_to_check, invalid_list incidences, invalid_incidences = check_list(incidences) emissions, invalid_emissions = check_list(emissions) azimuths, invalid_azimuths = check_list(azimuths) if invalid_incidences != [] or invalid_emissions != [] or invalid_azimuths != []: error_string = "Warning! Not all angles entered are valid.\n" if invalid_incidences != []: error_string += "\nInvalid incidences: " + str( invalid_incidences) if invalid_emissions != []: error_string += "\nInvalid emissions: " + str( invalid_emissions) if invalid_azimuths != []: error_string += "\nInvalid azimuths: " + str(invalid_azimuths) ErrorDialog(self.controller, "Warning!", error_string) return incidences, emissions, azimuths def select_tab(self): self.controller.view_notebook.select(self.tab.top)
class ConcordanceSearchView(object): _BACKGROUND_COLOUR='#FFF' #white #Colour of highlighted results _HIGHLIGHT_WORD_COLOUR='#F00' #red _HIGHLIGHT_WORD_TAG='HL_WRD_TAG' _HIGHLIGHT_LABEL_COLOUR='#C0C0C0' # dark grey _HIGHLIGHT_LABEL_TAG='HL_LBL_TAG' #Percentage of text left of the scrollbar position _FRACTION_LEFT_TEXT=0.30 def __init__(self): self.queue = q.Queue() self.model = ConcordanceSearchModel(self.queue) self.top = Tk() self._init_top(self.top) self._init_menubar() self._init_widgets(self.top) self.load_corpus(self.model.DEFAULT_CORPUS) self.after = self.top.after(POLL_INTERVAL, self._poll) def _init_top(self, top): top.geometry('950x680+50+50') top.title('NLTK Concordance Search') top.bind('<Control-q>', self.destroy) top.protocol('WM_DELETE_WINDOW', self.destroy) top.minsize(950,680) def _init_widgets(self, parent): self.main_frame = Frame(parent, dict(background=self._BACKGROUND_COLOUR, padx=1, pady=1, border=1)) self._init_corpus_select(self.main_frame) self._init_query_box(self.main_frame) self._init_results_box(self.main_frame) self._init_paging(self.main_frame) self._init_status(self.main_frame) self.main_frame.pack(fill='both', expand=True) def _init_menubar(self): self._result_size = IntVar(self.top) self._cntx_bf_len = IntVar(self.top) self._cntx_af_len = IntVar(self.top) menubar = Menu(self.top) filemenu = Menu(menubar, tearoff=0, borderwidth=0) filemenu.add_command(label='Exit', underline=1, command=self.destroy, accelerator='Ctrl-q') menubar.add_cascade(label='File', underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) rescntmenu = Menu(editmenu, tearoff=0) rescntmenu.add_radiobutton(label='20', variable=self._result_size, underline=0, value=20, command=self.set_result_size) rescntmenu.add_radiobutton(label='50', variable=self._result_size, underline=0, value=50, command=self.set_result_size) rescntmenu.add_radiobutton(label='100', variable=self._result_size, underline=0, value=100, command=self.set_result_size) rescntmenu.invoke(1) editmenu.add_cascade(label='Result Count', underline=0, menu=rescntmenu) cntxmenu = Menu(editmenu, tearoff=0) cntxbfmenu = Menu(cntxmenu, tearoff=0) cntxbfmenu.add_radiobutton(label='60 characters', variable=self._cntx_bf_len, underline=0, value=60, command=self.set_cntx_bf_len) cntxbfmenu.add_radiobutton(label='80 characters', variable=self._cntx_bf_len, underline=0, value=80, command=self.set_cntx_bf_len) cntxbfmenu.add_radiobutton(label='100 characters', variable=self._cntx_bf_len, underline=0, value=100, command=self.set_cntx_bf_len) cntxbfmenu.invoke(1) cntxmenu.add_cascade(label='Before', underline=0, menu=cntxbfmenu) cntxafmenu = Menu(cntxmenu, tearoff=0) cntxafmenu.add_radiobutton(label='70 characters', variable=self._cntx_af_len, underline=0, value=70, command=self.set_cntx_af_len) cntxafmenu.add_radiobutton(label='90 characters', variable=self._cntx_af_len, underline=0, value=90, command=self.set_cntx_af_len) cntxafmenu.add_radiobutton(label='110 characters', variable=self._cntx_af_len, underline=0, value=110, command=self.set_cntx_af_len) cntxafmenu.invoke(1) cntxmenu.add_cascade(label='After', underline=0, menu=cntxafmenu) editmenu.add_cascade(label='Context', underline=0, menu=cntxmenu) menubar.add_cascade(label='Edit', underline=0, menu=editmenu) self.top.config(menu=menubar) def set_result_size(self, **kwargs): self.model.result_count = self._result_size.get() def set_cntx_af_len(self, **kwargs): self._char_after = self._cntx_af_len.get() def set_cntx_bf_len(self, **kwargs): self._char_before = self._cntx_bf_len.get() def _init_corpus_select(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) self.var = StringVar(innerframe) self.var.set(self.model.DEFAULT_CORPUS) Label(innerframe, justify=LEFT, text=' Corpus: ', background=self._BACKGROUND_COLOUR, padx = 2, pady = 1, border = 0).pack(side='left') other_corpora = list(self.model.CORPORA.keys()).remove(self.model.DEFAULT_CORPUS) om = OptionMenu(innerframe, self.var, self.model.DEFAULT_CORPUS, command=self.corpus_selected, *self.model.non_default_corpora()) om['borderwidth'] = 0 om['highlightthickness'] = 1 om.pack(side='left') innerframe.pack(side='top', fill='x', anchor='n') def _init_status(self, parent): self.status = Label(parent, justify=LEFT, relief=SUNKEN, background=self._BACKGROUND_COLOUR, border=0, padx = 1, pady = 0) self.status.pack(side='top', anchor='sw') def _init_query_box(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) another = Frame(innerframe, background=self._BACKGROUND_COLOUR) self.query_box = Entry(another, width=60) self.query_box.pack(side='left', fill='x', pady=25, anchor='center') self.search_button = Button(another, text='Search', command=self.search, borderwidth=1, highlightthickness=1) self.search_button.pack(side='left', fill='x', pady=25, anchor='center') self.query_box.bind('<KeyPress-Return>', self.search_enter_keypress_handler) another.pack() innerframe.pack(side='top', fill='x', anchor='n') def search_enter_keypress_handler(self, *event): self.search() def _init_results_box(self, parent): innerframe = Frame(parent) i1 = Frame(innerframe) i2 = Frame(innerframe) vscrollbar = Scrollbar(i1, borderwidth=1) hscrollbar = Scrollbar(i2, borderwidth=1, orient='horiz') self.results_box = Text(i1, font=tkinter.font.Font(family='courier', size='16'), state='disabled', borderwidth=1, yscrollcommand=vscrollbar.set, xscrollcommand=hscrollbar.set, wrap='none', width='40', height = '20', exportselection=1) self.results_box.pack(side='left', fill='both', expand=True) self.results_box.tag_config(self._HIGHLIGHT_WORD_TAG, foreground=self._HIGHLIGHT_WORD_COLOUR) self.results_box.tag_config(self._HIGHLIGHT_LABEL_TAG, foreground=self._HIGHLIGHT_LABEL_COLOUR) vscrollbar.pack(side='left', fill='y', anchor='e') vscrollbar.config(command=self.results_box.yview) hscrollbar.pack(side='left', fill='x', expand=True, anchor='w') hscrollbar.config(command=self.results_box.xview) #there is no other way of avoiding the overlap of scrollbars while using pack layout manager!!! Label(i2, text=' ', background=self._BACKGROUND_COLOUR).pack(side='left', anchor='e') i1.pack(side='top', fill='both', expand=True, anchor='n') i2.pack(side='bottom', fill='x', anchor='s') innerframe.pack(side='top', fill='both', expand=True) def _init_paging(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) self.prev = prev = Button(innerframe, text='Previous', command=self.previous, width='10', borderwidth=1, highlightthickness=1, state='disabled') prev.pack(side='left', anchor='center') self.next = next = Button(innerframe, text='Next', command=self.__next__, width='10', borderwidth=1, highlightthickness=1, state='disabled') next.pack(side='right', anchor='center') innerframe.pack(side='top', fill='y') self.current_page = 0 def previous(self): self.clear_results_box() self.freeze_editable() self.model.prev(self.current_page - 1) def __next__(self): self.clear_results_box() self.freeze_editable() self.model.next(self.current_page + 1) def about(self, *e): ABOUT = ("NLTK Concordance Search Demo\n") TITLE = 'About: NLTK Concordance Search Demo' try: from tkinter.messagebox import Message Message(message=ABOUT, title=TITLE, parent=self.main_frame).show() except: ShowText(self.top, TITLE, ABOUT) def _bind_event_handlers(self): self.top.bind(CORPUS_LOADED_EVENT, self.handle_corpus_loaded) self.top.bind(SEARCH_TERMINATED_EVENT, self.handle_search_terminated) self.top.bind(SEARCH_ERROR_EVENT, self.handle_search_error) self.top.bind(ERROR_LOADING_CORPUS_EVENT, self.handle_error_loading_corpus) def _poll(self): try: event = self.queue.get(block=False) except q.Empty: pass else: if event == CORPUS_LOADED_EVENT: self.handle_corpus_loaded(event) elif event == SEARCH_TERMINATED_EVENT: self.handle_search_terminated(event) elif event == SEARCH_ERROR_EVENT: self.handle_search_error(event) elif event == ERROR_LOADING_CORPUS_EVENT: self.handle_error_loading_corpus(event) self.after = self.top.after(POLL_INTERVAL, self._poll) def handle_error_loading_corpus(self, event): self.status['text'] = 'Error in loading ' + self.var.get() self.unfreeze_editable() self.clear_all() self.freeze_editable() def handle_corpus_loaded(self, event): self.status['text'] = self.var.get() + ' is loaded' self.unfreeze_editable() self.clear_all() self.query_box.focus_set() def handle_search_terminated(self, event): #todo: refactor the model such that it is less state sensitive results = self.model.get_results() self.write_results(results) self.status['text'] = '' if len(results) == 0: self.status['text'] = 'No results found for ' + self.model.query else: self.current_page = self.model.last_requested_page self.unfreeze_editable() self.results_box.xview_moveto(self._FRACTION_LEFT_TEXT) def handle_search_error(self, event): self.status['text'] = 'Error in query ' + self.model.query self.unfreeze_editable() def corpus_selected(self, *args): new_selection = self.var.get() self.load_corpus(new_selection) def load_corpus(self, selection): if self.model.selected_corpus != selection: self.status['text'] = 'Loading ' + selection + '...' self.freeze_editable() self.model.load_corpus(selection) def search(self): self.current_page = 0 self.clear_results_box() self.model.reset_results() query = self.query_box.get() if (len(query.strip()) == 0): return self.status['text'] = 'Searching for ' + query self.freeze_editable() self.model.search(query, self.current_page + 1, ) def write_results(self, results): self.results_box['state'] = 'normal' row = 1 for each in results: sent, pos1, pos2 = each[0].strip(), each[1], each[2] if len(sent) != 0: if (pos1 < self._char_before): sent, pos1, pos2 = self.pad(sent, pos1, pos2) sentence = sent[pos1-self._char_before:pos1+self._char_after] if not row == len(results): sentence += '\n' self.results_box.insert(str(row) + '.0', sentence) word_markers, label_markers = self.words_and_labels(sent, pos1, pos2) for marker in word_markers: self.results_box.tag_add(self._HIGHLIGHT_WORD_TAG, str(row) + '.' + str(marker[0]), str(row) + '.' + str(marker[1])) for marker in label_markers: self.results_box.tag_add(self._HIGHLIGHT_LABEL_TAG, str(row) + '.' + str(marker[0]), str(row) + '.' + str(marker[1])) row += 1 self.results_box['state'] = 'disabled' def words_and_labels(self, sentence, pos1, pos2): search_exp = sentence[pos1:pos2] words, labels = [], [] labeled_words = search_exp.split(' ') index = 0 for each in labeled_words: if each == '': index += 1 else: word, label = each.split('/') words.append((self._char_before + index, self._char_before + index + len(word))) index += len(word) + 1 labels.append((self._char_before + index, self._char_before + index + len(label))) index += len(label) index += 1 return words, labels def pad(self, sent, hstart, hend): if hstart >= self._char_before: return sent, hstart, hend d = self._char_before - hstart sent = ''.join([' '] * d) + sent return sent, hstart + d, hend + d def destroy(self, *e): if self.top is None: return self.top.after_cancel(self.after) self.top.destroy() self.top = None def clear_all(self): self.query_box.delete(0, END) self.model.reset_query() self.clear_results_box() def clear_results_box(self): self.results_box['state'] = 'normal' self.results_box.delete("1.0", END) self.results_box['state'] = 'disabled' def freeze_editable(self): self.query_box['state'] = 'disabled' self.search_button['state'] = 'disabled' self.prev['state'] = 'disabled' self.next['state'] = 'disabled' def unfreeze_editable(self): self.query_box['state'] = 'normal' self.search_button['state'] = 'normal' self.set_paging_button_states() def set_paging_button_states(self): if self.current_page == 0 or self.current_page == 1: self.prev['state'] = 'disabled' else: self.prev['state'] = 'normal' if self.model.has_more_pages(self.current_page): self.next['state'] = 'normal' else: self.next['state'] = 'disabled' def fire_event(self, event): #Firing an event so that rendering of widgets happen in the mainloop thread self.top.event_generate(event, when='tail') def mainloop(self, *args, **kwargs): if in_idle(): return self.top.mainloop(*args, **kwargs)
class Config: """Read/write and store all data from config files.""" def __init__(self, cmdLineParams, master=None): self.cmdLineParams = cmdLineParams self.master = master self.ai_path = '' # Path to FG_ROOT/AI directory. self.apt_path = '' # Path to FG_ROOT/Airports/apt.dat.gz file. self.metar_path = '' # Path to FG_ROOT/Airports/metar.dat.gz file. self.aircraft_dirs = [] # List of aircraft directories. # Dictionary whose keys are aircraft names. For each aircraft name 'n', # self.aircraftDict[n] is the list, in self.aircraft_dirs priority # order, of all Aircraft instances with that name. self.aircraftDict = {} self.aircraftList = [] # Sorted list of Aircraft instances. self.scenario_list = [] # List of selected scenarios. # List of all aircraft carriers found in AI scenario folder. # Each entry format is: # ["ship name", "parking position"... , "scenario name"] self.carrier_list = [] self.settings = [] # List of basic settings read from config file. self.text = '' # String to be shown in command line options window. # 'self.aircraftId' is the central variable telling which particular # aircraft is selected in FFGo's interface. It is a tuple of the form # (aircraftName, aircraftDir). self.aircraftId = misc.Observable() self.aircraft = StringVar() self.aircraftDir = StringVar() # Whenever 'self.aircraftId' is set, 'self.aircraft' and # 'self.aircraftDir' are automatically updated to reflect the new value # (and their observers called, even if the values didn't change). self.aircraftId.trace("w", self.updateAircraftNameAndDirFromAircraftId) # Note: the FFGo config file stores the values of 'self.aircraft' and # 'self.aircraftDir' separately (this makes the compatibility # path easy with versions that don't know about aircraftDir). self.airport = StringVar() # ICAO code of the selected airport self.alreadyProposedChanges = StringVar() self.apt_data_source = IntVar() self.auto_update_apt = IntVar() self.carrier = StringVar() # when non-empty, we are in “carrier mode” self.FG_aircraft = StringVar() self.FG_bin = StringVar() self.FG_root = StringVar() self.FG_scenery = StringVar() self.FG_working_dir = StringVar() self.MagneticField_bin = StringVar() self.MagneticField_bin.trace('w', self.updateMagFieldProvider) self.filteredAptList = IntVar() self.language = StringVar() self.park = StringVar() self.rwy = StringVar() self.scenario = StringVar() self.mainWindowGeometry = StringVar() self.saveWindowPosition = IntVar() self.baseFontSize = StringVar() self.TkDefaultFontSize = IntVar() # tkinter.BooleanVar feels kind of messy. Sometimes, it prints out as # 'True', other times as '1'... IntVar seems more predictable. self.showFGCommand = IntVar() self.showFGCommandInSeparateWindow = IntVar() self.FGCommandGeometry = StringVar() self.showFGOutput = IntVar() self.showFGOutputInSeparateWindow = IntVar() self.FGOutputGeometry = StringVar() self.autoscrollFGOutput = IntVar() # Option to translate --parkpos into --lat, --lon and --heading (useful # when --parkpos is broken in FlightGear) self.fakeParkposOption = IntVar() self.airportStatsManager = None # will be initialized later self.aircraftStatsManager = None # ditto self.airportStatsShowPeriod = IntVar() self.airportStatsExpiryPeriod = IntVar() self.aircraftStatsShowPeriod = IntVar() self.aircraftStatsExpiryPeriod = IntVar() self.keywords = {'--aircraft=': self.aircraft, '--airport=': self.airport, '--fg-root=': self.FG_root, '--fg-scenery=': self.FG_scenery, '--carrier=': self.carrier, '--parkpos=': self.park, '--runway=': self.rwy, 'AIRCRAFT_DIR=': self.aircraftDir, 'AI_SCENARIOS=': self.scenario, 'ALREADY_PROPOSED_CHANGES=': self.alreadyProposedChanges, 'APT_DATA_SOURCE=': self.apt_data_source, 'AUTO_UPDATE_APT=': self.auto_update_apt, 'FG_BIN=': self.FG_bin, 'FG_AIRCRAFT=': self.FG_aircraft, 'FG_WORKING_DIR=': self.FG_working_dir, 'MAGNETICFIELD_BIN=': self.MagneticField_bin, 'FILTER_APT_LIST=': self.filteredAptList, 'LANG=': self.language, 'WINDOW_GEOMETRY=': self.mainWindowGeometry, 'SAVE_WINDOW_POSITION=': self.saveWindowPosition, 'BASE_FONT_SIZE=': self.baseFontSize, 'SHOW_FG_COMMAND=': self.showFGCommand, 'SHOW_FG_COMMAND_IN_SEPARATE_WINDOW=': self.showFGCommandInSeparateWindow, 'FG_COMMAND_GEOMETRY=': self.FGCommandGeometry, 'SHOW_FG_OUTPUT=': self.showFGOutput, 'SHOW_FG_OUTPUT_IN_SEPARATE_WINDOW=': self.showFGOutputInSeparateWindow, 'FG_OUTPUT_GEOMETRY=': self.FGOutputGeometry, 'AUTOSCROLL_FG_OUTPUT=': self.autoscrollFGOutput, 'FAKE_PARKPOS_OPTION=': self.fakeParkposOption, 'AIRPORT_STATS_SHOW_PERIOD=': self.airportStatsShowPeriod, 'AIRPORT_STATS_EXPIRY_PERIOD=': self.airportStatsExpiryPeriod, 'AIRCRAFT_STATS_SHOW_PERIOD=': self.aircraftStatsShowPeriod, 'AIRCRAFT_STATS_EXPIRY_PERIOD=': self.aircraftStatsExpiryPeriod} # In order to avoid using a lot of memory, detailed airport data is # only loaded on demand. Since this is quite slow, keep a cache of the # last retrieved data. self.aptDatCache = collections.deque(maxlen=50) self._earlyTranslationsSetup() self._createUserDirectories() self._maybeMigrateFromFGoConfig() # Not having the FlightGear version at this point is not important # enough to justify pestering the user about it. :-) # Defer logging of the detected FG version to fit nicely with # the other startup messages. self.update(ignoreFGVersionError=True, logFGVersion=False) self.setTkDefaultFontSize() self.setupFonts(init=True) def setTkDefaultFontSize(self): """Save unaltered TkDefaultFont size.""" size = tkinter.font.nametofont("TkDefaultFont").actual()["size"] self.TkDefaultFontSize.set(size) def setupFonts(self, init=False): """Setup the default fonts. When called with init=True, custom fonts are created and stored as attributes of self. Otherwise, they are simply configured. """ # According to <http://www.tcl.tk/man/tcl8.4/TkCmd/font.htm>, font # sizes are interpreted this way: # - for positive values, the unit is points; # - for negative values, the unit is pixels; # - 0 is a special value for "a platform-dependent default size". # # Apparently, Tkinter doesn't accept floats for the 'size' parameter of # <font>.configure(), even when positive (tested with Python 2.7.3). baseSize = int(float(self.baseFontSize.get())) # Get the actual size when baseSize == 0, otherwise scaling won't work # since 0*factor == 0, regardless of the (finite) factor. if baseSize == 0: baseSize = self.TkDefaultFontSize.get() def scale(factor): return int(round(baseSize * factor)) def configFontSize(style, factor): font = tkinter.font.nametofont("Tk%sFont" % style) font.configure(size=scale(factor)) # Configure built-in fonts for style in ("Default", "Text", "Fixed", "Caption", "Tooltip"): # The 'if init:' here is a workaround for a weird problem: when # saving the settings from the Preferences dialog, even if the very # same font size is set here as the one that was used at program # initialization, the main window layout gets broken, with the # airport chooser Treeview taking more and more horizontal space # every time the settings are saved. Avoiding to reconfigure the # fonts in such "reinit" conditions works around the problem... if init: configFontSize(style, 1) for style, factor in (("Menu", 20 / 18.), ("Heading", 20 / 18.), ("SmallCaption", 16 / 18.), ("Icon", 14 / 18.)): if init: # Second part of the workaround mentioned above configFontSize(style, factor) # Create or configure custom fonts, depending on 'init' aboutTitleFontSize = scale(42 / 18.) if init: self.aboutTitleFont = tkinter.font.Font( family="Helvetica", weight="bold", size=aboutTitleFontSize) else: self.aboutTitleFont.configure(size=aboutTitleFontSize) # Final part of the workaround mentioned above. Normally, the code # should always be executed, regardless of the value of 'init'. if init: # For the ttk.Treeview widget treeviewHeadingFontSize = scale(1.) # Redundant test, right. Hopefully, one day, we'll be able to get # rid of the workaround and this test won't be redundant anymore. if init: self.treeviewHeadingFont = tkinter.font.Font( weight="normal", size=treeviewHeadingFontSize) else: self.treeviewHeadingFont.configure(size=treeviewHeadingFontSize) style = ttk.Style() style.configure("Treeview.Heading", font=self.treeviewHeadingFont) def makeInstalledAptList(self): logger.notice(_("Building the list of installed airports " "(this may take some time)...")) # writelines() used below doesn't automatically add line terminators airports = [ icao + '\n' for icao in self._findInstalledApt() ] logger.info("Opening '{}' for writing".format(INSTALLED_APT)) with open(INSTALLED_APT, "w", encoding="utf-8") as fout: fout.writelines(airports) def readMetarDat(self): """Fetch METAR station list from metar.dat.gz file""" logger.info("Opening '{}' for reading".format(self.metar_path)) res = [] with gzip.open(self.metar_path, mode='rt', encoding='utf-8') as fin: for line in fin: if not line.startswith('#'): res.append(line.strip()) return res def rebuildApt(self): """Rebuild apt file.""" self._makeAptDigest() def _computeAircraftDirList(self): FG_AIRCRAFT_env = os.getenv("FG_AIRCRAFT", "") if FG_AIRCRAFT_env: FG_AIRCRAFT_envList = FG_AIRCRAFT_env.split(os.pathsep) else: FG_AIRCRAFT_envList = [] # FG_ROOT/Aircraft defaultAircraftDir = os.path.join(self.FG_root.get(), DEFAULT_AIRCRAFT_DIR) aircraft_dirs = (self.FG_aircraft.get().split(os.pathsep) + FG_AIRCRAFT_envList + [defaultAircraftDir]) return aircraft_dirs def logDetectedFlightGearVersion(self, logLevel=LogLevel.notice, prefix=True): if self.FG_version is not None: FG_version = str(self.FG_version) else: FG_version = pgettext("FlightGear version", "none") # Uses the same string as in App.about() message = _("Detected FlightGear version: {ver}").format( ver=FG_version) logger.log(logLevel, prefix, message) def getFlightGearVersion(self, ignoreFGVersionError=False, log=False): # This import requires the translation system [_() function] to be in # place. from .fgdata import fgversion self.FG_version = None # in case an exception is raised below FG_bin = self.FG_bin.get() FG_root = self.FG_root.get() exc = None if FG_bin and FG_root: try: self.FG_version = fgversion.getFlightGearVersion( FG_bin, FG_root, self.FG_working_dir.get()) except fgversion.error as e: exc = e # may need to be raised later if log: self.logDetectedFlightGearVersion() if exc is not None and not ignoreFGVersionError: raise exc # This is a callback for FFGo's misc.Observable class. def updateAircraftNameAndDirFromAircraftId(self, aircraftId): aircraftName, aircraftDir = aircraftId self.aircraft.set(aircraftName) self.aircraftDir.set(aircraftDir) def aircraftWithNameAndDir(self, name, dir_): """Get the Aircraft instance for a given name and directory.""" try: aircrafts = self.aircraftDict[name] except KeyError: raise NoSuchAircraft(name, dir_) for aircraft in aircrafts: # The idea is that the directory 'dir_' passed here should have # been discovered earlier by a filesystem exploration, therefore # there must be one Aircraft instance that has an exact match for # both 'name' and 'dir_' (no need to use 'os.path.samefile()', # which would be slower, could raise errors...). if aircraft.dir == dir_: return aircraft else: raise NoSuchAircraft(name, dir_) def aircraftWithId(self, aircraftId): """Get the Aircraft instance for a given aircraft ID.""" return self.aircraftWithNameAndDir(*self.aircraftId.get()) def getCurrentAircraft(self): """Get the Aircraft instance for the currently-selected aircraft.""" return self.aircraftWithId(self.aircraftId.get()) def _findAircraft(self, acName, acDir): """Return an aircraft ID for 'acName' and 'acDir' if possible. If no aircraft is found with the given name and directory, fall back to: - an identically-named aircraft in a different directory (taking the first in FG_AIRCRAFT precedence order); - if this isn't possible either, fall back to the default aircraft. The returned aircraft ID will have an empty directory component if even the default aircraft isn't available in this case. Log an appropriate warning or notice when a fallback strategy is used. """ if acName in self.aircraftDict: for ac in self.aircraftDict[acName]: if ac.dir == acDir: aircraft = ac break else: aircraft = self.aircraftDict[acName][0] logger.notice( _("Could not find aircraft '{aircraft}' under '{dir}', " "taking it from '{fallback}' instead").format( aircraft=acName, dir=acDir, fallback=aircraft.dir)) else: try: defaultAircrafts = self.aircraftDict[DEFAULT_AIRCRAFT] except KeyError: aircraft = None logger.warning( _("Could not find the default aircraft: {aircraft}") .format(aircraft=DEFAULT_AIRCRAFT)) else: aircraft = defaultAircrafts[0] logger.notice( _("Could not find aircraft '{aircraft}', using " "'{fallback}' from '{dir}' instead").format( aircraft=acName, fallback=aircraft.name, dir=aircraft.dir)) if aircraft is None: return (DEFAULT_AIRCRAFT, '') else: return (aircraft.name, aircraft.dir) def sanityChecks(self): status, *rest = self.decodeParkingSetting(self.park.get()) if status == "invalid": logger.warning( _("Invalid syntax for the parking setting ({setting!r}), " "resetting it.").format(setting=self.park.get())) self.park.set('') if self.rwy.get() and self.park.get(): # Impossible to at the same time set a non-default runway and a # parking position. The latter wins. :-) self.rwy.set('') def update(self, path=None, ignoreFGVersionError=False, logFGVersion=True): """Read config file and update variables. path is a path to different than default config file """ if self.aircraftStatsManager is None: # application init # Requires the translation system to be in place from . import stats_manager self.aircraftStatsManager = \ stats_manager.AircraftStatsManager(self) else: # Save the in-memory statistics (from Aircraft instances) to # persistent storage. This expires old stats, according to # self.aircraftStatsExpiryPeriod. self.aircraftStatsManager.save() del self.settings del self.text del self.aircraft_dirs del self.apt_path del self.ai_path del self.metar_path del self.aircraftDict del self.aircraftList del self.scenario_list del self.carrier_list # The variable will be set again right after reading the config # file, therefore there is no need to run the callbacks now # (such as updating the aircraft image). self.aircraftId.set((DEFAULT_AIRCRAFT, ''), runCallbacks=False) self.airport.set(DEFAULT_AIRPORT) self.alreadyProposedChanges.set('') self.apt_data_source.set(1) self.auto_update_apt.set(1) self.carrier.set('') self.FG_aircraft.set('') self.FG_bin.set('') self.FG_root.set('') self.FG_scenery.set('') self.FG_working_dir.set('') self.MagneticField_bin.set('') self.language.set('') self.baseFontSize.set(DEFAULT_BASE_FONT_SIZE) self.mainWindowGeometry.set('') self.saveWindowPosition.set('1') self.showFGCommand.set('1') self.showFGCommandInSeparateWindow.set('0') self.FGCommandGeometry.set('') self.showFGOutput.set('1') self.showFGOutputInSeparateWindow.set('0') self.FGOutputGeometry.set('') self.autoscrollFGOutput.set('1') self.park.set('') self.fakeParkposOption.set('0') self.rwy.set('') self.scenario.set('') self.filteredAptList.set(0) self.airportStatsShowPeriod.set('365') # approx. one year self.airportStatsExpiryPeriod.set('3652') # approx. ten years self.aircraftStatsShowPeriod.set('365') self.aircraftStatsExpiryPeriod.set('3652') self.settings, self.text = self._read(path) for line in self.settings: cut = line.find('=') + 1 if cut: name = line[:cut] value = line[cut:] if value: if name in self.keywords: var = self.keywords[name] var.set(value) # Useful to know when the airport has been changed self.previousAirport = self.airport.get() self._setLanguage(self.language.get()) setupTranslationHelper(self) self.aircraft_dirs = self._computeAircraftDirList() self.apt_path = os.path.join(self.FG_root.get(), APT_DAT) self.ai_path = os.path.join(self.FG_root.get(), AI_DIR) self.metar_path = os.path.join(self.FG_root.get(), METAR_DAT) self.aircraftDict, self.aircraftList = self._readAircraft() # Load the saved statistics into the new in-memory Aircraft instances # (the set of aircrafts may have just changed, hence the need to save # the stats before the in-memory aircraft list is updated, and reload # them afterwards). self.aircraftStatsManager.load() # Choose a suitable aircraft, even if the one defined by # 'self.aircraft' and 'self.aircraftDir' isn't available. self.aircraftId.set(self._findAircraft(self.aircraft.get(), self.aircraftDir.get())) self.scenario_list, self.carrier_list = self._readScenarios() self.sanityChecks() self.getFlightGearVersion(ignoreFGVersionError=ignoreFGVersionError, log=logFGVersion) def write(self, text=None, path=None): """Write the configuration to a file. text -- content of text window processed by CondConfigParser (pass None to use the value of Config.text) path -- path to the file the config will be written to (the default config file is used if this argument is empty or None) """ if not path: path = CONFIG if text is None: text = self.text options = [] keys = list(self.keywords.keys()) keys.sort() for k in keys: v = self.keywords[k] if k in ('--carrier=', '--airport=', '--parkpos=', '--runway='): if v.get(): options.append(k + v.get()) else: options.append(k + str(v.get())) s = '\n'.join(options) logger.info("Opening config file for writing: '{}'".format(path)) with open(path, mode='w', encoding='utf-8') as config_out: config_out.write(s + '\n' + CUT_LINE + '\n') # Make sure the config file has exactly one newline at the end while text.endswith('\n\n'): text = text[:-1] if not text.endswith('\n'): text += '\n' config_out.write(text) def _findInstalledApt(self): """Walk thru all scenery and find installed airports. Take geographic coordinates from directories names and compare them with airports coordinates in apt file. The result is a sorted list of ICAO codes for matching airports. """ coord_dict = {} sceneries = self.FG_scenery.get().split(os.pathsep) for scenery in sceneries: path = os.path.join(scenery, 'Terrain') if os.path.exists(path): for dir in os.listdir(path): p = os.path.join(path, dir) for coords in os.listdir(p): d = os.path.join(p, coords) if not os.path.isdir(d): continue logger.debug("Exploring Terrain directory '{}' -> '{}'" .format(p, coords)) converted = self._stringToCoordinates(coords) if converted is not None: coord_dict[converted] = None else: logger.notice( _("Ignoring directory '{}' (unexpected name)") .format(d)) coords = coord_dict.keys() res = [] for icao in self.sortedIcao(): airport = self.airports[icao] for c in coords: if (c[0][0] < airport.lat < c[0][1] and c[1][0] < airport.lon < c[1][1]): res.append(icao) return res def _calculateRange(self, coordinates): c = coordinates if c.startswith('s') or c.startswith('w'): c = int(c[1:]) * (-1) return c, c + 1 else: c = int(c[1:]) return c, c + 1 def _createUserDirectories(self): """Create config, log and stats directories if they don't exist.""" for d in USER_DATA_DIR, LOG_DIR, STATS_DIR: os.makedirs(d, exist_ok=True) def _maybeMigrateFromFGoConfig_dialogs(self, parent): message = _("Initialize {prg}'s configuration from your existing " \ "FGo! configuration?").format(prg=PROGNAME) detail = (_("""\ You have no {cfgfile} file but you do have a {fgo_cfgfile} file, which normally belongs to FGo!. Except in rare circumstances (such as using braces or backslashes, or opening brackets at the beginning of a config line), a configuration file from FGo! 1.5.5 or earlier should be usable as is by {prg}.""") .replace('\n', ' ') + "\n\n" + _("""\ If {fgo_cfgfile} was written by FGo! 1.5.5 or earlier, you should probably say “Yes” here in order to initialize {prg}'s configuration based on your FGo! config file (precisely: copy {fgo_cfgfile} to {cfgfile}).""") .replace('\n', ' ') + "\n\n" + _("""\ If {fgo_cfgfile} was written by a version of FGo! that is greater than 1.5.5, it is advised to say “No” here.""") .replace('\n', ' ') ).format(prg=PROGNAME, cfgfile=CONFIG, fgo_cfgfile=FGO_CONFIG) if askyesno(PROGNAME, message, detail=detail, parent=parent): choice = "migrate from FGo!" else: message = _("Create a default {prg} configuration?").format( prg=PROGNAME) detail = _("""\ Choose “Yes” to create a basic {prg} configuration now. If you choose “No”, {prg} will exit and you'll have to create {cfgfile} yourself, or restart {prg} to see the same questions again.""") \ .replace('\n', ' ').format(prg=PROGNAME, cfgfile=CONFIG) if askyesno(PROGNAME, message, detail=detail, parent=parent): choice = "create default cfg" message = _("Creating a default {prg} configuration.").format( prg=PROGNAME) detail = (_("""\ It is suggested that you go to the Settings menu and choose Preferences to review your newly-created configuration.""") .replace('\n', ' ') + "\n\n" + _("""\ You can also reuse most, if not all FlightGear options you had in FGo!'s main text box (the “options window”). Just copy them to the corresponding {prg} text box.""") .replace('\n', ' ') + "\n\n" + _("""\ Note: you may run both FGo! and {prg} simultaneously, as their configurations are kept separate.""") .replace('\n', ' ') ).format(prg=PROGNAME) showinfo(PROGNAME, message, detail=detail, parent=parent) else: choice = "abort" return choice def _maybeMigrateFromFGoConfig(self): if os.path.isfile(FGO_CONFIG) and not os.path.isfile(CONFIG): baseSize = tkinter.font.nametofont("TkDefaultFont").actual()["size"] def configFontSize(val, absolute=False): for style in ("Default", "Text", "Fixed", "Caption", "Tooltip"): font = tkinter.font.nametofont("Tk{}Font".format(style)) if absolute: font.configure(size=val) else: font.configure(size=int(round(baseSize * val))) # Make sure most people can read the following dialogs (the # standard Tk size may be rather small): 140% increase configFontSize(1.4, absolute=False) choice = None # user choice in the to-be-displayed dialogs # It seems we need an otherwise useless Toplevel window in order to # center the Tk standard dialogs... t = tkinter.Toplevel() try: # Transparent if the OS supports it t.attributes('-alpha', '0.0') # Center the Toplevel. To be effective, this would probably # need a visit to the Tk event loop, however it is enough to # have the child dialogs centered, which is what matters here. self.master.eval('tk::PlaceWindow {} center'.format( t.winfo_pathname(t.winfo_id()))) choice = self._maybeMigrateFromFGoConfig_dialogs(t) finally: t.destroy() # Restore font size for later self.setupFonts() call configFontSize(baseSize, absolute=True) if choice in (None, "abort"): raise AbortConfig elif choice == "migrate from FGo!": # shutil.copy() and shutil.copy2() attempt to preserve the file's # permission mode, which is undesirable here → manual copy. with open(FGO_CONFIG, "r", encoding='utf-8') as fgoConfig, \ open(CONFIG, "w", encoding='utf-8') as config: config.write(fgoConfig.read()) else: assert choice == "create default cfg", repr(choice) def _makeAptDigest(self, head=None): """Build apt database from apt.dat.gz""" if self.FG_root.get(): _ProcessApt(self.master, self, self.apt_path, head) def _read(self, path=None): """Read the specified or a default configuration file. - If 'path' is None and CONFIG exists, load CONFIG; - if 'path' is None and CONFIG does not exist, load the configuration from the presets and default, localized config_ll resource; - otherwise, load configuration from the specified file. """ try: # ExitStack not strictly necessary here, but allows clean and # convenient handling of the various files or resources the # configuration may be loaded from. with contextlib.ExitStack() as stack: res = self._read0(stack, path) except OSError as e: message = _('Error loading configuration') showerror(_('{prg}').format(prg=PROGNAME), message, detail=str(e)) res = ([''], '') return res _presetsBlankLineOrCommentCre = re.compile(r"^[ \t]*(#|$)") def _read0(self, stack, path): # Data before the CUT_LINE in the config file, destined to # self.settings settings = [] # Data after the CUT_LINE in the config file, destined to # self.text and to be parsed by CondConfigParser condConfLines = [] if path is not None or (path is None and os.path.exists(CONFIG)): if path is None: path = CONFIG logger.info("Opening config file '{}' for reading".format(path)) configStream = stack.enter_context(open(path, "r", encoding="utf-8")) beforeCutLine = True else: # Use default config if no regular config exists. # Load presets if exists. if resourceExists(PRESETS): with textResourceStream(PRESETS) as presets: for line in presets: line = line.strip() if not self._presetsBlankLineOrCommentCre.match(line): settings.append(line) # Find the currently used language according to the environment. try: lang_code = gettext.translation( MESSAGES, LOCALE_DIR).info()['language'] except OSError: lang_code = 'en' if not resourceExists(DEFAULT_CONFIG_STEM + lang_code): lang_code = 'en' resPath = DEFAULT_CONFIG_STEM + lang_code configStream = stack.enter_context(textResourceStream(resPath)) # There is no "cut line" in the template config files. beforeCutLine = False for line in configStream: if beforeCutLine: line = line.strip() if line != CUT_LINE: if beforeCutLine: # Comments wouldn't be preserved on saving, therefore don't # try to handle them before the "cut line". if line: settings.append(line) else: condConfLines.append(line) else: beforeCutLine = False return (settings, ''.join(condConfLines)) def _readAircraft(self): """ Walk through Aircraft directories and return the available aircrafts. Return a tuple (aircraftDict, aircraftList) listing all aircrafts found via self.aircraft_dirs. aircraftDict is a dictionary whose keys are the names (derived from the -set.xml files) of all aircrafts. For each aircraft name 'n', aircraftDict[n] is the list, in self.aircraft_dirs priority order, of all Aircraft instances with that name. aircraftList is the sorted list of all Aircraft instances, suitable for quick building of the aircraft list in the GUI. """ aircraftDict = {} for dir_ in self.aircraft_dirs: if os.path.isdir(dir_): for d in os.listdir(dir_): self._readAircraftData(dir_, d, aircraftDict) aircraftList = [] # First sort by lowercased aircraft name sortFunc = lambda s: (s.lower(), s) for acName in sorted(aircraftDict.keys(), key=sortFunc): # Then sort by position in self.aircraft_dirs aircraftList.extend(aircraftDict[acName]) return (aircraftDict, aircraftList) def _readAircraftData(self, dir_, d, aircraftDict): path = os.path.join(dir_, d) if os.path.isdir(path): for f in os.listdir(path): self._appendAircraft(f, aircraftDict, path) def _appendAircraft(self, f, aircraftDict, path): if f.endswith('-set.xml'): # Dirty and ugly hack to prevent carrier-set.xml in # seahawk directory to be attached to the aircraft # list. if (not path.startswith('seahawk') and f != 'carrier-set.xml'): name = f[:-8] if name not in aircraftDict: aircraftDict[name] = [] aircraft = Aircraft(name, path) aircraftDict[name].append(aircraft) def sortedIcao(self): return sorted(self.airports.keys()) def _readApt(self): """Read the apt digest file (create a new one if none exists). Return a list of AirportStub instances. """ from .fgdata import apt_dat if not os.path.exists(APT): # Create a new file if self.FG_root is non-empty self._makeAptDigest() if not os.path.isfile(APT): # may happen if self.FG_root was empty self.aptDatSize, self.airports = 0, {} return [] for attempt in itertools.count(start=1): try: self.aptDatSize, self.airports = apt_dat.AptDatDigest.read(APT) except apt_dat.UnableToParseAptDigest: if attempt < 2: self._makeAptDigest() else: raise else: break if self.filteredAptList.get(): installedApt = self._readInstalledAptSet() res = [ self.airports[icao] for icao in self.sortedIcao() if icao in installedApt ] else: res = [ self.airports[icao] for icao in self.sortedIcao() ] return res def _readInstalledAptSet(self): """Read the set of locally installed airports from INSTALLED_APT. Create a new INSTALLED_APT file if none exists yet. Return a frozenset(), which offers very fast membership test compared to a list. """ if not os.path.exists(INSTALLED_APT): self.makeInstalledAptList() logger.info("Opening installed apt file '{}' for reading".format( INSTALLED_APT)) with open(INSTALLED_APT, "r", encoding="utf-8") as f: # Strip the newline char ending every line res = frozenset([ line[:-1] for line in f ]) return res def _readScenarios(self): """Walk through AI scenarios and read carrier data. Return two lists: scenarios: [scenario name, ...] carrier data: [[name, parkking pos, ..., scenario name], ...] Return two empty lists if no scenario is found. """ carriers = [] scenarios = [] if os.path.isdir(self.ai_path): for f in os.listdir(self.ai_path): path = os.path.join(self.ai_path, f) if os.path.isfile(path) and f.lower().endswith('.xml'): scenario_name = f[:-4] scenarios.append(scenario_name) # Appends to 'carriers' self._append_carrier_data(carriers, path, scenario_name) return sorted(scenarios), sorted(carriers) def _append_carrier_data(self, carriers, xmlFilePath, scenario_name): logger.info("Reading scenario data from '{}'".format(xmlFilePath)) root = self._get_root(xmlFilePath) scenario = root.find('scenario') if scenario is not None: for e in scenario.iterfind('entry'): typeElt = e.find('type') if typeElt is not None and typeElt.text == 'carrier': data = self._get_carrier_data(e, scenario_name) carriers.append(data) def _get_root(self, xmlFilePath): tree = ElementTree.parse(xmlFilePath) return tree.getroot() def _get_carrier_data(self, e, scenario_name): nameElt = e.find('name') if nameElt is not None: data = [nameElt.text] else: data = ['unnamed'] for child in e.iterfind('parking-pos'): parkingNameElt = child.find('name') if parkingNameElt is not None: data.append(parkingNameElt.text) data.append(scenario_name) return data # The '1' is the version number of this custom format for the contents of # Config.park, in case we need to change it. aptDatParkConfStart_cre = re.compile(r"::apt\.dat::1::(?P<nameLen>\d+),") aptDatParkConfEnd_cre = re.compile( r"""lat=(?P<lat>{floatRegexp}), lon=(?P<lon>{floatRegexp}), heading=(?P<heading>{floatRegexp})$""".format( floatRegexp=r"-?\d+(\.\d*)?"), re.VERBOSE) def decodeParkingSetting(self, parkConf): status = "invalid" # will be overridden if correct in the end parkName = None options = [] if not parkConf: status = "none" # no parking position else: mo = self.aptDatParkConfStart_cre.match(parkConf) if mo: # Length of the following parking name (after the comma) nameLen = int(mo.group("nameLen")) i = mo.end("nameLen") + 1 + nameLen if len(parkConf) > i and parkConf[i] == ";": mo2 = self.aptDatParkConfEnd_cre.match(parkConf[i+1:]) if mo2: parkName = parkConf[mo.end("nameLen")+1:i] options = ["--lat=" + mo2.group("lat"), "--lon=" + mo2.group("lon"), "--heading=" + mo2.group("heading")] status = "apt.dat" else: # plain parking name parkName = parkConf options = ["--parkpos=" + parkName] status = "groundnet" return (status, parkName, options) def _earlyTranslationsSetup(self): """Setup translations before the config file has been read. The language is determined from the environment (LANGUAGE, LC_ALL, LC_MESSAGES, and LANG—cf. gettext.translation() and gettext.find()). """ try: langCode = gettext.translation( MESSAGES, LOCALE_DIR).info()['language'] except OSError: langCode = 'en' self._setLanguage(langCode) def _setLanguage(self, lang): # Initialize provided language... try: L = gettext.translation(MESSAGES, LOCALE_DIR, languages=[lang]) L.install() # ...or fallback to system default. except Exception: gettext.install(MESSAGES, LOCALE_DIR) # Regexp for directory names such as w040n20 _geoDirCre = re.compile(r"[we]\d{3}[ns]\d{2}$") def _stringToCoordinates(self, coordinates): """Convert geo coordinates to decimal format.""" if not self._geoDirCre.match(coordinates): return None lat = coordinates[4:] lon = coordinates[:4] lat_range = self._calculateRange(lat) lon_range = self._calculateRange(lon) return lat_range, lon_range def _autoUpdateApt(self): if not self.auto_update_apt.get() or not os.path.exists(self.apt_path): return old_timestamp = self._readAptTimestamp() self._updateApt(old_timestamp) def _readAptTimestamp(self): if not os.path.exists(APT_TIMESTAMP): self._writeAptTimestamp('') logger.info("Opening apt timestamp file '{}' for reading".format( APT_TIMESTAMP)) with open(APT_TIMESTAMP, "r", encoding="utf-8") as timestamp: old_modtime = timestamp.read() return old_modtime def _writeAptTimestamp(self, s=None): if s is None: s = self._getAptModTime() logger.info("Opening apt timestamp file '{}' for writing".format( APT_TIMESTAMP)) with open(APT_TIMESTAMP, "w", encoding="utf-8") as timestamp: timestamp.write(s) def _getAptModTime(self): return str(os.path.getmtime(self.apt_path)) def _updateApt(self, old_timestamp): if old_timestamp != self._getAptModTime(): self._makeAptDigest(head=_('Modification of apt.dat.gz detected.')) # The new apt.dat may invalidate the current parking status, *rest = self.decodeParkingSetting(self.park.get()) if status == "apt.dat": # This was a parking position obtained from apt.dat; it may be # invalid with the new file, reset. self.park.set('') # This is also outdated with respect to the new apt.dat. self.aptDatCache.clear() # Accept any arguments to allow safe use as a Tkinter variable observer def updateMagFieldProvider(self, *args): from .geo.magfield import EarthMagneticField, MagVarUnavailable try: self.earthMagneticField = EarthMagneticField(self) except MagVarUnavailable as e: self.earthMagneticField = None self.earthMagneticFieldLastProblem = e.message from .fgdata import airport as airport_mod from .fgdata import parking as parking_mod from .gui import airport_finder as airport_finder_mod from .gui import gps_tool as gps_tool_mod for module in (airport_mod, parking_mod, airport_finder_mod, gps_tool_mod): module.setupEarthMagneticFieldProvider(self.earthMagneticField)
class App(tk.Frame): def __init__(self, master): #class variables self.blurb = StringVar() self.blurb.set('Preset 1') self.state = IntVar() self.state.set(1) self.preheat = IntVar() self.preheat.set(presets[preset_list[self.state.get()-1]][0]) self.soak = IntVar() self.soak.set(presets[preset_list[self.state.get()-1]][1]) self.peak_temp = IntVar() self.peak_temp.set(presets[preset_list[self.state.get()-1]][2]) self.peak_time = IntVar() self.peak_time.set(presets[preset_list[self.state.get()-1]][3]) self.liquid = IntVar() self.liquid.set(presets[preset_list[self.state.get()-1]][4]) self.saved = True #_____________________________________________________________________ # Window Configurations tk.Frame.__init__(self, master) self.master.protocol('WM_DELETE_WINDOW', self.click_exit) self.master.resizable(False, False) #self.master.tk_setPalette(background = '#2288d8') self.configure(background = background_color) x = (self.master.winfo_screenwidth()-self.master.winfo_reqwidth())/2 y = (self.master.winfo_screenheight()-self.master.winfo_reqheight())/5 self.master.geometry(f"+{int(x)}+{int(y)}") #self.master.config(menu= tk.Menu(self.master)) self.pack() self.master.title("Oven Controller") #_____________________________________________________________________ # Dialog Box my_dialog_frame = tk.Frame(self) my_dialog_frame.pack(padx = 50, pady = 50) tk.Label(my_dialog_frame, textvariable=self.blurb, font = ('Times',20), background = background_color).pack() #_____________________________________________________________________ # Buttons my_preset_frame = tk.Frame(self) my_preset_frame.pack(padx =15, pady = (0,15), anchor = 'e') tk.Button(my_preset_frame, text='Preset 1', font = ('Times',12), command = self.click_preset_1, background = background_color).pack(side = 'left') tk.Button(my_preset_frame, text='Preset 2', font = ('Times',12), command = self.click_preset_2, background = background_color).pack(side = 'left') tk.Button(my_preset_frame, text='Preset 3', font = ('Times',12), command = self.click_preset_3, background = background_color).pack(side = 'left') tk.Button(my_preset_frame, text='Reheat Pizza', font = ('Times',12), command = self.click_preset_4, background = background_color).pack(side = 'left') #_____________________________________________________________________ # Entry Box my_entry_frame = tk.Frame(self) my_entry_frame.configure(background = background_color) my_entry_frame.pack(padx = 60, pady = 30) tk.Label(my_entry_frame, text = 'Preheat Temperature', font = ('',12), background = background_color).pack() tk.Entry(my_entry_frame, textvariable = self.preheat, font = ('',12), background = entry_color).pack() tk.Label(my_entry_frame, text = 'Soak Time', font = ('',12), background = background_color).pack() tk.Entry(my_entry_frame, textvariable = self.soak, font = ('',12), background = entry_color).pack() tk.Label(my_entry_frame, text = 'Peak Temperature', font = ('',12), background = background_color).pack() tk.Entry(my_entry_frame, textvariable = self.peak_temp, font = ('',12), background = entry_color).pack() tk.Label(my_entry_frame, text = 'Peak Time', font = ('',12), background = background_color).pack() tk.Entry(my_entry_frame, textvariable = self.peak_time, font = ('',12), background = entry_color).pack() tk.Label(my_entry_frame, text = 'Liquid Temperature', font = ('',12), background = background_color).pack() tk.Entry(my_entry_frame, textvariable = self.liquid, font = ('',12), background = entry_color).pack() #_____________________________________________________________________ # Other buttons my_button_frame = tk.Frame(self) my_button_frame.pack(padx = 50, pady = 30) my_button_frame.configure(background = background_color) tk.Button(my_button_frame, text = 'Exit', command = self.click_exit, font = ('',12), background = background_color).pack(side = 'right') tk.Button(my_button_frame, text = 'Save', command = self.click_save, font = ('',12), background = background_color).pack(side = 'right') tk.Button(my_button_frame, text = 'Update', command = self.click_update, font = ('',12), background = background_color).pack(side = 'right') #tk.Button(my_button_frame, text = 'test button', command = self.popup).pack() my_flash_frame = tk.Frame(self) my_flash_frame.pack(padx = 50, pady = 30) my_flash_frame.configure(background = background_color) tk.Button(my_flash_frame, text = 'Send', command = self.send_data, font = ('',12), background = background_color).pack(side = 'right') tk.Button(my_flash_frame, text = 'Reflow', command = self.start_reflow, font = ('',12), background = background_color).pack(side = 'right') #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #class methods def set_all(self): self.preheat.set(presets[preset_list[self.state.get()-1]][0]) self.soak.set(presets[preset_list[self.state.get()-1]][1]) self.peak_temp.set(presets[preset_list[self.state.get()-1]][2]) self.peak_time.set(presets[preset_list[self.state.get()-1]][3]) self.liquid.set(presets[preset_list[self.state.get()-1]][4]) def click_preset_1(self): self.blurb.set('Preset 1') self.state.set(1) self.set_all() def click_preset_2(self): self.blurb.set('Preset 2') self.state.set(2) self.set_all() def click_preset_3(self): self.blurb.set('Preset 3') self.state.set(3) self.set_all() def click_preset_4(self): self.blurb.set('Reheat Pizza') self.state.set(4) self.set_all() def click_exit(self): if self.saved == False: self.popup() else: self.user_exit() def click_save(self): self.click_update() Save_Presets() self.saved = True def user_exit(self): print('user has exited') self.master.destroy() def click_update(self): presets[preset_list[self.state.get()-1]][0] = self.preheat.get() presets[preset_list[self.state.get()-1]][1] = self.soak.get() presets[preset_list[self.state.get()-1]][2] = self.peak_temp.get() presets[preset_list[self.state.get()-1]][3] = self.peak_time.get() presets[preset_list[self.state.get()-1]][4] = self.liquid.get() self.saved = False def save_and_exit(self): self.click_save() self.click_exit() def start_reflow(self): global ser data_out = bytearray([63]) print(data_out) if(just_demo_menu == False): ser.write(data_out) else: print("Just Demo Menu, No actual Output") self.user_exit() def send_data(self): global ser self.click_save() data_out = bytearray([77]+presets[preset_list[self.state.get()-1]]) print(data_out) if(just_demo_menu == False): ser.write(data_out) else: print("Just Demo Menu, No actual Output") def popup(self): toplevel = tk.Toplevel() xx = 880 yy = 420 toplevel.geometry(f"+{int(xx)}+{int(yy)}") toplevel.configure(background = grey_color) new_label = tk.Label(toplevel, text = 'Warning, you have not saved \n Would you like to save?', font = ('',15), background = grey_color) new_label.pack(pady = [10,0]) save_button = tk.Button(toplevel, text = 'Save', font = ('',12), background = grey_color, command = self.save_and_exit) save_button.pack(padx = [70,0], pady = 10, side = 'left') exit_button = tk.Button(toplevel, text = 'Exit', font = ('',12), background = grey_color, command = self.user_exit) exit_button.pack(side = 'left') cancel_button = tk.Button(toplevel, text = 'Cancel', font = ('',12), background = grey_color, command = toplevel.destroy) cancel_button.pack(side = 'left')
class TreeView(object): def __init__(self, *trees): from math import sqrt, ceil self._trees = trees self._top = Tk() self._top.title('NLTK') self._top.bind('<Control-x>', self.destroy) self._top.bind('<Control-q>', self.destroy) cf = self._cframe = CanvasFrame(self._top) self._top.bind('<Control-p>', self._cframe.print_to_file) # Size is variable. self._size = IntVar(self._top) self._size.set(12) bold = ('helvetica', -self._size.get(), 'bold') helv = ('helvetica', -self._size.get()) # Lay the trees out in a square. self._width = int(ceil(sqrt(len(trees)))) self._widgets = [] for i in range(len(trees)): widget = TreeWidget(cf.canvas(), trees[i], node_font=bold, leaf_color='#008040', node_color='#004080', roof_color='#004040', roof_fill='white', line_color='#004040', draggable=1, leaf_font=helv) widget.bind_click_trees(widget.toggle_collapsed) self._widgets.append(widget) cf.add_widget(widget, 0, 0) self._layout() self._cframe.pack(expand=1, fill='both') self._init_menubar() def _layout(self): i = x = y = ymax = 0 width = self._width for i in range(len(self._widgets)): widget = self._widgets[i] (oldx, oldy) = widget.bbox()[:2] if i % width == 0: y = ymax x = 0 widget.move(x-oldx, y-oldy) x = widget.bbox()[2] + 10 ymax = max(ymax, widget.bbox()[3] + 10) def _init_menubar(self): menubar = Menu(self._top) filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label='Print to Postscript', underline=0, command=self._cframe.print_to_file, accelerator='Ctrl-p') filemenu.add_command(label='Exit', underline=1, command=self.destroy, accelerator='Ctrl-x') menubar.add_cascade(label='File', underline=0, menu=filemenu) zoommenu = Menu(menubar, tearoff=0) zoommenu.add_radiobutton(label='Tiny', variable=self._size, underline=0, value=10, command=self.resize) zoommenu.add_radiobutton(label='Small', variable=self._size, underline=0, value=12, command=self.resize) zoommenu.add_radiobutton(label='Medium', variable=self._size, underline=0, value=14, command=self.resize) zoommenu.add_radiobutton(label='Large', variable=self._size, underline=0, value=28, command=self.resize) zoommenu.add_radiobutton(label='Huge', variable=self._size, underline=0, value=50, command=self.resize) menubar.add_cascade(label='Zoom', underline=0, menu=zoommenu) self._top.config(menu=menubar) def resize(self, *e): bold = ('helvetica', -self._size.get(), 'bold') helv = ('helvetica', -self._size.get()) xspace = self._size.get() yspace = self._size.get() for widget in self._widgets: widget['node_font'] = bold widget['leaf_font'] = helv widget['xspace'] = xspace widget['yspace'] = yspace if self._size.get() < 20: widget['line_width'] = 1 elif self._size.get() < 30: widget['line_width'] = 2 else: widget['line_width'] = 3 self._layout() def destroy(self, *e): if self._top is None: return self._top.destroy() self._top = None def mainloop(self, *args, **kwargs): """ Enter the Tkinter mainloop. This function must be called if this demo is created from a non-interactive program (e.g. from a secript); otherwise, the demo will close as soon as the script completes. """ if in_idle(): return self._top.mainloop(*args, **kwargs)
class Controlador: def setVista(self, vista): """ Define la vista que será controlada """ self.vista = vista self.recurso = None def cargarurl(self): """ Método encargado de llamar al método cargarInfo en un hilo distinto """ self.vista.button.config(state=DISABLED) self.vista.bvideo.config(state=DISABLED) self.vista.baudio.config(state=DISABLED) self.vista.bborrar.config(state=DISABLED) if platform.system() == 'Windows': self.vista.config(cursor="wait") if "facebook" in self.vista.url.get(): self.t = threading.Thread(target=self.cargarFB) self.t.start() else: try: self.recursoPL = pafy.get_playlist(self.vista.url.get()) self.t = threading.Thread(target=self.cargarPlayList) self.t.start() except ValueError as e: try: self.recurso = pafy.new(self.vista.url.get()) self.t = threading.Thread(target=self.cargarInfo) self.t.start() except ValueError as e: mensaje = "La url es inválida o no se encuentra conectado " mensaje += "a internet, intentelo nuevamente." msg.showerror("Error", mensaje) self.vista.button.config(state=NORMAL) self.vista.bvideo.config(state=NORMAL) self.vista.baudio.config(state=NORMAL) self.vista.bborrar.config(state=NORMAL) self.vista.config(cursor="") def cargarInfo(self): self.vista.notebook.select(self.vista.tab1) """ Método encargado de obtener información dela url ingresada """ info = "" info += "■Título: " + self.recurso.title+"\n" info += "■Duración: " + self.recurso.duration+"\n" info += "■Autor: " + self.recurso.author+"\n" try: info += "■Categoría: " + self.recurso.category+"\n" except: info += "■Categoría: No disponible\n" pass info += "■Likes: " + str(self.recurso.likes)+"\n" info += "■Dislikes: " + str(self.recurso.dislikes)+"\n" mejor = self.recurso.getbest() info += "■Mejor resolución: " + mejor.resolution+"\n" info += "■Mejor formato: " + mejor.extension if self.recurso.bigthumb != '': response = requests.get(self.recurso.bigthumb) img_data = response.content img = ImageTk.PhotoImage(opp(BytesIO(img_data))) self.vista.imagen.config(text="", image=img) self.vista.imagen.image = img self.vista.text.config(state=NORMAL) self.vista.text.delete(1.0, END) self.vista.text.insert(INSERT, info) self.vista.text.config(state=DISABLED) self.cargarLista() self.vista.button.config(state=NORMAL) self.vista.bvideo.config(state=NORMAL) self.vista.baudio.config(state=NORMAL) self.vista.bborrar.config(state=NORMAL) self.vista.config(cursor="") def cargarLista(self): """ Método encargado de obtener los formatos disponibles del video que se busca """ self.streams = self.recurso.streams self.vista.listbox.delete(0, END) i = 0 texto_a_insertar = "{}) Resolución: {}, Extensión: {}, Tamaño: {}" for s in self.streams: i += 1 tamanio = str("%.2f MB." % (s.get_filesize()/(1024**2))) self.vista.listbox.insert(END, texto_a_insertar.format( i, s.resolution, s.extension, tamanio)) def descargaVideo(self): """ Método encargado de llamar al método __descargaVideo, según lo seleccionado por el usuario además que se ejecuta en un hilo distinto """ index = self.vista.listbox.curselection() if len(index) > 0: self.seleccion = self.streams[index[0]] self.size = self.seleccion.get_filesize() self.mostrarDialogo() t = threading.Thread(target=self.__descargarVideo) t.start() self.vista.button.config(state=DISABLED) self.vista.bvideo.config(state=DISABLED) self.vista.baudio.config(state=DISABLED) self.vista.bborrar.config(state=DISABLED) else: msg.showerror("Error", "Se debe seleccionar un video de la lista.") def __descargarVideo(self): """ Método que descarga el video seleccionado y muestra la carga """ self.d = True try: file = self.seleccion.download( quiet=True, filepath=self.vista.path.get(), callback=self.callback) except Exception as e: raise e msg.showerror("Error", "El archivo ya existe.") self.top.destroy() self.d = False msg.showinfo("Mensaje", "Archivo descargado correctamente") self.vista.text.config(state=NORMAL) self.vista.text.delete(1.0, END) self.vista.text.config(state=DISABLED) self.vista.listbox.delete(0, END) self.vista.url.set("") self.vista.imagen.config(text="No disponible", image='') self.vista.imagen.image = '' self.vista.button.config(state=NORMAL) self.vista.bvideo.config(state=NORMAL) self.vista.baudio.config(state=NORMAL) self.vista.bborrar.config(state=NORMAL) self.vista.config(cursor="") def descargaAudio(self): """ Método encargado de llamar al método __descargaAudio, que descarga la mejor resolución de audio, además que se ejecuta en un hilo distinto """ if self.recurso != None: t = threading.Thread(target=self.__descargaAudio) t.start() self.vista.button.config(state=DISABLED) self.vista.bvideo.config(state=DISABLED) self.vista.baudio.config(state=DISABLED) self.vista.bborrar.config(state=DISABLED) self.mostrarDialogo() def __descargaAudio(self): """ Método que descarga el video seleccionado y muestra la carga """ self.bestaudio = self.recurso.getbestaudio(preftype='m4a') if self.bestaudio != None: self.d = True self.fileaudio = self.bestaudio.title+".m4a" self.size = self.bestaudio.get_filesize() try: self.bestaudio.download( quiet=True, callback=self.callback, filepath=self.vista.path.get()) msg.showinfo("Mensaje", "Archivo descargado correctamente.") except Exception as e: msg.showerror("Error", "El archivo ya existe.") self.top.destroy() self.d = False self.vista.text.config(state=NORMAL) self.vista.text.delete(1.0, END) self.vista.text.config(state=DISABLED) self.vista.listbox.delete(0, END) self.vista.url.set("") self.vista.imagen.config(text="No disponible", image='') self.vista.imagen.image = '' self.vista.button.config(state=NORMAL) self.vista.bvideo.config(state=NORMAL) self.vista.baudio.config(state=NORMAL) self.vista.bborrar.config(state=NORMAL) self.vista.config(cursor="") def mostrarDialogo(self): """ Método que muestra la GUI de descarga del archivo """ self.top = Toplevel(self.vista) self.top.resizable(0, 0) geometry = "400x250+" geometry += str(int(self.vista.ancho/2)-150)+"+" geometry += str(int(self.vista.alto/2)-50) self.top.geometry(geometry) self.top.title("Descarga en progreso...") self.top.iconbitmap('descarga.ico') self.progress = IntVar() self.progress.set(0) self.progressbar = ttk.Progressbar(self.top, variable=self.progress) self.label = ttk.Label(self.top, text="Descargando: ", font=("Arial", 14)) self.label.place(x=5, y=15) self.label2 = ttk.Label(self.top, text="Tiempo restante: ", font=("Arial", 14)) self.label2.place(x=5, y=65) self.label3 = ttk.Label(self.top, text="Velocidad: ", font=("Arial", 14)) self.label3.place(x=5, y=115) self.progressbar.place(x=30, y=160, width=320) if platform.system() == 'Windows': self.vista.config(cursor="wait") self.bcancelar = ttk.Button(self.top, text="cancelar", command=self.cancelar) self.bcancelar.place(x=150,y=200) self.top.transient(self.vista) self.top.config(bg="#4C4C4D") def iniciar(self): """ Método que muestra la GUI """ self.vista.mainloop() def cancelar(self): pass def borrarurl(self): """ Método borra la url ingresada """ self.vista.url.set("") def callback(self, total, recvd, ratio, rate, eta): """ Método que controla la descarga del archivo """ carga = int(ratio*100) self.progressbar.step(carga - self.progress.get()) self.progress.set(carga) self.label.config(text="Descarga: "+str(carga)+" %") self.label2.config(text="Tiempo restante: "+str("%.0f" % (eta))+" segundos") self.label3.config(text="Velocidad: "+str("%.2f" % (rate/1024))+" Mb/s") def cambiaPath(self): """ Método para cambiar la carpeta destino """ path = filedialog.askdirectory() if path != None and path != '': self.vista.path.set(path) def copia(self, event): """ Método que pega la url del portapapeles """ self.vista.url.set(self.vista.clipboard_get()) def cargarPlayList(self): self.vista.notebook.select(self.vista.tabPL) self.disponibles = self.recursoPL['items'] self.vista.listPL.delete(0, END) i = 0 texto_a_insertar = "{}) Título: {}, Duración: {}" for s in self.disponibles: i += 1 insertar = texto_a_insertar.format(i, s['pafy'].title[:40]+"...", s['pafy'].duration) try: self.vista.listPL.insert(END,insertar) except TclError as e: pass self.vista.button.config(state=NORMAL) self.vista.bvideo.config(state=NORMAL) self.vista.baudio.config(state=NORMAL) self.vista.bborrar.config(state=NORMAL) self.vista.config(cursor="") def cargarInfoDesdePL(self): index = self.vista.listPL.curselection() if len(index) > 0: if platform.system() == 'Windows': self.vista.config(cursor="wait") self.recurso = self.recursoPL['items'][index[0]]['pafy'] self.vista.button.config(state=DISABLED) self.vista.bvideo.config(state=DISABLED) self.vista.baudio.config(state=DISABLED) self.vista.bborrar.config(state=DISABLED) self.t = threading.Thread(target=self.cargarInfo) self.t.start() else: msg.showerror("Error", "Se debe seleccionar un video de la lista.") def cargarFB(self): try: rpta = msg.askyesno("Pregunta", "No se puede obtener información "+ "de un video de facebook, desea continuar con la descarga?") if rpta: path = filedialog.asksaveasfilename() os.popen("facebook-dl.py {} hd {}".format(self.vista.url.get(),path)) msg.showinfo("Mensaje", "Archivo descargado correctamente.") except: msg.showerror("Error", "El video no es público, o la url es inválida.") self.vista.button.config(state=NORMAL) self.vista.bvideo.config(state=NORMAL) self.vista.baudio.config(state=NORMAL) self.vista.bborrar.config(state=NORMAL) self.vista.config(cursor="")
class MainUI: __PLATFORM = ['IOS', 'ANDROID'] __rootList = [] def __init__(self): self.__rootList = [] def initUI(self): self.frame = tkinter.Tk() self.frame.geometry('600x600') # 是x 不是* self.frame.resizable(width=True, height=True) # 宽不可变, 高可变,默认为True self.frame.minsize(700, 600) self.frame.title('工具集') '''工作目录''' panel1 = ttk.Labelframe(self.frame, text='工作目录') # 打包路径label packRootLabel = ttk.Label(panel1, text='打包路径:') packRootLabel.grid(row=0, column=0, padx=3, pady=3) # root下拉菜单 self.packRootPathVar = StringVar() self.packRootPathVar.trace('w', self.__packRootPathChangeCallBack) self.packRootPath = ttk.Combobox(panel1, textvariable=self.packRootPathVar) self.packRootPath.grid(row=0, column=1, padx=3, pady=3, stick='we') # root路径选择按钮 packRootSelBtn = ttk.Button(panel1, text='选择', command=self.selectRootDir) packRootSelBtn.grid(row=0, column=2, padx=3, pady=3) panel1.columnconfigure(1, weight=1) panel1.pack(fill='x', side=TOP, padx=5, pady=5, ipadx=10, ipady=5) '''打包设置''' panel2 = ttk.LabelFrame(self.frame, text='打包设置') childRow1 = ttk.Frame(panel2) # 资源目录label srcPathLabel = ttk.Label(childRow1, text='资源目录:') srcPathLabel.grid(row=0, column=0, padx=3, pady=3) # 资源目录路径 self.srcPathVar = StringVar() self.srcPathVar.trace('w', callback=self.__platformChangeCallBack) srcPath = ttk.Entry(childRow1, textvariable=self.srcPathVar) srcPath.grid(row=0, column=1, padx=3, pady=3, stick='we') # 资源目录路径选择按钮 srcPathBtn = ttk.Button(childRow1, text='选择', command=self.selectSrcDir) srcPathBtn.grid(row=0, column=2, padx=3, pady=3) childRow1.columnconfigure(1, weight=1) childRow1.pack(fill='x', side=TOP) childRow2 = ttk.Frame(panel2) # 平台类型 self.platformComboVar = StringVar() platformCombo = ttk.Combobox(childRow2, values=self.__PLATFORM, state='readonly', width=10, textvariable=self.platformComboVar) platformCombo.current(0) platformCombo.grid(row=0, column=1, padx=3, pady=3) # 是否全新打包 self.isNew = IntVar() isNewCheck = ttk.Checkbutton(childRow2, text='全新打包', variable=self.isNew) isNewCheck.grid(row=0, column=3, padx=3, pady=3) # 是否整包 self.isFull = IntVar() isFullCheck = ttk.Checkbutton(childRow2, text='整包', variable=self.isFull) isFullCheck.grid(row=0, column=4, padx=3, pady=3) childRow2.columnconfigure(5, weight=1) childRow2.pack(fill='x', side=TOP) panel2.pack(fill='x', side=TOP, padx=5, pady=5, ipadx=10, ipady=5) # 开始按钮 startBtn = ttk.Button(self.frame, text='开始打包', command=self.startPack) startBtn.pack() '''输出步骤''' panel3 = ttk.LabelFrame(self.frame, text='总览') headTextBar = ttk.Scrollbar(panel3, orient=VERTICAL) headTextBar.pack(side=RIGHT, fill='y') self.headConsole = Text(panel3, state='disabled', yscrollcommand=headTextBar.set, width=40, foreground='white', background='black') self.headConsole.pack(expand=1, fill=BOTH) panel3.pack(fill='y', side=LEFT, padx=5, pady=5, ipadx=10, ipady=5) '''输出详细信息''' panel4 = ttk.LabelFrame(self.frame, text='详细信息') bottomTextBar = ttk.Scrollbar(panel4, orient=VERTICAL) bottomTextBar.pack(side=RIGHT, fill='y') self.bottomConsole = Text(panel4, state='disabled', yscrollcommand=bottomTextBar.set, foreground='white', background='black') self.bottomConsole.pack(expand=1, fill=BOTH) panel4.pack(expand=1, fill=BOTH, side=LEFT, padx=5, pady=5, ipadx=10, ipady=5) self.frame.after(50, func=self.updateLog) def initUIValues(self): RootInfoMgr.load() self.__rootList = RootInfoMgr.rootPathList self.updateRootList() def show(self): self.frame.mainloop() def updateLog(self): self.headConsole.configure(state='normal') while not Log.infoQueue.empty() : text = Log.infoQueue.get(True, 1) self.headConsole.insert('end', text) self.headConsole.configure(state='disabled') self.bottomConsole.configure(state='normal') while not Log.detailQueue.empty() : text = Log.detailQueue.get(True, 1) self.bottomConsole.insert('end', text) self.bottomConsole.configure(state='disabled') self.frame.after(50, func=self.updateLog) def selectRootDir(self): rootdir = askdirectory() if len(rootdir) > 0 and os.path.exists(rootdir) : self.packRootPathVar.set(rootdir) def selectSrcDir(self): srcdir = askdirectory() if len(srcdir) > 0 and os.path.exists(srcdir) : self.srcPathVar.set(srcdir) def updateRootList(self): self.packRootPath['values'] = self.__rootList if len(self.__rootList) > 0: self.packRootPath.current(0) def startPack(self): self.headConsole.configure(state='normal') self.headConsole.delete(0.0, 'end') self.headConsole.configure(state='disabled') self.bottomConsole.configure(state='normal') self.bottomConsole.delete(0.0, 'end') self.bottomConsole.configure(state='disabled') if not os.path.exists(self.packRootPathVar.get()) : Log.printInfoln('打包目录错了,骚年,你确定有这文件夹?? ' + self.packRootPathVar.get()) return if not os.path.exists(self.srcPathVar.get()) : Log.printInfoln('资源文件目录错了!' + self.srcPathVar.get()) return RootInfoMgr.updateRoot(self.packRootPathVar.get()) RootInfoMgr.writeRootInfo(self.packRootPathVar.get(), os.path.normpath(self.srcPathVar.get()), self.platformComboVar.get()) self.updateRootList() ProcessMgr.start(self.srcPathVar.get(), self.getPlatformType(), self.isNew.get() > 0, self.isFull.get() > 0) def getPlatformType(self): if self.__PLATFORM[0] == self.platformComboVar : return PLATFORM_IOS else : return PLATFORM_ANDROID def __packRootPathChangeCallBack(self, *args): if os.path.exists(self.packRootPathVar.get()) : rootInfo = RootInfoMgr.loadRootInfo(self.packRootPathVar.get()) if rootInfo != None : self.srcPathVar.set(os.path.normpath(rootInfo.srcPath)) self.platformComboVar.set(rootInfo.platform) def __platformChangeCallBack(self, *args): if os.path.exists(self.srcPathVar.get()) : try: self.headConsole.configure(state='normal') self.headConsole.delete(0.0, 'end') self.headConsole.configure(state='disabled') self.bottomConsole.configure(state='normal') self.bottomConsole.delete(0.0, 'end') self.bottomConsole.configure(state='disabled') ProcessMgr.createContext(self.packRootPathVar.get()) except : t, v, tb = sys.exc_info() print(t, v) traceback.print_tb(tb)
class TreeView(object): def __init__(self, *trees): from math import sqrt, ceil self._trees = trees self._top = Tk() self._top.title("NLTK") self._top.bind("<Control-x>", self.destroy) self._top.bind("<Control-q>", self.destroy) cf = self._cframe = CanvasFrame(self._top) self._top.bind("<Control-p>", self._cframe.print_to_file) # Size is variable. self._size = IntVar(self._top) self._size.set(12) bold = ("helvetica", -self._size.get(), "bold") helv = ("helvetica", -self._size.get()) # Lay the trees out in a square. self._width = int(ceil(sqrt(len(trees)))) self._widgets = [] for i in range(len(trees)): widget = TreeWidget( cf.canvas(), trees[i], node_font=bold, leaf_color="#008040", node_color="#004080", roof_color="#004040", roof_fill="white", line_color="#004040", draggable=1, leaf_font=helv, ) widget.bind_click_trees(widget.toggle_collapsed) self._widgets.append(widget) cf.add_widget(widget, 0, 0) self._layout() self._cframe.pack(expand=1, fill="both") self._init_menubar() def _layout(self): i = x = y = ymax = 0 width = self._width for i in range(len(self._widgets)): widget = self._widgets[i] (oldx, oldy) = widget.bbox()[:2] if i % width == 0: y = ymax x = 0 widget.move(x - oldx, y - oldy) x = widget.bbox()[2] + 10 ymax = max(ymax, widget.bbox()[3] + 10) def _init_menubar(self): menubar = Menu(self._top) filemenu = Menu(menubar, tearoff=0) filemenu.add_command( label="Print to Postscript", underline=0, command=self._cframe.print_to_file, accelerator="Ctrl-p", ) filemenu.add_command(label="Exit", underline=1, command=self.destroy, accelerator="Ctrl-x") menubar.add_cascade(label="File", underline=0, menu=filemenu) zoommenu = Menu(menubar, tearoff=0) zoommenu.add_radiobutton( label="Tiny", variable=self._size, underline=0, value=10, command=self.resize, ) zoommenu.add_radiobutton( label="Small", variable=self._size, underline=0, value=12, command=self.resize, ) zoommenu.add_radiobutton( label="Medium", variable=self._size, underline=0, value=14, command=self.resize, ) zoommenu.add_radiobutton( label="Large", variable=self._size, underline=0, value=28, command=self.resize, ) zoommenu.add_radiobutton( label="Huge", variable=self._size, underline=0, value=50, command=self.resize, ) menubar.add_cascade(label="Zoom", underline=0, menu=zoommenu) self._top.config(menu=menubar) def resize(self, *e): bold = ("helvetica", -self._size.get(), "bold") helv = ("helvetica", -self._size.get()) xspace = self._size.get() yspace = self._size.get() for widget in self._widgets: widget["node_font"] = bold widget["leaf_font"] = helv widget["xspace"] = xspace widget["yspace"] = yspace if self._size.get() < 20: widget["line_width"] = 1 elif self._size.get() < 30: widget["line_width"] = 2 else: widget["line_width"] = 3 self._layout() def destroy(self, *e): if self._top is None: return self._top.destroy() self._top = None def mainloop(self, *args, **kwargs): """ Enter the Tkinter mainloop. This function must be called if this demo is created from a non-interactive program (e.g. from a secript); otherwise, the demo will close as soon as the script completes. """ if in_idle(): return self._top.mainloop(*args, **kwargs)
class menu(Toplevel): def __init__(self, master): super().__init__(master) self.master = master self.transient(master) self.grab_set() self.title("Veuillez indiquer les noms des joueurs pour le Poker d'As") self.nom_joueur1 = Entry(self) self.nom_joueur1.grid(row=2, column=3) joueur1 = Label(self, text="Joueur 1").grid(row=1, column=3) self.nom_joueur2 = Entry(self) self.nom_joueur2.grid(row=2, column=4) joueur2 = Label(self, text="Joueur 2").grid(row=1, column=4) self.nom_joueur3 = Entry(self) self.nom_joueur3.grid(row=2, column=5) joueur3 = Label(self, text="Joueur 3").grid(row=1, column=5) self.joker_d_as = IntVar() self.check = Checkbutton(self, text="As en tant que Joker", variable=self.joker_d_as) self.check.grid(row=4, column=5) commencer_partie = Button(self, text="Commencer", command=self.nouvelle_parti).grid(row=4, column=2) regles = Button(self, text="Règles du jeu", command=self.lire_regles).grid(row=4, column=3) quitter = Button(self, text="Quitter", command=self.master.destroy).grid(row=5, column=3) if os.path.isfile("save.yml"): restaurer = Button(self, text="Restaurer", command=self.charger_partie, state="normal").grid(row=5, column=2) else: restaurer = Button(self, text="Restaurer", command=self.charger_partie, state="disabled").grid(row=5, column=2) def nouvelle_parti(self): """Fonction qui démarre la partie et ferme la fenêtre. """ if self.nom_joueur1 == "" or self.nom_joueur2.get() == "": w = Message(self, text="SVP veuillez ajouter le nom des joueurs 1 et 2", width=300) w.grid(row=6, column=1, columnspan=6) else: list_joueur = [] est_joker = self.joker_d_as.get() for i in range(0, len(self.master.de_buttom)): self.master.de_buttom[i].config(state="normal") self.master.list_obj_joueur = [] if (self.nom_joueur3.get() == ""): self.master.frame_player3.destroy() list_joueur.append(self.nom_joueur1.get()) list_joueur.append(self.nom_joueur2.get()) else: list_joueur.append(self.nom_joueur1.get()) list_joueur.append(self.nom_joueur2.get()) list_joueur.append(self.nom_joueur3.get()) for i in list_joueur: joueur = Joueur(i, self.master, est_joker) self.master.list_obj_joueur.append(joueur) self.master.partie = Partie(self.master.list_obj_joueur, self.master) self.grab_release() self.master.focus_set() self.destroy() self.master.blancer.config(state="normal") self.master.tour.config(state="disabled") self.master.partie.jouer_partie() self.master.tour.config(state="normal") self.master.blancer.config(state="disabled") for i in self.master.de_buttom: i.config(state="disabled") # On sauvegarde le résultat. # On redonne le contrôle au parent. def lire_regles(self): """ Affiche une fenêtre avec les instructions du jeu. :return:une fenêtre pop-up avec les règles du jeu. """ messagebox.showinfo( "Règles du jeu", "Le but du jeu est d'obtenir la combinaison ayant la plus grande valeur.\n\n" "La combinaison valant le plus est \nLe Quinton avec 5 figures similaires;\n Le carré avec 4 figures similaires;\n" "Le full avec 3 figures similaires suivies de 2 autres figures similaires;\nLe brelan avec 3 figures similaires.\n" "La séquence avec toutes des figures formante une suite consécutive; \nDeux paires de figures\n " "Une paire de figures.\n Chacun des joueurs a droit à 3 lancés sauf si le premier joueur " "a réussi à créer sa combinaison en moins de coups. Dans ce cas, le nombre de coups du premier joueur devient le nouveau critère pour le deuxième joueur." ) def charger_partie(self): """ Crée ou restaure une partie à partir de la fenêtre de départ, là où les joueurs doivent inscrire leurs paramètres. :return:une fenêtre permettant au joueur de restaurer la partie déjà commencée """ self.master.partie = Partie(interface=self.master, joueurs=[]) self.master.partie.restaure() self.master.partie.restore = True self.grab_release() self.master.focus_set() self.destroy() self.master.blancer.config(state="normal") self.master.tour.config(state="disabled") self.master.partie.jouer_partie() self.master.tour.config(state="normal") self.master.blancer.config(state="disable")
class MainWindow(): '''Parent window''' def __init__(self, master: Tk): # TODO CLEAN INIT self.master = master self.error_var = StringVar() self.master.title('Area Calculator') val_float_cmd = (self.master.register(vcmdtk.test_float), '%d', '%S', '%s') # Labels self.fx_text = Label(self.master, text="Function") self.start_range_text = Label(self.master, text="Start Range") self.end_range_text = Label(self.master, text="End Range") self.n_text = Label(self.master, text="N") self.error_text = Label(self.master, fg="red", textvariable=self.error_var, font=(None, 12)) # Buttons self.graph_button = Button(self.master, text="Graph", command=self.run_graph) # Calculate Button self.calculate_button = Button(self.master, text="Calculate", command=self.run_calculate) # Settings Button self.settings_button = Button( self.master, text='Settings', command=lambda: settingswindow.SettingsWindow()) # Help Button self.help_button = Button(self.master, text='Help') # Text Entry Fields self.start_range_entry = Entry(self.master, validate="key", validatecommand=val_float_cmd) self.end_range_entry = Entry(self.master, validate="key", validatecommand=val_float_cmd) self.n_entry = Entry(self.master, validate='key', validatecommand=(self.master.register( vcmdtk.test_int), '%d', '%S')) self.fx_entry = Entry(self.master) self.splash = StringVar(self.master) self.splash.set('Riemman Draw Location') self.menu = Combobox(self.master, textvariable=self.splash, values=["Left", "Right", "Middle"], state="readonly", width=22) # CheckButton (radiobutton) self.tk_int_var = IntVar(value=2) self.is_riemann_check_box = Radiobutton(self.master, text="Riemann", value=0, variable=self.tk_int_var, command=self.radio_selection) self.is_trapezoid_check_box = Radiobutton(self.master, text="Trapezoid", value=1, variable=self.tk_int_var, command=self.radio_selection) self.only_graph_radio = Radiobutton(self.master, text='Only Graph', value=2, variable=self.tk_int_var, command=self.radio_selection) # Breakline self.break_line = ttk.Separator(orient=HORIZONTAL) self.grid_gui() def grid_gui(self): '''grids widgets''' self.fx_text.grid(row=0, column=0) self.is_riemann_check_box.grid(row=0, column=3, sticky=W, pady=2, padx=(4, 0)) self.fx_entry.grid(row=0, column=1, sticky=W, pady=2) self.only_graph_radio.grid(row=0, column=3, sticky=E) self.start_range_text.grid(row=1, column=0) self.start_range_entry.grid(row=1, column=1, sticky=W, pady=2) self.is_trapezoid_check_box.grid(row=1, column=3, sticky=W, pady=2, padx=(4, 0), columnspan=2) self.end_range_text.grid(row=2, column=0) self.end_range_entry.grid(row=2, column=1, stick=W, pady=2) self.break_line.grid(row=2, column=3, sticky=EW, pady=2, padx=(4, 5)) self.n_text.grid(row=3, column=0) self.n_entry.grid(row=3, column=1, stick=W, pady=2) self.menu.grid(row=3, column=3, sticky=EW, pady=2, padx=(4, 2)) self.calculate_button.grid(row=4, column=0, pady=2) self.graph_button.grid(row=4, column=1, pady=2, sticky=W) self.error_text.grid(row=4, column=3) self.settings_button.grid(row=5, column=0) #self.help_button.grid(row=5, column=1, sticky=W, pady=2) def validate(self): '''Grab input from tk.entrys''' status_s, strt_val = self.val_float( self.start_range_entry.get()) # statuses are a boolean return status_e, end_val = self.val_float(self.end_range_entry.get()) status_n, n_val = self.val_n() status_fx, fx = self.val_fx() if not status_s: self.error_var.set('Invalid Start Range') return False, [] elif not status_e: self.error_var.set('Invalid End Range') return False, [] elif not status_n: self.error_var.set("Invalid N") return False, [] elif not status_fx: self.error_var.set("Invalid Function") return False, [] elif int(self.start_range_entry.get()) > int( self.end_range_entry.get()): self.error_var.set("Invalid Range") return False, [] return True, [strt_val, end_val, n_val, fx] def run_graph(self) -> None: '''Grab input from tk.entrys''' is_good, argum = self.validate() if is_good: self.error_var.set('') try: graph.draw(*argum, self.tk_int_var.get(), self.menu.get()) # pylint: disable=no-value-for-parameter except ValueError: self.error_var.set("Function does not exist in range") def radio_selection(self) -> None: '''switches state of draw_type and combobox''' selection = self.tk_int_var.get() if selection == 0: self.menu.state(['!disabled']) elif selection > 0: # Riemann(selection 0 ) is the only one that needs the combobox self.menu.state(['disabled']) def run_calculate(self) -> None: '''Runs integral root''' is_good, argum = self.validate() if is_good: integral_window.IntegralWindow(*argum) # pylint: disable=no-value-for-parameter def val_float(self, entry: str) -> Tuple[bool, Union[None, int]]: '''checks for entry''' if entry: return True, float(entry) else: return False, None def val_n(self) -> Tuple[bool, Union[None, int]]: '''Retrieves and validates number of rectangles wanted''' if self.n_entry.get(): return True, int(self.n_entry.get()) else: return False, None def val_fx(self) -> Tuple[bool, str]: '''retrieve function''' temp_fx = self.fx_entry.get().lower() if temp_fx == '': return False, temp_fx temp_fx = temp_fx.replace("^", "**").replace("log", "log10").replace("ln", "log") fx = '' for i in range(0, len(temp_fx) - 1): fx += temp_fx[i] if temp_fx[i].isdigit() and (temp_fx[i + 1] == 'x' or temp_fx[i + 1] == '(' or temp_fx[i + 1].isalpha()): fx += '*' #5x -> 5*x which python can evaluate fx += temp_fx[-1] return True, fx
class RecursiveDescentApp(object): """ A graphical tool for exploring the recursive descent parser. The tool displays the parser's tree and the remaining text, and allows the user to control the parser's operation. In particular, the user can expand subtrees on the frontier, match tokens on the frontier against the text, and backtrack. A "step" button simply steps through the parsing process, performing the operations that ``RecursiveDescentParser`` would use. """ def __init__(self, grammar, sent, trace=0): self._sent = sent self._parser = SteppingRecursiveDescentParser(grammar, trace) # Set up the main window. self._top = Tk() self._top.title('Recursive Descent Parser Application') # Set up key bindings. self._init_bindings() # Initialize the fonts. self._init_fonts(self._top) # Animations. animating_lock is a lock to prevent the demo # from performing new operations while it's animating. self._animation_frames = IntVar(self._top) self._animation_frames.set(5) self._animating_lock = 0 self._autostep = 0 # The user can hide the grammar. self._show_grammar = IntVar(self._top) self._show_grammar.set(1) # Create the basic frames. self._init_menubar(self._top) self._init_buttons(self._top) self._init_feedback(self._top) self._init_grammar(self._top) self._init_canvas(self._top) # Initialize the parser. self._parser.initialize(self._sent) # Resize callback self._canvas.bind('<Configure>', self._configure) ######################################### ## Initialization Helpers ######################################### def _init_fonts(self, root): # See: <http://www.astro.washington.edu/owen/ROTKFolklore.html> self._sysfont = tkinter.font.Font(font=Button()["font"]) root.option_add("*Font", self._sysfont) # TWhat's our font size (default=same as sysfont) self._size = IntVar(root) self._size.set(self._sysfont.cget('size')) self._boldfont = tkinter.font.Font(family='helvetica', weight='bold', size=self._size.get()) self._font = tkinter.font.Font(family='helvetica', size=self._size.get()) if self._size.get() < 0: big = self._size.get()-2 else: big = self._size.get()+2 self._bigfont = tkinter.font.Font(family='helvetica', weight='bold', size=big) def _init_grammar(self, parent): # Grammar view. self._prodframe = listframe = Frame(parent) self._prodframe.pack(fill='both', side='left', padx=2) self._prodlist_label = Label(self._prodframe, font=self._boldfont, text='Available Expansions') self._prodlist_label.pack() self._prodlist = Listbox(self._prodframe, selectmode='single', relief='groove', background='white', foreground='#909090', font=self._font, selectforeground='#004040', selectbackground='#c0f0c0') self._prodlist.pack(side='right', fill='both', expand=1) self._productions = list(self._parser.grammar().productions()) for production in self._productions: self._prodlist.insert('end', (' %s' % production)) self._prodlist.config(height=min(len(self._productions), 25)) # Add a scrollbar if there are more than 25 productions. if len(self._productions) > 25: listscroll = Scrollbar(self._prodframe, orient='vertical') self._prodlist.config(yscrollcommand = listscroll.set) listscroll.config(command=self._prodlist.yview) listscroll.pack(side='left', fill='y') # If they select a production, apply it. self._prodlist.bind('<<ListboxSelect>>', self._prodlist_select) def _init_bindings(self): # Key bindings are a good thing. self._top.bind('<Control-q>', self.destroy) self._top.bind('<Control-x>', self.destroy) self._top.bind('<Escape>', self.destroy) self._top.bind('e', self.expand) #self._top.bind('<Alt-e>', self.expand) #self._top.bind('<Control-e>', self.expand) self._top.bind('m', self.match) self._top.bind('<Alt-m>', self.match) self._top.bind('<Control-m>', self.match) self._top.bind('b', self.backtrack) self._top.bind('<Alt-b>', self.backtrack) self._top.bind('<Control-b>', self.backtrack) self._top.bind('<Control-z>', self.backtrack) self._top.bind('<BackSpace>', self.backtrack) self._top.bind('a', self.autostep) #self._top.bind('<Control-a>', self.autostep) self._top.bind('<Control-space>', self.autostep) self._top.bind('<Control-c>', self.cancel_autostep) self._top.bind('<space>', self.step) self._top.bind('<Delete>', self.reset) self._top.bind('<Control-p>', self.postscript) #self._top.bind('<h>', self.help) #self._top.bind('<Alt-h>', self.help) self._top.bind('<Control-h>', self.help) self._top.bind('<F1>', self.help) #self._top.bind('<g>', self.toggle_grammar) #self._top.bind('<Alt-g>', self.toggle_grammar) #self._top.bind('<Control-g>', self.toggle_grammar) self._top.bind('<Control-g>', self.edit_grammar) self._top.bind('<Control-t>', self.edit_sentence) def _init_buttons(self, parent): # Set up the frames. self._buttonframe = buttonframe = Frame(parent) buttonframe.pack(fill='none', side='bottom', padx=3, pady=2) Button(buttonframe, text='Step', background='#90c0d0', foreground='black', command=self.step,).pack(side='left') Button(buttonframe, text='Autostep', background='#90c0d0', foreground='black', command=self.autostep,).pack(side='left') Button(buttonframe, text='Expand', underline=0, background='#90f090', foreground='black', command=self.expand).pack(side='left') Button(buttonframe, text='Match', underline=0, background='#90f090', foreground='black', command=self.match).pack(side='left') Button(buttonframe, text='Backtrack', underline=0, background='#f0a0a0', foreground='black', command=self.backtrack).pack(side='left') # Replace autostep... # self._autostep_button = Button(buttonframe, text='Autostep', # underline=0, command=self.autostep) # self._autostep_button.pack(side='left') def _configure(self, event): self._autostep = 0 (x1, y1, x2, y2) = self._cframe.scrollregion() y2 = event.height - 6 self._canvas['scrollregion'] = '%d %d %d %d' % (x1,y1,x2,y2) self._redraw() def _init_feedback(self, parent): self._feedbackframe = feedbackframe = Frame(parent) feedbackframe.pack(fill='x', side='bottom', padx=3, pady=3) self._lastoper_label = Label(feedbackframe, text='Last Operation:', font=self._font) self._lastoper_label.pack(side='left') lastoperframe = Frame(feedbackframe, relief='sunken', border=1) lastoperframe.pack(fill='x', side='right', expand=1, padx=5) self._lastoper1 = Label(lastoperframe, foreground='#007070', background='#f0f0f0', font=self._font) self._lastoper2 = Label(lastoperframe, anchor='w', width=30, foreground='#004040', background='#f0f0f0', font=self._font) self._lastoper1.pack(side='left') self._lastoper2.pack(side='left', fill='x', expand=1) def _init_canvas(self, parent): self._cframe = CanvasFrame(parent, background='white', #width=525, height=250, closeenough=10, border=2, relief='sunken') self._cframe.pack(expand=1, fill='both', side='top', pady=2) canvas = self._canvas = self._cframe.canvas() # Initially, there's no tree or text self._tree = None self._textwidgets = [] self._textline = None def _init_menubar(self, parent): menubar = Menu(parent) filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label='Reset Parser', underline=0, command=self.reset, accelerator='Del') filemenu.add_command(label='Print to Postscript', underline=0, command=self.postscript, accelerator='Ctrl-p') filemenu.add_command(label='Exit', underline=1, command=self.destroy, accelerator='Ctrl-x') menubar.add_cascade(label='File', underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) editmenu.add_command(label='Edit Grammar', underline=5, command=self.edit_grammar, accelerator='Ctrl-g') editmenu.add_command(label='Edit Text', underline=5, command=self.edit_sentence, accelerator='Ctrl-t') menubar.add_cascade(label='Edit', underline=0, menu=editmenu) rulemenu = Menu(menubar, tearoff=0) rulemenu.add_command(label='Step', underline=1, command=self.step, accelerator='Space') rulemenu.add_separator() rulemenu.add_command(label='Match', underline=0, command=self.match, accelerator='Ctrl-m') rulemenu.add_command(label='Expand', underline=0, command=self.expand, accelerator='Ctrl-e') rulemenu.add_separator() rulemenu.add_command(label='Backtrack', underline=0, command=self.backtrack, accelerator='Ctrl-b') menubar.add_cascade(label='Apply', underline=0, menu=rulemenu) viewmenu = Menu(menubar, tearoff=0) viewmenu.add_checkbutton(label="Show Grammar", underline=0, variable=self._show_grammar, command=self._toggle_grammar) viewmenu.add_separator() viewmenu.add_radiobutton(label='Tiny', variable=self._size, underline=0, value=10, command=self.resize) viewmenu.add_radiobutton(label='Small', variable=self._size, underline=0, value=12, command=self.resize) viewmenu.add_radiobutton(label='Medium', variable=self._size, underline=0, value=14, command=self.resize) viewmenu.add_radiobutton(label='Large', variable=self._size, underline=0, value=18, command=self.resize) viewmenu.add_radiobutton(label='Huge', variable=self._size, underline=0, value=24, command=self.resize) menubar.add_cascade(label='View', underline=0, menu=viewmenu) animatemenu = Menu(menubar, tearoff=0) animatemenu.add_radiobutton(label="No Animation", underline=0, variable=self._animation_frames, value=0) animatemenu.add_radiobutton(label="Slow Animation", underline=0, variable=self._animation_frames, value=10, accelerator='-') animatemenu.add_radiobutton(label="Normal Animation", underline=0, variable=self._animation_frames, value=5, accelerator='=') animatemenu.add_radiobutton(label="Fast Animation", underline=0, variable=self._animation_frames, value=2, accelerator='+') menubar.add_cascade(label="Animate", underline=1, menu=animatemenu) helpmenu = Menu(menubar, tearoff=0) helpmenu.add_command(label='About', underline=0, command=self.about) helpmenu.add_command(label='Instructions', underline=0, command=self.help, accelerator='F1') menubar.add_cascade(label='Help', underline=0, menu=helpmenu) parent.config(menu=menubar) ######################################### ## Helper ######################################### def _get(self, widget, treeloc): for i in treeloc: widget = widget.subtrees()[i] if isinstance(widget, TreeSegmentWidget): widget = widget.label() return widget ######################################### ## Main draw procedure ######################################### def _redraw(self): canvas = self._canvas # Delete the old tree, widgets, etc. if self._tree is not None: self._cframe.destroy_widget(self._tree) for twidget in self._textwidgets: self._cframe.destroy_widget(twidget) if self._textline is not None: self._canvas.delete(self._textline) # Draw the tree. helv = ('helvetica', -self._size.get()) bold = ('helvetica', -self._size.get(), 'bold') attribs = {'tree_color': '#000000', 'tree_width': 2, 'node_font': bold, 'leaf_font': helv,} tree = self._parser.tree() self._tree = tree_to_treesegment(canvas, tree, **attribs) self._cframe.add_widget(self._tree, 30, 5) # Draw the text. helv = ('helvetica', -self._size.get()) bottom = y = self._cframe.scrollregion()[3] self._textwidgets = [TextWidget(canvas, word, font=self._font) for word in self._sent] for twidget in self._textwidgets: self._cframe.add_widget(twidget, 0, 0) twidget.move(0, bottom-twidget.bbox()[3]-5) y = min(y, twidget.bbox()[1]) # Draw a line over the text, to separate it from the tree. self._textline = canvas.create_line(-5000, y-5, 5000, y-5, dash='.') # Highlight appropriate nodes. self._highlight_nodes() self._highlight_prodlist() # Make sure the text lines up. self._position_text() def _redraw_quick(self): # This should be more-or-less sufficient after an animation. self._highlight_nodes() self._highlight_prodlist() self._position_text() def _highlight_nodes(self): # Highlight the list of nodes to be checked. bold = ('helvetica', -self._size.get(), 'bold') for treeloc in self._parser.frontier()[:1]: self._get(self._tree, treeloc)['color'] = '#20a050' self._get(self._tree, treeloc)['font'] = bold for treeloc in self._parser.frontier()[1:]: self._get(self._tree, treeloc)['color'] = '#008080' def _highlight_prodlist(self): # Highlight the productions that can be expanded. # Boy, too bad tkinter doesn't implement Listbox.itemconfig; # that would be pretty useful here. self._prodlist.delete(0, 'end') expandable = self._parser.expandable_productions() untried = self._parser.untried_expandable_productions() productions = self._productions for index in range(len(productions)): if productions[index] in expandable: if productions[index] in untried: self._prodlist.insert(index, ' %s' % productions[index]) else: self._prodlist.insert(index, ' %s (TRIED)' % productions[index]) self._prodlist.selection_set(index) else: self._prodlist.insert(index, ' %s' % productions[index]) def _position_text(self): # Line up the text widgets that are matched against the tree numwords = len(self._sent) num_matched = numwords - len(self._parser.remaining_text()) leaves = self._tree_leaves()[:num_matched] xmax = self._tree.bbox()[0] for i in range(0, len(leaves)): widget = self._textwidgets[i] leaf = leaves[i] widget['color'] = '#006040' leaf['color'] = '#006040' widget.move(leaf.bbox()[0] - widget.bbox()[0], 0) xmax = widget.bbox()[2] + 10 # Line up the text widgets that are not matched against the tree. for i in range(len(leaves), numwords): widget = self._textwidgets[i] widget['color'] = '#a0a0a0' widget.move(xmax - widget.bbox()[0], 0) xmax = widget.bbox()[2] + 10 # If we have a complete parse, make everything green :) if self._parser.currently_complete(): for twidget in self._textwidgets: twidget['color'] = '#00a000' # Move the matched leaves down to the text. for i in range(0, len(leaves)): widget = self._textwidgets[i] leaf = leaves[i] dy = widget.bbox()[1] - leaf.bbox()[3] - 10.0 dy = max(dy, leaf.parent().label().bbox()[3] - leaf.bbox()[3] + 10) leaf.move(0, dy) def _tree_leaves(self, tree=None): if tree is None: tree = self._tree if isinstance(tree, TreeSegmentWidget): leaves = [] for child in tree.subtrees(): leaves += self._tree_leaves(child) return leaves else: return [tree] ######################################### ## Button Callbacks ######################################### def destroy(self, *e): self._autostep = 0 if self._top is None: return self._top.destroy() self._top = None def reset(self, *e): self._autostep = 0 self._parser.initialize(self._sent) self._lastoper1['text'] = 'Reset Application' self._lastoper2['text'] = '' self._redraw() def autostep(self, *e): if self._animation_frames.get() == 0: self._animation_frames.set(2) if self._autostep: self._autostep = 0 else: self._autostep = 1 self._step() def cancel_autostep(self, *e): #self._autostep_button['text'] = 'Autostep' self._autostep = 0 # Make sure to stop auto-stepping if we get any user input. def step(self, *e): self._autostep = 0; self._step() def match(self, *e): self._autostep = 0; self._match() def expand(self, *e): self._autostep = 0; self._expand() def backtrack(self, *e): self._autostep = 0; self._backtrack() def _step(self): if self._animating_lock: return # Try expanding, matching, and backtracking (in that order) if self._expand(): pass elif self._parser.untried_match() and self._match(): pass elif self._backtrack(): pass else: self._lastoper1['text'] = 'Finished' self._lastoper2['text'] = '' self._autostep = 0 # Check if we just completed a parse. if self._parser.currently_complete(): self._autostep = 0 self._lastoper2['text'] += ' [COMPLETE PARSE]' def _expand(self, *e): if self._animating_lock: return old_frontier = self._parser.frontier() rv = self._parser.expand() if rv is not None: self._lastoper1['text'] = 'Expand:' self._lastoper2['text'] = rv self._prodlist.selection_clear(0, 'end') index = self._productions.index(rv) self._prodlist.selection_set(index) self._animate_expand(old_frontier[0]) return 1 else: self._lastoper1['text'] = 'Expand:' self._lastoper2['text'] = '(all expansions tried)' return 0 def _match(self, *e): if self._animating_lock: return old_frontier = self._parser.frontier() rv = self._parser.match() if rv is not None: self._lastoper1['text'] = 'Match:' self._lastoper2['text'] = rv self._animate_match(old_frontier[0]) return 1 else: self._lastoper1['text'] = 'Match:' self._lastoper2['text'] = '(failed)' return 0 def _backtrack(self, *e): if self._animating_lock: return if self._parser.backtrack(): elt = self._parser.tree() for i in self._parser.frontier()[0]: elt = elt[i] self._lastoper1['text'] = 'Backtrack' self._lastoper2['text'] = '' if isinstance(elt, Tree): self._animate_backtrack(self._parser.frontier()[0]) else: self._animate_match_backtrack(self._parser.frontier()[0]) return 1 else: self._autostep = 0 self._lastoper1['text'] = 'Finished' self._lastoper2['text'] = '' return 0 def about(self, *e): ABOUT = ("NLTK Recursive Descent Parser Application\n"+ "Written by Edward Loper") TITLE = 'About: Recursive Descent Parser Application' try: from tkinter.messagebox import Message Message(message=ABOUT, title=TITLE).show() except: ShowText(self._top, TITLE, ABOUT) def help(self, *e): self._autostep = 0 # The default font's not very legible; try using 'fixed' instead. try: ShowText(self._top, 'Help: Recursive Descent Parser Application', (__doc__ or '').strip(), width=75, font='fixed') except: ShowText(self._top, 'Help: Recursive Descent Parser Application', (__doc__ or '').strip(), width=75) def postscript(self, *e): self._autostep = 0 self._cframe.print_to_file() def mainloop(self, *args, **kwargs): """ Enter the Tkinter mainloop. This function must be called if this demo is created from a non-interactive program (e.g. from a secript); otherwise, the demo will close as soon as the script completes. """ if in_idle(): return self._top.mainloop(*args, **kwargs) def resize(self, size=None): if size is not None: self._size.set(size) size = self._size.get() self._font.configure(size=-(abs(size))) self._boldfont.configure(size=-(abs(size))) self._sysfont.configure(size=-(abs(size))) self._bigfont.configure(size=-(abs(size+2))) self._redraw() ######################################### ## Expand Production Selection ######################################### def _toggle_grammar(self, *e): if self._show_grammar.get(): self._prodframe.pack(fill='both', side='left', padx=2, after=self._feedbackframe) self._lastoper1['text'] = 'Show Grammar' else: self._prodframe.pack_forget() self._lastoper1['text'] = 'Hide Grammar' self._lastoper2['text'] = '' # def toggle_grammar(self, *e): # self._show_grammar = not self._show_grammar # if self._show_grammar: # self._prodframe.pack(fill='both', expand='y', side='left', # after=self._feedbackframe) # self._lastoper1['text'] = 'Show Grammar' # else: # self._prodframe.pack_forget() # self._lastoper1['text'] = 'Hide Grammar' # self._lastoper2['text'] = '' def _prodlist_select(self, event): selection = self._prodlist.curselection() if len(selection) != 1: return index = int(selection[0]) old_frontier = self._parser.frontier() production = self._parser.expand(self._productions[index]) if production: self._lastoper1['text'] = 'Expand:' self._lastoper2['text'] = production self._prodlist.selection_clear(0, 'end') self._prodlist.selection_set(index) self._animate_expand(old_frontier[0]) else: # Reset the production selections. self._prodlist.selection_clear(0, 'end') for prod in self._parser.expandable_productions(): index = self._productions.index(prod) self._prodlist.selection_set(index) ######################################### ## Animation ######################################### def _animate_expand(self, treeloc): oldwidget = self._get(self._tree, treeloc) oldtree = oldwidget.parent() top = not isinstance(oldtree.parent(), TreeSegmentWidget) tree = self._parser.tree() for i in treeloc: tree = tree[i] widget = tree_to_treesegment(self._canvas, tree, node_font=self._boldfont, leaf_color='white', tree_width=2, tree_color='white', node_color='white', leaf_font=self._font) widget.label()['color'] = '#20a050' (oldx, oldy) = oldtree.label().bbox()[:2] (newx, newy) = widget.label().bbox()[:2] widget.move(oldx-newx, oldy-newy) if top: self._cframe.add_widget(widget, 0, 5) widget.move(30-widget.label().bbox()[0], 0) self._tree = widget else: oldtree.parent().replace_child(oldtree, widget) # Move the children over so they don't overlap. # Line the children up in a strange way. if widget.subtrees(): dx = (oldx + widget.label().width()/2 - widget.subtrees()[0].bbox()[0]/2 - widget.subtrees()[0].bbox()[2]/2) for subtree in widget.subtrees(): subtree.move(dx, 0) self._makeroom(widget) if top: self._cframe.destroy_widget(oldtree) else: oldtree.destroy() colors = ['gray%d' % (10*int(10*x/self._animation_frames.get())) for x in range(self._animation_frames.get(),0,-1)] # Move the text string down, if necessary. dy = widget.bbox()[3] + 30 - self._canvas.coords(self._textline)[1] if dy > 0: for twidget in self._textwidgets: twidget.move(0, dy) self._canvas.move(self._textline, 0, dy) self._animate_expand_frame(widget, colors) def _makeroom(self, treeseg): """ Make sure that no sibling tree bbox's overlap. """ parent = treeseg.parent() if not isinstance(parent, TreeSegmentWidget): return index = parent.subtrees().index(treeseg) # Handle siblings to the right rsiblings = parent.subtrees()[index+1:] if rsiblings: dx = treeseg.bbox()[2] - rsiblings[0].bbox()[0] + 10 for sibling in rsiblings: sibling.move(dx, 0) # Handle siblings to the left if index > 0: lsibling = parent.subtrees()[index-1] dx = max(0, lsibling.bbox()[2] - treeseg.bbox()[0] + 10) treeseg.move(dx, 0) # Keep working up the tree. self._makeroom(parent) def _animate_expand_frame(self, widget, colors): if len(colors) > 0: self._animating_lock = 1 widget['color'] = colors[0] for subtree in widget.subtrees(): if isinstance(subtree, TreeSegmentWidget): subtree.label()['color'] = colors[0] else: subtree['color'] = colors[0] self._top.after(50, self._animate_expand_frame, widget, colors[1:]) else: widget['color'] = 'black' for subtree in widget.subtrees(): if isinstance(subtree, TreeSegmentWidget): subtree.label()['color'] = 'black' else: subtree['color'] = 'black' self._redraw_quick() widget.label()['color'] = 'black' self._animating_lock = 0 if self._autostep: self._step() def _animate_backtrack(self, treeloc): # Flash red first, if we're animating. if self._animation_frames.get() == 0: colors = [] else: colors = ['#a00000', '#000000', '#a00000'] colors += ['gray%d' % (10*int(10*x/(self._animation_frames.get()))) for x in range(1, self._animation_frames.get()+1)] widgets = [self._get(self._tree, treeloc).parent()] for subtree in widgets[0].subtrees(): if isinstance(subtree, TreeSegmentWidget): widgets.append(subtree.label()) else: widgets.append(subtree) self._animate_backtrack_frame(widgets, colors) def _animate_backtrack_frame(self, widgets, colors): if len(colors) > 0: self._animating_lock = 1 for widget in widgets: widget['color'] = colors[0] self._top.after(50, self._animate_backtrack_frame, widgets, colors[1:]) else: for widget in widgets[0].subtrees(): widgets[0].remove_child(widget) widget.destroy() self._redraw_quick() self._animating_lock = 0 if self._autostep: self._step() def _animate_match_backtrack(self, treeloc): widget = self._get(self._tree, treeloc) node = widget.parent().label() dy = (1.0 * (node.bbox()[3] - widget.bbox()[1] + 14) / max(1, self._animation_frames.get())) self._animate_match_backtrack_frame(self._animation_frames.get(), widget, dy) def _animate_match(self, treeloc): widget = self._get(self._tree, treeloc) dy = ((self._textwidgets[0].bbox()[1] - widget.bbox()[3] - 10.0) / max(1, self._animation_frames.get())) self._animate_match_frame(self._animation_frames.get(), widget, dy) def _animate_match_frame(self, frame, widget, dy): if frame > 0: self._animating_lock = 1 widget.move(0, dy) self._top.after(10, self._animate_match_frame, frame-1, widget, dy) else: widget['color'] = '#006040' self._redraw_quick() self._animating_lock = 0 if self._autostep: self._step() def _animate_match_backtrack_frame(self, frame, widget, dy): if frame > 0: self._animating_lock = 1 widget.move(0, dy) self._top.after(10, self._animate_match_backtrack_frame, frame-1, widget, dy) else: widget.parent().remove_child(widget) widget.destroy() self._animating_lock = 0 if self._autostep: self._step() def edit_grammar(self, *e): CFGEditor(self._top, self._parser.grammar(), self.set_grammar) def set_grammar(self, grammar): self._parser.set_grammar(grammar) self._productions = list(grammar.productions()) self._prodlist.delete(0, 'end') for production in self._productions: self._prodlist.insert('end', (' %s' % production)) def edit_sentence(self, *e): sentence = " ".join(self._sent) title = 'Edit Text' instr = 'Enter a new sentence to parse.' EntryDialog(self._top, sentence, instr, self.set_sentence, title) def set_sentence(self, sentence): self._sent = sentence.split() #[XX] use tagged? self.reset()
class Gui: def __init__(self, root): global CONFIG, CURPATH self.root = root root.geometry( "%dx%d+0+0" % (round(root.winfo_screenwidth() * 0.8), round(root.winfo_screenheight() * 0.8))) #default window size 80% root.title('Chords Autoscroll 0.9b') root.iconphoto( True, PhotoImage(file=os.path.join(CURPATH, "media", "icon.png"))) root.option_add("*Font", "Helvetica 12") #default font root.protocol("WM_DELETE_WINDOW", self.onClose) #general vars if CONFIG.get("recent"): self.file = FileManager(os.path.dirname(CONFIG.get("recent")[0])) else: self.file = FileManager() self.speed = IntVar() self.speed.set(30) self.runningScroll = False self.settingsPattern = re.compile( '\n\nChordsAutoscrollSettings:(\{.*\})') self.settings = {} #menu self.menubar = Menu(self.root) self.filemenu = Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="File", menu=self.filemenu) self.filemenu.add_command(label="Open...", command=lambda: self.openNewFile()) self.filemenu.add_separator() self.filemenu.add_command(label="Save (Ctrl+S)", command=lambda: self.saveFile(True)) self.filemenu.add_command(label="Save as...", command=lambda: self.saveFile()) self.filemenu.add_separator() self.filemenu.add_command(label="Close", command=lambda: self.closeFile()) #recent files (I should update this at runtime...) self.filemenu.add_separator() self.recent = Menu(self.filemenu, tearoff=0) self.filemenu.add_cascade(label="Recent files", menu=self.recent) if CONFIG.get("recent") and len(CONFIG.get("recent")) > 0: for n, p in enumerate(CONFIG.get("recent")): self.recent.add_command( label=str(n + 1) + ": " + str(p), command=lambda p=p: self.openNewFile(str(p))) self.root.config(menu=self.menubar) #root frame froot = Frame(root) froot.pack(side=c.TOP, pady=5, padx=5, fill=c.BOTH, expand=1) #main frame fmain = Frame(froot) fmain.pack(side=c.TOP, fill=c.BOTH, expand=1, anchor=c.N) f1 = Frame(fmain) #text window frame f1.pack(side=c.LEFT, fill=c.BOTH, expand=1) self.txtMain = Text( f1, height=1, width=1, font=("Courier", 14), undo=True) #maybe we can set a DARK MODE to help reading self.txtMain.pack(side=c.LEFT, fill=c.BOTH, expand=1) self.scrollbar = Scrollbar(f1, command=self.txtMain.yview) self.scrollbar.pack(side=c.LEFT, fill=c.Y) self.txtMain.config(yscrollcommand=self.scrollbar.set) f2 = Frame(fmain, width=100) #right buttons panel f2.pack(side=c.RIGHT, anchor=c.N, padx=5, fill=c.X) self.btnPlay = Button(f2, text="Play", relief=c.RAISED, font=(None, 0, "bold")) self.btnPlay.pack(side=c.TOP, padx=5, pady=5, fill=c.BOTH, expand=1, ipady=6) self.btnPlay['command'] = lambda: self.autoscroll() f2_1 = Frame(f2) #child frame SPEED CONTROL f2_1.pack(side=c.TOP, anchor=c.N, pady=(10, 0), fill=c.X) Label(f2_1, text="Speed:", font=("*", 8), anchor=c.E).pack(side=c.LEFT, padx=(2, 0)) Label(f2_1, font=("*", 8), anchor=c.W, textvariable=self.speed).pack(side=c.LEFT, padx=(0, 2)) self.btnSpeedUp = Button(f2, text="+") self.btnSpeedUp.pack(side=c.TOP, padx=5, pady=2, fill=c.BOTH, ipady=6) self.btnSpeedUp['command'] = lambda: self.speedAdd(1) self.btnSpeedDown = Button(f2, text="-") self.btnSpeedDown.pack(side=c.TOP, padx=5, pady=(2, 5), fill=c.BOTH, ipady=6) self.btnSpeedDown['command'] = lambda: self.speedAdd(-1) f2_2 = Frame(f2, width=5) #child frame FONT SIZE #f2_2.pack_propagate(0) f2_2.pack(side=c.TOP, anchor=c.N, pady=(10, 0), fill=c.X) self.btnTextUp = Button(f2, text="A", font=(None, 18)) self.btnTextUp.pack(side=c.TOP, padx=5, pady=2, fill=c.BOTH, ipady=0) self.btnTextUp['command'] = lambda: self.changeFontSize(1) self.btnTextDown = Button(f2, text="A", font=(None, 10)) self.btnTextDown.pack(side=c.TOP, padx=5, pady=(2, 5), fill=c.BOTH, ipady=8) self.btnTextDown['command'] = lambda: self.changeFontSize(-1) #credits f4 = Frame(root) f4.pack(side=c.BOTTOM, pady=0, padx=0, fill=c.X, anchor=c.S) Label( f4, text= "© 2017 Pasquale Lafiosca. Distributed under the terms of the Apache License 2.0.", fg='#111111', bg='#BBBBBB', font=('', 9), bd=0, padx=10).pack(fill=c.X, ipady=2, ipadx=2) #shortcuts root.bind('<Control-s>', lambda e: self.saveFile(True)) root.bind('<Control-S>', lambda e: self.saveFile(True)) def startStop(e): if self.runningScroll: self.stopAutoscroll() else: self.autoscroll() root.bind('<Control-space>', startStop) def openNewFile(self, path=None): global CONFIG filename = None if not path: filename = filedialog.askopenfilename( initialdir=self.file.getLastUsedDir(), filetypes=[("Text files", "*.*")], title="Select a text file to open") else: if os.path.isfile(path): filename = path else: messagebox.showwarning("Not found", "Selected file was not found. Sorry.") if filename: self.closeFile() self.recent.delete(0, len(CONFIG.get("recent")) - 1) CONFIG.insertRecentFile(filename) for n, p in enumerate(CONFIG.get("recent")): self.recent.add_command( label=str(n + 1) + ": " + str(p), command=lambda p=p: self.openNewFile(str(p))) self.file.open(filename) self.txtMain.delete(1.0, c.END) content = self.file.getContent() #Settings m = re.search(self.settingsPattern, content) if m and m.group(1): try: self.settings = json.loads( m.group(1)) # Loads settings from file self.speed.set(self.settings["Speed"]) self._setFontSize(self.settings["Size"]) except: messagebox.showwarning("Warning", "Cannot load setting data. Sorry.") self._setSettingsData() else: self._setSettingsData() content = re.sub( self.settingsPattern, '', content) # Remove settings string before write on screen self.txtMain.insert(1.0, content) def _setSettingsData(self): self.settings = { "Speed": self.speed.get(), "Size": self._getFontSize() } def _settingsChanged(self): if "Speed" in self.settings and "Size" in self.settings and ( self.settings["Speed"] != self.speed.get() or self.settings["Size"] != self._getFontSize()): return True else: return False def saveFile(self, current=False): global CONFIG if current: filename = self.file.getLastFile() if not current or not filename: filename = filedialog.asksaveasfilename( initialdir=self.file.getLastUsedDir(), initialfile=self.file.getLastFile(), filetypes=[("Text files", "*.txt")], title="Select destionation", defaultextension=".txt") if filename: CONFIG.insertRecentFile(filename) self.file.open(filename) self._setSettingsData() self.file.writeContent( self.txtMain.get(1.0, c.END)[:-1] + "\n\nChordsAutoscrollSettings:" + json.dumps(self.settings)) def closeFile(self): if not self.txtMain.get(1.0, c.END)[:-1]: # Empty view return True if self.file.hasChanged( hashlib.md5( (self.txtMain.get(1.0, c.END)[:-1] + "\n\nChordsAutoscrollSettings:" + json.dumps(self.settings) ).encode()).hexdigest()) or self._settingsChanged(): if messagebox.askyesno( "Save changes", "Current document has been modified. Do you want to save changes?" ): self.saveFile() self.txtMain.delete(1.0, c.END) self.file.close() return True def mainloop(self): self.root.mainloop() def onClose(self): if messagebox.askokcancel("Quit", "Do you want to quit?"): self.closeFile() self.root.destroy() def _getFontSize(self): return font.Font(font=self.txtMain["font"])["size"] def _setFontSize(self, newsize): f = font.Font(font=self.txtMain["font"]) f.config(size=newsize) self.txtMain.config(font=f) self.txtMain.update_idletasks() def changeFontSize(self, a): f = font.Font(font=self.txtMain["font"]) newsize = f["size"] + a if (newsize < 8 or newsize > 72): #limits return f.config(size=newsize) self.txtMain.config(font=f) self.txtMain.update_idletasks() def autoscroll(self): if not self.runningScroll and threading.active_count( ) < 2: # Check to avoid multiple scrolling threads if (float(self.scrollbar.get()[1]) == 1 ): #if we are at the end, let's start from beginning self.txtMain.see(1.0) self.runningScroll = True #INITIAL DELAY self.txtMain.mark_set("initialDelay", 1.0) self.txtMain.mark_gravity("initialDelay", c.RIGHT) self.txtMain.insert("initialDelay", os.linesep * 20) # SET CONSTANT HERE self.txtMain.config(state=c.DISABLED) self.txtMain.update_idletasks() threading.Thread(target=self.autoscroll_callback, name="ScrollingThread", daemon=True).start() self.btnPlay.config(text="Stop", relief=c.SUNKEN, command=lambda: self.stopAutoscroll()) self.btnPlay.update_idletasks() def autoscroll_callback(self): while (float(self.scrollbar.get()[1]) < 1 and self.runningScroll): self.txtMain.yview(c.SCROLL, 1, c.UNITS) end = time.time() + 60 / self.speed.get() while (time.time() < end and self.runningScroll): # trick to stop immediately time.sleep(.1) if self.runningScroll: self.stopAutoscroll() def stopAutoscroll(self): self.runningScroll = False self.txtMain.config(state=c.NORMAL) self.txtMain.delete(1.0, "initialDelay") self.txtMain.mark_unset("initialDelay") self.txtMain.update_idletasks() self.btnPlay.config(text="Play", relief=c.RAISED, command=lambda: self.autoscroll()) self.btnPlay.update_idletasks() def speedAdd(self, n): n = self.speed.get() + n if (n > 0 and n < 1000): self.speed.set(n)
class menu_esq_view(Frame): def __init__(self, framePai, controller): super().__init__(framePai) self.controller = controller # Bloco (2.1): Abaixo, é declarado o frame que conterá o menu. O frame está contido no frame-pai: self.frameLocal = Frame(self, padx=2, pady=4) self.frameLocal.grid(row=0, column=0, sticky=N + S) # Subtítulos do programa: # O subTitulo1 é declarado e "fixado"(.grid) dentro do frameLocal com o nome do programa: self.tit1 = Label(self.frameLocal, text='Ondas', font='Verdana', anchor=CENTER, relief=GROOVE, padx=3, pady=3) self.tit1.grid( row=0, column=0, sticky=E + W, padx=3, pady=3 ) # , sticky = E+W)#Subtitulo fixado na origem do "frameLocal"(row=0, column=0) self.separadorV1 = ttk.Separator(self.frameLocal, orient=VERTICAL, style="TSeparator") self.separadorV1.grid(row=0, column=1, rowspan=13, sticky="ns", padx=2, pady=3) # O subtitulo3 é declarado no sub-bloco abaixo, dentro do frameLocal: self.title_font = tkfont.Font(family='Helvetica', size=14, weight="bold", slant="italic") self.arduinoStatus = ttk.Label(self.frameLocal, text='Arduino status', font=self.title_font) self.arduinoStatus.grid(row=1, column=0, sticky=E + W, padx=3, pady=3) # O subtitulo4 é declarado no sub-bloco abaixo, dentro do frameLocal: self.tit3 = Label(self.frameLocal, text='Menu', relief=FLAT, font='Verdana', anchor=CENTER) self.tit3.grid(row=2, column=0, sticky=E + W) # ttk.Style().configure("Toolbutton", relief = "ridge") # ttk.Style().configure('Toolbutton.label', 'sticky' = 'we') # ~ print(ttk.Style().layout('Toolbutton')) # A variável varRb guardará o valor dos Radiobuttons self.varRb = IntVar() self.Rb1 = ttk.Radiobutton(self.frameLocal, text="Propagação de ondas na corda", value=1, variable=self.varRb, style='Toolbutton') self.Rb1.config( command=lambda: self.controller.show_frame("frame_onda_corda")) self.Rb1.grid(row=3, column=0, sticky=E + W, padx=3, pady=1) # O botao2 é declarado no sub-bloco abaixo, dentro do frameLocal: self.Rb2 = ttk.Radiobutton(self.frameLocal, text="Propagação de ondas na superfície", value=2, variable=self.varRb, style='Toolbutton') self.Rb2.config( command=lambda: self.controller.show_frame("frame_onda_membr")) self.Rb2.grid(row=4, column=0, sticky=E + W, padx=3, pady=1) # O botao2 é declarado no sub-bloco abaixo, dentro do frameLocal: self.Rb4 = ttk.Radiobutton(self.frameLocal, text="Levitador acústico", value=2, variable=self.varRb, style='Toolbutton') self.Rb4.config( command=lambda: self.controller.show_frame("frame_onda_membr")) self.Rb4.grid(row=6, column=0, sticky=E + W, padx=3, pady=1) # O botao3 é declarado no sub-bloco abaixo, dentro do frameLocal: self.Rb3 = ttk.Button(self.frameLocal, style='Toolbutton', text="Tanque de ondas") self.Rb3.config(command=lambda: self.verfArduinoPopUp()) self.Rb3.grid(row=5, column=0, sticky=E + W, padx=3, pady=1) # O botao4 é declarado no sub-bloco abaixo, dentro do frameLocal: self.Rb4 = ttk.Radiobutton(self.frameLocal, text='', value=4, variable=self.varRb, style='Toolbutton', state='disabled') self.Rb4.grid(row=6, column=0, sticky=E + W, padx=3, pady=1) # O botao4 é declarado no sub-bloco abaixo, dentro do frameLocal: self.Rb5 = ttk.Radiobutton(self.frameLocal, text='', value=4, variable=self.varRb, style='Toolbutton', state='disabled') self.Rb5.grid(row=7, column=0, sticky=E + W, padx=3, pady=1) # O botao4 é declarado no sub-bloco abaixo, dentro do frameLocal: self.Rb6 = ttk.Radiobutton(self.frameLocal, text='', value=4, variable=self.varRb, style='Toolbutton', state='disabled') self.Rb6.grid(row=8, column=0, sticky=E + W, padx=3, pady=1) # O botao4 é declarado no sub-bloco abaixo, dentro do frameLocal: self.Rb7 = ttk.Radiobutton(self.frameLocal, text='', value=4, variable=self.varRb, style='Toolbutton', state='disabled') self.Rb7.grid(row=9, column=0, sticky=E + W, padx=3, pady=1) # O botao4 é declarado no sub-bloco abaixo, dentro do frameLocal: self.Rb7 = ttk.Radiobutton(self.frameLocal, text='', value=4, variable=self.varRb, style='Toolbutton', state='disabled') self.Rb7.grid(row=10, column=0, sticky=E + W, padx=3, pady=1) # imageIn = PIL.Image.open(".\DBApp\pictures\IFES2.png") # self.image = imageIn.resize((200, 115), PIL.Image.ANTIALIAS) # self.photo = PIL.ImageTk.PhotoImage(self.image) # self.label_photo = Label(self.frameLocal, image=self.photo) # self.label_photo.image = self.photo # keep a reference! self.wd_photo = wd_GUI_Image(self.frameLocal, pic_name='IFES2', pic_resolution=(200, 115)) self.wd_photo.grid(row=11, column=0, sticky=S) def verfArduinoPopUp(self): self.controller.verfArduinoPopUp() def ardStatusLabel(self, status): if status is True: self.arduinoStatus.config(text='Arduino conectado!', foreground='green') else: self.arduinoStatus.config(text='Arduino não conectado!', foreground='red') def desativa_todos_Rb(self): self.Rb1.config(state="disabled") self.Rb2.config(state="disabled") self.Rb3.config(state="disabled") # ~ self.Rb4.config(state = "disabled") def ativa_todos_Rbs(self): self.Rb1.config(state="eneable") self.Rb2.config(state="eneable") self.Rb3.config(state="eneable") # ~ self.Rb4.config(state = "eneable") def escolha_Rb(self): escolha = self.varRb.get() return (escolha)
class GoogleSearcher(): def __init__(self, master): self.window = master ''' --- Create the labels and entries to get the search query --- Create the button to open up the search result(s) pages ''' self.query_frame = Frame(self.window) self.query_lbl = Label(self.query_frame, text="search for", width=20, height=2, padx=20, anchor=W, font=(None, 15)) self.query_lbl.grid(row=0, column=0) self.no_of_links_lbl = Label(self.query_frame, text="No of links to open", width=20, height=2, padx=20, anchor=W, font=(None, 15)) self.no_of_links_lbl.grid(row=1, column=0) # Create Entry widgets for User to enter the query to search and the no of links User want to open self.query = StringVar() self.query_entry = Entry(self.query_frame, textvariable=self.query, width=25) self.query_entry.grid(row=0, column=1, columnspan=5, padx=2, pady=2, sticky=W + E) self.query_entry.focus_set() self.no_of_links = IntVar() self.no_of_links.set(1) self.no_of_links_entry = Entry(self.query_frame, textvariable=self.no_of_links, width=25) self.no_of_links_entry.grid(row=1, column=1, columnspan=5, padx=2, pady=2, sticky=W + E) self.info_lbl = Label( self.query_frame, text="[optional - opens a tab by default - even if entered 0!]", width=35, height=1, font=(None, 8)) self.info_lbl.grid(row=2, column=1, columnspan=5, padx=2, pady=2, sticky=W) self.query_frame.grid(row=0, column=0, pady=10) # Create search button to search the entered query self.search_button = Button( self.window, text="SEARCH", width=8, command=lambda: open_url(str(self.query.get()), self.get_no_of_links())) self.search_button.grid(row=1, column=0) def get_no_of_links(self): ''' Handling exception if User skips with the no_of_links_entry box ! ''' try: return self.no_of_links.get() except TclError: return 1
class CFGDemo(object): def __init__(self, grammar, text): self._grammar = grammar self._text = text # Set up the main window. self._top = Tk() self._top.title('Context Free Grammar Demo') # Base font size self._size = IntVar(self._top) self._size.set(12) # = medium # Set up the key bindings self._init_bindings(self._top) # Create the basic frames frame1 = Frame(self._top) frame1.pack(side='left', fill='y', expand=0) self._init_menubar(self._top) self._init_buttons(self._top) self._init_grammar(frame1) self._init_treelet(frame1) self._init_workspace(self._top) #////////////////////////////////////////////////// # Initialization #////////////////////////////////////////////////// def _init_bindings(self, top): top.bind('<Control-q>', self.destroy) def _init_menubar(self, parent): pass def _init_buttons(self, parent): pass def _init_grammar(self, parent): self._prodlist = ProductionList(parent, self._grammar, width=20) self._prodlist.pack(side='top', fill='both', expand=1) self._prodlist.focus() self._prodlist.add_callback('select', self._selectprod_cb) self._prodlist.add_callback('move', self._selectprod_cb) def _init_treelet(self, parent): self._treelet_canvas = Canvas(parent, background='white') self._treelet_canvas.pack(side='bottom', fill='x') self._treelet = None def _init_workspace(self, parent): self._workspace = CanvasFrame(parent, background='white') self._workspace.pack(side='right', fill='both', expand=1) self._tree = None self.reset_workspace() #////////////////////////////////////////////////// # Workspace #////////////////////////////////////////////////// def reset_workspace(self): c = self._workspace.canvas() fontsize = int(self._size.get()) node_font = ('helvetica', -(fontsize+4), 'bold') leaf_font = ('helvetica', -(fontsize+2)) # Remove the old tree if self._tree is not None: self._workspace.remove_widget(self._tree) # The root of the tree. start = self._grammar.start().symbol() rootnode = TextWidget(c, start, font=node_font, draggable=1) # The leaves of the tree. leaves = [] for word in self._text: leaves.append(TextWidget(c, word, font=leaf_font, draggable=1)) # Put it all together into one tree self._tree = TreeSegmentWidget(c, rootnode, leaves, color='white') # Add it to the workspace. self._workspace.add_widget(self._tree) # Move the leaves to the bottom of the workspace. for leaf in leaves: leaf.move(0,100) #self._nodes = {start:1} #self._leaves = dict([(l,1) for l in leaves]) def workspace_markprod(self, production): pass def _markproduction(self, prod, tree=None): if tree is None: tree = self._tree for i in range(len(tree.subtrees())-len(prod.rhs())): if tree['color', i] == 'white': self._markproduction for j, node in enumerate(prod.rhs()): widget = tree.subtrees()[i+j] if (isinstance(node, Nonterminal) and isinstance(widget, TreeSegmentWidget) and node.symbol == widget.label().text()): pass # matching nonterminal elif (isinstance(node, compat.string_types) and isinstance(widget, TextWidget) and node == widget.text()): pass # matching nonterminal else: break else: # Everything matched! print('MATCH AT', i) #////////////////////////////////////////////////// # Grammar #////////////////////////////////////////////////// def _selectprod_cb(self, production): canvas = self._treelet_canvas self._prodlist.highlight(production) if self._treelet is not None: self._treelet.destroy() # Convert the production to a tree. rhs = production.rhs() for (i, elt) in enumerate(rhs): if isinstance(elt, Nonterminal): elt = Tree(elt) tree = Tree(production.lhs().symbol(), *rhs) # Draw the tree in the treelet area. fontsize = int(self._size.get()) node_font = ('helvetica', -(fontsize+4), 'bold') leaf_font = ('helvetica', -(fontsize+2)) self._treelet = tree_to_treesegment(canvas, tree, node_font=node_font, leaf_font=leaf_font) self._treelet['draggable'] = 1 # Center the treelet. (x1, y1, x2, y2) = self._treelet.bbox() w, h = int(canvas['width']), int(canvas['height']) self._treelet.move((w-x1-x2)/2, (h-y1-y2)/2) # Mark the places where we can add it to the workspace. self._markproduction(production) def destroy(self, *args): self._top.destroy() def mainloop(self, *args, **kwargs): self._top.mainloop(*args, **kwargs)
class ServerEntryBox: def __init__(self, parent, display=False): self.params_file = "serverparams.csv" self.column_names = [ "hostname", "user", "password", "keyfile", "partition", "nodes", "cores", "nsg_url", "nsg_user", "nsg_pass", "nsg_app", "nsg_id", "use_ssh" ] self.load_file(parent) if display: self.display(parent) return def display(self, parent): top = self.top = tk.Toplevel(parent) top.geometry('325x400') top.resizable(0, 0) tk.Label(top, text='Server Connection Properties').grid(row=0, column=0, sticky="WE", columnspan=2) self.server_type = IntVar() self.server_type.set(int(self.use_ssh.get())) #0 for nsg 1 for ssh def on_server_type_change(): if (self.server_type.get() == 0): conn_option_frame.grid_forget() nsgconn_option_frame.grid(column=0, row=3, sticky='news', padx=10, pady=5, columnspan=2) self.use_ssh.set(str(0)) else: nsgconn_option_frame.grid_forget() conn_option_frame.grid(column=0, row=2, sticky='news', padx=10, pady=5, columnspan=2) self.use_ssh.set(str(1)) return tk.Radiobutton(top, text="NSG", variable=self.server_type, command=on_server_type_change, value=0).grid(column=0, row=1) tk.Radiobutton(top, text="Other (SSH)", variable=self.server_type, command=on_server_type_change, value=1).grid(column=1, row=1) conn_option_frame = tk.LabelFrame(top, text="Connection Parameters") nsgconn_option_frame = tk.LabelFrame( top, text="NSG Connection Parameters") if (self.use_ssh.get() is "0"): nsgconn_option_frame.grid(column=0, row=3, sticky='news', padx=10, pady=5, columnspan=2) else: conn_option_frame.grid(column=0, row=2, sticky='news', padx=10, pady=5, columnspan=2) run_option_frame = tk.LabelFrame(top, text="Runtime Parameters") run_option_frame.grid(column=0, row=4, sticky='news', padx=10, pady=5, columnspan=2) ###GENERAL### l = tk.Label(conn_option_frame, text='Hostname', width=15, background='light gray') l.grid(row=2, column=0, pady=5, padx=5) l.config(relief=tk.GROOVE) self.host_e = tk.Entry(conn_option_frame, width=25, textvariable=self.hostname) self.host_e.grid(row=2, column=1, padx=5) l = tk.Label(conn_option_frame, text='Username', width=15, background='light gray') l.grid(row=3, column=0, pady=5, padx=5) l.config(relief=tk.GROOVE) self.user_e = tk.Entry(conn_option_frame, width=25, textvariable=self.user) self.user_e.grid(row=3, column=1, padx=5) l = tk.Label(conn_option_frame, text='Password', width=15, background='light gray') l.grid(row=4, column=0, pady=5, padx=5) l.config(relief=tk.GROOVE) self.pass_e = tk.Entry(conn_option_frame, width=25, show="*", textvariable=self.password) self.pass_e.grid(row=4, column=1, padx=5) l = tk.Label(conn_option_frame, text='Private Key', width=15, background='light gray') l.grid(row=5, column=0, pady=5, padx=5) l.config(relief=tk.GROOVE) self.key_e = tk.Entry(conn_option_frame, width=25, textvariable=self.keyfile) self.key_e.grid(row=5, column=1, padx=5) ####NSG### l = tk.Label(nsgconn_option_frame, text='Base URL', width=15, background='light gray') l.grid(row=2, column=0, pady=5, padx=5) l.config(relief=tk.GROOVE) self.nsg_url_e = tk.Entry(nsgconn_option_frame, width=25, textvariable=self.nsg_url) self.nsg_url_e.grid(row=2, column=1, padx=5) l = tk.Label(nsgconn_option_frame, text='Username', width=15, background='light gray') l.grid(row=3, column=0, pady=5, padx=5) l.config(relief=tk.GROOVE) self.nsg_user_e = tk.Entry(nsgconn_option_frame, width=25, textvariable=self.nsg_user) self.nsg_user_e.grid(row=3, column=1, padx=5) l = tk.Label(nsgconn_option_frame, text='Password', width=15, background='light gray') l.grid(row=4, column=0, pady=5, padx=5) l.config(relief=tk.GROOVE) self.nsg_pass_e = tk.Entry(nsgconn_option_frame, width=25, show="*", textvariable=self.nsg_password) self.nsg_pass_e.grid(row=4, column=1, padx=5) l = tk.Label(nsgconn_option_frame, text='Application Name', width=15, background='light gray') l.grid(row=5, column=0, pady=5, padx=5) l.config(relief=tk.GROOVE) self.nsg_app_name_e = tk.Entry(nsgconn_option_frame, width=25, textvariable=self.nsg_app_name) self.nsg_app_name_e.grid(row=5, column=1, padx=5) l = tk.Label(nsgconn_option_frame, text='Application ID', width=15, background='light gray') l.grid(row=6, column=0, pady=5, padx=5) l.config(relief=tk.GROOVE) self.nsg_app_id_e = tk.Entry(nsgconn_option_frame, width=25, textvariable=self.nsg_app_id) self.nsg_app_id_e.grid(row=6, column=1, padx=5) ####RUN PROPS##### l = tk.Label(run_option_frame, text='Partition', width=15, background='light gray') l.grid(row=2, column=0, pady=5, padx=5) l.config(relief=tk.GROOVE) self.partition_e = tk.Entry(run_option_frame, width=25, textvariable=self.partition) self.partition_e.grid(row=2, column=1, padx=5) l = tk.Label(run_option_frame, text='Nodes', width=15, background='light gray') l.grid(row=3, column=0, pady=5, padx=5) l.config(relief=tk.GROOVE) self.nodes_e = tk.Entry(run_option_frame, width=25, textvariable=self.nodes) self.nodes_e.grid(row=3, column=1, padx=5) l = tk.Label(run_option_frame, text='Cores per Node', width=15, background='light gray') l.grid(row=4, column=0, pady=5, padx=5) l.config(relief=tk.GROOVE) self.cores_e = tk.Entry(run_option_frame, width=25, textvariable=self.cores) self.cores_e.grid(row=4, column=1, padx=5) #Return button_frame = tk.Frame(top) button_frame.grid(row=20, column=0, columnspan=2) b = tk.Button(button_frame, text="Ok", command=self.ok) b.grid(pady=5, padx=5, column=0, row=0, sticky="WE") b = tk.Button(button_frame, text="Cancel", command=self.cancel) b.grid(pady=5, padx=5, column=1, row=0, sticky="WE") def load_file(self, top): self.hostname = tk.StringVar(top) self.user = tk.StringVar(top) self.password = tk.StringVar(top) self.keyfile = tk.StringVar(top) self.partition = tk.StringVar(top) self.nodes = tk.StringVar(top) self.cores = tk.StringVar(top) self.nsg_url = tk.StringVar(top) self.nsg_user = tk.StringVar(top) self.nsg_password = tk.StringVar(top) self.nsg_app_name = tk.StringVar(top) self.nsg_app_id = tk.StringVar(top) self.use_ssh = tk.StringVar(top) self.confirm = False #Inputs #tc.rnet.missouri.edu tbg28 INPUT NONE General 2 40 params_pd = pd.read_csv(self.params_file ,delimiter=';',\ header=None,\ names = self.column_names) self.hostname.set(params_pd[self.column_names[0]].get(0)) self.user.set(params_pd[self.column_names[1]].get(0)) self.password.set(params_pd[self.column_names[2]].get(0)) self.keyfile.set(params_pd[self.column_names[3]].get(0)) self.partition.set(params_pd[self.column_names[4]].get(0)) self.nodes.set(params_pd[self.column_names[5]].get(0)) self.cores.set(params_pd[self.column_names[6]].get(0)) self.nsg_url.set(params_pd[self.column_names[7]].get(0)) self.nsg_user.set(params_pd[self.column_names[8]].get(0)) self.nsg_password.set(params_pd[self.column_names[9]].get(0)) self.nsg_app_name.set(params_pd[self.column_names[10]].get(0)) self.nsg_app_id.set(params_pd[self.column_names[11]].get(0)) self.use_ssh.set(params_pd[self.column_names[12]].get(0)) def save_file(self): d = [self.hostname.get(), self.user.get(),\ self.password.get(), self.keyfile.get(),\ self.partition.get(), self.nodes.get(),\ self.cores.get(), self.nsg_url.get(),\ self.nsg_user.get(), self.nsg_password.get(),\ self.nsg_app_name.get(), self.nsg_app_id.get(),\ self.use_ssh.get()] df = pd.DataFrame(d) df.transpose().to_csv(self.params_file, sep=';',\ header=None,index=False) def verify_good(self): return True def ok(self): self.confirm = True self.save_file() self.top.destroy() def cancel(self): self.top.destroy()