class DlgDelay(Dialog): def body(self, master, cfg={}): "place user dialog widgets" self.config = cfg self.config["OK button"] = False self.delay = StringVar() self.delay.set(cfg.get("delay", "")) self.edelay = Entry(master, width=15, textvariable=self.delay) self.edelay.grid(column=1, row=0, sticky="e") Label(master, text=_("Delay:")).grid(column=0, row=0, sticky="w") self.resizable(width=0, height=0) return self.edelay def validate(self): try: flt = float(self.delay.get()) except ValueError: return self.edelay if flt < 0 or flt > 5: return self.edelay return None def apply(self): "On ok button pressed" self.config["delay"] = self.delay.get() self.config["OK button"] = True
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 ParseGUI(object): """Class used for the GUI The object parameter is the root widget for the Tkinter GUI """ def __init__(self, master): """Constructor method :param master: A "master" wigdet """ self.mainframe = Frame(master) # Create a Frame child widget self.mainframe.pack() # Make the widget visible self.path = '' # Define default path for the .xmcd file self.texfile_path = '' # Define path for the .tex file self.name = Label(self.mainframe, text="Welcome to Mathcad to LaTeX converter") # Create a static text label self.name.pack(side="top") # Make the widget visible and define location self.filename = StringVar() # Create a dynamic string variable self.filename.set("Current selected file: none") # Set the string value self.filename_label = Label(self.mainframe, textvariable=self.filename) # Create a label with the dynamic var self.filename_label.pack() self.text_updater = Entry(self.mainframe, textvariable=self.filename) # Create a Entry widget for auto updates self.status = StringVar() # Used for displaying the status of the file operation self.status.set("Status: Not parsed") self.status_label = Label(self.mainframe, textvariable=self.status) self.status_label.pack() self.text_updater2 = Entry(self.mainframe, textvariable=self.status) self.parse_file = Button(self.mainframe, text="Parse and save!", command=self.parse_file) # Button for parsing self.parse_file.pack(side="right") self.parse_file = Button(self.mainframe, text="Open LaTeX file", command=self.open_file) self.parse_file.pack(side="right") self.select_file = Button(self.mainframe, text="Select file", command=self.select_file) # Runs a class method self.select_file.pack(side="right") def select_file(self): # Method used for selecting a file self.path = askopenfilename() # Display native os file dialog for choosing a file self.filename.set("Current selected file: " + os.path.basename(self.path)) # Change the dynamic variable self.status.set("Status: Not parsed") # Set status def open_file(self): # Method used for opening the parsed LaTeX file self.texfile_path = os.path.dirname(self.path) + '/ParsedLatexFile/' + os.path.splitext(os.path.basename(self.path))[0] + '.tex' if self.status.get() == "Status: File tried parsed! Look under the folder \ParsedLatexFile !": os.system("start " + "\"\" \"" + self.texfile_path + "\"") def parse_file(self): # Method for parsing the chosen file # Make sure a file is selected and it is a Mathcad file before trying to parse it if self.filename.get() != 'Current selected file: none' and os.path.splitext(self.path)[1] == '.xmcd': self.status.set("Status: Tring to parse... (most files takes a few seconds)") MathcadXMLParser(self.path) # Call the MathcadXMLParser class with the path self.status.set("Status: File tried parsed! Look under the folder \ParsedLatexFile !") # Display a error message to the user else: self.status.set("Status: You need to select a .xmcd (Mathcad) file!")
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 DiceTab(Frame): def __init__(self,master=None): Frame.__init__(self,master) #Sides of Dice labelSides=Label(self,text="Sides") labelSides.grid(row=0,column=0) self.sides=StringVar() self.sides.set(20) spinboxSides=Spinbox(self,from_=1,to=20,increment=1,width=4) spinboxSides.config(textvariable=self.sides, font="sans 24", justify="center") spinboxSides.grid(row=0,column=1) #Number of Dices labelNumber=Label(self,text="Number") labelNumber.grid(row=1,column=0) self.number=StringVar() self.number.set(1) spinboxNumber=Spinbox(self,from_=1,to=30,increment=1,width=4) spinboxNumber.config(textvariable=self.number, font="sans 24", justify="center") spinboxNumber.grid(row=1,column=1) #Modifier labelModifier=Label(self,text="Modifier") labelModifier.grid(row=2,column=0) self.modifier=StringVar() self.modifier.set(0) spinboxModifier=Spinbox(self,from_=-5,to=5,increment=1,width=4) spinboxModifier.config(textvariable=self.modifier, font="sans 24", justify="center") spinboxModifier.grid(row=2,column=1) #Hide Checkbox labelHide=Label(self, text="Hide") labelHide.grid(row=2, column=2) self.hide=IntVar() self.hide.set(0) checkbuttonHide=Checkbutton(self,variable=self.hide) checkbuttonHide.grid(row=2,column=3) #Result display self.result=StringVar() self.result.set("") labelResult1=Label(self,text="Result") labelResult1.grid(row=1, column=4) labelResult2=Label(self,text=self.result.get(),relief=SUNKEN,width=4) labelResult2.grid(row=1,column=5) #Button to roll buttonRoll=Button(self,text="Roll!", command=self.roll) buttonRoll.grid(row=2,column=5) def roll(self): self.throws=[] numberOfDices=int(self.number.get()) sidesOfDice=int(self.sides.get()) modifierOfDice=int(self.modifier.get()) for i in range(numberOfDices): self.throws.append(rd.randint(1,sidesOfDice)) self.result.set(str(sum(self.throws)+modifierOfDice)) labelResult2=Label(self,text=self.result.get(),relief=SUNKEN, width=4) labelResult2.grid(row=1,column=5)
class Valve: def __init__(self, name, setting, action_a, action_b, interval): self.name = StringVar() self.name.set('Valve') self.set_name(name) self.setting = setting self.interval = interval self.action_a = StringVar() self.action_a.set('ACTION A') self.set_action_a(action_a) self.action_b = StringVar() self.action_b.set('ACTION B') self.set_action_b(action_b) def __str__(self): string = 'NAME:\t ' + self.name.get() + '\nACTION A:\t' + self.action_a.get() + '\t\tSETTNG:\t' + self.setting string += '\nACTION B:\t' + self.action_b.get() + '\t\tINTERVAL:\t(' + str(self.interval[0]) + ', ' + str(self.interval[1]) + ')\n' return string def get_name(self): return self.name def set_name(self, name): self.name.set(name) def get_setting(self): return self.setting def set_setting(self, setting): self.setting = setting def get_interval(self): return self.interval def set_interval(self, interval): self.interval = interval def get_action_a(self): return self.action_a def set_action_a(self, action): self.action_a.set(action) def get_action_b(self): return self.action_b def set_action_b(self, action): self.action_b.set(action)
class Select_Py_Version(_Dialog): """ Select_Py_Version is a tkinter pop-up dialog used to select a python interpreter for use with Tk_Nosy. """ def body(self, master): dialogframe = Frame(master, width=300, height=300) dialogframe.pack() self.Label_1 = Label(dialogframe, text="Select Python Version") self.Label_1.pack() if self.dialogOptions: rbL = self.dialogOptions.get('rbL', ['No Options','No Options']) else: rbL = ['No Options', 'No Options'] self.RadioGroup1_StringVar = StringVar() self.RadioGroup1_StringVar.set(rbL[0]) self.RadioGroup1_StringVar_traceName = \ self.RadioGroup1_StringVar.trace_variable("w", self.RadioGroup1_StringVar_Callback) for rb in rbL: self.Radiobutton_1 = Radiobutton(dialogframe, text=rb, value=rb) self.Radiobutton_1.pack(anchor=W) self.Radiobutton_1.configure( variable=self.RadioGroup1_StringVar ) self.resizable(0, 0) # Linux may not respect this def RadioGroup1_StringVar_Callback(self, varName, index, mode): """When radio group selection changes, print message to CLI.""" print( "RadioGroup1_StringVar_Callback varName, index, mode", varName, index, mode ) print( " new StringVar value =", self.RadioGroup1_StringVar.get() ) def validate(self): """Validates and packages dialog selections prior to return to calling routine. set values in "self.result" dictionary for return """ self.result = {} # return a dictionary of results self.result["selection"] = self.RadioGroup1_StringVar.get() return 1 def apply(self): print( 'apply called')
class KRCCModule: __metaclass__ = ABCMeta def __init__(self): self._terminate = BooleanVar(False) self._id = StringVar(False) @property def terminate(self): return self._terminate.get() @terminate.setter def terminate(self, value): self._terminate.set(value) @property def id(self): return self._id.get() @id.setter def id(self, value): self._id.set(value) @abstractproperty def name(self): pass @abstractmethod def run(self): pass
class Example(Frame): def __init__(self, master): Frame.__init__(self, master) self.dict = {'Asia': ['Japan', 'China', 'India'], 'Europe': ['Portugal', 'Switzerland', 'Ukraine']} self.var_a = StringVar(self) self.var_b = StringVar(self) self.var_a.trace('w', self.update_options) self.option_menu_a = OptionMenu(self, self.var_a, *self.dict.keys()) self.option_menu_a.pack(side="top") self.option_menu_a["width"] = 10 self.option_menu_b = OptionMenu(self, self.var_b, '') self.option_menu_b["width"] = 10 self.option_menu_b.pack(side="top") self.var_a.set('Asia') def update_options(self, *args): countries = self.dict[self.var_a.get()] self.var_b.set(countries[0]) menu = self.option_menu_b['menu'] menu.delete(0, 'end') for c in countries: menu.add_command(label=c, command=lambda x=c: self.var_b.set(x))
class GuiGeneratorSelect(Frame): def __init__(self, parent, generators): Frame.__init__(self, parent) self.parent = parent self.pack() self._generators = generators self._generatorName = StringVar() self._generatorName.set(generators[0].getName()) self._generatorName.trace("w", self._switchSettings) self._generatorLbl = Label(self, text="Generator"); self._generatorLbl.pack(side=LEFT) param = (self, self._generatorName) + tuple(i.getName() for i in generators) self._generatorOpt = OptionMenu(*param) self._generatorOpt.pack(side=LEFT) self._switchSettings() def _switchSettings(self, *args): print("DBG: switch generator settings") for i in self._generators: if i.getName() == self._generatorName.get(): i.pack() self._generatorGui = i print("pack " + str(i.getName())) else: i.pack_forget() print("unpack " + str(i.getName())) def getCurrGeneratorGui(self): return self._generatorGui
class PredictionWidget(Frame): """Shows a prediction to the user.""" def __init__(self, master): """Make boxes, register callbacks etc.""" Frame.__init__(self, master) self.active_category = StringVar() self.bind("<Configure>", self.onResize) self.date = None self.predictor = Predictor() self.category_buttons = self.createCategoryButtons() self.text = Label(self, justify=CENTER, font="Arial 14") def createCategoryButtons(self): """Create the buttons used to choose category. Return them.""" result = [] icons = self.readIcons() categories = self.predictor.categories() for i in categories: if i in icons: icon = icons[i] else: icon = icons["= default ="] category_button = Radiobutton(self, image=icon, variable=self.active_category, value=i, indicatoron=False, width=icon_size, height=icon_size, command=self.update) category_button.image_data = icon result.append(category_button) self.active_category.set(categories[0]) return result def readIcons(self): """Read the gui icons from disk. Return them.""" result = {} categories = open(nextToThisFile("icons.txt")).read().split("\n\n") for i in categories: category_name, file_data = i.split("\n", maxsplit=1) image = PhotoImage(data=file_data) result[category_name] = image return result def onResize(self, event): """Rearrange the children when the geometry of self changes.""" if event.widget == self: center = (event.width / 2, event.height / 2) radius = min(center) - icon_size / 2 self.text.place(anchor=CENTER, x=center[0], y=center[1]) for i, j in enumerate(self.category_buttons): turn = 2 * math.pi angle = turn * (1 / 4 - i / len(self.category_buttons)) j.place(anchor=CENTER, x=center[0] + math.cos(angle) * radius, y=center[1] - math.sin(angle) * radius) def update(self, date=None): """Change contents based on circumstances. Set date if given.""" if date: self.date = date if self.date: predictions = self.predictor.predict(self.date) prediction = predictions[self.active_category.get()] prediction = textwrap.fill(prediction, width=20) else: prediction = "" self.text.configure(text=prediction)
def test_CheckbuttonWithVar(): parent = Tk() var = StringVar(master=parent) var.set(1) box = CheckbuttonWithVar(parent, var) box.deselect() assert var.get() == '0' parent.destroy()
class OptionMenu45(OptionMenu): def __init__(self,parent,title,option_list,**config): self.result = StringVar() self.result.set(title) OptionMenu.__init__(self,parent,self.result,*option_list,**config) def get(self): return self.result.get()
class FeasDisp(ttk.Frame): """Widget for displaying all of the feasible states in the conflict.""" def __init__(self, master=None, conflict=None, *args): """Initialize the widget.""" ttk.Frame.__init__(self, master, padding=5) self.columnconfigure(1, weight=1) self.rowconfigure(2, weight=1) self.conflict = conflict self.dispFormat = StringVar(value='pattern') self.dispList = StringVar() self.feasList = [] self.fmts = {'Pattern': 'YN-', 'List (YN)': 'YN', 'List (ordered and [decimal])': 'ord_dec'} cBoxOpts = ('Pattern', 'List (YN)', 'List (ordered and [decimal])') self.feasText = ttk.Label(self, text='Feasible States') self.feasText.grid(row=0, column=0, columnspan=3) self.cBox = ttk.Combobox(self, textvariable=self.dispFormat, values=cBoxOpts, state='readonly') self.cBoxLb = ttk.Label(self, text='Format:') self.feasLBx = Listbox(self, listvariable=self.dispList) self.scrl = ttk.Scrollbar(self, orient=VERTICAL, command=self.feasLBx.yview) # ########### self.cBoxLb.grid(column=0, row=1, sticky=NSEW, pady=3) self.cBox.grid(column=1, row=1, columnspan=2, sticky=NSEW, pady=3) self.feasLBx.grid(column=0, row=2, columnspan=2, sticky=NSEW) self.scrl.grid(column=2, row=2, sticky=NSEW) self.cBox.bind('<<ComboboxSelected>>', self.fmtSel) self.feasLBx.configure(yscrollcommand=self.scrl.set) self.dispFormat.set('Pattern') self.fmtSel() def fmtSel(self, *args): """Action on selection of a new format.""" self.refreshList() def setFeas(self, feasList): """Change the list of feasible states to be displayed.""" self.feasList = feasList self.refreshList() def refreshList(self): """Update the list of feasible states displayed and the format.""" fmt = self.fmts[self.dispFormat.get()] if fmt == "YN-": feas = self.conflict.feasibles.dash if fmt == "YN": feas = self.conflict.feasibles.yn if fmt == "ord_dec": feas = self.conflict.feasibles.ordDec self.dispList.set(tuple(feas))
class RankingEditor(ttk.Frame): """Display and edit the state ranking for a single Decision Maker.""" def __init__(self, master, conflict, dm): """Initialize a RankingEditor widget for a decision maker.""" ttk.Frame.__init__(self, master, borderwidth=2) self.master = master self.conflict = conflict self.dm = dm self.columnconfigure(1, weight=1) self.dmText = StringVar(value=dm.name + ': ') self.dmLabel = ttk.Label(self, textvariable=self.dmText, width=20) self.dmLabel.grid(row=0, column=0, sticky=NSEW) self.prefRankVar = StringVar(value=str(dm.perceivedRanking)) self.prefRankEntry = ttk.Entry(self, textvariable=self.prefRankVar) self.prefRankEntry.grid(row=0, column=1, sticky=NSEW) self.errorDetails = None self.prefRankEntry.bind("<FocusOut>", self.onFocusOut) def onFocusOut(self, event): """Validate the preference ranking when focus leaves the widget.""" try: perceivedRank = literal_eval(self.prefRankVar.get()) except SyntaxError: self.errorDetails = ("DM {}'s preference ranking is " "invalid.").format(self.dm.name) self.master.event_generate("<<errorChange>>") return except NameError: self.errorDetails = ("DM {}'s preference ranking is " "invalid.").format(self.dm.name) self.master.event_generate("<<errorChange>>") return prefRank = perceivedRank + self.dm.misperceived self.errorDetails = gmcrUtil.validatePreferenceRanking( prefRank, self.conflict.feasibles) if self.errorDetails: self.errorDetails += (" Check DM {}'s preference " "ranking.").format(self.dm.name) self.master.event_generate("<<errorChange>>") return self.dm.preferenceRanking = prefRank self.dm.calculatePreferences() self.master.event_generate("<<errorChange>>") def enableWidget(self): """Enable editting of the ranking.""" self.prefRankEntry['state'] = 'normal' def disableWidget(self): """Disable editting of the ranking.""" self.prefRankEntry['state'] = 'disabled'
class GuiBasicSettings(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.pack() #Unit self.sizeUnits = {"Byte": 1, "KiB":1024, "MiB":1024**2, "GiB":1024**3} self._initFile() self._initSize() def _initFile(self): self._fileLbl = Label(self, text="File: ") self._fileTxt = Entry(self) self._fileTxt.insert(0, "/tmp/out.txt") self._fileBtn = Button(self, text="Create", command=self._callbackFun) self._fileLbl.grid(row=0, column=0) self._fileTxt.grid(row=0, column=1) self._fileBtn.grid(row=0, column=2) def _initSize(self): self._sizeLbl = Label(self, text="FileSize: ") self._sizeTxt = Entry(self) self._sizeTxt.insert(0, "1024") self._sizeVar = StringVar() self._sizeVar.set("Byte") #FIXME: replace "Byte" with variable sizeOptParam = (self, self._sizeVar) + tuple(self.sizeUnits.keys()) self._sizeOptMen = OptionMenu(*sizeOptParam) self._sizeLbl.grid(row=1, column=0) self._sizeTxt.grid(row=1, column=1) self._sizeOptMen.grid(row=1, column=2) def _callbackFun(self): print("_callbackBtn") self.outerCallback() def enableButton(self, enabled=True): if enabled: self._fileBtn.config(state="normal") else: self._fileBtn.config(state="disabled") def getFileName(self): return self._fileTxt.get() def getFileSize(self): mult = int(self.sizeUnits[self._sizeVar.get()]) val = int(self._sizeTxt.get()) return val * mult def setCallback(self, aCallback): self.outerCallback = aCallback
class SliderFrequency(Frame): def __init__(self,root, freq, val, Min=0.0, Max=1.0, sId=0): Frame.__init__(self,root) self.root = root self.id = sId self.freq = freq self.min = Min self.max = Max self.gain = StringVar() self.gain.set(val) self.value = StringVar() self.value.set( str(self._Gain(val))+" dB") self.initialize() self.gain.set(self._Gain(val)) def initialize(self): self.slider = Scale(self.root, orient=VERTICAL, from_=self.min, to=self.max, value=float(self.gain.get()), command=self._updateValue) self.slider.grid(row=0,column=self.id, padx=10) self.valueLbl = Label(self.root, anchor="w", textvariable=self.value) self.valueLbl.grid(row=1,column=self.id, padx=10) self.freqLbl = Label(self.root,text=str(self.freq)+" Hz") self.freqLbl.grid(row=2,column=self.id, padx=10) def _updateValue(self,event): self.gain.set(self._Gain(self.slider.get())) self.value.set(str(self.gain.get())+" dB") self.valueLbl.update() def _Gain(self, value): v = -(float(value)-((self.max-self.min)/2)) v = int(v*10)/10 return v def getGain(self): return float(self.gain.get())
class Application: def __init__(self, root): self.root = root self.create_frame_top() def create_frame_top(self): self.frm_bottom = tk.LabelFrame(self.root) self.frm_bottom.grid(row=1, column=0, padx=15, pady=2) self.frm_top_label = tk.Label(self.root, text="sqlite db数据对比工具") self.frm_top_label.grid(row=0, column=0, padx=15, pady=2) self.frm_bottom_entry_var_0_db1 = StringVar() self.frm_bottom_entry_0 = tk.Entry(self.frm_bottom, text=self.frm_bottom_entry_var_0_db1) self.frm_bottom_entry_0.grid(row=0, column=1, padx=15, pady=2) self.frm_bottom_btn_0 = tk.Button(self.frm_bottom, text="Do compare", command=self.open_file1) self.frm_bottom_btn_0.grid(row=0, column=2, padx=15, pady=2) self.frm_bottom_entry_var_1_db2 = StringVar() self.frm_bottom_entry_1 = tk.Entry(self.frm_bottom, text=self.frm_bottom_entry_var_1_db2) self.frm_bottom_entry_1.grid(row=1, column=1, padx=15, pady=2) self.frm_bottom_btn_1 = tk.Button(self.frm_bottom, text="Do compare", command=self.open_file2) self.frm_bottom_btn_1.grid(row=1, column=2, padx=15, pady=2) def open_file1(self): self.fname1 = filedialog.askopenfilename( filetypes=(("sqlite files", "*.sqlite;*.db"), ("All files", "*.*"))) print(self.fname1) self.frm_bottom_entry_var_0_db1.set(self.fname1) print(self.frm_bottom_entry_var_0_db1.get()) def open_file2(self): self.fname2 = filedialog.askopenfilename( filetypes=(("sqlite files", "*.sqlite;*.db"), ("All files", "*.*"))) print(self.fname2) self.frm_bottom_entry_var_1_db2.set(self.fname2) print(self.frm_bottom_entry_var_1_db2.get())
class AccountDialog(gui.tksimpledialog.Dialog): def __init__(self, parent, title="", login_name="", password="", path="", dx="dx11"): self.login_name = login_name self.password = password self.path = path self.dx = dx self.entry_ln = None self.variable = None self.entry_pw = None self.entry_path = None self.entry_dx = None super().__init__(parent, title) def body(self, master): Label(master, text="Login Name:").grid(row=0) Label(master, text="Password:"******"Eve Path:").grid(row=2) Label(master, text="DirectX:").grid(row=3) self.entry_ln = Entry(master) self.entry_pw = Entry(master, show="*") self.entry_path = Entry(master) self.variable = StringVar(master) self.variable.set(self.dx) self.entry_dx = OptionMenu(master, self.variable, "dx9", "dx11") self.entry_ln.insert(END, self.login_name) self.entry_pw.insert(END, self.password) self.entry_path.insert(END, self.path) # self.entry_path.bind("<FocusIn>", self.select_eve_path) self.entry_ln.grid(row=0, column=1) self.entry_pw.grid(row=1, column=1) self.entry_path.grid(row=2, column=1) self.entry_dx.grid(row=3, column=1) return self.entry_ln # def select_eve_path(self, event): # if event.widget == self.entry_path: # self.path # res = os.path.normpath(askdirectory(initialdir=self.path)) # self.path = res # self.entry_path.insert(END, res) def apply(self): login_name = self.entry_ln.get() password = self.entry_pw.get() path = self.entry_path.get() dx = self.variable.get() self.result = [login_name, password, path, dx]
class ApplicationController(Tk): def __init__(self, *args, **kwargs): Tk.__init__(self, *args, **kwargs) container = Frame(self) self.title("3d Printer") #This fied is populated on the first view #and displayed on the second self.customer_id = StringVar() container.pack(side="top", fill="both", expand=True) container.grid_rowconfigure(0, weight=1) container.grid_columnconfigure(0, weight=1) self.frames = {} for F in (CreateCustomerView, ExecuteScriptView): frame = F(container, self) self.frames[F] = frame # put all of the pages in the same location; # the one on the top of the stacking order # will be the one that is visible. frame.grid(row=0, column=0, sticky="nsew") self.model = CreateCustomerModel() self.show_frame(CreateCustomerView) def show_frame(self, c): '''Show a frame for the given class''' frame = self.frames[c] frame.tkraise() def save_customer(self, customer): """Save customer and go to next page""" customer_id = self.model.save_customer(customer) if customer_id: self.customer_id.set(customer_id) print(self.customer_id.get()) self.show_frame(ExecuteScriptView) else: messagebox.showerror(message = "All fields are mandatory, please fill in all the fields") def run_take_picture_script(self, customer_id, picture_mode): """Example of executing outside python script""" return self.model.run_take_picture_script(customer_id, picture_mode) def run_update_script(self): pass
def nameHandler(name, message): '''Takes a string name and character, provides an interface for correcting the illegal name, returns a new legal string name.''' #todo: create a proper validate method def destroy(*args): root.destroy() root = Toplevel() root.title('Bad Name') root.resizable(False, False) root.after(100, root.focus_force) #todo: temp? mainFrame = ttk.Frame(root, padding=MAIN_PAD) mainFrame.grid(column=0, row=0, sticky='nwes') newname = StringVar(value=name) nameEntry = ttk.Entry(mainFrame, textvariable=newname) nameEntry.grid(row=1, sticky='we') ttk.Label(mainFrame, text=message).grid(row=0) for child in mainFrame.winfo_children(): child.grid(padx=5, pady=5) nameEntry.after(100, nameEntry.focus) #todo: temp? root.bind('<Return>', destroy) root.wait_window() #todo: disable the ability to close the window instead? add abort option? if len(newname.get()) < 1: return nameHandler(name, message) else: return newname.get()
def ask_class_name(): win = Toplevel() module_name = StringVar() class_name = StringVar() module_item = LabeledEntry(win) module_item.label_text = 'Module Name' module_item.pack() module_item.entry_variable = module_name class_item = LabeledEntry(win) class_item.label_text = 'Class Name' class_item.pack() class_item.entry_variable = class_name Button(win, text='OK', command=win.quit).pack() win.protocol('WM_DELETE_WINDOW', win.quit) win.focus_set() win.grab_set() win.mainloop() win.destroy() return module_name.get(), class_name.get()
def widget_checkmark(parent: tk.Frame, var: tk.StringVar, conf: Property): """Allows ticking a box.""" # Ensure it's a bool value. if conv_bool(var.get()): var.set('1') else: var.set('0') return ttk.Checkbutton( parent, text='', variable=var, onvalue='1', offvalue='0', command=widget_sfx, )
class EntryTextHolder(Entry): def __init__(self, master=None): Entry.__init__(self, master) self._value = StringVar() self['textvariable'] = self._value self._value.trace('w', self._valuechanged) self.model = TextHolderModel(view=self) def _valuechanged(self, *args): self.model.text = self._value.get() #--- model --> view def update_text(self): text = self.model.text if text != self.get(): self.delete(0, 'end') self.insert(0, text)
class SliderParameter(Frame): """ A frame contening additionnals parameters for filter (represented by a SliderFrequency) to set the type and the Q factor parameters: root: Canvas the canvas to place the SliderParameter type: String A string representing the type of a filter Q: String the Q factor of a filter id: int ID of th SliderParameter """ def __init__(self,root, type, Q, id): Frame.__init__(self,root) self.root = root self.typeFilter = StringVar() self.typeFilter.set(type) self.qFactor = StringVar() self.qFactor.set(Q) self.id = id self.initialize() def initialize(self): """ Initialize the combobox contening all available type of filter and the entry text to choose the value of Q factor """ self.typeCombo = Combobox(self.root, textvariable=self.typeFilter, values=F.values(), width="5") self.typeCombo.grid(row=1,column=self.id, padx=10) self.qText = Entry(self.root, textvariable=self.qFactor, width="5") self.qText.grid(row=2,column=self.id, padx=10, pady=5) def getQ(self): """ return the value of the Q factor """ return self.qFactor.get() def getType(self): """ Return the type of the filter """ return self.typeCombo.get()
class Options(Frame): def __init__(self, master, ordinances=False, **kwargs): super(Options, self).__init__(master, **kwargs) self.ancestors = IntVar() self.ancestors.set(4) self.descendants = IntVar() self.spouses = IntVar() self.ordinances = IntVar() self.contributors = IntVar() self.start_indis = StartIndis(self) self.fid = StringVar() btn = Frame(self) entry_fid = EntryWithMenu(btn, textvariable=self.fid, width=16) entry_fid.bind('<Key>', self.enter) label_ancestors = Label(self, text=_('Number of generations to ascend')) entry_ancestors = EntryWithMenu(self, textvariable=self.ancestors, width=5) label_descendants = Label(self, text=_('Number of generations to descend')) entry_descendants = EntryWithMenu(self, textvariable=self.descendants, width=5) btn_add_indi = Button(btn, text=_('Add a FamilySearch ID'), command=self.add_indi) btn_spouses = Checkbutton(self, text='\t' + _('Add spouses and couples information'), variable=self.spouses) btn_ordinances = Checkbutton(self, text='\t' + _('Add Temple information'), variable=self.ordinances) btn_contributors = Checkbutton(self, text='\t' + _('Add list of contributors in notes'), variable=self.contributors) self.start_indis.grid(row=0, column=0, columnspan=3) entry_fid.grid(row=0, column=0, sticky='w') btn_add_indi.grid(row=0, column=1, sticky='w') btn.grid(row=1, column=0, columnspan=2, sticky='w') entry_ancestors.grid(row=2, column=0, sticky='w') label_ancestors.grid(row=2, column=1, sticky='w') entry_descendants.grid(row=3, column=0, sticky='w') label_descendants.grid(row=3, column=1, sticky='w') btn_spouses.grid(row=4, column=0, columnspan=2, sticky='w') if ordinances: btn_ordinances.grid(row=5, column=0, columnspan=3, sticky='w') btn_contributors.grid(row=6, column=0, columnspan=3, sticky='w') entry_ancestors.focus_set() def add_indi(self): if self.start_indis.add_indi(self.fid.get()): self.fid.set('') def enter(self, evt): if evt.keysym in {'Return', 'KP_Enter'}: self.add_indi()
class SaveGui: __name = None def __init__(self, main_controller, window): self.__main_controller = main_controller self.__window = window self.__menu = None def show(self): self.__menu = Frame(self.__window) self.__menu.configure(padx=10, pady=20) self.__menu.pack(fill=BOTH, expand=True) line1 = Frame(self.__menu) line1.pack(fill=X) self.__name = StringVar() self.__name.set("my_game_at_"+strftime("%H:%M")+"-"+strftime("%d.%m.%Y")) name_input = Entry(line1) name_input.configure(textvariable=self.__name) name_input.pack(fill=X) line2 = Frame(self.__menu) line2.pack(fill=X, pady=20) save_btn = Button(line2) save_btn.configure(text="Save Game", command=self.save) save_btn.pack(fill=X) def remove(self): if self.__menu is not None: self.__menu.destroy() self.__memu = None def save(self): if self.__name is not None: self.__main_controller.save_game(self.__name.get()) self.remove() self.__main_controller.show_game() self.__main_controller.toggle_game() self.__main_controller.toggle_game()
class NumberEntry(Entry): def __init__(self, master, **kw): self.strVar = StringVar() vcmd = (master.register(self.isValid), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W') Entry.__init__(self, master, textvariable=self.strVar, validate='key', validatecommand=vcmd, **kw) def setVal(self, val): self.delete(0, END) self.insert(0, '%.2f' % (val)) def getVal(self): return float(self.strVar.get()) def isValid(self, action, index, value_if_allowed, prior_value, text, validation_type, trigger_type, widget_name): try: float(value_if_allowed) return True except ValueError: return False
class ConsultaSaldo: def __init__(self, master, produto, main=None): self.app_main = tkinter.Toplevel(master) self.app_main.title("Cadastro de Tipo de Carregamento") self.centralizar_tela() self.main = main self.tipo_carregamento_atual = None self.produto_atual = produto self.entry_nome = None self.cb_inspecao_veiculo = None self.cb_inspecao_produto = None self.cb_remover_a = None self.rb_nao_informar_lacres = None self.rb_informar_lacres_lona = None self.rb_informar_lacres = None self.rb_informar_lacres_lona = None self.entry_codigo_transportador = None self.entry_tipo_frete = None self.entry_destino_frete = None self.entry_docs_diversos = None self.entry_numero_ordem = None self.entry_numero_pedido_frete = None self.nome = StringVar() self.inspecao_produto = IntVar() self.inspecao_veiculo = IntVar() self.remover_a = IntVar() self.tipo_lacre = IntVar() self.codigo_transportador = StringVar() self.tipo_frete = StringVar() self.destino_frete = StringVar() self.numero_ordem = StringVar() self.numero_pedido_frete = StringVar() self.quantidade_item_remessa = StringVar() self.entry_cnpj = None self.entry_data_inicial = None self.entry_data_final = None self.dif_icms = StringVar() self.cnpj = StringVar() self.data_inicial = StringVar() self.data_final = StringVar() self.treeview_itens = None self.atualizando_cadastro = False Label(self.app_main, text="CNPJ").grid(sticky=W, column=0, row=0, padx=10) self.entry_cnpj = Entry(self.app_main, textvariable=self.cnpj) self.entry_cnpj.grid(sticky="we", column=0, row=1, padx=10, ipady=2, columnspan=7) self.entry_cnpj.config(validate="key", validatecommand=(self.app_main.register(NumberUtils.eh_inteiro), '%P')) self.entry_cnpj.bind('<Return>', self.consultar_saldo) Label(self.app_main, text="Data Inicial", ).grid(sticky=W, column=7, row=0, padx=10) self.entry_cnpj = Entry(self.app_main, textvariable=self.data_inicial) self.entry_cnpj.grid(sticky="we", column=7, row=1, padx=10, ipady=2) Label(self.app_main, text="Data Final").grid(sticky=W, column=8, row=0, padx=10) self.entry_cnpj = Entry(self.app_main, textvariable=self.data_final) self.entry_cnpj.grid(sticky="we", column=8, row=1, padx=10, ipady=2) Button(self.app_main, text='Pesquisar', command=self.consultar_saldo) \ .grid(sticky="we", column=9, row=1, padx=10) self.treeview_itens = Treeview(self.app_main, height=10, column=("c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8") , show="headings") self.treeview_itens.bind("<Double-1>", self.inserir_quantidade_item) self.treeview_itens.heading("#1", text="Data") self.treeview_itens.heading("#2", text="Ordem") self.treeview_itens.heading("#3", text="Material") self.treeview_itens.heading("#4", text="Cliente") self.treeview_itens.heading("#5", text="Cidade") self.treeview_itens.heading("#6", text="Qtd") self.treeview_itens.heading("#7", text="Qtd. Disp.") self.treeview_itens.heading("#8", text="Pedido") self.treeview_itens.heading("#9", text="Tipo") self.treeview_itens.column("c0", width=70, stretch=NO, anchor=CENTER) self.treeview_itens.column("c1", width=60, stretch=NO, anchor=CENTER) self.treeview_itens.column("c2", width=120, stretch=NO, anchor=CENTER) self.treeview_itens.column("c3", width=150, stretch=NO, anchor=CENTER) self.treeview_itens.column("c4", width=100, stretch=NO, anchor=CENTER) self.treeview_itens.column("c5", width=70, stretch=NO, anchor=CENTER) self.treeview_itens.column("c6", width=70, stretch=NO, anchor=CENTER) self.treeview_itens.column("c7", width=70, stretch=NO, anchor=CENTER) self.treeview_itens.column("c8", width=50, stretch=NO, anchor=CENTER) self.treeview_itens.tag_configure('teste', background='red') self.treeview_itens.tag_configure('fg', foreground='red') self.treeview_itens.grid(sticky="we", row=7, padx=10, pady=5, columnspan=10) Label(self.app_main, text="Quantidade: ").grid(sticky=W, row=8, padx=10) self.entry_data_inicial = Entry(self.app_main, textvariable=self.quantidade_item_remessa) self.entry_data_inicial.grid(sticky="we", row=9, column=0, padx=10, ipady=2, pady=(0, 15)) self.entry_data_inicial.config(validate="key", validatecommand=(self.app_main.register(NumberUtils.eh_decimal), '%P')) Button(self.app_main, text='Inserir', command=self.inserir_main) \ .grid(sticky="we", column=1, row=9, pady=(0, 15)) self.setar_datas() def centralizar_tela(self): # Gets the requested values of the height and widht. window_width = self.app_main.winfo_reqwidth() window_height = self.app_main.winfo_reqheight() # Gets both half the screen width/height and window width/height position_right = int(self.app_main.winfo_screenwidth() / 2.3 - window_width / 2) position_down = int(self.app_main.winfo_screenheight() / 3 - window_height / 2) # Positions the window in the center of the page. self.app_main.geometry("+{}+{}".format(position_right, position_down)) def setar_datas(self): hoje = date.today() hoje_formatado = hoje.strftime("%d.%m.%Y") data_inicial = hoje - relativedelta(years=1) data_inicial_formatada = data_inicial.strftime("%d.%m.%Y") self.data_inicial.set(data_inicial_formatada) self.data_final.set(hoje_formatado) def consultar_saldo(self, event=None): try: session = SAPGuiApplication.connect() ordens = ZSD020.consultar_saldo_cliente( session, self.cnpj.get(), self.data_inicial.get(), self.data_final.get(), self.produto_atual) self.inserir_item_remessa(ordens) except Exception as e: traceback.print_exc(file=sys.stdout) messagebox.showerror("Erro", e) def inserir_item_remessa(self, ordens): try: self.validar_novo_item() except RuntimeError as e: messagebox.showerror("Erro", str(e)) return self.limpar_treeview() for ordem in ordens: self.treeview_itens.insert("", "end", values=(ordem.data, ordem.numero, ordem.material, ordem.cliente, ordem.cidade, ordem.qtd, ordem.qtd_disponivel, ordem.pedido, ordem.tipo), tags='teste') def inserir_quantidade_item(self, event): selection = self.treeview_itens.selection() tipo_ordem = self.treeview_itens.item(selection, "values")[8] if tipo_ordem == 'ZORT': confirmar_op_triangular = messagebox.askokcancel("Atenção", "Ordem referente a uma 'OPERAÇÂO TRIANGULAR'." "\nConfirmar utilização ?") if confirmar_op_triangular: saldo = self.treeview_itens.item(selection, "values")[6] self.quantidade_item_remessa.set(saldo) def inserir_main(self): selection = self.treeview_itens.selection() ordem = self.treeview_itens.item(selection, "values")[1] self.main.ordem_item_remessa.set(ordem) self.main.quantidade_item_remessa.set(self.quantidade_item_remessa.get()) self.main.inserir_item_remessa(None) def limpar_treeview(self): for item in self.treeview_itens.get_children(): self.treeview_itens.delete(item) def validar_novo_item(self): return True def eliminar_item_remessas(self): selected_items = self.treeview_itens.selection() if len(selected_items) == 0: messagebox.showerror("Erro", "Sem ítens para eliminar!") return for item in selected_items: self.treeview_itens.delete(item) def salvar(self): self.tipo_carregamento_atual = TipoCarregamento() self.tipo_carregamento_atual.nome = self.nome.get().strip() self.tipo_carregamento_atual.inspecao_veiculo = self.inspecao_veiculo.get() self.tipo_carregamento_atual.inspecao_produto = self.inspecao_produto.get() self.tipo_carregamento_atual.remover_a = self.remover_a.get() self.tipo_carregamento_atual.tipo_lacre = self.tipo_lacre.get() self.tipo_carregamento_atual.numero_ordem = self.numero_ordem.get().strip() self.tipo_carregamento_atual.numero_pedido_frete = self.numero_pedido_frete.get().strip() self.tipo_carregamento_atual.tipo_frete = self.tipo_frete.get().strip() self.tipo_carregamento_atual.destino_frete = self.destino_frete.get().strip() self.tipo_carregamento_atual.doc_diversos = self.entry_docs_diversos.get("1.0", END) self.tipo_carregamento_atual.codigo_transportador = self.codigo_transportador.get() self.tipo_carregamento_atual.itens_str = self.extrair_itens() try: TipoCarregamentoService.inserir_tipo_carregamento(self.tipo_carregamento_atual) messagebox.showinfo("Sucesso", "Tipo de carregamento salvo com sucesso!") self.app_main.destroy() except Exception as e: messagebox.showerror("Erro", "Erro ao salvar tipo de carregamento\n{}".format(e)) def verificar_campos_obrigatorios(self): return True def extrair_itens(self): lista = [] itens = self.treeview_itens.get_children() for item in itens: i = ';'.join(self.treeview_itens.item(item, "values")) lista.append('[{}]'.format(i)) return ''.join(lista)
class MyEntry(object): """ Base class for labeled Entry fields. *text* is the Label/error box text. Parameters ---------- text : `str` The text label for the checkbox. cfg : `dict` A dictionary representing of widgets with `key` being the key in the cfg for this widget. key : `str` The key for this widget in `cfg`. optional : `bool`, default: ``False`` Specifies if entry input is optional or not. Attributes ---------- entry : `Entry` A tk Entry widget. enabled : `bool` Boolean indicating if this widget is enabled. value : `StringVar` The tk variable linked to the widget. text : `str` The text label for the widget cfg : `dict` A dictionary representing of widgets with `key` being the key in the cfg for this widget. key : `str` The key for this widget in `cfg`. Methods ------- body Place the required elements using the grid layout method. Returns the number of rows taken by this element. validate Validates the input. Returns ``True`` unless the field is blank and *optional* is ``False``. apply If enabled, sets the configuration at `key` as the current entry text stored in the tkvar. enable Enables the widget to allow interaction. disable Disables the widget from interaction. """ def __init__(self, text, cfg, key, optional=False): self.entry = None self.enabled = True self.value = StringVar() self.text = text self.cfg = cfg self.key = key self.optional = optional try: if self.cfg[self.key] is None: self.value.set("") else: self.value.set(self.cfg[self.key]) except KeyError: self.value.set("") def body(self, master, row, columns=DEFAULT_COLUMNS, **kwargs): """ Place the required elements using the grid layout method. Returns the number of rows taken by this element. Parameters ---------- master : A tk widget or window. row : `int` The row variable to use during packing/grid columns : `int` The columnspan to use during packing/grid kwargs : `dict` Keyword arguements to pass to packing/grid. Currently ignored. Returns ------- `int` Returns the number of rows taken by this element. """ label = Label(master, text=self.text, justify=LEFT) label.grid(row=row, column=0, columnspan=1, sticky="e") self.entry = Entry(master, textvariable=self.value) self.entry.grid(row=row, column=1, columnspan=columns - 1, sticky="ew") return 1 def validate(self): """ Validates the input. Returns ``True`` unless the field is blank and *optional* is ``False``. """ if not self.enabled: return True elif not self.optional and len(self.value.get()) == 0: messagebox.showwarning("", "{} not specified.".format(self.text)) return False else: return True def apply(self): """ If enabled, sets the configuration at `key` as the current entry text stored in the tkvar. """ if self.enabled and len(self.value.get()) > 0: self.cfg[self.key] = self.value.get() else: self.cfg[self.key] = None def enable(self): """ Enables the widget. """ self.enabled = True self.entry.state(["!disabled"]) def disable(self): """ Disables the widget from interaction. """ self.enabled = False self.entry.state(["disabled"])
class App(tk.Frame): def __init__(self, master=None): super().__init__(master) self.master = master self.pack() self.data_folder = StringVar() self.comp_order = StringVar() self.test_order = StringVar() self.set_correct = IntVar() self.area = StringVar() self.resistance = StringVar() self.benchmark = StringVar() self.overpotent = StringVar() self.X_title = StringVar() self.Y_title = StringVar() self.set_normalized = IntVar() self.create_widgets() def create_widgets(self): self.folder = tk.Entry(self, textvariable=self.data_folder) self.folder.grid(row=0, column=0, columnspan=2) self.browse = tk.Button(self) self.browse["text"] = "选择数据目录..." self.browse["command"] = self.select_folder self.browse.grid(row=0, column=2) self.comp_label = tk.Label(self, text="沉积文件序号") self.comp_label.grid(row=1, column=0) self.comp_order_input = tk.Entry(self, textvariable=self.comp_order, width=5) self.comp_order_input.grid(row=1, column=1) self.import_button = tk.Button(self) self.import_button["text"] = "导入数据" self.import_button["width"] = 12 self.import_button["command"] = self.import_data self.import_button.grid(row=1, column=2) self.test_label = tk.Label(self, text="测试文件序号") self.test_label.grid(row=2, column=0) self.test_order_input = tk.Entry(self, textvariable=self.test_order, width=5) self.test_order_input.grid(row=2, column=1) self.check_normalized = tk.Checkbutton(self, variable=self.set_normalized) self.check_normalized["text"] = "组分归一化" self.check_normalized.grid(row=2, column=2) self.X_title_label = tk.Label(self, text="横轴标题") self.X_title_label.grid(row=3, column=0) self.X_title_input = tk.Entry(self, textvariable=self.X_title) self.X_title_input.grid(row=3, column=1, columnspan=2) self.Y_title_label = tk.Label(self, text="纵轴标题") self.Y_title_label.grid(row=4, column=0) self.Y_title_input = tk.Entry(self, textvariable=self.Y_title) self.Y_title_input.grid(row=4, column=1, columnspan=2) self.benchmark_label = tk.Label(self, text="性能比较线") self.benchmark_label.grid(row=5, column=0, sticky="w") self.benchmark_input = tk.Entry(self, textvariable=self.benchmark, width=5) self.benchmark_input.grid(row=5, column=1) self.benchmark_label2 = tk.Label(self, text="mA (注意正负)", anchor="w") self.benchmark_label2.grid(row=5, column=2, sticky="w") self.overpotent_label = tk.Label(self, text="过电势计算") self.overpotent_label.grid(row=6, column=0, sticky="w") self.overpotent_input = tk.Entry(self, textvariable=self.overpotent, width=5) self.overpotent_input.grid(row=6, column=1) self.overpotent_label = tk.Label(self, text="V", anchor="w") self.overpotent_label.grid(row=6, column=2, sticky="w") self.plot = tk.Button(self) self.plot["text"] = "作图" self.plot["width"] = 12 self.plot["command"] = self.plot_data self.plot.grid(row=7, column=1) self.closeapp = tk.Button(self) self.closeapp["text"] = "退出Origin" self.closeapp["width"] = 12 self.closeapp["command"] = self.close_app self.closeapp.grid(row=7, column=2) self.check_correct = tk.Checkbutton(self, variable=self.set_correct) self.check_correct["text"] = "修正原始数据" self.check_correct.grid(row=8, column=0) self.area_label = tk.Label(self, text="电极面积") self.area_label.grid(row=9, column=0, sticky="w") self.area_input = tk.Entry(self, textvariable=self.area, width=5) self.area_input.grid(row=9, column=1) self.area_label2 = tk.Label(self, text="平方厘米", anchor="w") self.area_label2.grid(row=9, column=2, sticky="w") self.resist_label = tk.Label(self, text="电解液电阻") self.resist_label.grid(row=10, column=0, sticky="w") self.resist_input = tk.Entry(self, textvariable=self.resistance, width=5) self.resist_input.grid(row=10, column=1) self.resist_label2 = tk.Label(self, text="欧姆", anchor="w") self.resist_label2.grid(row=10, column=2, sticky="w") #self.y_max = 0.0 #self.y_min = 0.0 self.x_max = 0.0 self.x_min = 0.0 self.mark_x_max = 0.0 self.mark_x_min = 0.0 self.cmark_x_max = 0.0 self.cmark_x_min = 0.0 self.comp_order.set("1") self.test_order.set("3") self.area.set("1") self.resistance.set("2") self.benchmark.set("10") self.overpotent.set("0") self.set_correct.set(1) self.X_title.set("Voltage (V vs.)") self.Y_title.set("Current (A)") def select_folder(self): self.data_folder.set(filedialog.askdirectory()) print(self.data_folder.get()) return def close_app(self): self.oapp.Exit() def import_data(self): # file_names = [] # for (dirpath, dirnames, filenames) in walk(self.data_folder.get()): # file_names.extend(filenames) # for file_name in file_names: # id = str.split(str.split(file_name,'.')[1],']')[0] # print(id) # files = list(filter(os.path.isfile, glob.glob(self.data_folder.get() + "/*"))) # files.sort(key=lambda x: os.path.getmtime(x)) # print(files) # print(len(files)) self.import_button["text"] = "正在导入数据..." self.import_button["state"] = "disabled" self.import_button.update() self.oapp = Origin.Application() self.oapp.NewProject() self.datasheet_page = self.oapp.WorksheetPages.Add() self.datasheet_page.Name = "数据" self.datasheet = self.datasheet_page.Layers(0) self.datasheet.Name = "原始数据" self.datasheet_page.AddLayer() self.ternarysheet = self.datasheet_page.Layers(1) self.ternarysheet.Name = "原始数据三元" if self.set_correct.get() == 1: self.datasheet_page.AddLayer() self.cdatasheet = self.datasheet_page.Layers(2) self.cdatasheet.Name = "修正数据" files = list( filter(os.path.isfile, Path(self.data_folder.get()).rglob("*.csv"))) files.sort(key=lambda x: os.path.getmtime(x)) previous = 0 expset = 0 i = 0 tech = "" el_info = "" mark_x = [] cmark_x = [] el_infos = [] el_list = [] x_range_set = False bench = float(self.benchmark.get()) / 1000 resist = float(self.resistance.get()) area = float(self.area.get()) overpot = float(self.overpotent.get()) for file in files: current = str.split(str.split(file.name, '.')[1], ']')[0] if current != previous: expset = 1 # print(file.name) else: expset += 1 if str(expset) == self.comp_order.get(): with open(file, newline='', encoding="utf8") as csvfile: csvreader = csv.reader(csvfile) el_infoline = 0 el_info = [] totalcont = 0 for row in csvreader: if row[0].lstrip('-').replace('.', '', 1).isdigit(): break if el_infoline > 0: el_name = row[0][:2] if el_name not in el_list: el_list.append(el_name) if self.set_normalized.get() == 1: totalcont += float(row[1]) el_info.append(el_name + ":" + row[1]) elif "电解液" in row[0]: el_infoline = csvreader.line_num + 1 if self.set_normalized.get() == 1: normalized_el_info = [] for el in el_info: info = el.split(":") normal_cont = round(float(info[1]) / totalcont, 2) normalized_el_info.append(info[0] + ":" + str(normal_cont)) el_info = normalized_el_info el_infos.append(el_info) if str(expset) == self.test_order.get(): x, y, data = [], [], [] cx, cy, cdata = [], [], [] #修正后的数据 with open(file, newline='', encoding="utf8") as csvfile: csvreader = csv.reader(csvfile) startrow = 0 for row in csvreader: if tech == "" and csvreader.line_num == 2: tech = str.split(row[0], ':', 1)[1] if not x_range_set and csvreader.line_num == 3: self.x_min = float(row[1]) if not x_range_set and csvreader.line_num == 4: self.x_max = float(row[1]) x_range_set = True if startrow > 0: x.append(float(row[0])) y.append(float(row[1])) if self.set_correct.get() == 1: cx.append( float(row[0]) - float(row[1]) * resist + overpot) cy.append(float(row[1]) / area) elif row[0].lstrip('-').replace('.', '', 1).isdigit(): startrow = csvreader.line_num x.append(float(row[0])) y.append(float(row[1])) if self.set_correct.get() == 1: cx.append( float(row[0]) - float(row[1]) * resist + overpot) cy.append(float(row[1]) / area) data.append(x) data.append(y) if self.set_correct.get() == 1: cdata.append(cx) cdata.append(cy) cj = len(cy) - 1 while cj >= 0: if cy[cj] < bench: break cj -= 1 cmark = cx[cj] + (cx[cj] - cx[cj - 1]) / ( cy[cj] - cy[cj - 1]) * (bench - cy[cj]) cmark_x.append(cmark) j = len(y) - 1 while j >= 0: if y[j] < bench: break j -= 1 mark = x[j] + (x[j] - x[j - 1]) / (y[j] - y[j - 1]) * (bench - y[j]) mark_x.append(mark) # datasheet.Columns(i+1).SetName("I")#Name属性不可更改 self.datasheet.SetData(data, 0, i) self.datasheet.Columns(i).Type = COLTYPE_DESIGN_X self.datasheet.Columns(i + 1).Type = COLTYPE_DESIGN_Y self.datasheet.Columns(i).DataFormat = Origin.COLFORMAT_NUMERIC self.datasheet.Columns(i + 1).DataFormat = Origin.COLFORMAT_NUMERIC self.datasheet.Columns(i).Comments = current self.datasheet.Columns(i + 1).Comments = ( "".join(el_info)).replace(":", "") self.datasheet.Columns(i).LongName = self.X_title.get() self.datasheet.Columns(i + 1).LongName = self.Y_title.get() if self.set_correct.get() == 1: self.cdatasheet.SetData(cdata, 0, i) self.cdatasheet.Columns(i).Type = COLTYPE_DESIGN_X self.cdatasheet.Columns(i + 1).Type = COLTYPE_DESIGN_Y self.cdatasheet.Columns( i).DataFormat = Origin.COLFORMAT_NUMERIC self.cdatasheet.Columns( i + 1).DataFormat = Origin.COLFORMAT_NUMERIC self.cdatasheet.Columns(i).Comments = current self.cdatasheet.Columns(i + 1).Comments = ( "".join(el_info)).replace(":", "") self.cdatasheet.Columns(i).LongName = self.X_title.get() self.cdatasheet.Columns(i + 1).LongName = self.Y_title.get() i += 2 previous = current if self.x_max < self.x_min: temp = self.x_max self.x_max = self.x_min self.x_min = temp self.mark_x_max = min([max(mark_x), self.x_max]) self.mark_x_min = max([round_down(min(mark_x), 2), self.x_min]) temp_max = self.mark_x_min self.num_levels = 0 while temp_max < self.mark_x_max: temp_max += 0.01 self.num_levels += 1 self.mark_x_max = round(temp_max, 2) if self.set_correct.get() == 1: self.cmark_x_max = min([max(cmark_x), self.x_max]) self.cmark_x_min = max([round_down(min(cmark_x), 2), self.x_min]) temp_cmax = self.cmark_x_min self.cnum_levels = 0 while temp_cmax < self.cmark_x_max: temp_cmax += 0.01 self.cnum_levels += 1 self.cmark_x_max = round(temp_cmax, 2) el_cont = [[0.0 for h in range(int(i / 2))] for k in range(len(el_list))] l = 0 while l < len(el_infos): for els in el_infos[l]: el_name = els.split(":")[0] el_cont[el_list.index(el_name)][l] = float(els.split(":")[1]) l += 1 el_cont.append(mark_x) if self.set_correct.get() == 1: el_cont.append(cmark_x) self.ternarysheet.SetData(el_cont, 0, 0) self.ternarysheet.Columns(0).Type = COLTYPE_DESIGN_X self.ternarysheet.Columns(1).Type = COLTYPE_DESIGN_Y self.ternarysheet.Columns(2).Type = COLTYPE_DESIGN_Z self.ternarysheet.Columns(0).LongName = el_list[0] self.ternarysheet.Columns(1).LongName = el_list[1] self.ternarysheet.Columns(2).LongName = el_list[2] self.ternarysheet.Columns( 3).LongName = f"电势 at {self.benchmark_input.get()} mA" if self.set_correct.get() == 1: self.ternarysheet.Columns( 4).LongName = f"修正电势 at {self.benchmark_input.get()} mA" # self.ternarysheet.Columns() self.import_button["state"] = "normal" self.import_button["text"] = "导入数据" self.import_button.update() self.datasheet.PutLabelVisible(Origin.LABEL_COMMENTS) self.datasheet.PutLabelVisible(Origin.LABEL_LONG_NAME) self.datasheet.Name += tech self.oapp.Visible = 1 # print(dir(datasheet.Columns(0))) return def plot_data(self): self.graphlayer = self.oapp.GraphPages.Add("Line").Layers(0) self.datarange = self.datasheet.NewDataRange(0, 0, -1, -1) # self.dataplot = self.graphlayer.DataPlots.Add(self.datarange) self.dataplot = self.graphlayer.AddPlot(self.datarange, 200) # Origin.GraphLayer. color_high = 1 color_low = 11 if self.mark_x_max < 0: color_high = 11 color_low = 1 labtalk = ";".join([ "page.dimension.unit=1", "page.dimension.width=7200", "page.dimension.height=4800", "layer.dimension.unit=1", "layer.width=80", "layer.height=80", "layer.top=5", "layer.left=16", "layer.y.MajorTicks=11", "layer.z.MajorTicks=11", "layer.x.ticks=1", "layer.y.ticks=1", "layer.x.showaxes=3", "layer.y.showaxes=3", "layer.x2.ticks=0", "layer.y2.ticks=0", "layer.x.thickness=2", "layer.x2.thickness=2", "layer.y.thickness=2", "layer.y2.thickness=2", "layer.x.label.pt=24", "layer.x.label.bold=1", "layer.x2.label.pt=24", "layer.x2.label.bold=1", "layer.y.label.pt=24", "layer.y.label.bold=1", "layer.y2.label.pt=24", "layer.y2.label.bold=1", "xb.text$=\"\\b(%(?X))\"", "xb.fsize=36", "yl.text$=\"\\b(%(?Y))\"", "yl.fsize=36", "set %c -w 1500", f"layer.x.from={self.x_min}", f"layer.x.to={self.x_max}", ]) print(labtalk) self.graphlayer.Execute(labtalk) if self.set_correct.get() == 1: self.cgraphlayer = self.oapp.GraphPages.Add("Line").Layers(0) self.cdatarange = self.cdatasheet.NewDataRange(0, 0, -1, -1) # self.dataplot = self.graphlayer.DataPlots.Add(self.datarange) self.cdataplot = self.cgraphlayer.AddPlot(self.cdatarange, 200) # Origin.GraphLayer. labtalk = ";".join([ "page.dimension.unit=1", "page.dimension.width=7200", "page.dimension.height=4800", "layer.dimension.unit=1", "layer.width=80", "layer.height=80", "layer.top=5", "layer.left=16", "layer.y.MajorTicks=11", "layer.z.MajorTicks=11", "layer.x.ticks=1", "layer.y.ticks=1", "layer.x.showaxes=3", "layer.y.showaxes=3", "layer.x2.ticks=0", "layer.y2.ticks=0", "layer.x.thickness=2", "layer.x2.thickness=2", "layer.y.thickness=2", "layer.y2.thickness=2", "layer.x.label.pt=24", "layer.x.label.bold=1", "layer.x2.label.pt=24", "layer.x2.label.bold=1", "layer.y.label.pt=24", "layer.y.label.bold=1", "layer.y2.label.pt=24", "layer.y2.label.bold=1", "xb.text$=\"\\b(%(?X))\"", "xb.fsize=36", "yl.text$=\"\\b(%(?Y))\"", "yl.fsize=36", "set %c -w 1500", f"layer.x.from={self.x_min}", f"layer.x.to={self.x_max}", ]) print(labtalk) self.cgraphlayer.Execute(labtalk) self.trirange = self.ternarysheet.NewDataRange(0, 0, -1, 2) # self.dataplot = self.graphlayer.DataPlots.Add(self.datarange) self.tripage = self.oapp.GraphPages.Add("ternary") self.trigraphlayer = self.tripage.Layers(0) self.triplot = self.trigraphlayer.AddPlot(self.trirange, 245) labtalk = ";".join([ "page.dimension.unit=1", "page.dimension.width=7200", "page.dimension.height=4800", "layer.x.MajorTicks=11", "layer.y.MajorTicks=11", "layer.z.MajorTicks=11", "layer.x.MinorTicks=0", "layer.y.MinorTicks=0", "layer.z.MinorTicks=0", "set %c -k 17", "set %c -z 20", "set %c -cse 102", "set %c -cset 2", "set %c -cpal rainbow balanced", f"layer.cmap.numMajorLevels={self.num_levels}", "layer.cmap.color7=14", f"layer.cmap.colorLow={color_low}", f"layer.cmap.colorHigh={color_high}", f"layer.cmap.zmax={self.mark_x_max}", f"layer.cmap.zmin={self.mark_x_min}", "layer.cmap.colormixmode=1", "layer.cmap.fill(2)", "layer.cmap.SetLevels()", "layer.cmap.updateScale()", "spectrum", "spectrum1.top=0", "spectrum1.labels.autodisp=0", "spectrum1.labels.decplaces=2", "spectrum1.width=1000", "spectrum1.height=4000", "spectrum1.top=200", "spectrum1.left=6000", "spectrum1.barthick=400", "label -r legend", "layer.x.label.pt=24", "layer.y2.label.pt=24", "layer.z.label.pt=24", "layer.x.label.bold=1", "layer.y2.label.bold=1", "layer.z.label.bold=1", "layer.x.thickness=2", "layer.y2.thickness=2", "layer.z.thickness=2", "layer.x.ticks=0", "layer.y2.ticks=0", "layer.z.ticks=0", "layer.z.label.offsetV = -90", "layer.z.label.offsetH = -50", "layer.y2.label.offsetH = 50", "layer.x.label.offsetV = -50", #"sec -p 5", "xb.text$=\"\\b(%(?X))\"", "xb.fsize=36", "yr.text$=\"\\b(%(?Y))\"", "yr.fsize=36", "zf.text$=\"\\b(%(?Z))\"", "zf.fsize=36", "xb.rotate=0", "yr.rotate=0", "zf.rotate=0", "sec -p 0.5", "xb.top=4300", "xb.left=5300", "yr.top=200", "yr.left=3000", "zf.top=4300", "zf.left=600", ]) print(labtalk) self.trigraphlayer.Execute(labtalk) if self.set_correct.get() == 1: self.ctrirange = self.ternarysheet.NewDataRange(0, 0, -1, 2) # self.dataplot = self.graphlayer.DataPlots.Add(self.datarange) self.ctripage = self.oapp.GraphPages.Add("ternary") self.ctrigraphlayer = self.ctripage.Layers(0) self.ctriplot = self.ctrigraphlayer.AddPlot(self.ctrirange, 245) labtalk = ";".join([ "page.dimension.unit=1", "page.dimension.width=7200", "page.dimension.height=4800", "layer.x.MajorTicks=11", "layer.y.MajorTicks=11", "layer.z.MajorTicks=11", "layer.x.MinorTicks=0", "layer.y.MinorTicks=0", "layer.z.MinorTicks=0", "set %c -k 17", "set %c -z 20", "set %c -cse 103", "set %c -cset 2", "set %c -cpal rainbow balanced", f"layer.cmap.numMajorLevels={self.cnum_levels}", "layer.cmap.color7=14", f"layer.cmap.colorLow={color_low}", f"layer.cmap.colorHigh={color_high}", f"layer.cmap.zmax={self.cmark_x_max}", f"layer.cmap.zmin={self.cmark_x_min}", "layer.cmap.colormixmode=1", "layer.cmap.fill(2)", "layer.cmap.SetLevels()", "layer.cmap.updateScale()", "spectrum", "spectrum1.top=0", "spectrum1.labels.autodisp=0", "spectrum1.labels.decplaces=2", "spectrum1.width=1000", "spectrum1.height=4000", "spectrum1.top=200", "spectrum1.left=6000", "spectrum1.barthick=400", "label -r legend", "layer.x.label.pt=24", "layer.y2.label.pt=24", "layer.z.label.pt=24", "layer.x.label.bold=1", "layer.y2.label.bold=1", "layer.z.label.bold=1", "layer.x.thickness=2", "layer.y2.thickness=2", "layer.z.thickness=2", "layer.x.ticks=0", "layer.y2.ticks=0", "layer.z.ticks=0", "layer.z.label.offsetV = -90", "layer.z.label.offsetH = -50", "layer.y2.label.offsetH = 50", "layer.x.label.offsetV = -50", #"sec -p 5", "xb.text$=\"\\b(%(?X))\"", "xb.fsize=36", "yr.text$=\"\\b(%(?Y))\"", "yr.fsize=36", "zf.text$=\"\\b(%(?Z))\"", "zf.fsize=36", "xb.rotate=0", "yr.rotate=0", "zf.rotate=0", "sec -p 0.5", "xb.top=4300", "xb.left=5300", "yr.top=200", "yr.left=3000", "zf.top=4300", "zf.left=600", ]) print(labtalk) self.ctrigraphlayer.Execute(labtalk)
class Combo(OptionMenu): def __init__(self, master, options, selected=None, command=None, grid=None, align=None): # If a command is specified, the function MUST take one positional argument # as it will be auto-given the current value of the Combo # You can only specify a command for a OptionMenu at init # Description of this object (for friendly error messages) self.description = "[Combo] object with default selection \"" + str( selected) + "\"" # Maintain a list of options (as strings, to avoid problems comparing) self.options = [str(x) for x in options] # Store currently selected item self.selected = StringVar() # The command associated with this combo self.command = command # Set the first item in the list as default if selected is None and len(options) > 0: self.selected.set(str(options[0])) else: self.selected.set(str(selected)) # Instantiate the object try: super().__init__(master, self.selected, *options, command=command) except AttributeError: utils.error_format(self.description + "\n" + "No options for [Combo] were provided") # Pack or grid self utils.auto_pack(self, master, grid, align) # Returns currently selected option def get(self): return self.selected.get() # Sets currently selected option (if it exists in the list) def set(self, text): if text in self.options: self.selected.set(str(text)) else: utils.error_format( "Tried to set [Combo] option to a value not in the list") # Resets the combo box to the first option being selected def select_default(self): try: self.selected.set(self.options[0]) except IndexError: utils.error_format( self.description + "\n" + "There are no options in the [Combo] box to be selected") # Add an option to the combo def add_option(self, option): # Add to the internal list self.options.append(str(option)) # self.children["menu"].add_command(label=option, command=self.command) # Delete all options menu = self.children["menu"] menu.delete(0, 'end') # Re-add all options for item in self.options: menu.add_command(label=item, command=Tk._setit(self.selected, item, self.command)) # Set the new option as selected self.selected.set(str(option)) # Clear all options from a combo def clear(self): self.options = [] self.children["menu"].delete(0, END) self.selected.set("")
class GrepDialog(SearchDialogBase): "Dialog for searching multiple files." title = "Find in Files Dialog" icon = "Grep" needwrapbutton = 0 def __init__(self, root, engine, flist): """Create search dialog for searching for a phrase in the file system. Uses SearchDialogBase as the basis for the GUI and a searchengine instance to prepare the search. Attributes: globvar: Value of Text Entry widget for path to search. recvar: Boolean value of Checkbutton widget for traversing through subdirectories. """ SearchDialogBase.__init__(self, root, engine) self.flist = flist self.globvar = StringVar(root) self.recvar = BooleanVar(root) def open(self, text, searchphrase, io=None): "Make dialog visible on top of others and ready to use." SearchDialogBase.open(self, text, searchphrase) if io: path = io.filename or "" else: path = "" dir, base = os.path.split(path) head, tail = os.path.splitext(base) if not tail: tail = ".py" self.globvar.set(os.path.join(dir, "*" + tail)) def create_entries(self): "Create base entry widgets and add widget for search path." SearchDialogBase.create_entries(self) self.globent = self.make_entry("In files:", self.globvar)[0] def create_other_buttons(self): "Add check button to recurse down subdirectories." btn = Checkbutton( self.make_frame()[0], variable=self.recvar, text="Recurse down subdirectories") btn.pack(side="top", fill="both") def create_command_buttons(self): "Create base command buttons and add button for search." SearchDialogBase.create_command_buttons(self) self.make_button("Search Files", self.default_command, 1) def default_command(self, event=None): """Grep for search pattern in file path. The default command is bound to <Return>. If entry values are populated, set OutputWindow as stdout and perform search. The search dialog is closed automatically when the search begins. """ prog = self.engine.getprog() if not prog: return path = self.globvar.get() if not path: self.top.bell() return from idlelib.outwin import OutputWindow # leave here! save = sys.stdout try: sys.stdout = OutputWindow(self.flist) self.grep_it(prog, path) finally: sys.stdout = save def grep_it(self, prog, path): """Search for prog within the lines of the files in path. For the each file in the path directory, open the file and search each line for the matching pattern. If the pattern is found, write the file and line information to stdout (which is an OutputWindow). """ dir, base = os.path.split(path) list = self.findfiles(dir, base, self.recvar.get()) list.sort() self.close() pat = self.engine.getpat() print(f"Searching {pat!r} in {path} ...") hits = 0 try: for fn in list: try: with open(fn, errors='replace') as f: for lineno, line in enumerate(f, 1): if line[-1:] == '\n': line = line[:-1] if prog.search(line): sys.stdout.write(f"{fn}: {lineno}: {line}\n") hits += 1 except OSError as msg: print(msg) print(f"Hits found: {hits}\n(Hint: right-click to open locations.)" if hits else "No hits.") except AttributeError: # Tk window has been closed, OutputWindow.text = None, # so in OW.write, OW.text.insert fails. pass def findfiles(self, dir, base, rec): """Return list of files in the dir that match the base pattern. If rec is True, recursively iterate through subdirectories. """ try: names = os.listdir(dir or os.curdir) except OSError as msg: print(msg) return [] list = [] subdirs = [] for name in names: fn = os.path.join(dir, name) if os.path.isdir(fn): subdirs.append(fn) else: if fnmatch.fnmatch(name, base): list.append(fn) if rec: for subdir in subdirs: list.extend(self.findfiles(subdir, base, rec)) return list
class BaseWidget(Toplevel): def __init__(self, master, name, config, save_config): """Create base desktop widget.""" Toplevel.__init__(self, master, class_=APP_NAME) self.rowconfigure(2, weight=1) self.columnconfigure(0, weight=1) self.minsize(50, 50) self.protocol('WM_DELETE_WINDOW', self.withdraw) self.ewmh = EWMH() self.name = name self.config = config # configparser self.save_config = save_config # save config method # get splash window type compatibility if CONFIG.getboolean('General', 'splash_supported', fallback=True): self.attributes('-type', 'splash') else: self.attributes('-type', 'toolbar') # control main menu checkbutton self.variable = BooleanVar(self, False) # save widget's position self._position = StringVar( self, self.config.get(name, 'position', fallback='normal')) add_trace(self._position, 'write', self._position_trace) self.title('feedagregator.widget.{}'.format(name.replace(' ', '_'))) self.withdraw() # window dragging self.x = None self.y = None # --- menu self._create_menu() # --- elements # --- --- title bar frame = Frame(self, style='widget.TFrame') Button(frame, style='widget.close.TButton', command=self.withdraw).pack(side='left') self.label = Label(frame, text=name, style='widget.title.TLabel', anchor='center') self.label.pack(side='left', fill='x', expand=True) frame.grid(row=0, columnspan=2, padx=4, pady=4, sticky='ew') sep = Separator(self, style='widget.Horizontal.TSeparator') sep.grid(row=1, columnspan=2, sticky='ew') # --- --- widget body self.canvas = Canvas(self, highlightthickness=0) self.canvas.grid(row=2, column=0, sticky='ewsn', padx=(2, 8), pady=(2, 4)) scroll = AutoScrollbar(self, orient='vertical', style='widget.Vertical.TScrollbar', command=self.canvas.yview) scroll.grid(row=2, column=1, sticky='ns', pady=(2, 14)) self.canvas.configure(yscrollcommand=scroll.set) self.display = Frame(self.canvas, style='widget.TFrame') self.canvas.create_window(0, 0, anchor='nw', window=self.display, tags=('display', )) self.display.columnconfigure(0, weight=1) # --- style self.style = Style(self) self._font_size = 10 self.update_style() # --- resizing and geometry corner = Sizegrip(self, style="widget.TSizegrip") corner.place(relx=1, rely=1, anchor='se', bordermode='outside') geometry = self.config.get(self.name, 'geometry') if geometry: self.geometry(geometry) self.update_idletasks() if self.config.getboolean(self.name, 'visible', fallback=True): self.deiconify() # --- bindings self.bind('<3>', lambda e: self.menu.tk_popup(e.x_root, e.y_root)) for widget in [self.label, self.canvas, sep]: widget.bind('<ButtonPress-1>', self._start_move) widget.bind('<ButtonRelease-1>', self._stop_move) widget.bind('<B1-Motion>', self._move) self.label.bind('<Map>', self._change_position) self.bind('<Configure>', self._on_configure) self.bind('<4>', lambda e: self._scroll(-1)) self.bind('<5>', lambda e: self._scroll(1)) self.update_idletasks() self.canvas.configure(scrollregion=self.canvas.bbox('all')) self.populate_widget() if not CONFIG.getboolean('General', 'splash_supported', fallback=True) and self.config.getboolean( self.name, 'visible', fallback=True): Toplevel.withdraw(self) Toplevel.deiconify(self) def _create_menu(self): self.menu = Menu(self, tearoff=False) self.menu_sort = Menu(self.menu, tearoff=False) menu_pos = Menu(self.menu, tearoff=False) menu_pos.add_radiobutton(label=_('Normal'), value='normal', variable=self._position, command=self._change_position) menu_pos.add_radiobutton(label=_('Above'), value='above', variable=self._position, command=self._change_position) menu_pos.add_radiobutton(label=_('Below'), value='below', variable=self._position, command=self._change_position) self.menu.add_cascade(label=_('Sort'), menu=self.menu_sort) self.menu.add_cascade(label=_('Position'), menu=menu_pos) self.menu.add_command(label=_('Hide'), command=self.withdraw) self.menu.add_command(label=_('Open all'), command=self.open_all) self.menu.add_command(label=_('Close all'), command=self.close_all) def populate_widget(self): pass # to be overriden by subclass def open_all(self): pass # to be overriden by subclass def close_all(self): pass # to be overriden by subclass def entry_add(self, title, date, summary, url): """Display entry and return the toggleframe and htmlframe.""" def unwrap(event): l.update_idletasks() try: h = l.html.bbox()[-1] except TclError: pass else: l.configure(height=h + 2) def resize(event): if l.winfo_viewable(): try: h = l.html.bbox()[-1] except TclError: pass else: l.configure(height=h + 2) # convert date to locale time formatted_date = format_datetime(datetime.strptime( date, '%Y-%m-%d %H:%M').astimezone(tz=None), 'short', locale=getlocale()[0]) tf = ToggledFrame(self.display, text="{} - {}".format(title, formatted_date), style='widget.TFrame') l = HtmlFrame(tf.interior, height=50, style='widget.interior.TFrame') l.set_content(summary) l.set_style(self._stylesheet) l.set_font_size(self._font_size) tf.interior.configure(style='widget.interior.TFrame') tf.interior.rowconfigure(0, weight=1) tf.interior.columnconfigure(0, weight=1) l.grid(padx=4, sticky='eswn') Button(tf.interior, text='Open', style='widget.TButton', command=lambda: webopen(url)).grid(pady=4, padx=6, sticky='e') tf.grid(sticky='we', row=len(self.entries), pady=2, padx=(8, 4)) tf.bind("<<ToggledFrameOpen>>", unwrap) l.bind("<Configure>", resize) return tf, l def update_position(self): if self._position.get() == 'normal': if CONFIG.getboolean('General', 'splash_supported', fallback=True): self.attributes('-type', 'splash') else: self.attributes('-type', 'toolbar') if self.variable.get(): Toplevel.withdraw(self) Toplevel.deiconify(self) def update_style(self): self.attributes('-alpha', CONFIG.getint('Widget', 'alpha') / 100) text_font = Font(self, font=CONFIG.get('Widget', 'font')).actual() bg = CONFIG.get('Widget', 'background') feed_bg = CONFIG.get('Widget', 'feed_background', fallback='gray20') feed_fg = CONFIG.get('Widget', 'feed_foreground', fallback='white') self._stylesheet = """ body { background-color: %(bg)s; color: %(fg)s; font-family: %(family)s; font-weight: %(weight)s; font-style: %(slant)s; } ul { padding-left: 5px; } ol { padding-left: 5px; } #title { font-weight: bold; font-size: large; } a { color: %(link)s; font-style: italic; } code {font-family: monospace;} a:hover { font-style: italic; border-bottom: 1px solid %(link)s; } """ % (dict(bg=feed_bg, fg=feed_fg, link=CONFIG.get('Widget', 'link_color', fallback='#89B9F6'), **text_font)) self.configure(bg=bg) self.canvas.configure(background=bg) self._font_size = text_font['size'] def withdraw(self): Toplevel.withdraw(self) self.variable.set(False) def deiconify(self): Toplevel.deiconify(self) self.variable.set(True) def _scroll(self, delta): top, bottom = self.canvas.yview() top += delta * 0.05 top = min(max(top, 0), 1) self.canvas.yview_moveto(top) def _position_trace(self, *args): self.config.set(self.name, 'position', self._position.get()) self.save_config() def _change_position(self, event=None): '''Make widget sticky and set its position with respects to the other windows.''' pos = self._position.get() splash_supp = CONFIG.getboolean('General', 'splash_supported', fallback=True) try: for w in self.ewmh.getClientList(): if w.get_wm_name() == self.title(): self.ewmh.setWmState(w, 1, '_NET_WM_STATE_STICKY') self.ewmh.setWmState(w, 1, '_NET_WM_STATE_SKIP_TASKBAR') self.ewmh.setWmState(w, 1, '_NET_WM_STATE_SKIP_PAGER') if pos == 'above': self.attributes('-type', 'dock') self.ewmh.setWmState(w, 1, '_NET_WM_STATE_ABOVE') self.ewmh.setWmState(w, 0, '_NET_WM_STATE_BELOW') elif pos == 'below': self.attributes('-type', 'desktop') self.ewmh.setWmState(w, 0, '_NET_WM_STATE_ABOVE') self.ewmh.setWmState(w, 1, '_NET_WM_STATE_BELOW') else: if splash_supp: self.attributes('-type', 'splash') else: self.attributes('-type', 'toolbar') self.ewmh.setWmState(w, 0, '_NET_WM_STATE_BELOW') self.ewmh.setWmState(w, 0, '_NET_WM_STATE_ABOVE') self.ewmh.display.flush() if event is None and not splash_supp: Toplevel.withdraw(self) Toplevel.deiconify(self) except ewmh.display.error.BadWindow: pass def _on_configure(self, event): if event.widget is self: geometry = self.geometry() if geometry != '1x1+0+0': self.config.set(self.name, 'geometry', geometry) self.save_config() elif event.widget in [self.canvas, self.display]: self.canvas.configure(scrollregion=self.canvas.bbox('all')) self.canvas.itemconfigure('display', width=self.canvas.winfo_width() - 4) def _start_move(self, event): self.x = event.x self.y = event.y self.configure(cursor='fleur') self.display.configure(cursor='fleur') def _stop_move(self, event): self.x = None self.y = None self.configure(cursor='arrow') self.display.configure(cursor='arrow') def _move(self, event): if self.x is not None and self.y is not None: deltax = event.x - self.x deltay = event.y - self.y x = self.winfo_x() + deltax y = self.winfo_y() + deltay self.geometry("+%s+%s" % (x, y))
class FormularioArticulos: def __init__(self): self.articulo1=idleArticulos.Articulos() self.ventana1=tk.Tk() self.ventana1.title("Mantenimiento de artículos") self.cuaderno1 = ttk.Notebook(self.ventana1) self.carga_articulos() self.consulta_por_codigo() self.listado_completo() self.borrar_articulo() self.modificacion() self.cuaderno1.grid(column=0, row=0, padx=10, pady=10) self.ventana1.mainloop() def carga_articulos(self): self.pagina1 = ttk.Frame(self.cuaderno1) self.cuaderno1.add(self.pagina1, text="Carga de artículos") self.labelframe1=ttk.LabelFrame(self.pagina1, text="Artículo") self.labelframe1.grid(column=0, row=0, padx=5, pady=10) self.label1=ttk.Label(self.labelframe1, text="Descripción:") self.label1.grid(column=0, row=0, padx=4, pady=4) self.descripcioncarga=tk.StringVar() self.entrydescripcion=ttk.Entry(self.labelframe1, textvariable=self.descripcioncarga) self.entrydescripcion.grid(column=1, row=0, padx=4, pady=4) self.label2=ttk.Label(self.labelframe1, text="Precio:") self.label2.grid(column=0, row=1, padx=4, pady=4) self.preciocarga=tk.StringVar() self.entryprecio=ttk.Entry(self.labelframe1, textvariable=self.preciocarga) self.entryprecio.grid(column=1, row=1, padx=4, pady=4) self.boton1=ttk.Button(self.labelframe1, text="Confirmar", command=self.agregar) self.boton1.grid(column=1, row=2, padx=4, pady=4) def agregar(self): datos=(self.descripcioncarga.get(), self.preciocarga.get()) self.articulo1.alta(datos) mb.showinfo("Información", "Los datos fueron cargados") self.descripcioncarga.set("") self.preciocarga.set("") def consulta_por_codigo(self): self.pagina2 = ttk.Frame(self.cuaderno1) self.cuaderno1.add(self.pagina2, text="Consulta por código") self.labelframe2=ttk.LabelFrame(self.pagina2, text="Artículo") self.labelframe2.grid(column=0, row=0, padx=5, pady=10) self.label1=ttk.Label(self.labelframe2, text="Código:") self.label1.grid(column=0, row=0, padx=4, pady=4) self.codigo=tk.StringVar() self.entrycodigo=ttk.Entry(self.labelframe2, textvariable=self.codigo) self.entrycodigo.grid(column=1, row=0, padx=4, pady=4) self.label2=ttk.Label(self.labelframe2, text="Descripción:") self.label2.grid(column=0, row=1, padx=4, pady=4) self.descripcion=tk.StringVar() self.entrydescripcion=ttk.Entry(self.labelframe2, textvariable=self.descripcion, state="readonly") self.entrydescripcion.grid(column=1, row=1, padx=4, pady=4) self.label3=ttk.Label(self.labelframe2, text="Precio:") self.label3.grid(column=0, row=2, padx=4, pady=4) self.precio=tk.StringVar() self.entryprecio=ttk.Entry(self.labelframe2, textvariable=self.precio, state="readonly") self.entryprecio.grid(column=1, row=2, padx=4, pady=4) self.boton1=ttk.Button(self.labelframe2, text="Consultar", command=self.consultar) self.boton1.grid(column=1, row=3, padx=4, pady=4) def consultar(self): datos=(self.codigo.get(), ) respuesta=self.articulo1.consulta(datos) if len(respuesta)>0: self.descripcion.set(respuesta[0][0]) self.precio.set(respuesta[0][1]) else: self.descripcion.set('') self.precio.set('') mb.showinfo("Información", "No existe un artículo con dicho código") def listado_completo(self): self.pagina3 = ttk.Frame(self.cuaderno1) self.cuaderno1.add(self.pagina3, text="Listado completo") self.labelframe3=ttk.LabelFrame(self.pagina3, text="Artículo") self.labelframe3.grid(column=0, row=0, padx=5, pady=10) self.boton1=ttk.Button(self.labelframe3, text="Listado completo", command=self.listar) self.boton1.grid(column=0, row=0, padx=4, pady=4) self.scrolledtext1=st.ScrolledText(self.labelframe3, width=30, height=10) self.scrolledtext1.grid(column=0,row=1, padx=10, pady=10) def listar(self): respuesta=self.articulo1.recuperar_todos() self.scrolledtext1.delete("1.0", tk.END) for fila in respuesta: self.scrolledtext1.insert(tk.END, "código:"+str(fila[0])+"\ndescripción:"+fila[1]+"\nprecio:"+str(fila[2])+"\n\n") def borrar_articulo(self): self.pagina4=ttk.Frame(self.cuaderno1) self.cuaderno1.add(self.pagina4, text="Borrar articulo") self.labelframe4=ttk.Labelframe(self.pagina4, text="articulo") self.labelframe4.grid(column=0, row=0, padx=5, pady=5) self.label4=ttk.Label(self.labelframe4, text="Codigo del articulo:") self.label4.grid(column=0, row=0, padx=4, pady=4) self.dato=StringVar() self.entrydato=ttk.Entry(self.labelframe4, textvariable=self.dato) self.entrydato.grid(column=1, row=0, padx=4, pady=4) self.boton1=ttk.Button(self.labelframe4, text="Eliminar", command=self.eliminar) self.boton1.grid(column=1, row=1, padx=4, pady=5) def eliminar(self): codigo=(self.dato.get(), ) respuesta=self.articulo1.baja(codigo) if respuesta > 0: mb.showinfo("Informacion!", "El articulo ha sido eliminado") else: mb.showerror("Error!", "No existe ningun articulo con ese codigo") def modificacion(self): self.pagina5=ttk.Frame(self.cuaderno1) self.cuaderno1.add(self.pagina5, text="Modificacar articulo") self.labelframe5=ttk.Labelframe(self.pagina5, text="Articulo") self.labelframe5.grid(column=0, row=0, padx=5, pady=5) self.label5=ttk.Label(self.labelframe5, text="Codigo del articulo") self.label5.grid(column=0, row=0, padx=4, pady=4) self.dato_mod=StringVar() self.entry_mod=ttk.Entry(self.labelframe5, textvariable=self.dato_mod) self.entry_mod.grid(column=1, row=0, padx=4, pady=4) self.label6=ttk.Label(self.labelframe5, text="Descripcion:") self.label6.grid(column=0, row=1, padx=4, pady=4) self.descripcion_mod=StringVar() self.descripcion_mod_entry=ttk.Entry(self.labelframe5, textvariable=self.descripcion_mod) self.descripcion_mod_entry.grid(column=1, row=1, padx=4, pady=4) self.label7=ttk.Label(self.labelframe5, text="Precio:") self.label7.grid(column=0, row=2, padx=4, pady=4) self.precio_mod=tk.StringVar() self.precio_mod_entry=ttk.Entry(self.labelframe5, textvariable=self.precio_mod) self.precio_mod_entry.grid(column=1, row=2, padx=4, pady=4) self.boton2=ttk.Button(self.labelframe5, text="Consultar", command=self.consulta_mod) self.boton2.grid(column=1, row=3, padx=4, pady=4) self.boton3=ttk.Button(self.labelframe5, text="Modificar", command=self.editar) self.boton3.grid(column=1, row=4, padx=4, pady=4) def consulta_mod(self): codigo=(self.dato_mod.get(), ) respuesta=self.articulo1.consulta_mod(codigo) if len(respuesta) > 0: self.descripcion_mod.set(respuesta[0][0]) self.precio_mod.set(respuesta[0][1]) else: mb.showerror("Error!", "No existe ningun articulo con ese codigo") self.descripcion_mod.set("") self.precio_mod.set("") def editar(self): actualizacion=(self.descripcion_mod.get(), self.precio_mod.get(), self.dato_mod.get() ) respuesta=self.articulo1.modificacion(actualizacion) if respuesta > 0: mb.showinfo("Informacion", "EL articulo ha sido actualizado") else: mb.showerror("Error!", "No existe ningun articulo con ese codigo")
class RollerGroup(LabelFrame): def __init__(self, mainframe, index): LabelFrame.__init__(self, mainframe) self.mainframe = mainframe self.index = index self.hist_index = 0 self.collapsed = False self.rollers = [] self.control_frame = Frame(None) default_font = ('Verdana', 10) self.name = StringVar() self.name.trace('w', self.mainframe.set_unsaved_title) self.expand_img = PhotoImage( data= b'R0lGODlhEAAQAIABAAAAAP///yH5BAEKAAEALAAAAAAQABAAAAIlhI+pq+EPHYo0TGjifRkfDYAdI33WUnZc6KmlyK5wNdMrg+dJAQA7' ) self.collapse_img = PhotoImage( data= b'R0lGODlhEAAQAIABAAAAAP///yH5BAEKAAEALAAAAAAQABAAAAIfhI+pq+EPHYo0zAovlme/y3CGmJCeeWqbirEVA8dLAQA7' ) self.collapse_btn = Button(self.control_frame, bd=0, image=self.collapse_img, command=self.show_hide) self.menu_btn = Menubutton(self.control_frame, bd=1, relief='solid', font=('Courier', 8), text='\u25e2', takefocus=1, highlightthickness=1) self.name_entry = Entry(self.control_frame, bd=1, relief='solid', font=('Verdana', 12), width=16, textvariable=self.name) self.history_frame = LabelFrame(self.control_frame, bd=1, text='History', relief='solid', font=default_font, labelanchor='w') self.roll_frame = LabelFrame(self.control_frame, bd=1, text='Roll', relief='solid', font=default_font, labelanchor='w') self.roll_img = PhotoImage( data= b'R0lGODlhDgARAIABAAAAAP///yH5BAEKAAEALAAAAAAOABEAAAIkjB+Ai6C83GOy0iqjM7ltPoFhKEKeKZJadynfVa6HlbAp3ZIFADs=' ) self.left_arrow = PhotoImage( data= b'R0lGODlhBwANAIABAAAAAP///yH5BAEKAAEALAAAAAAHAA0AAAITjA9nkMj+Apty2lvt0jt2VYFSAQA7' ) self.right_arrow = PhotoImage( data= b'R0lGODlhBwANAIABAAAAAP///yH5BAEKAAEALAAAAAAHAA0AAAITRI5gGLrnXlzT1NsidEkx/zFHAQA7' ) self.roll_btn = Button(self.roll_frame, bd=0, image=self.roll_img, height=24, command=self.roll_group) self.hist_prev_btn = Button( self.history_frame, bd=0, image=self.left_arrow, height=24, width=16, repeatdelay=250, repeatinterval=100, command=lambda: self.navigate_history(offset=-1)) self.hist_next_btn = Button( self.history_frame, bd=0, image=self.right_arrow, height=24, width=16, repeatdelay=250, repeatinterval=100, command=lambda: self.navigate_history(offset=1)) self.menu_btn.config(menu=self.create_menu()) self.collapse_btn.grid(row=0, column=0, padx=(4, 0)) self.menu_btn.grid(row=0, column=1, padx=(4, 0)) self.name_entry.grid(row=0, column=2, padx=(4, 0)) self.history_frame.grid(row=0, column=3, padx=(6, 0)) self.hist_prev_btn.grid(row=0, column=0, padx=(6, 0)) self.hist_next_btn.grid(row=0, column=1, padx=(0, 2)) self.roll_frame.grid(row=0, column=4, padx=(6, 4)) self.roll_btn.grid(row=0, column=0, padx=(6, 2)) self.config(relief='solid', labelwidget=self.control_frame) self.name.set('Group {}'.format(len(roller_groups) + 1)) self.grid(row=index, padx=4, pady=4, sticky='w') def show_hide(self): if self.collapsed: for roller in self.rollers: roller.grid() self.collapse_btn.config(image=self.collapse_img) self.collapsed = False else: for roller in self.rollers: roller.grid_remove() self.collapse_btn.config(image=self.expand_img) width = 28 + self.collapse_btn.winfo_width( ) + self.menu_btn.winfo_width() + self.name_entry.winfo_width() self.config(height=36, width=width) self.collapsed = True def create_menu(self): menu = Menu(self.menu_btn, tearoff=0, postcommand=maintain_group_indices) menu.add_command(label='Add', underline=0, command=self.add_group) menu.add_command(label='Clone', underline=0, command=lambda: self.add_group(clone=True)) menu.add_command(label='Up', underline=0, command=lambda: self.move_group(offset=-1)) menu.add_command(label='Down', underline=0, command=lambda: self.move_group(offset=1)) menu.add_separator() # ------------- menu.add_command(label='Clear history', underline=6, command=self.clear_history) menu.add_command(label='Remove', underline=0, command=self.remove_group) return menu def add_group(self, clone=False): destination_index = self.index + 1 group = RollerGroup(self.mainframe, destination_index) roller_groups.insert(group.index, group) for i in range(destination_index, len(roller_groups)): roller_groups[i].grid(row=i + 1) if clone: for roller in self.rollers: new_roller = Roller(group, self.rollers.index(roller)) new_roller.name.set(roller.name.get()) new_roller.dice_qty.set(roller.dice_qty.get()) new_roller.die_faces.set(roller.die_faces.get()) new_roller.modifier.set(roller.modifier.get()) new_roller.finalmod.set(roller.finalmod.get()) group.rollers.append(new_roller) group.name.set(self.name.get()) else: group.rollers.append(Roller(group, 0)) group.name.set(group.name.get()) maintain_tabstops() self.mainframe.editmenu.entryconfigure( self.mainframe.editmenu.index('end'), command=lambda: self.add_group(clone=clone)) self.mainframe.bind_all('<Control-r>', lambda e: self.add_group(clone=clone)) def move_group(self, offset=0, destination_index=0): if not destination_index: destination_index = self.index + offset if destination_index >= 0: group = roller_groups.pop(self.index) roller_groups.insert(destination_index, group) maintain_group_indices() self.name.set(self.name.get()) self.mainframe.editmenu.entryconfigure( self.mainframe.editmenu.index('end'), command=lambda: self.move_group(offset=offset)) self.mainframe.bind_all('<Control-r>', lambda e: self.move_group(offset=offset)) def clear_history(self): for roller in self.rollers: roller.reset() roller.history = [] self.history_frame.config(text='History') def remove_group(self, override=False): if len(roller_groups) > 1 or override: self.grid_remove() roller_groups.remove(self) self.name.set('') def maintain_roller_indices(self): for roller in self.rollers: roller.index = self.rollers.index(roller) roller.grid(row=roller.index) def roll_group(self): for roller in self.rollers: roller.roll() self.navigate_history() self.mainframe.editmenu.entryconfigure( self.mainframe.editmenu.index('end'), command=lambda: self.roll_group()) self.mainframe.bind_all('<Control-r>', lambda e: self.roll_group()) def navigate_history(self, offset=0, desired_index=0): hist_len = len(self.rollers[0].history) if not hist_len: return if not desired_index: desired_index = self.hist_index + offset if desired_index >= -1 and desired_index <= hist_len: if desired_index == -1: desired_index = 0 if desired_index == hist_len: desired_index = hist_len - 1 for roller in self.rollers: hist_dict = roller.history[desired_index] roller.results = hist_dict['results'] roller.dice_qty.set(hist_dict['dice_qty']) roller.die_faces.set(hist_dict['die_faces']) roller.modifier.set(hist_dict['modifier']) roller.results_text.set(hist_dict['results_text']) roller.finalmod.set(hist_dict['finalmod']) self.history_frame.config(text=hist_dict['timestamp']) self.hist_index = desired_index self.maintain_result_widths() def maintain_result_widths(self): for roller in self.rollers: w = len(roller.results_text.get()) if w > 80: w = 80 roller.results_entry.config(width=w)
class DialogURL(Toplevel): def __init__(self, parent, url=None, buttonSEC=False, buttonRSS=False): super(DialogURL, self).__init__(parent) self.parent = parent parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", parent.geometry()) dialogX = int(parentGeometry.group(3)) dialogY = int(parentGeometry.group(4)) self.accepted = False self.url = None self.transient(self.parent) self.title("Enter URL") self.urlVar = StringVar() self.urlVar.set(url if url is not None else "http://") frame = Frame(self) urlLabel = Label(frame, text=_("URL:"), underline=0) urlEntry = Entry(frame, textvariable=self.urlVar, width=60) urlEntry.focus_set() okButton = Button(frame, text=_("OK"), command=self.ok) cancelButton = Button(frame, text=_("Cancel"), command=self.close) if buttonSEC: usSecButton = Button(frame, text=_("SEC search"), command=self.usSec) usSecButton.grid(row=1, column=1, sticky=W, pady=3) ToolTip(usSecButton, text=_("Opens US SEC Edgar Company Search (in web browser)\n\n" "(1) Find the company in web browser,\n" "(2) Click 'documents' button for desired filing,\n" "(3) Find 'data files' panel, instance document row, 'document' column,\n" "(4) On instance document file name, right-click browser menu: 'copy shortcut',\n" "(5) Come back to this dialog window,\n" "(6) Ctrl-v (paste) shortcut into above URL text box,\n" "(7) Click ok button to load instance document"), wraplength=480) if buttonRSS: rssButton = Button(frame, text=_("SEC RSS"), command=self.rssFeed) rssButton.grid(row=1, column=1, pady=3) ToolTip(rssButton, text=_("Opens current US SEC Edgar RSS feed"), wraplength=480) urlLabel.grid(row=0, column=0, sticky=W, pady=3, padx=3) urlEntry.grid(row=0, column=1, columnspan=3, sticky=EW, pady=3, padx=3) okButton.grid(row=1, column=2, sticky=E, pady=3) ToolTip(okButton, text=_("Opens above URL from web cache, downloading to cache if necessary"), wraplength=240) cancelButton.grid(row=1, column=3, sticky=EW, pady=3, padx=3) ToolTip(cancelButton, text=_("Cancel operation")) frame.grid(row=0, column=0, sticky=(N,S,E,W)) frame.columnconfigure(1, weight=1) window = self.winfo_toplevel() window.columnconfigure(0, weight=1) self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100)) self.bind("<Alt-u>", lambda *ignore: urlEntry.focus_set()) self.bind("<Return>", self.ok) self.bind("<Escape>", self.close) self.protocol("WM_DELETE_WINDOW", self.close) self.grab_set() self.wait_window(self) def ok(self, event=None): self.url = self.urlVar.get().strip() if self.url and self.url[0] == '"' and self.url[-1] == '"': self.url = self.url[1:-1] # strip double quotes (from cut and paste from database etc self.accepted = True self.close() def close(self, event=None): self.parent.focus_set() self.destroy() def usSec(self, event=None): import webbrowser webbrowser.open("http://www.sec.gov/edgar/searchedgar/companysearch.html") def rssFeed(self, event=None): self.url = "http://www.sec.gov/Archives/edgar/usgaap.rss.xml" self.accepted = True self.close()
class TextBox(TextWidget): def __init__(self, master, text="", width=10, height=1, grid=None, align=None, visible=True, enabled=None, multiline=False, scrollbar=False, command=None): description = "[TextBox] object with text \"" + str(text) + "\"" self._multiline = multiline # Set up controlling string variable self._text = StringVar() self._text.set(str(text)) # Create a tk object for the text box if multiline: if scrollbar: #tk = ScrolledText(master.tk, width=width, height=height, wrap="word") tk = ScrolledText(master.tk, wrap="word") else: #tk = Text(master.tk, width=width, height=height) tk = Text(master.tk) tk.insert(END, self._text.get()) else: #tk = Entry(master.tk, textvariable=self._text, width=width) tk = Entry(master.tk, textvariable=self._text) super(TextBox, self).__init__(master, tk, description, grid, align, visible, enabled, width, height) self.update_command(command) # Bind the key pressed event self.events.set_event("<TextBox.KeyRelease>", "<KeyRelease>", self._key_released) # PROPERTIES # ---------------------------------- # The text value @property def value(self): if self._multiline: return self.tk.get(1.0, END) else: return self._text.get() @value.setter def value(self, value): self._text.set(str(value)) if self._multiline: self.tk.delete(1.0, END) self.tk.insert(END, self._text.get()) self.description = "[TextBox] object with text \"" + str(value) + "\"" def resize(self, width, height): self._width = width if width != "fill": self._set_tk_config("width", width) if height is not None: if self._multiline: self._height = height if height != "fill": self.tk.config(height=height) else: if isinstance(height, int): if height > 1: utils.error_format( "Cannot change the height of a single line TextBox{}" .format(self.description)) # METHODS # ------------------------------------------- def _key_released(self, event): if self._command: args_expected = utils.no_args_expected(self._command) if args_expected == 0: self._command() elif args_expected == 1: self._command(event.key) else: utils.error_format( "TextBox command function must accept either 0 or 1 arguments.\nThe current command has {} arguments." .format(args_expected)) def update_command(self, command): if command is None: self._command = lambda: None else: self._command = command # Clear text box def clear(self): self.value = "" # Append text def append(self, text): self.value = self.value + str(text) # DEPRECATED METHODS # -------------------------------------------- # Returns the text def get(self): return self.value utils.deprecated( "TextBox get() is deprecated. Please use the value property instead." ) # Sets the text def set(self, text): self.value = text utils.deprecated( "TextBox set() is deprecated. Please use the value property instead." )
class HVPS: def __init__(self, master): self.master = master master.title("LoCoLab HVPS Console") self.ser = None LCOL = 0 RCOL = 4 # Critical parameters #self.CURRENTVOLTAGE = IntVar(master,value=0) #self.TARGETVOLTAGE = IntVar(master,value=0) #self.PWM = IntVar(master,value=0) self.CURRENTVOLTAGE = StringVar(master, value='0') self.TARGETVOLTAGE = StringVar(master, value='0') self.PWM = StringVar(master, value='30') self.IS_SERIAL_CONNECTED = False # Plotting parameters self.npoints = 240 self.current_line = [0 for x in range(self.npoints)] self.target_line = [0 for x in range(self.npoints)] # Plots =============================================================== self.f1 = plt.figure(figsize=PLOTRATIO, dpi=PLOTDPI) self.a1 = self.f1.add_subplot(111) self.a1.grid() self.a1.set_title("Voltage") self.canvas1 = FigureCanvasTkAgg(self.f1, master) self.canvas1.get_tk_widget().grid(sticky='W', row=0, rowspan=5, column=LCOL + 0, columnspan=RCOL) self.f2 = plt.figure(figsize=PLOTRATIO, dpi=PLOTDPI) self.a2 = self.f2.add_subplot(111) self.a2.grid() self.a2.set_title("PWM") self.canvas2 = FigureCanvasTkAgg(self.f2, master) self.canvas2.get_tk_widget().grid(sticky='W', row=6, rowspan=1, column=LCOL + 0, columnspan=RCOL) self.f3 = plt.figure(figsize=PLOTRATIO, dpi=PLOTDPI) self.a3 = self.f3.add_subplot(111) self.a3.grid() self.a3.set_title("Signal") self.canvas3 = FigureCanvasTkAgg(self.f3, master) self.canvas3.get_tk_widget().grid(sticky='W', row=6, rowspan=1, column=RCOL + 1, columnspan=7) self.a3_xlim = 0 self.a3_ylim = 0 # Labels ============================================================== self.currentlabel = Label(master, text="Current:", font=LABELFONT) self.currentlabel.grid(row=0, column=RCOL + 1) self.dynamic_currentlabel = Label(master, textvar=self.CURRENTVOLTAGE, font=LABELFONT) self.dynamic_currentlabel.grid(row=0, column=RCOL + 2, sticky='W') self.currentunitslabel = Label(master, text="kV") self.currentunitslabel.grid(row=0, column=RCOL + 3, sticky='W') self.targetlabel = Label(master, text="Target:", font=LABELFONT) self.targetlabel.grid(row=1, column=RCOL + 1) self.dynamic_targetlabel = Label(master, textvar=self.TARGETVOLTAGE, font=LABELFONT) self.dynamic_targetlabel.grid(row=1, column=RCOL + 2, sticky='W') self.targetunitslabel = Label(master, text="kV") self.targetunitslabel.grid(row=1, column=RCOL + 3, sticky='W') self.pwmlabel = Label(master, text="PWM:", font=LABELFONT) self.pwmlabel.grid(row=2, column=RCOL + 1) self.dynamic_pwmlabel = Label(master, textvar=self.PWM, font=LABELFONT) self.dynamic_pwmlabel.grid(row=2, column=RCOL + 2, sticky='W') self.pwmunitslabel = Label(master, text="/ 1023") self.pwmunitslabel.grid(row=2, column=RCOL + 3, sticky='W') # Target Voltage Input ================================================ self.targetvoltageentrystr = StringVar(master, value='0') self.targetvoltageentry = Entry(master, textvar=self.targetvoltageentrystr) self.targetvoltageentry.grid(row=1, column=RCOL + 4) self.targetvoltagesendbutton = Button(master, text="Send", command=self.SendVoltage) self.targetvoltagesendbutton.grid(row=1, column=RCOL + 5) # Signal ============================================================== # self.signallabel = Label(master,text="Signal:") # self.signallabel.grid(row=3,column=1) self.IS_SENDING_SIGNAL = False self.signalx = [] self.signaly = [] self.signallistbox = Listbox(master, height=2) self.signallistbox.insert(1, "Step") self.signallistbox.insert(2, "Stairstep") self.signallistbox.insert(3, "Sawtooth") self.signallistbox.grid(sticky='E', row=7, column=RCOL + 1, columnspan=2) self.amplitudelabel = Label(master, text="Amplitude:") self.amplitudelabel.grid(row=8, column=RCOL + 1) self.amplitudeentrystr = StringVar(master, value='0.5') self.amplitudeentry = Entry(master, textvar=self.amplitudeentrystr) self.amplitudeentry.grid(row=8, column=RCOL + 2, columnspan=2) self.amplitudeunitslabel = Label(master, text="kV") self.amplitudeunitslabel.grid(row=8, column=RCOL + 4) self.dwelltimelabel = Label(master, text="Dwell time:") self.dwelltimelabel.grid(row=9, column=RCOL + 1) self.dwelltimeentrystr = StringVar(master, value='30') self.dwelltimeentry = Entry(master, textvar=self.dwelltimeentrystr) self.dwelltimeentry.grid(row=9, column=RCOL + 2, columnspan=2) self.dwelltimeunitslabel = Label(master, text="sec") self.dwelltimeunitslabel.grid(row=9, column=RCOL + 4) self.nrepslabel = Label(master, text="# Reps:") self.nrepslabel.grid(row=10, column=RCOL + 1) self.nrepsspinbox = Spinbox(master, from_=0, to_=50) self.nrepsspinbox.grid(row=10, column=RCOL + 2, columnspan=2) self.updatesignalbutton = Button(master, text="Update", command=self.UpdateSignalButton) self.updatesignalbutton.grid(row=11, column=RCOL + 1) self.executesignalbutton = Button(master, text="Execute", command=self.ExecuteSignalButton) self.executesignalbutton.grid(row=11, column=RCOL + 2) # Serial port ========================================================= self.seriallabel = Label(master, text="Serial Port") self.seriallabel.grid(sticky='W', row=7, column=0) self.serialentrystr = StringVar(master, value='/dev/cu.wchusbserial1420') self.serialentry = Entry(master, textvar=self.serialentrystr) self.serialentry.grid(sticky='W', row=7, column=1) self.serialconnectbutton = Button(master, text="Connect", command=self.ConnectToSerial) self.serialconnectbutton.grid(sticky='W', row=7, column=2) self.baudratelabel = Label(master, text="Baud Rate") self.baudratelabel.grid(sticky='W', row=8, column=0) self.baudrateentrystr = StringVar(master, value='115200') self.baudrateentry = Entry(master, textvar=self.baudrateentrystr) self.baudrateentry.grid(sticky='W', row=8, column=1) # Data Logging ======================================================== self.loglabel = Label(master, text="Data Logging") self.loglabel.grid(sticky='W', row=9, column=0) self.logfnameentrystr = StringVar(master, value='SessionLog.txt') self.logfnameentry = Entry(master, textvar=self.logfnameentrystr) self.logfnameentry.grid(sticky='W', row=9, column=1) self.logging_variable = IntVar(master, value=0) self.logging_offbutton = Radiobutton(master, text="Off", variable=self.logging_variable, value=0, width=4) self.logging_offbutton.grid(row=9, column=2) self.logging_onbutton = Radiobutton(master, text="On", variable=self.logging_variable, value=1, width=4) self.logging_onbutton.grid(row=9, column=3) # Abort =============================================================== self.abortbutton = Button(master, text="ABORT", command=self.ABORT) self.abortbutton.grid(row=11, column=0) return def DoNothing(self): pass def SendVoltage(self, sendv=0): try: V = float(self.targetvoltageentrystr.get()) if sendv != 0: V = sendv self.TARGETVOLTAGE.set(str(V)) w_str = "%f\n" % (V) # Format to send voltage self.ser.write(w_str.encode()) except Exception as e: print("ERROR: %s" % (e)) return def ConnectToSerial(self): try: port = self.serialentrystr.get() baudrate = int(self.baudrateentrystr.get()) print("Trying to connect to %s at %d" % (port, baudrate)) self.ser = serial.Serial(port, baudrate) self.ser.flushInput() except ValueError: print("ERROR: Invalid serial parameter.") return -1 except: print("Error") return -1 print("Success.") self.IS_SERIAL_CONNECTED = True self.GetSerialValue() return def GetSerialValue(self): if not self.IS_SERIAL_CONNECTED: #self.master.after(50,self.GetSerialValue) return try: # Grab data rawdata = self.ser.readline().decode('utf8') # Parse data currentval = float(rawdata.split(' ')[0]) targetval = float(self.TARGETVOLTAGE.get()) self.CURRENTVOLTAGE.set(str(currentval)) if self.logging_variable.get() == 1: self.LogData([targetval, currentval]) # Append data, shift over lines self.current_line.append(currentval) self.current_line = self.current_line[1:self.npoints + 1] self.target_line.append(targetval) self.target_line = self.target_line[1:self.npoints + 1] if self.IS_SENDING_SIGNAL: if len(self.signaly) == 0: self.IS_SENDING_SIGNAL = False else: #print("Sending signal: %f, next is "%(self.signaly[0]),end="") #self.SendVoltage(self.signaly[0]) v = self.signaly[0] self.TARGETVOLTAGE.set("%f" % (v)) wstr = "%f\n" % (v) self.ser.write(wstr.encode()) self.signaly = self.signaly[1:] self.signalx = self.signalx[:-1] #print("%f"%(self.signaly[0])) self.a3.clear() self.a3.plot(self.signalx, self.signaly, color='tab:blue') self.a3.set_title("Signal") self.a3.set_xlim(0, self.a3_xlim) self.a3.set_ylim(0, self.a3_ylim) self.a3.grid() self.canvas3.draw() self.master.after_idle(self.PlotLine) except Exception as e: print(e) self.master.after(REFRESH_FREQ, self.GetSerialValue) return def PlotLine(self): #max_val = max(self.current_line) + 1e-5 # Include extra for padding? self.a1.clear() self.a1.plot(self.current_line, color='tab:blue', label='Actual') self.a1.plot(self.target_line, color='tab:green', linestyle=':', label='Target') self.a1.grid() self.a1.legend(loc=3) self.a1.set_ylim(-1.5, 1.5) self.canvas1.draw() #print("Beep") return def UpdateSignalButton(self): try: selected_signal = self.signallistbox.curselection()[0] except: print("No selection!") return #print(selected_signal) try: H = float(self.amplitudeentrystr.get()) W = float(self.dwelltimeentrystr.get()) n = int(self.nrepsspinbox.get()) except ValueError: print("ERROR: Invalid signal parameter.") return if selected_signal == 0: # Step case self.signalx, self.signaly = Step(H, W, n) elif selected_signal == 1: self.signalx, self.signaly = StairStep(H, W, n) elif selected_signal == 2: self.signalx, self.signaly = Sawtooth(H, W, n) # Plot to a3 self.a3_xlim = max(self.signalx) self.a3_ylim = max(self.signaly) * 1.2 self.a3.clear() self.a3.plot(self.signalx, self.signaly, color='tab:blue') self.a3.set_title("Signal") self.a3.set_xlim(0, self.a3_xlim) self.a3.set_ylim(0, self.a3_ylim) self.a3.grid() self.canvas3.draw() return def ExecuteSignalButton(self): self.IS_SENDING_SIGNAL = True self.targetvoltagesendbutton.state = DISABLED print("Beep") return def mainloop(self): self.master.mainloop() return def LogData(self, data): fname = self.logfnameentrystr.get() f = open(fname, 'a') writestr = '' for d in data: writestr += "%f," % (d) writestr = writestr[:-1] + '\n' f.write(writestr) f.close() return def OnUpdate(self): pass def OnExecute(self): pass def ABORT(self): self.IS_SERIAL_CONNECTED = False self.TARGETVOLTAGE.set('0') self.IS_SENDING_SIGNAL = False self.signalx = [] self.signaly = [] return
class AdvSettingsWindow(Toplevel): def __init__(self, app): # Инициализация и списки значений Toplevel.__init__(self) self.parentApp = app self.opentypes = ("list", "vectoroflists", "set", "vectorofsets", "priorityqueue", "vectorofpriorityqueues", "all types") self.metrictypes = ("euclidean", "diagonal", "manhattan", "chebyshev") self.searchtypes = ("astar", "dijkstra") self.breakingties = ("g-min", "g-max") # Переменные-параметры теста self.task = Mission() self.repstr = StringVar() self.xstr = StringVar() self.ystr = StringVar() self.opentype = StringVar() self.allowdupl = 0 self.rep = 1 self.x = 10000 self.y = 11000 self.mode = 0 self.mtype = StringVar() self.stype = StringVar() self.hwstr = StringVar() self.hw = 1 self.brt = StringVar() self.allowdiagonal = IntVar() self.allowsqueeze = IntVar() self.cutcorners = IntVar() self.allowdiagonal.set(1) self.allowsqueeze.set(1) self.cutcorners.set(1) # Переменные отвечающие за обработку ошибочных данных self.error = 0 self.errormes = "" # Описание окна self.wm_title("Advanced settings") self.bgcolor = '#%02x%02x%02x' % (236, 236, 236) self.redcolor = '#%02x%02x%02x' % (222, 110, 94) self.geometry("412x570") self.configure(background=self.bgcolor) self.resizable(False, False) self.readyButton = Button(self, text="Done", command=self.callback, width=8, height=5, highlightbackground=self.bgcolor) self.protocol("WM_DELETE_WINDOW", self.callback) # Описание фрейма отвечающего за настройку эксперимента self.expframe = Frame(self, height=140) self.expframe.configure(background=self.bgcolor) self.expLabel = Label(self.expframe, text="Experiment settings", font='Helvetica 14 bold', background=self.bgcolor) self.repLabel = Label(self.expframe, text="Number of repetition", width=19, anchor="w", background=self.bgcolor) self.repeatBox = Entry(self.expframe, width=5, textvariable=self.repstr, background=self.bgcolor, highlightbackground=self.bgcolor) self.opTypeLabel = Label(self.expframe, text="Open container type", width=19, anchor="w", background=self.bgcolor) self.openTypeMenu = ttk.Combobox(self.expframe, textvariable=self.opentype, values=self.opentypes, width=18, state="readonly", background=self.bgcolor) self.openTypeMenu.set(self.opentypes[0]) self.duplFrame = Frame(self.expframe, background=self.bgcolor) self.rbutton1 = Radiobutton(self.duplFrame, text='Without duplicates', variable=self.allowdupl, value=0, anchor="w", background=self.bgcolor) self.rbutton2 = Radiobutton(self.duplFrame, text='With duplicates', variable=self.allowdupl, value=1, anchor="w", background=self.bgcolor) self.rbutton1.select() self.rbutton1.pack(anchor="w") self.rbutton2.pack(anchor="w") self.expLabel.grid(row=0, column=0, padx=10, pady=10, sticky='new', columnspan=2) self.opTypeLabel.grid(row=1, column=0, padx=10, sticky='nw') self.openTypeMenu.grid(row=1, column=1, padx=10, sticky='nw') self.duplFrame.grid(row=2, column=1, padx=10, pady=10, sticky='nw') self.repLabel.grid(row=3, column=0, padx=10, sticky='nw') self.repeatBox.grid(row=3, column=1, padx=10, sticky='nw') self.repstr.trace("w", lambda name, index, mode, var=self.repstr: self. repeatEnrChange(var)) self.opentype.trace("w", self.CheckDupl) self.repeatBox.insert(0, str(self.rep)) # Описание фрейма отвечающего за настройку пустой карты self.empmapframe = Frame(self, height=140, background=self.bgcolor) self.empLabel = Label(self.empmapframe, text="Empty map settings", font='Helvetica 14 bold', background=self.bgcolor) self.stSiLab = Label(self.empmapframe, text="Starting size of map", width=19, anchor="w", background=self.bgcolor) self.startSize = Entry(self.empmapframe, textvariable=self.xstr, width=19, background=self.bgcolor, highlightbackground=self.bgcolor) self.fnSiLab = Label(self.empmapframe, text="Ending size of map", width=19, anchor="w", background=self.bgcolor) self.finSize = Entry(self.empmapframe, textvariable=self.ystr, width=19, background=self.bgcolor, highlightbackground=self.bgcolor) self.empLabel.grid(row=0, column=0, padx=10, pady=5, sticky='new', columnspan=2) self.stSiLab.grid(row=1, column=0, padx=10, pady=5, sticky='nw') self.startSize.grid(row=1, column=1, padx=10, pady=5, sticky='nw') self.fnSiLab.grid(row=2, column=0, padx=10, pady=5, sticky='nw') self.finSize.grid(row=2, column=1, padx=10, pady=5, sticky='nw') self.xstr.trace("w", lambda name, useless, mode, vars =(1, self.xstr, self.ystr): self.sizeEnrChanged(vars)) self.ystr.trace("w", lambda name, useless, mode, vars =(2, self.xstr, self.ystr): self.sizeEnrChanged(vars)) self.startSize.insert(0, str(self.x)) self.finSize.insert(0, str(self.y)) # Описание фрейма отвечающего за настройку алгоритма self.algframe = Frame(self, height=140, background=self.bgcolor) self.algLabel = Label(self.algframe, text="Algorithm settings", font='Helvetica 14 bold', background=self.bgcolor) self.sTypeLabel = Label(self.algframe, text="Search type", width=19, anchor="w", background=self.bgcolor) self.sTypeMenu = ttk.Combobox(self.algframe, textvariable=self.stype, values=self.searchtypes, width=18, state="readonly", background=self.bgcolor) self.sTypeMenu.set(self.searchtypes[0]) self.sTypeMenu.bind("<<ComboboxSelected>>", self.CheckSType) self.mTypeLabel = Label(self.algframe, text="AStar Metric type", width=19, anchor="w", background=self.bgcolor) self.mTypeMenu = ttk.Combobox(self.algframe, textvariable=self.mtype, values=self.metrictypes, width=18, state="readonly", background=self.bgcolor) self.mTypeMenu.set(self.metrictypes[0]) self.hwLabel = Label(self.algframe, text="Heuristic function weight", width=19, anchor="w", background=self.bgcolor) self.hwEntry = Entry(self.algframe, textvariable=self.hwstr, width=19, background=self.bgcolor, highlightbackground=self.bgcolor) self.hwstr.trace("w", self.HweightChanged) self.hwEntry.insert(0, str(self.hw)) self.brLabel = Label(self.algframe, text="Breakingties", width=19, anchor="w", background=self.bgcolor) self.brTypeMenu = ttk.Combobox(self.algframe, textvariable=self.brt, values=self.breakingties, width=18, state="readonly", background=self.bgcolor) self.brTypeMenu.set(self.breakingties[0]) self.alldiagLabel = Label(self.algframe, text="Allow diagonal moves", width=19, anchor="w", background=self.bgcolor) self.alldiagCheck = Checkbutton(self.algframe, text="", variable=self.allowdiagonal, anchor="w", background=self.bgcolor, command=self.CheckAllDiag) self.allsquLabel = Label(self.algframe, text="Allow squeeze", width=19, anchor="w", background=self.bgcolor) self.allsquCheck = Checkbutton(self.algframe, text="", variable=self.allowsqueeze, anchor="w", background=self.bgcolor) self.cutcornLabel = Label(self.algframe, text="Allow cutting corners", width=19, anchor="w", background=self.bgcolor) self.cutcornCheck = Checkbutton(self.algframe, text="", variable=self.cutcorners, anchor="w", background=self.bgcolor, command=self.CheckCutCorn) self.algLabel.grid(row=0, column=0, padx=10, pady=10, sticky='new', columnspan=2) self.sTypeLabel.grid(row=1, column=0, padx=10, pady=5, sticky='nw') self.sTypeMenu.grid(row=1, column=1, padx=10, pady=5, sticky='nw') self.mTypeLabel.grid(row=2, column=0, padx=10, pady=5, sticky='nw') self.mTypeMenu.grid(row=2, column=1, padx=10, pady=5, sticky='nw') self.brLabel.grid(row=3, column=0, padx=10, pady=5, sticky='nw') self.brTypeMenu.grid(row=3, column=1, padx=10, pady=5, sticky='nw') self.hwLabel.grid(row=4, column=0, padx=10, pady=5, sticky='nw') self.hwEntry.grid(row=4, column=1, padx=10, pady=5, sticky='nw') self.alldiagLabel.grid(row=5, column=0, padx=10, sticky='nw') self.alldiagCheck.grid(row=5, column=1, padx=10, sticky='nw') self.allsquLabel.grid(row=6, column=0, padx=10, sticky='nw') self.allsquCheck.grid(row=6, column=1, padx=10, sticky='nw') self.cutcornLabel.grid(row=7, column=0, padx=10, sticky='nw') self.cutcornCheck.grid(row=7, column=1, padx=10, sticky='nw') # Окончательное размещение объектов в окне self.expframe.pack(anchor="nw") self.empmapframe.pack(anchor="nw") self.algframe.pack(anchor="nw") self.readyButton.pack(anchor="se", padx=10, pady=5) # Проверка правильности всех введенных данных перед скрытием окна def callback(self): if self.error == 0: self.task.searchtype = self.stype.get() self.task.metrictype = self.mtype.get() self.task.breakingties = self.brt.get() self.task.hweight = self.hw self.task.allowdiagonal = self.allowdiagonal.get() self.task.allowsqueeze = self.allowsqueeze.get() self.task.cutcorners = self.cutcorners.get() self.task.opentype = self.opentype.get() self.task.allowdupl = self.allowdupl self.parentApp.UpdateTestAdvSettings(self.x, self.y, self.rep) self.withdraw() else: messagebox.showinfo('Enter correct information', self.errormes) # Изменение параметра повтора эксперимента def repeatEnrChange(self, sv): try: tmp = int(sv.get()) if tmp <= 0: raise ValueError('value should be more then 0') self.rep = tmp self.error = 0 self.repeatBox.config({"background": "White"}) except ValueError as e: self.repeatBox.config({"background": self.redcolor}) self.error = 1 self.errormes = "Enter correct number of repetition" return True # Изменение параметров отвечающих за размер карты def sizeEnrChanged(self, vars): if vars[0] == 1: entr = self.startSize else: entr = self.finSize try: tmp = int(vars[vars[0]].get()) if tmp <= 0: raise ValueError('Value should be more then 0') entr.config({"background": "White"}) if vars[0] == 1: self.x = tmp else: self.y = tmp if self.x >= self.y: raise Warning('Start valuse should be less then final') else: self.startSize.config({"background": "White"}) self.finSize.config({"background": "White"}) self.error = 0 except ValueError as e: entr.config({"background": self.redcolor}) self.error = 1 self.errormes = "Enter correct size" except Warning as e: self.startSize.config({"background": self.redcolor}) self.finSize.config({"background": self.redcolor}) self.error = 1 self.errormes = str(e) return True # Проверка режима тестирования def Update( self, mode, ): self.mode = mode if self.mode == 0: self.startSize.config(state="normal") self.finSize.config(state="normal") elif self.mode == 2: self.startSize.config(state="disable") self.finSize.config(state="disable") self.stype.set(self.task.searchtype) self.mtype.set(self.task.metrictype) self.brt.set(self.task.breakingties) self.hw = self.task.hweight self.hwstr.set(str(self.hw)) self.allowdiagonal.set(self.task.allowdiagonal) self.allowsqueeze.set(self.task.allowsqueeze) self.cutcorners.set(self.task.cutcorners) self.opentype.set(self.task.opentype) self.allowdupl = self.task.allowdupl # Проверка возможности дубликатов для выбранного типа контейнера def CheckDupl(self, *args): if (self.opentypes.index(self.opentype.get()) > 3): self.rbutton1.select() self.rbutton1.config(state="disable") self.rbutton2.config(state="disable") else: self.rbutton1.config(state="normal") self.rbutton2.config(state="normal") # Проверка на тип алгоритма def CheckSType(self, event): if self.stype.get() == "dijkstra": self.mTypeMenu.config(state="disable") self.hwEntry.config(state="disable") else: self.mTypeMenu.config(state="normal") self.hwEntry.config(state="normal") # Проверка параметра веса h(v) def HweightChanged(self, *args): try: tmp = float(self.hwstr.get()) if tmp <= 0 or tmp > 2: raise ValueError( 'hweight should be more then 0 and less then 2') self.hw = tmp self.error = 0 self.hwEntry.config({"background": "White"}) except ValueError as e: self.hwEntry.config({"background": self.redcolor}) self.error = 1 self.errormes = "Enter correct hweight value" return True def CheckAllDiag(self): if self.allowdiagonal.get() == 0: self.allsquCheck.config(state="disable") self.cutcornCheck.config(state="disable") self.allowsqueeze.set(0) self.cutcorners.set(0) else: self.allsquCheck.config(state="normal") self.cutcornCheck.config(state="normal") def CheckCutCorn(self): if self.cutcorners.get() == 0: self.allsquCheck.config(state="disable") self.allowsqueeze.set(0) else: self.allsquCheck.config(state="normal")
class Application(Frame): def __init__(self, master=None): super().__init__(master) self.pack() # First row f1 = LabelFrame(self, text='NAND file with No$GBA footer', padx=10, pady=10) # NAND Button self.nand_mode = False nand_icon = PhotoImage( data=('R0lGODlhEAAQAIMAAAAAADMzM2ZmZpmZmczMzP///wAAAAAAAAA' 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAMAAAYALAAAAAAQAB' 'AAAARG0MhJaxU4Y2sECAEgikE1CAFRhGMwSMJwBsU6frIgnR/bv' 'hTPrWUSDnGw3JGU2xmHrsvyU5xGO8ql6+S0AifPW8kCKpcpEQA7')) self.nand_button = Button(f1, image=nand_icon, command=self.change_mode, state=DISABLED) self.nand_button.image = nand_icon self.nand_button.pack(side='left') self.nand_file = StringVar() Entry(f1, textvariable=self.nand_file, state='readonly', width=40).pack(side='left') Button(f1, text='...', command=self.choose_nand).pack(side='left') f1.pack(padx=10, pady=10, fill=X) # Second row f2 = Frame(self) # Check boxes self.checks_frame = Frame(f2) # Install TWiLight check self.twilight = IntVar() twl_chk = Checkbutton( self.checks_frame, text='Install latest TWiLight Menu++ on custom firmware', variable=self.twilight) twl_chk.pack(padx=10, anchor=W) # Clean files check self.clean_downloaded = IntVar() self.clean_downloaded.set(1) clean_chk = Checkbutton(self.checks_frame, text='Clean downloaded files after completion', variable=self.clean_downloaded) clean_chk.pack(padx=10, anchor=W) # Extract photo check self.photo = IntVar() self.photo.set(1) photo_chk = Checkbutton(self.checks_frame, text='Extract photo partition from NAND', variable=self.photo) photo_chk.pack(padx=10, anchor=W) self.checks_frame.pack(fill=X) # NAND operation frame self.nand_frame = LabelFrame(f2, text='NAND operation', padx=10, pady=10) self.nand_operation = IntVar() self.nand_operation.set(0) Radiobutton(self.nand_frame, text='Remove No$GBA footer', variable=self.nand_operation, value=0, command=lambda: self.enable_entries(False)).pack(anchor=W) Radiobutton(self.nand_frame, text='Add No$GBA footer', variable=self.nand_operation, value=1, command=lambda: self.enable_entries(True)).pack(anchor=W) fl = Frame(self.nand_frame) self.cid_label = Label(fl, text='eMMC CID', state=DISABLED) self.cid_label.pack(anchor=W, padx=(24, 0)) self.cid = StringVar() self.cid_entry = Entry(fl, textvariable=self.cid, width=20, state=DISABLED) self.cid_entry.pack(anchor=W, padx=(24, 0)) fl.pack(side='left') fr = Frame(self.nand_frame) self.console_id_label = Label(fr, text='Console ID', state=DISABLED) self.console_id_label.pack(anchor=W) self.console_id = StringVar() self.console_id_entry = Entry(fr, textvariable=self.console_id, width=20, state=DISABLED) self.console_id_entry.pack(anchor=W) fr.pack(side='right') f2.pack(fill=X) # Third row f3 = Frame(self) self.start_button = Button(f3, text='Start', width=16, command=self.hiya, state=DISABLED) self.start_button.pack(side='left', padx=(0, 5)) Button(f3, text='Quit', command=root.destroy, width=16).pack(side='left', padx=(5, 0)) f3.pack(pady=(10, 20)) self.folders = [] self.files = [] ################################################################################################ def change_mode(self): if (self.nand_mode): self.nand_frame.pack_forget() self.checks_frame.pack(padx=10, anchor=W) self.nand_mode = False else: if askokcancel( 'Warning', ('You are about to enter NAND mode. Do it only if you know ' 'what you are doing. Proceed?'), icon=WARNING): self.checks_frame.pack_forget() self.nand_frame.pack(padx=10, pady=(0, 10), fill=X) self.nand_mode = True ################################################################################################ def enable_entries(self, status): self.cid_label['state'] = (NORMAL if status else DISABLED) self.cid_entry['state'] = (NORMAL if status else DISABLED) self.console_id_label['state'] = (NORMAL if status else DISABLED) self.console_id_entry['state'] = (NORMAL if status else DISABLED) ################################################################################################ def choose_nand(self): name = askopenfilename(filetypes=(('nand.bin', '*.bin'), ('DSi-1.mmc', '*.mmc'))) self.nand_file.set(name) self.nand_button['state'] = (NORMAL if name != '' else DISABLED) self.start_button['state'] = (NORMAL if name != '' else DISABLED) ################################################################################################ def hiya(self): if not self.nand_mode: showinfo( 'Info', 'Now you will be asked to choose the SD card path that will be used ' 'for installing the custom firmware (or an output folder).\n\nIn order to avoid ' 'boot errors please assure it is empty before continuing.') self.sd_path = askdirectory() # Exit if no path was selected if self.sd_path == '': return # If adding a No$GBA footer, check if CID and ConsoleID values are OK elif self.nand_operation.get() == 1: cid = self.cid.get() console_id = self.console_id.get() # Check lengths if len(cid) != 32: showerror('Error', 'Bad eMMC CID') return elif len(console_id) != 16: showerror('Error', 'Bad Console ID') return # Parse strings to hex try: cid = bytearray.fromhex(cid) except ValueError: showerror('Error', 'Bad eMMC CID') return try: console_id = bytearray(reversed(bytearray.fromhex(console_id))) except ValueError: showerror('Error', 'Bad Console ID') return dialog = Toplevel(self) # Open as dialog (parent disabled) dialog.grab_set() dialog.title('Status') # Disable maximizing dialog.resizable(0, 0) frame = Frame(dialog, bd=2, relief=SUNKEN) scrollbar = Scrollbar(frame) scrollbar.pack(side=RIGHT, fill=Y) self.log = ThreadSafeText(frame, bd=0, width=52, height=20, yscrollcommand=scrollbar.set) self.log.pack() scrollbar.config(command=self.log.yview) frame.pack() if sysname == 'Darwin' and getattr(sys, 'frozen', False): Label(dialog, text='Close').pack(side='top', pady=(10, 0)) Button(dialog, text='Close', command=dialog.destroy, width=16).pack(pady=(0, 10)) else: Button(dialog, text='Close', command=dialog.destroy, width=16).pack(pady=10) # Center in window dialog.update_idletasks() width = dialog.winfo_width() height = dialog.winfo_height() dialog.geometry( '%dx%d+%d+%d' % (width, height, root.winfo_x() + (root.winfo_width() / 2) - (width / 2), root.winfo_y() + (root.winfo_height() / 2) - (height / 2))) # Check if we'll be adding a No$GBA footer if self.nand_mode and self.nand_operation.get() == 1: Thread(target=self.add_footer, args=(cid, console_id)).start() else: Thread(target=self.check_nand).start() ################################################################################################ def check_nand(self): self.log.write('Checking NAND file...') # Read the NAND file try: with open(self.nand_file.get(), 'rb') as f: # Go to the No$GBA footer offset f.seek(-64, 2) # Read the footer's header :-) bstr = f.read(0x10) if bstr == b'DSi eMMC CID/CPU': # Read the CID bstr = f.read(0x10) self.cid.set(bstr.hex().upper()) self.log.write('- eMMC CID: ' + self.cid.get()) # Read the console ID bstr = f.read(8) self.console_id.set( bytearray(reversed(bstr)).hex().upper()) self.log.write('- Console ID: ' + self.console_id.get()) # Check we are removing the No$GBA footer if self.nand_mode: Thread(target=self.remove_footer).start() else: Thread(target=self.get_latest_hiyacfw).start() else: self.log.write('ERROR: No$GBA footer not found') except IOError as e: print(e) self.log.write('ERROR: Could not open the file ' + path.basename(self.nand_file.get())) ################################################################################################ def get_latest_hiyacfw(self): # Try to use already downloaded hiyaCFW archive filename = 'hiyaCFW.7z' try: if path.isfile(filename): self.log.write('\nPreparing hiyaCFW...') else: self.log.write('\nDownloading latest hiyaCFW release...') with urlopen( 'https://github.com/DS-Homebrew/hiyaCFW/releases/latest/download/' + filename) as src, open(filename, 'wb') as dst: copyfileobj(src, dst) self.log.write('- Extracting hiyaCFW archive...') proc = Popen([ _7za, 'x', '-bso0', '-y', filename, 'for PC', 'for SDNAND SD card' ]) ret_val = proc.wait() if ret_val == 0: if self.clean_downloaded.get() == 1: self.files.append(filename) self.folders.append('for PC') self.folders.append('for SDNAND SD card') # Got to decrypt NAND if bootloader.nds is present Thread(target=self.decrypt_nand if path.isfile( 'bootloader.nds') else self.extract_bios).start() else: self.log.write('ERROR: Extractor failed') except (URLError, IOError) as e: print(e) self.log.write('ERROR: Could not get hiyaCFW') except OSError as e: print(e) self.log.write('ERROR: Could not execute ' + exe) ################################################################################################ def extract_bios(self): self.log.write('\nExtracting ARM7/ARM9 BIOS from NAND...') try: proc = Popen([twltool, 'boot2', '--in', self.nand_file.get()]) ret_val = proc.wait() if ret_val == 0: # Hash arm7.bin sha1_hash = sha1() with open('arm7.bin', 'rb') as f: sha1_hash.update(f.read()) self.log.write('- arm7.bin SHA1:\n ' + sha1_hash.digest().hex().upper()) # Hash arm9.bin sha1_hash = sha1() with open('arm9.bin', 'rb') as f: sha1_hash.update(f.read()) self.log.write('- arm9.bin SHA1:\n ' + sha1_hash.digest().hex().upper()) self.files.append('arm7.bin') self.files.append('arm9.bin') Thread(target=self.patch_bios).start() else: self.log.write('ERROR: Extractor failed') Thread(target=self.clean, args=(True, )).start() except OSError as e: print(e) self.log.write('ERROR: Could not execute ' + exe) Thread(target=self.clean, args=(True, )).start() ################################################################################################ def patch_bios(self): self.log.write('\nPatching ARM7/ARM9 BIOS...') try: self.patcher( path.join('for PC', 'bootloader files', 'bootloader arm7 patch.ips'), 'arm7.bin') self.patcher( path.join('for PC', 'bootloader files', 'bootloader arm9 patch.ips'), 'arm9.bin') # Hash arm7.bin sha1_hash = sha1() with open('arm7.bin', 'rb') as f: sha1_hash.update(f.read()) self.log.write('- Patched arm7.bin SHA1:\n ' + sha1_hash.digest().hex().upper()) # Hash arm9.bin sha1_hash = sha1() with open('arm9.bin', 'rb') as f: sha1_hash.update(f.read()) self.log.write('- Patched arm9.bin SHA1:\n ' + sha1_hash.digest().hex().upper()) Thread(target=self.arm9_prepend).start() except IOError as e: print(e) self.log.write('ERROR: Could not patch BIOS') Thread(target=self.clean, args=(True, )).start() except Exception as e: print(e) self.log.write('ERROR: Invalid patch header') Thread(target=self.clean, args=(True, )).start() ################################################################################################ def arm9_prepend(self): self.log.write('\nPrepending data to ARM9 BIOS...') try: with open('arm9.bin', 'rb') as f: data = f.read() with open('arm9.bin', 'wb') as f: with open( path.join('for PC', 'bootloader files', 'bootloader arm9 append to start.bin'), 'rb') as pre: f.write(pre.read()) f.write(data) # Hash arm9.bin sha1_hash = sha1() with open('arm9.bin', 'rb') as f: sha1_hash.update(f.read()) self.log.write('- Prepended arm9.bin SHA1:\n ' + sha1_hash.digest().hex().upper()) Thread(target=self.make_bootloader).start() except IOError as e: print(e) self.log.write('ERROR: Could not prepend data to ARM9 BIOS') Thread(target=self.clean, args=(True, )).start() ################################################################################################ def make_bootloader(self): self.log.write('\nGenerating new bootloader...') exe = (path.join('for PC', 'bootloader files', 'ndstool.exe') if sysname == 'Windows' else path.join( scriptPath, sysname, 'ndsblc')) try: proc = Popen([ exe, '-c', 'bootloader.nds', '-9', 'arm9.bin', '-7', 'arm7.bin', '-t', path.join('for PC', 'bootloader files', 'banner.bin'), '-h', path.join('for PC', 'bootloader files', 'header.bin') ]) ret_val = proc.wait() if ret_val == 0: self.files.append('bootloader.nds') # Hash bootloader.nds sha1_hash = sha1() with open('bootloader.nds', 'rb') as f: sha1_hash.update(f.read()) self.log.write('- bootloader.nds SHA1:\n ' + sha1_hash.digest().hex().upper()) Thread(target=self.decrypt_nand).start() else: self.log.write('ERROR: Generator failed') Thread(target=self.clean, args=(True, )).start() except OSError as e: print(e) self.log.write('ERROR: Could not execute ' + exe) Thread(target=self.clean, args=(True, )).start() ################################################################################################ def decrypt_nand(self): self.log.write('\nDecrypting NAND...') try: proc = Popen([ twltool, 'nandcrypt', '--in', self.nand_file.get(), '--out', self.console_id.get() + '.img' ]) ret_val = proc.wait() print("\n") if ret_val == 0: self.files.append(self.console_id.get() + '.img') Thread(target=self.win_extract_nand if ( sysname == 'Windows' and _7z is not None ) else self.extract_nand).start() else: self.log.write('ERROR: Decryptor failed') Thread(target=self.clean, args=(True, )).start() except OSError as e: print(e) self.log.write('ERROR: Could not execute ' + exe) Thread(target=self.clean, args=(True, )).start() ################################################################################################ def win_extract_nand(self): self.log.write('\nExtracting files from NAND...') try: if self.photo.get() == 1: proc = Popen([ _7z, 'x', '-bso0', '-y', self.console_id.get() + '.img', '0.fat', '1.fat' ]) else: proc = Popen([ _7z, 'x', '-bso0', '-y', self.console_id.get() + '.img', '0.fat' ]) ret_val = proc.wait() if ret_val == 0: self.files.append('0.fat') if self.photo.get() == 1: self.files.append('1.fat') proc = Popen( [_7z, 'x', '-bso0', '-y', '-o' + self.sd_path, '0.fat']) ret_val = proc.wait() if ret_val == 0: if self.photo.get() == 1: proc = Popen([ _7z, 'x', '-bso0', '-y', '-o' + self.sd_path, '1.fat' ]) ret_val = proc.wait() if ret_val == 0: Thread(target=self.get_launcher).start() else: self.log.write( 'ERROR: Failed to extract photo partition') Thread(target=self.clean, args=(True, )).start() else: Thread(target=self.get_launcher).start() else: self.log.write( 'ERROR: Extractor failed, please update 7-Zip') if path.exists(fatcat): self.log.write('\nTrying with fatcat...') Thread(target=self.extract_nand).start() else: Thread(target=self.clean, args=(True, )).start() else: self.log.write('ERROR: Extractor failed') if path.exists(fatcat): self.log.write('\nTrying with fatcat...') Thread(target=self.extract_nand).start() else: Thread(target=self.clean, args=(True, )).start() except OSError as e: print(e) self.log.write('ERROR: Could not execute ' + exe) if path.exists(fatcat): self.log.write('\nTrying with fatcat...') Thread(target=self.extract_nand).start() else: Thread(target=self.clean, args=(True, )).start() ################################################################################################ def extract_nand(self): self.log.write('\nExtracting files from NAND...') try: # DSi first partition offset: 0010EE00h proc = Popen([ fatcat, '-O', '1109504', '-x', self.sd_path, self.console_id.get() + '.img' ]) ret_val = proc.wait() if ret_val == 0: if self.photo.get() == 1: # DSi photo partition offset: 0CF09A00h proc = Popen([ fatcat, '-O', '217094656', '-x', self.sd_path, self.console_id.get() + '.img' ]) ret_val = proc.wait() if ret_val == 0: Thread(target=self.get_launcher).start() else: self.log.write( 'ERROR: Failed to extract photo partition') Thread(target=self.clean, args=(True, )).start() else: Thread(target=self.get_launcher).start() else: self.log.write('ERROR: Extractor failed') Thread(target=self.clean, args=(True, )).start() except OSError as e: print(e) self.log.write('ERROR: Could not execute ' + exe) Thread(target=self.clean, args=(True, )).start() ################################################################################################ def get_launcher(self): app = self.detect_region() # Stop if no supported region was found if not app: Thread(target=self.clean, args=(True, )).start() return # Delete contents of the launcher folder as it will be replaced by the one from hiyaCFW launcher_folder = path.join(self.sd_path, 'title', '00030017', app, 'content') # Walk through all files in the launcher content folder for file in listdir(launcher_folder): file = path.join(launcher_folder, file) # Set current file as read/write in case we extracted with 7-Zip and unlaunch was # installed in the NAND. Fatcat doesn't keep file attributes if _7z is not None: chmod(file, 438) # Delete current file remove(file) # Try to use already downloaded launcher try: if path.isfile(self.launcher_region): self.log.write('\nPreparing ' + self.launcher_region + ' launcher...') else: self.log.write('\nDownloading ' + self.launcher_region + ' launcher...') with urlopen('https://raw.githubusercontent.com' '/mondul/HiyaCFW-Helper/master/launchers/' + self.launcher_region) as src, open( self.launcher_region, 'wb') as dst: copyfileobj(src, dst) self.log.write('- Decrypting launcher...') # Set launcher filename according to the region launcher_app = ('00000000.app' if self.launcher_region in ('CHN', 'KOR') else '00000002.app') # Prepare decryption params params = [ _7za, 'x', '-bso0', '-y', '-p' + app.lower(), self.launcher_region, launcher_app ] proc = Popen(params) ret_val = proc.wait() if ret_val == 0: if self.clean_downloaded.get() == 1: self.files.append(self.launcher_region) self.files.append(launcher_app) # Hash launcher app sha1_hash = sha1() with open(launcher_app, 'rb') as f: sha1_hash.update(f.read()) self.log.write('- Patched launcher SHA1:\n ' + sha1_hash.digest().hex().upper()) Thread(target=self.install_hiyacfw, args=(launcher_app, launcher_folder)).start() else: self.log.write('ERROR: Extractor failed') Thread(target=self.clean, args=(True, )).start() except IOError as e: print(e) self.log.write('ERROR: Could not download ' + self.launcher_region + ' launcher') Thread(target=self.clean, args=(True, )).start() except OSError as e: print(e) self.log.write('ERROR: Could not execute ' + exe) Thread(target=self.clean, args=(True, )).start() ################################################################################################ def install_hiyacfw(self, launcher_app, launcher_folder): self.log.write('\nCopying HiyaCFW files...') # Reset copied files cache _path_created.clear() copy_tree('for SDNAND SD card', self.sd_path, update=1) copyfile('bootloader.nds', path.join(self.sd_path, 'hiya', 'bootloader.nds')) copyfile(launcher_app, path.join(launcher_folder, launcher_app)) Thread(target=self.get_latest_twilight if self.twilight.get() == 1 else self.clean).start() ################################################################################################ def get_latest_twilight(self): # Try to use already downloaded TWiLight Menu++ archive filename = 'TWiLightMenu-DSi.7z' try: if path.isfile(filename): self.log.write('\nPreparing TWiLight Menu++...') else: self.log.write( '\nDownloading latest TWiLight Menu++ release...') with urlopen( 'https://github.com/DS-Homebrew/TWiLightMenu/releases/latest/download/' + filename) as src, open(filename, 'wb') as dst: copyfileobj(src, dst) self.log.write('- Extracting ' + filename[:-3] + ' archive...') proc = Popen( [_7za, 'x', '-bso0', '-y', filename, '-oTWiLight-temp']) ret_val = proc.wait() if ret_val == 0: if self.clean_downloaded.get() == 1: self.files.append(filename) self.folders.append('TWiLight-temp') Thread(target=self.install_twilight, args=(filename[:-3], )).start() else: self.log.write('ERROR: Extractor failed') Thread(target=self.clean, args=(True, )).start() except (URLError, IOError) as e: print(e) self.log.write('ERROR: Could not get TWiLight Menu++') Thread(target=self.clean, args=(True, )).start() except OSError as e: print(e) self.log.write('ERROR: Could not execute ' + exe) Thread(target=self.clean, args=(True, )).start() ################################################################################################ def install_twilight(self, name): self.log.write('\nCopying ' + name + ' files...') copy_tree('TWiLight-temp', self.sd_path, update=1) Thread(target=self.clean).start() ################################################################################################ def clean(self, err=False): self.log.write('\nCleaning...') while len(self.folders) > 0: rmtree(self.folders.pop(), ignore_errors=True) while len(self.files) > 0: try: remove(self.files.pop()) except: pass if err: self.log.write('Done') return self.log.write('Done!\nEject your SD card and insert it into your DSi') ################################################################################################ def patcher(self, patchpath, filepath): patch_size = path.getsize(patchpath) patchfile = open(patchpath, 'rb') if patchfile.read(5) != b'PATCH': patchfile.close() raise Exception() target = open(filepath, 'r+b') # Read First Record r = patchfile.read(3) while patchfile.tell() not in [patch_size, patch_size - 3]: # Unpack 3-byte pointers. offset = self.unpack_int(r) # Read size of data chunk r = patchfile.read(2) size = self.unpack_int(r) if size == 0: # RLE Record r = patchfile.read(2) rle_size = self.unpack_int(r) data = patchfile.read(1) * rle_size else: data = patchfile.read(size) # Write to file target.seek(offset) target.write(data) # Read Next Record r = patchfile.read(3) if patch_size - 3 == patchfile.tell(): trim_size = self.unpack_int(patchfile.read(3)) target.truncate(trim_size) # Cleanup target.close() patchfile.close() ################################################################################################ def unpack_int(self, bstr): # Read an n-byte big-endian integer from a byte string (ret_val, ) = unpack_from('>I', b'\x00' * (4 - len(bstr)) + bstr) return ret_val ################################################################################################ def detect_region(self): REGION_CODES = { '484e4143': 'CHN', '484e4145': 'USA', '484e414a': 'JPN', '484e414b': 'KOR', '484e4150': 'EUR', '484e4155': 'AUS' } # Autodetect console region try: for app in listdir(path.join(self.sd_path, 'title', '00030017')): for file in listdir( path.join(self.sd_path, 'title', '00030017', app, 'content')): if file.lower().endswith('.app'): try: self.log.write('- Detected ' + REGION_CODES[app.lower()] + ' console NAND dump') self.launcher_region = REGION_CODES[app.lower()] return app except KeyError: self.log.write('ERROR: Unsupported console region') return False self.log.write('ERROR: Could not detect console region') except OSError as e: self.log.write('ERROR: ' + e.strerror + ': ' + e.filename) return False ################################################################################################ def remove_footer(self): self.log.write('\nRemoving No$GBA footer...') file = self.console_id.get() + '-no-footer.bin' try: copyfile(self.nand_file.get(), file) # Back-up footer info with open(self.console_id.get() + '-info.txt', 'w') as f: f.write('eMMC CID: ' + self.cid.get() + '\r\n') f.write('Console ID: ' + self.console_id.get() + '\r\n') with open(file, 'r+b') as f: # Go to the No$GBA footer offset f.seek(-64, 2) # Remove footer f.truncate() self.log.write('\nDone!\nModified NAND stored as\n' + file + '\nStored footer info in ' + self.console_id.get() + '-info.txt') except IOError as e: print(e) self.log.write('ERROR: Could not open the file ' + path.basename(self.nand_file.get())) ################################################################################################ def add_footer(self, cid, console_id): self.log.write('Adding No$GBA footer...') file = self.console_id.get() + '-footer.bin' try: copyfile(self.nand_file.get(), file) with open(file, 'r+b') as f: # Go to the No$GBA footer offset f.seek(-64, 2) # Read the footer's header :-) bstr = f.read(0x10) # Check if it already has a footer if bstr == b'DSi eMMC CID/CPU': self.log.write('ERROR: File already has a No$GBA footer') f.close() remove(file) return # Go to the end of file f.seek(0, 2) # Write footer f.write(b'DSi eMMC CID/CPU') f.write(cid) f.write(console_id) f.write(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') self.log.write('\nDone!\nModified NAND stored as\n' + file) except IOError as e: print(e) self.log.write('ERROR: Could not open the file ' + path.basename(self.nand_file.get()))
class LayoutTester(object): """Gränssnitt för testning av layoutfunktioner.""" def __init__(self, layout_func, debug=False): """Skapa GUI och förbereder tkinter.Labels som ska layoutas. layout_func -- Funktionen som ska placera kvadraterna, se modulbeskrivning ovan. """ self.layout_func = layout_func self.debug = debug # storleksalternativ self.size_options = [ size for size in range(MIN_SQUARE_SIZE, MAX_SQUARE_SIZE + 1, SIZE_STEP) ] + ["random"] # lista för kvadraterna self.squares = [] # skapa gränssnittet och kör igång mainloop self.ui_xpadding = 4 self.ui_ypadding = 4 self.init_ui() # slumpa fram fönsterstorlek w_size = "{}x{}".format(705 + randint(0, 300), 250 + randint(0, 500)) self.root.geometry(w_size) self.root.mainloop() def init_ui(self): """Skapa gränssnittet och kör igång mainloop.""" self.root = Tk() self.root.title("Laboration 5") # root.resizable(width=False, height=False) # Tk-variabler till kvadratsstorlek, antal kvadrater, start_left och # start_top. self.size_value = StringVar() self.size_value.set(self.size_options[0]) self.number_of_squares = IntVar() self.start_left = BooleanVar() self.start_left.set(True) self.start_top = BooleanVar() self.start_top.set(True) # Frame att lägga kvadraterna i self.square_frame = Frame( self.root, # height=self.squares_frame_height, # width=self.squares_frame_width, bg="#eef") if self.debug: self.square_frame.bind("<Configure>", self.frame_changed) self.square_frame.pack(side=TOP, expand=1, fill=BOTH, padx=self.ui_xpadding, pady=self.ui_ypadding) # Frame med inställningar self.controll_panel = LabelFrame(self.root, text="Inställningar") self.init_controll_panel() self.controll_panel.pack(fill=BOTH, padx=self.ui_xpadding, pady=self.ui_ypadding) # Informationstext infotext = "Kom ihåg att ändra fönstrets storlek när du testar! " + \ "Se även utskrifterna i terminalen." self.instructions = Label(self.root, text=infotext) self.instructions.pack(anchor=W) def init_controll_panel(self): """Skapa kontrollpanel för inställningar.""" self.create_size_panel() self.create_num_squares_panel() # self.create_start_pos_panel() self.create_run_quit_panel() def create_size_panel(self): """Skapa OptionMenu för storlek på kvadraterna.""" size_panel = Frame(self.controll_panel) Label(size_panel, text="Kvadratsstorlek").pack(side=LEFT) OptionMenu(size_panel, self.size_value, *self.size_options).pack(side=LEFT) size_panel.pack(side=LEFT, padx=self.ui_xpadding, pady=self.ui_ypadding) def create_num_squares_panel(self): """Skapa kontroller för att välja antal kvadrater som skapas.""" num_squares_panel = Frame(self.controll_panel) Label(num_squares_panel, text="Antal kvadrater").pack(side=LEFT, anchor=S) Scale(num_squares_panel, variable=self.number_of_squares, from_=4, to=MAX_NUM_SQUARES, orient=HORIZONTAL).pack(side=LEFT, anchor=N) num_squares_panel.pack(side=LEFT, anchor=N, padx=self.ui_xpadding, pady=self.ui_ypadding) def create_start_pos_panel(self): """Skapa kontroller för att välja var layouten börjar.""" start_panel = Frame(self.controll_panel) Checkbutton(start_panel, text="Börja från vänster", justify=LEFT, variable=self.start_left, onvalue=True, offvalue=False).pack(fill=X, anchor=N) Checkbutton(start_panel, text="Börja uppifrån", variable=self.start_top, justify=LEFT, onvalue=True, offvalue=False).pack(fill=X, anchor=N) start_panel.pack(side=LEFT, anchor=N, padx=self.ui_xpadding, pady=self.ui_ypadding) def create_run_quit_panel(self): """Skapa knappar för att köra layout och avsluta programmet.""" button_panel = Frame(self.controll_panel) Button(button_panel, text="Kör layoutfunktion", command=self.run_layout).pack(fill=X) Button(button_panel, text="Avsluta", command=self.root.quit).pack(fill=X) button_panel.pack(side=RIGHT, anchor=N, padx=self.ui_xpadding, pady=self.ui_ypadding) def create_squares(self): """Skapa tkinter.Label objekt som sparas i LayoutTester-instansen. Antalet kvadrater som ska skapas, samt kvadraternas storlek hämtas från gränssnittet. """ number_of_squares = self.number_of_squares.get() size = self.size_value.get() square_counter = 0 hue_step = 1 / number_of_squares hue_value = 0 # Skapa kvadrater och lägg dem i listan self.squares while square_counter < number_of_squares: # konververa hsv-färg till rgb-trippel (heltal 0-255) rgb = [int(val * 255) for val in hsv_to_rgb(hue_value, 0.75, 0.70)] # konvertera rgb-trippel till sträng bg_color = "#{:x}{:x}{:x}".format(rgb[0], rgb[1], rgb[2]) # textfärg fg_color = "#fff" # sätt storleken på kvadraten if size != "random": square_size = int(size) else: square_size = choice(self.size_options[:-1]) # sätt storleken på texten baserat på kvadratstorleken font_size = int(square_size * 0.6) # skapa kvadraten square = Label(self.square_frame, fg=fg_color, bg=bg_color, font=Font(family="Verdana", weight=NORMAL, size=font_size), text=str(square_counter + 1)) # spara den i listan med kvadrater self.squares.append(square) # göm kvadraten utanför det synliga området och ställ in # dess storlek square.place(x=-square_size, y=-square_size, height=square_size, width=square_size) # gå vidare till nästa kvadrat och färg square_counter += 1 hue_value += hue_step # uppdatera geometri-info för alla widgets (ser till att de vet hur # stora de är) square.update_idletasks() def clear_squares(self): """Ta bort existerande kvadrater.""" for square in self.squares: square.destroy() del self.squares[:] def frame_changed(self, event): if event.widget == self.square_frame or event.widget == self.root: print("Resize. root: {}x{}, square_frame: {}x{}".format( self.root.winfo_width(), self.root.winfo_height(), self.square_frame.winfo_width(), self.square_frame.winfo_height())) def run_layout(self): """Skapa nya kvadrater och kör layoutfunktionen.""" # ta bort gamla kvadrater self.clear_squares() # skapa nya kvadrater self.create_squares() # placera ut kvadraterna print("Running '{0}(<squares>, {1}, {2})'...".format( self.layout_func.__name__, self.square_frame.winfo_height(), self.square_frame.winfo_width())) self.layout_func(self.squares, self.square_frame.winfo_height(), self.square_frame.winfo_width())
column=0) Radiobutton(text='Large City', variable=sett_size, value=7).grid(row=8, column=0) Radiobutton(text='Metropolis', variable=sett_size, value=8).grid(row=9, column=0) Label(root, text='Shop Size:').grid(row=0, column=1) Radiobutton(text='Tiny', variable=shop_size, value=1).grid(row=2, column=1) Radiobutton(text='Small', variable=shop_size, value=2).grid(row=3, column=1) Radiobutton(text='Medium', variable=shop_size, value=3).grid(row=4, column=1) Radiobutton(text='Large', variable=shop_size, value=4).grid(row=5, column=1) Label(root, text='Number to Make:').grid(row=6, column=1) count = Entry(root, width=7) count.grid(row=7, column=1) Checkbutton(root, text='Save to .xlsx file?', variable=flag).grid(row=10, column=0) Button(root, text='Data File...', command=lambda: handle_files(data_path, return_path, root)).grid( row=8, column=1) Button(root, text='Go', command=lambda: main(sett_size.get(), shop_size.get(), count.get(), data_path.get(), return_path.get())).grid(row=10, column=1) root.mainloop()
class GsrSensorTabContent(SensorTabContent): """ GsrSensorTabContent is the specialization of a SensorTabContent for the Shimmer3 GSR+ device. """ def __init__(self, master=None, sensor=None, available_ports=None, last_com_ports=None): """ Constructor :param master: the parent window :param sensor: the object Shimmer3 that represents the Shimmer3 GSR+ device :param available_ports: list of all available COM ports in that host :param last_com_ports: last COM ports used for a successfully connection with the Shimmer3 devices """ self._active_gsr_mu = StringVar(value=sensor.active_gsr_mu) super(GsrSensorTabContent, self).__init__(master=master, sensor=sensor, available_ports=available_ports, last_com_ports=last_com_ports) def _specialized_frame(self, master): """ Implement the specialized frame (bottom-left) of the sensor configuration's UI. :param master: the parent window :return: the specialized frame """ frame = ttk.Frame(master, style="Tab.TFrame") # In the case of GSR+ we want to choose what Measurement Units it should be used # for the GSR sensor. # (mu = Measurement Unit) label_mu = ttk.Label(frame, text="GSR Measurement Unit: ") label_mu.pack(pady=(0, 2)) selection = ttk.Combobox(frame, cursor="hand2", values=[util.GSR_SKIN_CONDUCTANCE, util.GSR_SKIN_RESISTANCE], state="readonly", justify=tk.LEFT, style="CustomCombobox.TCombobox", textvariable=self._active_gsr_mu) selection.pack() return frame def _specialized_func_write_all(self): """ Add specialized writing operations at the default 'write_all' :return: True in case of successfully operation, False otherwise """ # We want to set in AUTO mode the GSR range setting. # Read Shimmer3 GSR+ documentation on the Shimmer3 website for more info. if not self._sensor.set_gsr_range(4): return False if not self._sensor.set_active_gsr_mu(new_mu=self._active_gsr_mu.get()): return False return True def _specialized_update_all(self): """ Add specialized reading operations at the default 'update_all'. :return: True in case of successfully operation, False otherwise """ self._active_gsr_mu.set(self._sensor.active_gsr_mu) return True
class ftp_client(): def __init__(self): self.root = Tk() self.root.title("FTP客户端GUI") self.root.geometry("700x500+500+100") self.root.minsize(700, 500) # self.root.resizable(False, False) self.root.update() self.var_port = IntVar(value=3333) self.var_address = StringVar(value="0.0.0.0") self.default_timeout = IntVar(value=-999) self.path_remote = StringVar() self.path_local = StringVar() self.inputFileName = "" self.filelist_local = None self.filelist_remote = None self.ftp_connect = FTP() self.init_view() self.root.mainloop() def init_view(self): """界面""" self.init_menu() self.head_box = Frame(self.root, relief="ridge", borderwidth=0) self.head_box.pack(fill="x", expand=None, side="top", anchor="n") self.btn_box = Frame(self.root, relief="ridge", borderwidth=0) self.btn_box.pack(fill="x", expand=None, side="top", anchor="n") self.content_box = Frame(self.root, relief="ridge", borderwidth=0, bd=1) self.content_box.pack(fill="both", expand=True) self.remote_box = Frame(self.content_box, relief="ridge", borderwidth=0) self.remote_box.pack(fill="both", expand=True, side="right") self.local_box = Frame(self.content_box, relief="ridge", borderwidth=0) self.local_box.pack(fill="both", expand=True, side="left") self.footer_box = Frame(self.root, relief="ridge", borderwidth=0, bd=1) self.footer_box.pack(fill="x", expand=None, side="bottom", anchor="s") self.init_header() self.init_btns() self.init_remote() self.init_local() self.init_footer() def init_header(self): """头部栏""" label_ip = Label(self.head_box, text="地址:") label_ip.grid(row=0, column=0, sticky="e") self.entry_ip = Entry(self.head_box, textvariable=self.var_address) self.entry_ip.grid(row=0, column=1, sticky="w") label_port = Label(self.head_box, text="端口:") label_port.grid(row=1, column=0, sticky="e") self.entry_port = Entry(self.head_box, textvariable=self.var_port) self.entry_port.grid(row=1, column=1, sticky="w") label_user = Label(self.head_box, text="账号:") label_user.grid(row=2, column=0, sticky="e") self.entry_user = Entry(self.head_box) self.entry_user.grid(row=2, column=1, sticky="w") label_passwd = Label(self.head_box, text="密码:") label_passwd.grid(row=3, column=0, sticky="e") self.entry_passwd = Entry(self.head_box, show="*") self.entry_passwd.grid(row=3, column=1, sticky="w") def init_btns(self): button_connect = Button(self.btn_box, text="连接", command=self.ftp_login) button_connect.pack(side="left") button_disconnect = Button(self.btn_box, text="断开", command=self.ftp_quit) button_disconnect.pack(side="left") button_reflash = Button(self.btn_box, text="刷新", command=self.flash_remote) button_reflash.pack(side="left") def init_remote(self): """远程文件列表""" btns = Frame(self.remote_box, relief="ridge", borderwidth=0) btns.pack(fill="x", expand=False, side="top") Label(btns, text="远程:").pack(fill="x", expand=None, side="left") Entry(btns, textvariable=self.path_remote).pack(fill="x", expand=None, side="left") Button(btns, text="打开", command=self.select_path_local).pack(fill="x", expand=None, side="left") Button(btns, text="重连", command=self.ftp_login).pack(side="left") Button(btns, text="断开", command=self.ftp_quit).pack(side="left") Button(btns, text="刷新", command=self.flash_remote).pack(fill="x", expand=None, side="right") file_list = Frame(self.remote_box, relief="ridge", borderwidth=0) file_list.pack(fill="both", expand=True, side="top") # Listbox # self.filelist_remote = Listbox(self.remote_box) # self.filelist_remote.bind("<Double-Button-1>", self.click_db) # self.filelist_remote.pack(fill="both", expand=True, side="top") tree = Treeview(file_list, show="headings") # 列索引ID tree["columns"] = ("pra", "id", "user", "group", "size", "date", "name") # 表头设置 tree.heading("pra", text="权限") tree.heading("id", text="ID") tree.heading("user", text="用户") tree.heading("group", text="组") tree.heading("size", text="大小") tree.heading("date", text="最后修改日期") tree.heading("name", text="文件名") tree.column("pra", width="100") tree.column("id", width="50", anchor="center") tree.column("user", width="50") tree.column("group", width="50") tree.column("size", width="50") tree.column("date", width="50") tree.column("name", width="50") self.filelist_remote = tree vbar = Scrollbar(file_list, orient="vertical", command=tree.yview) tree.configure(yscrollcommand=vbar.set) tree.grid(row=0, column=0, sticky="nswe") vbar.grid(row=0, column=1, sticky="ns") def init_local(self): """本地文件列表""" btns = Frame(self.local_box, relief="ridge", borderwidth=0) btns.pack(fill="x", expand=False, side="top") Label(btns, text="本地:").pack(fill="x", expand=None, side="left") Entry(btns, textvariable=self.path_local).pack(fill="x", expand=None, side="left") Button(btns, text="打开", command=self.select_path_local).pack(fill="x", expand=None, side="left") Button(btns, text="刷新", command=self.flash_local).pack(fill="x", expand=None, side="right") self.filelist_local = Listbox(self.local_box) self.filelist_local.bind("<Double-Button-1>", self.click_db) self.filelist_local.pack(fill="both", expand=True, side="top") def init_footer(self): Label(self.footer_box, text="欢迎使用").pack(side="left") Label(self.footer_box, text="欢迎使用").pack(fill="x", side="left") self.clock = Label(self.footer_box, text=time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))) self.clock.pack(side="right") self.clock.after(1000, self.trickit) self.trickit() def trickit(self): currentTime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) self.clock["text"] = currentTime self.clock.update() self.clock.after(1000, self.trickit) def init_menu(self): self.menubar = Menu(self.root) self.menu_f = Menu(self.menubar, tearoff=0) for each in ["打开", "保存", "另存为", "关闭"]: self.menu_f.add_command(label=each) self.menu_f.add_separator() self.menu_f.add_command(label="退出", command=self.quit) self.menubar.add_cascade(label="文件", menu=self.menu_f) self.menu_e = Menu(self.menubar, tearoff=0) for each in ["复制", "剪切", "粘贴"]: self.menu_e.add_command(label=each) self.menubar.add_cascade(label="编辑", menu=self.menu_e) self.menu_v = Menu(self.menubar, tearoff=0) self.menu_v.add_command(label="状态") self.menubar.add_cascade(label="查看", menu=self.menu_v) self.t_menu = Menu(self.menubar) self.t_menu.add_command(label="状态", accelerator='Alt+H') self.menubar.add_cascade(label="传输", menu=self.t_menu) self.menu_s = Menu(self.menubar) self.menu_s.add_command(label="状态", accelerator='Ctrl+N') self.menubar.add_cascade(label="服务器", menu=self.menu_s) self.menu_b = Menu(self.menubar) self.menu_b.add_command(label="状态") self.menubar.add_cascade(label="书签", menu=self.menu_b) self.menu_h = Menu(self.menubar, tearoff=1) self.menu_h.add_separator() self.menu_h.add_command(label="版本信息") self.menu_h.add_separator() self.menu_h.add_command(label="关于我们") self.menubar.add_cascade(label="帮助", menu=self.menu_h) self.root["menu"] = self.menubar def ftp_login(self): self.ftp_connect.connect(self.var_address.get().strip(), int(self.entry_port.get().strip())) self.ftp_connect.login(self.entry_user.get(), self.entry_passwd.get()) self.flash_remote() # 加载列表 def ftp_quit(self): if self.ftp_connect is not None: self.ftp_connect.quit() def ftp_close(self): if self.ftp_connect is not None: self.ftp_connect.close() def flash_remote(self): file_list = [] self.ftp_connect.dir("", file_list.append) for x in file_list: i = x.split() # 或者filename = x.split("\t")[列的起始值:列的终止值] self.filelist_remote.insert("", "end", text="", values=(i[0], i[1], i[2], i[3], i[4], i[5:8], i[-1])) def flash_local(self): filelist = self.ftp_connect.nlst() if self.filelist_local.size() > 0: self.filelist_local.delete(0, "end") for i in range(len(filelist)): self.filelist_local.insert("end", filelist[i]) def click_db(self, event): self.download() def download(self): inputFileName = self.filelist_remote.get( self.filelist_remote.curselection()) file_handler = open(self.path_remote.get() + "/" + inputFileName, "wb").write self.ftp_connect.retrbinary( "RETR %s" % os.path.basename(inputFileName), file_handler, 1024) def select_path_local(self): path = filedialog.askdirectory() if os.path.isdir(path): self.path_local.set(path) self.path_remote.set(path) def quit(self): self.root.quit()
#Champ d'entrée pour la saisie champ_lettre = Entry(app_pendu) champ_lettre.focus_set() #Bouton de proposition de la saisie bouton_proposition = Button(app_pendu, text='Proposer', command = verification_actualisation_lettre) #initialisation image pendu lien_img = 'data/img_pendu/bonhomme' source_image = StringVar() source_image.set(lien_img + str(chances.get()) + '.gif') #Création Canvas contenant l'image canevas_pendu = Canvas(app_pendu, width = 300, height = 300) img = PhotoImage(file = str(source_image.get())) creation_img = canevas_pendu.create_image(150, 150, image = img) #initialisation de message info info = StringVar() info.set('') #création label info label_info = Label(app_pendu, textvariable = info) #Initialisation du pseudo pseudo = StringVar() #Bouton pour sauvegarder le score et quitter le jeu bouton_sauvegarder_quitter = Button(app_pendu, text='Sauvegarder et Quitter', command = save_quit)
class SensorTabContent(ttk.Frame): """ SensorTabContent represents the general tab for a Shimmer device (tab of the Notebook) """ def __init__(self, master=None, sensor=None, available_ports=None, last_com_ports=None): """ Constructor :param master: the parent window :param sensor: the Shimmer3 object that represents the device of this tab :param available_ports: list of all available COM ports in that host :param last_com_ports: last COM ports used for a successfully connection with the Shimmer3 devices """ super(SensorTabContent, self).__init__(master=master, style="Tab.TFrame") self._sensor = sensor self._available_ports = available_ports self._last_com_ports = last_com_ports self._available_sensors = self._sensor.get_available_sensors() self._selected_sensors = {} for sensor in self._available_sensors: value = 0 if sensor["name"] in self._sensor.enabled_sensors: value = 1 self._selected_sensors[sensor["name"]] = IntVar(value=value) # DYNAMIC VARIABLES for input widgets self._selected_port = StringVar( value=self._last_com_ports[self._sensor.shimmer_type]) self._sampling_rate = DoubleVar(value=self._sensor.sampling_rate) # Checkbox styling self._check_on_image = tk.PhotoImage(data=SELECTED_THEME["check_on"]) self._check_off_image = tk.PhotoImage(data=SELECTED_THEME["check_off"]) self._not_connected_main_frame = self._not_yet_connected_page() self._connected_main_frame = self._connected_page() self._current_view = "Not Connected" # Let's show the correct view if self._sensor.current_state != util_shimmer.IDLE \ and self._sensor.current_state != util_shimmer.SD_LOGGING: self._connected_main_frame.pack(expand=1, fill=tk.BOTH) self._current_view = "Connected" else: self._not_connected_main_frame.pack(expand=1, fill=tk.BOTH) def _not_yet_connected_page(self): """ Implement the "NotYetConnected" view. This view is shown when the Shimmer device is not connected yet. :return: the main Frame of the view """ main_frame = ttk.Frame(self, style="Tab.TFrame") form_frame = ttk.Frame(main_frame, style="Tab.TFrame") # useful for center widgets form_frame.pack(expand=1) label_selection = ttk.Label(form_frame, text="Select COM Port: ") label_selection.pack(pady=(0, 2)) self._selection = ttk.Combobox(form_frame, cursor="hand2", values=self._available_ports, state="readonly", justify=tk.LEFT, style="CustomCombobox.TCombobox", textvariable=self._selected_port) self._selection.pack() label_warning = ttk.Label( form_frame, style="Warning.TLabel", text= "Be sure that you choose the correct \nport for the correct sensor!" ) label_warning.pack(pady=(1, 0)) self._label_hint = ttk.Label(form_frame, text="discover how", style="Link.Small.TLabel", cursor="hand2") self._label_hint.pack(pady=(0, 5)) # Customizing for 'over' event self._label_hint.bind( "<Enter>", lambda event: self._configure_text_window( foreground=SELECTED_THEME["link_over_text_color"], )) # Customizing for 'leave' event (normal) self._label_hint.bind( "<Leave>", lambda event: self._configure_text_window( foreground=SELECTED_THEME["link_normal_text_color"], )) # Customizing for 'click-in' event self._label_hint.bind( "<Button-1>", lambda event: self._configure_text_window( foreground=SELECTED_THEME["link_clicking_text_color"])) self._label_hint.bind( "<ButtonRelease-1>", lambda event: showinfo( "How to check COM Ports", "Go to: START -> BLUETOOTH DEVICES -> " "DEVICES AND " "PRINTERS.\nNow search for your DEVICE (e.g. " "Shimmer3-XXXX), " "right click on it: PROPERTIES.\nClick on " "the HARDWARE tab " " and you'll find the COM port.")) connect_button = ttk.Button(form_frame, text="Connect", command=self._connect, cursor="hand2", style="RoundedButtonLight.TButton") connect_button.pack(pady=5, ipady=1) return main_frame def _connected_page(self): """ Implement the "Connected" view. That view is shown where the Shimmer device is connected. :return: the main Frame of the view """ # Main Frame main_frame = ttk.Frame(self, style="Tab.TFrame") main_frame.rowconfigure(0, weight=2) main_frame.rowconfigure(1, weight=1) main_frame.columnconfigure(0, weight=2) main_frame.columnconfigure(1, weight=1) # General Options Frame left_frame = ttk.Frame(main_frame, style="Tab.TFrame") left_frame.grid(row=0, column=0, sticky="nwes") # Frequency Management frequency_frame = ttk.Frame(left_frame, style="Tab.TFrame") frequency_frame.pack(expand=1, side=tk.TOP) frequency_entry_label = ttk.Label(frequency_frame, text="Sampling Rate: (Hz)") frequency_entry_label.pack(expand=1) frequency_entry = ttk.Entry(frequency_frame, textvariable=self._sampling_rate) frequency_entry.pack(expand=1) frequency_entry.bind("<Leave>", self._rounding_sampling_rate) frequency_entry.bind( "<FocusOut>", self._rounding_sampling_rate) # little bit defensive ? specialized_frame = self._specialized_frame(left_frame) if specialized_frame is not None: specialized_frame.pack(expand=1, side=tk.TOP) # Sensors Options Frame enabled_sensors_frame = ttk.Frame(main_frame, style="Tab.TFrame") enabled_sensors_frame.grid(row=0, column=1, sticky="nwes") enabled_sensors_frame.rowconfigure(0, weight=1) enabled_sensors_frame.rowconfigure(1, weight=5) enabled_sensors_frame.columnconfigure(0, weight=1) enabled_sensors_label = ttk.Label(enabled_sensors_frame, text="Enabled Sensors: ") enabled_sensors_label.grid(row=0, column=0) enabled_sensors_grid = ttk.Frame(enabled_sensors_frame, style="Tab.TFrame") enabled_sensors_grid.grid(row=1, column=0, sticky="nwes") # Showing all sensors, to enable/disable them i = 0 j = 0 for sensor in self._available_sensors: enabled_sensors_grid.rowconfigure(i, weight=1) enabled_sensors_grid.columnconfigure(j, weight=1) sensor_frame = ttk.Frame(enabled_sensors_grid, style="Tab.TFrame") sensor_frame.grid(row=i, column=j) sensor_name = sensor["name"] label = ttk.Label(sensor_frame, text=sensor_name, style="Light.TLabel") label.grid(row=0, column=0) checkbutton = tk.Checkbutton( sensor_frame, variable=self._selected_sensors[sensor["name"]], onvalue=1, offvalue=0, image=self._check_off_image, selectimage=self._check_on_image, indicatoron=0, borderwidth=0, highlightthickness=0, relief=tk.FLAT, highlightcolor="red", overrelief=tk.FLAT, offrelief=tk.FLAT, background=SELECTED_THEME["light_frame_background"], takefocus=0, cursor="hand2") checkbutton.grid(row=0, column=1) j += 1 if j == 3: j = 0 i += 1 # Read/Write All Properties self._read_write_all_properties_frame = ttk.Frame(main_frame, style="Tab.TFrame") self._read_write_all_properties_frame.grid(row=1, column=0, columnspan=2) self._read_all_properties_btn = ttk.Button( self._read_write_all_properties_frame, text="Read Properties", command=self.update_all, style="RoundedButtonLight.TButton") self._read_all_properties_btn.grid(row=0, column=0, padx=20) self._write_all_properties_btn = ttk.Button( self._read_write_all_properties_frame, text="Write Properties", command=self.write_all, style="RoundedButtonLight.TButton") self._write_all_properties_btn.grid(row=0, column=1, padx=20) return main_frame def _connect(self): """ This method is the callback linked to the button "Connect". It use 'func_connect' to implement the connection. """ if self._selected_port.get( ) is not None and self._selected_port.get() != "": popup = TaskPopup(master=self, func=self._func_connect, args=()) popup.start() self.wait_window(popup.top_level) if popup.result: self.update_all() else: showerror("ERROR", "Something went wrong during connection") else: showerror("ERROR", "You have to choose a COM port before!") # DEBUG -> only switch # self._switch_current_view() def _func_connect(self): """ 'func_connect' implement the connection with the Shimmer3 device. :return: True in case of successfully operation, False otherwise """ if self._sensor.connect(self._selected_port.get(), write_rtc=True, update_all_properties=True, reset_sensors=False): # Update Last Port File self._last_com_ports[ self._sensor.shimmer_type] = self._selected_port.get() file = open('last_com_ports.pkl', 'wb') pickle.dump(self._last_com_ports, file) file.close() return True else: return False def _switch_current_view(self): """ This method switch between the "NotYetConnected" page and the "Connected" page. """ if self._current_view == "Not Connected": self._not_connected_main_frame.pack_forget() self._connected_main_frame.pack(expand=1, fill=tk.BOTH) self._current_view = "Connected" else: self._connected_main_frame.pack_forget() self._not_connected_main_frame.pack(expand=1, fill=tk.BOTH) self._current_view = "Not Connected" def _configure_text_window(self, **kwargs): """ Auxiliary function to customize a widget. :param kwargs: list of params of customization """ for avp in kwargs.items(): attrib, value = avp self._label_hint[attrib] = value def update_all(self, show_info=True): """ This method update the UI with info from the device. :param show_info: show a modal window that notifies the updating :type show_info: bool """ if self._sensor.current_state == util_shimmer.BT_CONNECTED: self._selected_port.set(self._sensor.com_port) self._sampling_rate.set(self._sensor.sampling_rate) for sensor in self._available_sensors: value = 0 if sensor["name"] in self._sensor.enabled_sensors: value = 1 self._selected_sensors[sensor["name"]].set(value) # Switch View if (self._current_view == "Not Connected" and self._sensor.current_state == util_shimmer.BT_CONNECTED ) or (self._current_view == "Connected" and self._sensor.current_state == util_shimmer.IDLE): self._switch_current_view() res = self._specialized_update_all() if res: # Notify the end of update if show_info: showinfo("UPDATE", "All properties are succesfully readed!") else: showerror("ERROR", "Something went wrong during reading...") else: if self._current_view == "Connected": self._switch_current_view() # noinspection PyUnusedLocal def _rounding_sampling_rate(self, event): """ This method rounds the sampling rate to show the correct configured sampling rate (that's probably different from the sampling rate requested, consider to read documentation of the LogAndStream firmware on Shimmer3 website) :param event: the Event of the widget """ if self._sampling_rate.get() != 0: self._sampling_rate.set( round(32768.0 / round(32768.0 / self._sampling_rate.get()), 2)) def update_sensor(self, sensor): """ This method update the 'sensor' object linked to this tab. It is useful in case of deserialization. :param sensor: the new Shimmer3 object linked to the tab """ self._sensor = sensor self.update_all(show_info=False) def _specialized_func_write_all(self): """ This method should be override on sub-classes to specify some additional, specific, operations. :return: True in case of successfully operation, False otherwise """ return True def _func_write_all(self): """ This method implements the operations for writing settings on the Shimmer3 device. :return: True in case of successfully operation, False otherwise """ if not self._sensor.set_sampling_rate(self._sampling_rate.get()): return False # Enabling selected sensors sensors_to_enable = [] for sensor in self._available_sensors: if self._selected_sensors[sensor["name"]].get(): sensors_to_enable.append(sensor) if not self._sensor.set_enabled_sensors(*sensors_to_enable): return False # This is a custom choice, for simplicity if not self._sensor.set_wide_acc_range(util_shimmer.WIDE_ACC_RANGE_2g): return False # This is a custom choice, for simplicity if not self._sensor.set_gyro_range(1): return False # Call all the specialized operation (useful for sub-classes) res = self._specialized_func_write_all() return res def write_all(self): """ Callback linked to 'Write' button click. It use 'TaskPopup' to write all settings to the Shimmer3 device. """ if self._sensor.current_state == util_shimmer.BT_CONNECTED: popup = TaskPopup(master=self, func=self._func_write_all, args=()) popup.start() self.wait_window(popup.top_level) if popup.result: showinfo("WRITE", "All properties are written to the Shimmer.") self.update_all(show_info=False) else: showerror("ERROR", "Something went wrong...") else: showerror("ERROR", "The Shimmer is not connected...") def _specialized_update_all(self): """ This method should be override on sub-classes to specify some additional, specific, operations. :return: True in case of successfully operation, False otherwise """ return True def _specialized_frame(self, master): """ This method should be override on sub-classes to implements eventual specialized settings' frame :param master: the parent window :return: the specialized frame """ return None
class ReplaceDialog(SearchDialogBase): "Dialog for finding and replacing a pattern in text." title = "Replace Dialog" icon = "Replace" def __init__(self, root, engine): """Create search dialog for finding and replacing text. Uses SearchDialogBase as the basis for the GUI and a searchengine instance to prepare the search. Attributes: replvar: StringVar containing 'Replace with:' value. replent: Entry widget for replvar. Created in create_entries(). ok: Boolean used in searchengine.search_text to indicate whether the search includes the selection. """ super().__init__(root, engine) self.replvar = StringVar(root) self.insert_tags = None def open(self, text, insert_tags=None): """Make dialog visible on top of others and ready to use. Also, highlight the currently selected text and set the search to include the current selection (self.ok). Args: text: Text widget being searched. """ SearchDialogBase.open(self, text) try: first = text.index("sel.first") except TclError: first = None try: last = text.index("sel.last") except TclError: last = None first = first or text.index("insert") last = last or first self.show_hit(first, last) self.ok = True self.insert_tags = insert_tags def create_entries(self): "Create base and additional label and text entry widgets." SearchDialogBase.create_entries(self) self.replent = self.make_entry("Replace with:", self.replvar)[0] def create_command_buttons(self): """Create base and additional command buttons. The additional buttons are for Find, Replace, Replace+Find, and Replace All. """ SearchDialogBase.create_command_buttons(self) self.make_button("Find", self.find_it) self.make_button("Replace", self.replace_it) self.make_button("Replace+Find", self.default_command, isdef=True) self.make_button("Replace All", self.replace_all) def find_it(self, event=None): "Handle the Find button." self.do_find(False) def replace_it(self, event=None): """Handle the Replace button. If the find is successful, then perform replace. """ if self.do_find(self.ok): self.do_replace() def default_command(self, event=None): """Handle the Replace+Find button as the default command. First performs a replace and then, if the replace was successful, a find next. """ if self.do_find(self.ok): if self.do_replace(): # Only find next match if replace succeeded. # A bad re can cause it to fail. self.do_find(False) def _replace_expand(self, m, repl): "Expand replacement text if regular expression." if self.engine.isre(): try: new = m.expand(repl) except re.error: self.engine.report_error(repl, 'Invalid Replace Expression') new = None else: new = repl return new def replace_all(self, event=None): """Handle the Replace All button. Search text for occurrences of the Find value and replace each of them. The 'wrap around' value controls the start point for searching. If wrap isn't set, then the searching starts at the first occurrence after the current selection; if wrap is set, the replacement starts at the first line. The replacement is always done top-to-bottom in the text. """ prog = self.engine.getprog() if not prog: return repl = self.replvar.get() text = self.text res = self.engine.search_text(text, prog) if not res: self.bell() return text.tag_remove("sel", "1.0", "end") text.tag_remove("hit", "1.0", "end") line = res[0] col = res[1].start() if self.engine.iswrap(): line = 1 col = 0 ok = True first = last = None # XXX ought to replace circular instead of top-to-bottom when wrapping text.undo_block_start() while True: res = self.engine.search_forward(text, prog, line, col, wrap=False, ok=ok) if not res: break line, m = res chars = text.get("%d.0" % line, "%d.0" % (line+1)) orig = m.group() new = self._replace_expand(m, repl) if new is None: break i, j = m.span() first = "%d.%d" % (line, i) last = "%d.%d" % (line, j) if new == orig: text.mark_set("insert", last) else: text.mark_set("insert", first) if first != last: text.delete(first, last) if new: text.insert(first, new, self.insert_tags) col = i + len(new) ok = False text.undo_block_stop() if first and last: self.show_hit(first, last) self.close() def do_find(self, ok=False): """Search for and highlight next occurrence of pattern in text. No text replacement is done with this option. """ if not self.engine.getprog(): return False text = self.text res = self.engine.search_text(text, None, ok) if not res: self.bell() return False line, m = res i, j = m.span() first = "%d.%d" % (line, i) last = "%d.%d" % (line, j) self.show_hit(first, last) self.ok = True return True def do_replace(self): "Replace search pattern in text with replacement value." prog = self.engine.getprog() if not prog: return False text = self.text try: first = pos = text.index("sel.first") last = text.index("sel.last") except TclError: pos = None if not pos: first = last = pos = text.index("insert") line, col = searchengine.get_line_col(pos) chars = text.get("%d.0" % line, "%d.0" % (line+1)) m = prog.match(chars, col) if not prog: return False new = self._replace_expand(m, self.replvar.get()) if new is None: return False text.mark_set("insert", first) text.undo_block_start() if m.group(): text.delete(first, last) if new: text.insert(first, new, self.insert_tags) text.undo_block_stop() self.show_hit(first, text.index("insert")) self.ok = False return True def show_hit(self, first, last): """Highlight text between first and last indices. Text is highlighted via the 'hit' tag and the marked section is brought into view. The colors from the 'hit' tag aren't currently shown when the text is displayed. This is due to the 'sel' tag being added first, so the colors in the 'sel' config are seen instead of the colors for 'hit'. """ text = self.text text.mark_set("insert", first) text.tag_remove("sel", "1.0", "end") text.tag_add("sel", first, last) text.tag_remove("hit", "1.0", "end") if first == last: text.tag_add("hit", first) else: text.tag_add("hit", first, last) text.see("insert") text.update_idletasks() def close(self, event=None): "Close the dialog and remove hit tags." SearchDialogBase.close(self, event) self.text.tag_remove("hit", "1.0", "end") self.insert_tags = None
class StatisticsTab: def __init__(self, tab_control, expense_controller, user_controller, username): """Initializes statistics tab with all visual elements""" self.statistics_tab = ttk.Frame(tab_control) tab_control.add(self.statistics_tab, text='Statistics') self.expense_controller = expense_controller self.user_controller = user_controller self.username = username self.dateformat_menu = StringVar() self.start_date = StringVar() self.end_date = StringVar() Label(self.statistics_tab, text='Graph settings', font='Helvetica 16 bold').grid(row=0, column=0, padx=15, pady=15, sticky='w') Label(self.statistics_tab, text="Show expenses").grid(row=1, column=0, padx=(15, 0), sticky='w') option_list_format = ['daily', 'weekly', 'monthly', 'yearly'] OptionMenu(self.statistics_tab, self.dateformat_menu, option_list_format[2], *option_list_format)\ .grid(row=1, column=1, sticky='w') self.radio_btn_selection = IntVar( value=2 ) # has to be part of self, otherwise preselection doesn't work Radiobutton(self.statistics_tab, text='Select period:', variable=self.radio_btn_selection, value=1)\ .grid(row=2, column=0, padx=(15, 0), sticky='w') DateEntry(self.statistics_tab, width=9, textvariable=self.start_date, date_pattern='dd/MM/yyyy')\ .grid(row=2, column=1, sticky='w') Label(self.statistics_tab, text='to').grid(row=2, column=2, sticky='w') DateEntry(self.statistics_tab, width=9, textvariable=self.end_date, date_pattern='dd/MM/yyyy')\ .grid(row=2, column=3, sticky='w') Radiobutton(self.statistics_tab, text='Entire period', variable=self.radio_btn_selection, value=2) \ .grid(row=3, column=0, padx=(15, 0), sticky='w') Button(self.statistics_tab, text="Update graphs", command=self.display_graph).grid(row=4, column=0, padx=(15, 0), pady=10, sticky='w') # FIRST FIGURE: Barchart self.fig1, self.ax1 = plt.subplots(figsize=(6, 3), dpi=100) self.canvas1 = FigureCanvasTkAgg(self.fig1, master=self.statistics_tab) self.canvas1.get_tk_widget().grid(row=0, column=4, rowspan=8, padx=15, pady=(15, 0)) self.toolbarFrame = Frame(master=self.statistics_tab) self.toolbarFrame.grid(row=8, column=4) self.toolbar = NavigationToolbar2Tk(self.canvas1, self.toolbarFrame) # SECOND FIGURE: Barchart self.fig2, self.ax2 = plt.subplots(figsize=(6, 3), dpi=100) self.canvas2 = FigureCanvasTkAgg(self.fig2, master=self.statistics_tab) self.canvas2.get_tk_widget().grid(row=9, column=4, padx=15, pady=(15, 0)) self.toolbarFrame2 = Frame(master=self.statistics_tab) self.toolbarFrame2.grid(row=10, column=4) self.toolbar2 = NavigationToolbar2Tk(self.canvas2, self.toolbarFrame2) # THIRD FIGURE: Piechart self.fig3, self.ax3 = plt.subplots(figsize=(4, 3), dpi=100) self.canvas3 = FigureCanvasTkAgg(self.fig3, master=self.statistics_tab) self.canvas3.get_tk_widget().grid(row=9, column=0, columnspan=4, padx=15, pady=(15, 0)) self.toolbarFrame3 = Frame(master=self.statistics_tab) self.toolbarFrame3.grid(row=10, column=0, columnspan=4) self.toolbar3 = NavigationToolbar2Tk(self.canvas3, self.toolbarFrame3) def display_graph(self): """Calculates the information required and displays the three graphs""" # clear all figures self.ax1.cla() self.ax2.cla() self.ax3.cla() expenses = self.expense_controller.get_expenses_for_user(self.username) if not expenses: messagebox.showerror( 'No Expenses', 'There are no expenses to analyse, You can enter a new expense in the ' 'expense tab') return df = pd.DataFrame() for v in expenses.values(): df = df.append(pd.DataFrame.from_dict([v]), ignore_index=True) df_reduced = df[['price_in_euro', 'category']] df_reduced.index = pd.to_datetime(df['date'], format='%d/%m/%Y') df_reduced = df_reduced.sort_index() # get selected period if self.radio_btn_selection.get() == 1: # selected period start_date = datetime.strptime(self.start_date.get(), '%d/%m/%Y') end_date = datetime.strptime(self.end_date.get(), '%d/%m/%Y') # Verify if selected start and end dates are correct if start_date > end_date: messagebox.showerror( "Date Selection Error", "Starting date should be smaller than ending date") return # filter dataframe to only contain selected date period df_reduced = df_reduced.loc[(df_reduced.index <= end_date) & (df_reduced.index >= start_date)] grouping = self.dateformat_menu.get( ) # retrieve how user wants expenses to be grouped # group according to user preferences: By day, week, month or year if grouping == 'daily': sum_for_period = df_reduced.groupby(by=[ df_reduced.index.year, df_reduced.index.month, df_reduced.index.day ]).sum() self.ax1.set_title('Your expenses per day') self.ax2.set_title('Your remaining budget per day') self.ax1.set_xlabel('Year, Month, Day') elif grouping == 'weekly': sum_for_period = df_reduced.groupby(by=[df_reduced.index.year, df_reduced.index.isocalendar()['week']])\ .sum() self.ax1.set_title('Your expenses per week') self.ax2.set_title('Your remaining budget per week') self.ax1.set_xlabel('Year, Calendarweek') elif grouping == 'monthly': sum_for_period = df_reduced.groupby( by=[df_reduced.index.year, df_reduced.index.month]).sum() self.ax1.set_title('Your expenses per month') self.ax2.set_title('Your remaining budget per month') self.ax1.set_xlabel('Year, Month') elif grouping == 'yearly': sum_for_period = df_reduced.groupby(by=df_reduced.index.year).sum() self.ax1.set_title('Your expenses per year') self.ax2.set_title('Your remaining budget per year') self.ax1.set_xlabel('Year') else: messagebox.showerror("Selection error", "No grouping selected") return x_arr = sum_for_period.index.to_numpy() for i, x in enumerate(x_arr): if str(x)[0] == '(': x_arr[i] = str(x)[1:-1] y_arr = sum_for_period['price_in_euro'].to_numpy() self.ax1.set_ylabel('Total expenses in €') self.ax1.set_xticks(np.arange(len(x_arr))) self.ax1.set_xticklabels(x_arr) self.ax1.bar(np.arange(len(x_arr)), y_arr, 0.5, align='center') for i, v in enumerate(y_arr): self.ax1.text(i - 0.25, v + 3, "{:.2f} €".format(v)) self.fig1.autofmt_xdate() # placing the canvas on the Tkinter window self.canvas1.draw() self.toolbar.update() # SECOND FIGURE: Bar chart showing budget difference try: budget = float(self.user_controller.get_budget(self.username)[0]) period = self.user_controller.get_budget(self.username)[1] budget = budget_pro_rata_temporis(budget, period, grouping) except TypeError: messagebox.showerror( "No budget", "You haven't set a budget. You can do so in the preferences") budget = 0 except ValueError: messagebox.showerror( "No budget", "You haven't set a budget. You can do so in the preferences") budget = 0 sum_for_period['price_in_euro'] = sum_for_period['price_in_euro'].mul( -1).add(budget) sum_for_period['positive'] = sum_for_period['price_in_euro'] > 0 y_arr_budget = sum_for_period['price_in_euro'].to_numpy() self.ax2.set_ylabel("Total in €") self.ax2.set_xticks([]) self.ax2.bar(np.arange(len(x_arr)), y_arr_budget, 0.5, align='center', color=sum_for_period.positive.map({ True: 'g', False: 'r' })) for i, v in enumerate(y_arr_budget): if v >= 0: self.ax2.text(i - 0.25, v + 3, "{:.2f} €".format(v)) else: self.ax2.text(i - 0.25, v - 15, "{:.2f} €".format(v)) self.ax2.spines['bottom'].set_position('zero') self.ax2.spines['top'].set_color('none') self.ax2.spines['right'].set_color('none') self.canvas2.draw() # FIGURE 3: Pie chart of expenses per category purchases = {} category_list = df_reduced['category'].unique() if category_list.any(): for i in category_list: c = [] for idx, row in df_reduced.iterrows(): if row["category"] == i: if float(row["price_in_euro"]) > 0: c.append(float(row["price_in_euro"])) purchases[i] = sum(c) def func(val): return "{:.2f} €".format( np.round(val / 100. * sum(purchases.values()), 2)) self.ax3.set_title('Your expenses per category') self.ax3.pie([float(v) for v in purchases.values()], labels=[k for k in purchases.keys()], autopct=func, shadow=True) self.canvas3.draw()
class HangMan(Frame): def centre_window(self): ''' Create frame size and center frame to the middle of the screen ''' w = 320 h = 580 sw = self.root.winfo_screenwidth() sh = self.root.winfo_screenheight() x = (sw - w) / 2 y = (sh - h) / 2 self.root.geometry('%dx%d+%d+%d' % (w, h, x, y)) def __init__(self, parent, *args, **kwargs): ''' Initialize variables and widgets ''' Frame.__init__(self, parent, *args, **kwargs) self.root = parent self.root.title(' HangMan - Python3') self.centre_window() self.grid(column=0, row=0, sticky='nsew', padx=0, pady=0) # list of variables used self.word_list = [] self.random_word = '' self.hash_string = '' self.guess_counter = 0 self.guessed_letters = '' # Load the screen widgets onto canvas self.create_word_list() self.load_widgets() def load_widgets(self): ''' All widgets go under here ''' self.canvas = Canvas(self, width=316, height=520, background='cyan2') self.canvas.grid(column=0, row=0) # create word_entry widget self.word = StringVar() self.word_entry = Entry(self, textvariable=self.word, state='readonly') self.word_entry.config(justify='center', width=16, font='Times 14 bold') self.word_entry.grid(column=0, row=1) # The current guess letter section self.guess_var = StringVar() self.guess_entry = Entry(self, textvariable=self.guess_var) self.guess_entry.config(state='readonly', width=2, justify='center') self.guess_entry.grid(column=0, row=1, sticky='E', padx=55) self.guess_entry.bind('<Return>', self.check_guess) # The used letters section from all guesses self.used_char = StringVar() self.guessed_entry = Entry(self, textvariable=self.used_char, state='readonly') self.guessed_entry.config(justify='center', width=16, font="Times 14 bold") self.guessed_entry.grid(column=0, row=2) # create Labels self.word_label = Label(self, text='Hashed Word: ') self.word_label.grid(column=0, row=1, sticky='W') # create button Widgets self.check = Button(self, text='Check ', command=self.check_guess) self.check.config(state='disabled') self.check.grid(column=0, row=1, sticky='E') self.start = Button(self, text=' Start ', command=self.start_game) self.start.grid(column=0, row=2, sticky='SW') self.exit_btn = Button(self, text=' Exit ', command=self.on_exit) self.exit_btn.grid(column=0, row=2, sticky='SE') def start_game(self): ''' Starts the game or starts a new game when round is over Make sure canvas is cleared when new round starts. Enable guess button and entry widget. Set random word and hashed word and length ''' self.canvas.delete("all") self.guess_counter = 0 self.guess_entry.config(state='normal') self.check.config(state='normal') self.random_word = random.choice(self.word_list).strip() self.hash_string = len(self.random_word) * '#' self.word.set(self.hash_string) self.hashes_left = self.hash_string.count('#') self.used_char.set('') self.guessed_letters = '' self.guess_var.set('') def draw_body_parts(self): ''' Draw body part for every failed guess attempt ''' if self.guess_counter == 1: self.gallow() elif self.guess_counter == 2: self.body() elif self.guess_counter == 3: self.left_leg() self.left_foot() elif self.guess_counter == 4: self.right_leg() self.right_foot() elif self.guess_counter == 5: self.left_arm() self.left_hand() elif self.guess_counter == 6: self.right_arm() self.right_hand() elif self.guess_counter == 7: self.head() self.canvas.create_text(150, 290, text='Game\nOver!', fill='red', font='Bold 56') # Disables Guess button and entry field if game over self.guess_entry.config(state='readonly') self.check.config(state='disabled') def validate_guess(self, guess): ''' Check if Guess is in the word If guess is not in word, increase guess_counter Then call the draw_body_parts function Update the original hash string to include correct letters Check if player wins ''' tmp_str = '' count_hash = self.hash_string.count('#') for r, h in zip(self.random_word, self.hash_string): if r == guess: tmp_str += guess # if final letter was guessed correctly, you win if count_hash == 1: self.canvas.create_text(150, 290, text='You Win', fill='red', font='Bold 56') else: tmp_str += h if count_hash == tmp_str.count('#'): self.guess_counter += 1 self.draw_body_parts() self.word.set(tmp_str) self.hash_string = self.word.get() def check_guess(self, event=None): ''' Checks to see if the entered guess is valid ''' guess = self.guess_entry.get() if len(guess) > 1: msg = "You can only guess one letter at a time, please retry" messagebox.showinfo('Too many letters', msg) else: if guess.isalpha() is True: self.guessed_letters += guess self.validate_guess(guess) else: messagebox.showinfo('Not a letter', 'Only letters allowed') self.used_char.set(self.guessed_letters) def create_word_list(self): ''' Creates a list of words from a dictionery file ''' with open('words.txt', "r") as file: data = file.readlines() for d in data: self.word_list.append(d) def gallow(self): ''' Draws the gallow onto the screen ''' gallow_coord = [[75, 28, 75, 518], [200, 28, 200, 115], [72, 25, 203, 25], [20, 515, 270, 515], [178, 25, 75, 128]] for g in gallow_coord: self.canvas.create_line(g, fill="black", width='6') def head(self): ''' Draws the head onto the screen ''' head_coord = [[160, 110, 240, 212]] head_coord2 = [[198, 212, 198, 240], [202, 212, 202, 240], [176, 145, 195, 145], [207, 145, 225, 145], [216, 135, 216, 154], [185, 135, 185, 154], [185, 180, 216, 180]] for h in head_coord: self.canvas.create_oval(h, fill="lime", outline="blue", width='2') for h in head_coord2: self.canvas.create_line(h, fill="black", width='6') def body(self): ''' Draws the body onto the screen ''' self.canvas.create_oval(140, 240, 260, 420, fill="lime", outline="blue", width='2') def left_arm(self): ''' Draws the left_arm onto the screen ''' self.canvas.create_line(175, 265, 135, 370, fill="black", width='6') def right_arm(self): ''' Draws right_arm onto the screen ''' self.canvas.create_line(225, 265, 265, 370, fill="black", width='6') def left_leg(self): ''' Draws the left_leg onto the screen ''' self.canvas.create_line(180, 400, 180, 485, fill="black", width='6') def right_leg(self): ''' Draws the right_leg onto the screen ''' self.canvas.create_line(220, 400, 220, 485, fill="black", width='6') def left_hand(self): ''' Draws the left_hand onto the screen ''' self.canvas.create_line(115, 365, 137, 370, fill="black", width='6') def right_hand(self): ''' Draws the right_hand onto the screen ''' self.canvas.create_line(265, 367, 280, 360, fill="black", width='6') def left_foot(self): ''' Draws the left_foot onto the screen ''' self.canvas.create_line(160, 485, 183, 485, fill="black", width='6') def right_foot(self): ''' Draws the right_foot onto the screen ''' self.canvas.create_line(217, 485, 240, 485, fill="black", width='6') # Exit the program. Linked to the Exit Button def on_exit(self): self.root.destroy()
class scRNASeqFrame(PipelineFrame): def __init__(self, pipepanel, pipeline_name, *args, **kwargs): PipelineFrame.__init__(self, pipepanel, pipeline_name, *args, **kwargs) self.info = None eframe = self.eframe = LabelFrame(self, text="Options") #,fg=textLightColor,bg=baseColor) eframe.grid(row=5, column=1, sticky=W, columnspan=7, padx=10, pady=5) label = Label(eframe, text="Pipeline") #,fg=textLightColor,bg=baseColor) label.grid(row=3, column=0, sticky=W, padx=10, pady=5) PipelineLabels = [ "CellRanger", "Initial/QC", "Clustering", "Multi-Sample Clustering" ] Pipelines = [ "cellranger", "scrnaseqinit", "scrnaseqcluster", "scrnaseqmulticluster" ] self.label2pipeline = {k: v for k, v in zip(PipelineLabels, Pipelines)} PipelineLabel = self.PipelineLabel = StringVar() self.Pipeline = StringVar() PipelineLabel.set(PipelineLabels[0]) om = OptionMenu(eframe, PipelineLabel, *PipelineLabels, command=self.option_controller) om.config() #bg = widgetBgColor,fg=widgetFgColor) om["menu"].config() #bg = widgetBgColor,fg=widgetFgColor) #om.pack(side=LEFT,padx=20,pady=5) om.grid(row=3, column=1, sticky=W, padx=10, pady=5) self.crOpts = crOpts = LabelFrame(eframe, text="CellRanger Settings") self.scrCRID = scrCRID = StringVar() scrCRID.set("SPECIFY_PREFIX_HERE") self.scrExpected = scrExpected = StringVar() scrExpected.set("3000") scrcridL = Label(crOpts, text="CellRanger Sample ID: ") scrcridE = Entry(crOpts, bd=2, width=25, textvariable=scrCRID) scrcridL.grid(row=9, column=1, sticky=W, padx=10, pady=5) scrcridE.grid(row=9, column=2, sticky=W, padx=0, pady=5) screxpectedL = Label(crOpts, text="Expected number of cells: ") screxpectedE = Entry(crOpts, bd=2, width=8, textvariable=scrExpected) screxpectedL.grid(row=10, column=1, sticky=W, padx=10, pady=5) screxpectedE.grid(row=10, column=2, sticky=W, padx=0, pady=5) self.clusterOpts = clusterOpts = LabelFrame( eframe, text="Clustering and tSNE Options") self.scrPCs = scrPCs = StringVar() scrPCs.set("12") self.scrRes = scrRes = StringVar() scrRes.set("0.6") #scrPCs.trace('w', lambda a,b,c,x="scrPCs": makejson(x)) #Filter out genes < [5] read counts in < [2] samples scrpcsL = Label(clusterOpts, text="Include principal components 1 through ") scrpcsE = Entry(clusterOpts, bd=2, width=3, textvariable=scrPCs) scrresL = Label(clusterOpts, text="with clustering resolution: ") scrresE = Entry(clusterOpts, bd=2, width=3, textvariable=scrRes) scrpcsL.grid(row=9, column=1, sticky=W, padx=10, pady=5) scrpcsE.grid(row=9, column=2, sticky=W, padx=0, pady=5) scrresL.grid(row=9, column=3, sticky=W, padx=5, pady=5) scrresE.grid(row=9, column=4, sticky=W, padx=0, pady=5) #scrRes.trace('w', lambda a,b,c,x="scrPCs": makejson(x)) clusterOpts.grid(row=8, column=0, columnspan=4, sticky=W, padx=20, pady=10) self.multiclusterOpts = multiclusterOpts = LabelFrame( eframe, text="Multi-Sample Clustering and tSNE Options") scrccsL = Label(multiclusterOpts, text="Include canonical components 1 through ") scrccsE = Entry(multiclusterOpts, bd=2, width=3, textvariable=scrPCs) scrmcresL = Label(multiclusterOpts, text="with clustering resolution: ") scrmcresE = Entry(multiclusterOpts, bd=2, width=3, textvariable=scrRes) scrccsL.grid(row=9, column=1, sticky=W, padx=10, pady=5) scrccsE.grid(row=9, column=2, sticky=W, padx=0, pady=5) scrmcresL.grid(row=9, column=3, sticky=W, padx=5, pady=5) scrmcresE.grid(row=9, column=4, sticky=W, padx=0, pady=5) self.qcOpts = qcOpts = LabelFrame(eframe, text="Initial Settings") countL = Label(qcOpts, text="Counts/Matrix Dir:") countL.grid(row=9, column=1, sticky=W, padx=10, pady=5) countpath = StringVar() self.countpath = countpath count_entry = Entry( qcOpts, bd=2, width=50, #bg = entryBgColor, #fg = entryFgColor, textvariable=countpath, state='normal') count_entry.grid(row=9, column=2, columnspan=3) self.count_button = count_button = Button( qcOpts, text="Open Directory", command=self.set_count_directory) count_button.grid(row=9, column=5) self.mattype = mattype = StringVar() mattypeL = Label(qcOpts, text="Count matrix format: ") scrMatTypeDropdown = ["cellranger", "cellranger_raw", "zumi", "biorad"] mattype.set(scrMatTypeDropdown[0]) mattype_om = OptionMenu(qcOpts, mattype, *scrMatTypeDropdown) mattypeL.grid(row=10, column=1, sticky=W, padx=10, pady=5) mattype_om.grid(row=10, column=2, sticky=W, padx=0, pady=5) self.docycleregress = docycleregress = StringVar() docycleregressL = Label(qcOpts, text="Do cell cycle regression? ") scrCycleDropdown = ["TRUE", "FALSE"] docycleregress.set(scrCycleDropdown[0]) cycle_om = OptionMenu(qcOpts, docycleregress, *scrCycleDropdown) docycleregressL.grid(row=11, column=1, sticky=W, padx=10, pady=5) cycle_om.grid(row=11, column=2, sticky=W, padx=0, pady=5) usecycleregressL_c = Label(clusterOpts, text="Use cell cycle regressed data? ") docycleregress.set(scrCycleDropdown[0]) cycle_om_c = OptionMenu(clusterOpts, docycleregress, *scrCycleDropdown) usecycleregressL_c.grid(row=10, column=1, sticky=W, padx=10, pady=5) cycle_om_c.grid(row=10, column=2, sticky=W, padx=0, pady=5) usecycleregressL_mc = Label(multiclusterOpts, text="Use cell cycle regressed data? ") docycleregress.set(scrCycleDropdown[0]) cycle_om_mc = OptionMenu(multiclusterOpts, docycleregress, *scrCycleDropdown) usecycleregressL_mc.grid(row=10, column=1, sticky=W, padx=10, pady=5) cycle_om_mc.grid(row=10, column=2, sticky=W, padx=0, pady=5) groups_buttonL = Label(qcOpts, text="SAMPLE INFORMATION: ") groups_button = Button(qcOpts, text="Set Groups", command=self.popup_groups) groups_buttonL.grid(row=12, column=1, sticky=W, padx=10, pady=5) groups_button.grid(row=12, column=2, sticky=W, padx=0, pady=5) ##################### self.option_controller() def popup_groups(self): self.popup_window("Groups Information", "groups.tab") def popup_window(self, text, filename): top = Toplevel() info = LabelFrame(top, text=text) #"Group Information") info_text = Text( info, width=50, height=8, #bg=projectBgColor, #fg=projectFgColor, font=("nimbus mono bold", "11")) def savefunc(): self.writepaste(filename, info_text) def loadfunc(): self.readpaste(filename, info_text) info_save_button = Button(info, text="Save", command=savefunc) info_load_button = Button(info, text="Load", command=loadfunc) #self.pairs_load_button.pack( side=BOTTOM, padx=5, pady=5 ) #self.pairs_save_button.pack( side=BOTTOM, padx=5, pady=5 ) info_load_button.grid(row=5, column=5, padx=10, pady=5) info_save_button.grid(row=5, column=6, padx=10, pady=5) info_text.grid(row=1, rowspan=3, column=1, columnspan=7, padx=5, pady=5) info.grid(row=7, column=0, columnspan=6, sticky=W, padx=20, pady=10) top.focus_force() def set_count_directory(self): fname = askdirectory(initialdir=USER_HOME, title="Select Data Directory") self.countpath.set(fname) def option_controller(self, *args, **kwargs): PipelineFrame.option_controller(self) self.Pipeline.set(self.label2pipeline[self.PipelineLabel.get()]) print(self.Pipeline.get()) if self.Pipeline.get() == 'cellranger': self.clusterOpts.grid_forget() self.crOpts.grid(row=8, column=0, columnspan=6, sticky=W, padx=20, pady=10) self.qcOpts.grid_forget() self.multiclusterOpts.grid_forget() elif self.Pipeline.get() == 'scrnaseqcluster': self.clusterOpts.grid(row=8, column=0, columnspan=4, sticky=W, padx=20, pady=10) self.crOpts.grid_forget() self.qcOpts.grid_forget() self.multiclusterOpts.grid_forget() elif self.Pipeline.get() == 'scrnaseqinit': self.clusterOpts.grid_forget() self.crOpts.grid_forget() self.qcOpts.grid(row=8, column=0, columnspan=4, sticky=W, padx=20, pady=10) self.multiclusterOpts.grid_forget() elif self.Pipeline.get() == 'scrnaseqmulticluster': self.clusterOpts.grid_forget() self.crOpts.grid_forget() self.qcOpts.grid_forget() self.multiclusterOpts.grid(row=8, column=0, columnspan=4, sticky=W, padx=20, pady=10) def makejson_wrapper(self, *args, **kwargs): self.makejson(*args, **kwargs) def makejson(self, *args): ###################################################### FROM RNASEQ.PY, NOT SURE WHAT ALL THIS DOES #############################3 #print(args[0]) caller = args[0] #global PD #global UnitsBak #global RGbak D = dict() try: F = open(self.workpath.get() + "/samples", "r") f = F.read().split("\n") F.close() for line in f: L = line.split() a = L.pop(0) D[a] = L samples = D except: samples = {"na": "na"} D = dict() try: F = open(self.workpath.get() + "/pairs", "r") f = F.read().split() F.close() for i in range(0, len(f), 2): # a=f[i].split(".")[0] # b=f[i+1].split(".")[0] a = f[i] b = f[i + 1] D[a + "+" + b] = [a, b] pairs = D except: pairs = {"na": "na"} D = dict() try: F = open(self.workpath.get() + "/contrasts.tab", "r") # f=F.read().split('\n') # F.close() # D["rsamps"]=f[0].split() # D["rgroups"]=f[1].split() # D["rcontrasts"]=f[2].split() # D["rlabels"]=f[3].split() f = F.readlines() F.close() ## sampl=[] ## grp=[] cont = [] ## lbl=[] for x in f: if len(x.split()) == 2: cont.append(x.split()[0]) cont.append(x.split()[1]) D["rcontrasts"] = cont # contrasts["rcontrasts"]=cont contrasts = D except: contrasts = {"rcontrasts": "na"} ## contrasts={"rsamps":"na","rgroups":"na","rcontrasts":"na","rlabels":"na"} ##------ D = dict() try: F = open(self.workpath.get() + "/groups.tab", "r") f = F.readlines() F.close() sampl = [] grp = [] # cont=[] lbl = [] for x in f: # if len(x.split()) == 4 or len(x.split()) == 3: if len(x.split()) == 3: sampl.append(x.split()[0]) grp.append(x.split()[1]) lbl.append(x.split()[2]) D["rsamps"] = sampl D["rgroups"] = grp D["rlabels"] = lbl # D["rcontrasts"]="na" # contrasts=D groups = D except: # contrasts={"rsamps":"na","rgroups":"na","rcontrasts":"na","rlabels":"na"} groups = {"rsamps": "na", "rgroups": "na", "rlabels": "na"} ##------ D = dict() FT = filetype #.get() # p = Popen("ls "+workpath.get()+"/*."+FT, shell=True, stdin=PIPE, stdout=PIPE, stderr=DEVNULL, close_fds=True) p = Popen("find " + self.workpath.get() + " -maxdepth 1 -type l -printf '%f\n' ", shell=True, stdin=PIPE, stdout=PIPE, stderr=DEVNULL, close_fds=True) a = p.stdout.read().decode(encoding='UTF-8').split("\n") RG = dict() b = a.pop() # tkinter.messagebox.showerror("",a) # if freezeunits.get()=="no": for i in a: key = re.sub(".realign", "", i.split("/")[-1]) key = re.sub(".bai", "", key) key = re.sub(".bam", "", key) key = re.sub(".sam", "", key) key = re.sub(".recal", "", key) key = re.sub(".dedup", "", key) key = re.sub(".sorted", "", key) key = re.sub(".fin", "", key) key = re.sub("\.R[12]", "", key) key = re.sub("_R[12]", "", key) key = re.sub(".fastq", "", key) key = re.sub(".gz", "", key) # key=re.sub("[\._](R[12]\.)*"+FT+"$","",i.split("/")[-1]) # key=re.sub(".R[12]."+FT+"$","",i.split("/")[-1]) # key=re.sub("([._]R[12][._])*([fin|sorted|dedup|recal|realign])*\.{0}$".format(FT),"",i.split("/")[-1]) D[key] = key RG[key] = { 'rgsm': key, 'rglb': 'na', 'rgpu': 'na', 'rgpl': 'ILLUMINA', 'rgcn': 'na' } units = D UnitsBak = D try: F = open(self.workpath.get() + "/rg.tab", "r") f = F.read().splitlines() F.close() for theLine in f: if not re.match("^ID", theLine): (rgid, rgsm, rglb, rgpl, rgpu, rgcn) = theLine.split("\t") RG[rgid] = { 'rgsm': rgsm, 'rglb': rglb, 'rgpu': rgpu, 'rgpl': rgpl, 'rgcn': rgcn } except: pass RGbak = RG # else: # units=UnitsBak # RG=RGbak # ########################################################################################################################### PD = dict() smparams = [] for i in range(len(self.parameters)): if cp[i].var.get() == "1": smparams.append(parameters[i]) AD = eval( open(join(PIPELINER_HOME, self.annotation.get() + ".json"), "r").read()) gi = self.global_info PD = { 'project': { 'pfamily': gi.pfamily.get(), 'units': units, 'samples': samples, 'pairs': pairs, 'id': gi.eprojectid.get(), 'pi': gi.epi.get(), 'organism': gi.eorganism.get(), 'analyst': gi.eanalyst.get(), 'poc': gi.epoc.get(), 'pipeline': self.Pipeline.get(), 'version': "4.0", 'annotation': gi.annotation.get(), 'datapath': self.datapath.get(), 'targetspath': self.targetspath.get(), 'filetype': filetype, 'binset': "standard-bin", 'username': gi.euser.get(), 'flowcellid': gi.eflowcell.get(), 'platform': gi.eplatform.get(), 'custom': customRules, 'efiletype': efiletype, 'workpath': self.workpath.get(), 'batchsize': batchsize, "smparams": smparams, "rgid": RG, "cluster": "cluster_medium.json", "description": gi.description.get('1.0', END), "technique": gi.technique.get(), "CRID": self.scrCRID.get(), "EXPECTED": self.scrExpected.get(), "COUNTSPATH": self.countpath.get(), "MATTYPE": self.mattype.get(), "DOCYCLEREGRESS": self.docycleregress.get(), "RESOLUTION": self.scrRes.get(), "PCS": self.scrPCs.get(), "groups": groups } } J = json.dumps(PD, sort_keys=True, indent=4, ensure_ascii=True) gi.jsonconf.delete("1.0", END) gi.jsonconf.insert(INSERT, J) self.saveproject(gi.jsonconf.get("1.0", END))
class App_test(object): def __init__(self): self.win = Tk() self.win.title('12306火车票查询系统V2.6') self.win.geometry('860x400') self.creat_res() self.add_train_info() self.add_check_button() self.res_config() self.train_message = {} # self.get_train_args() self.win.mainloop() def creat_res(self): self.v = IntVar() #车票查询 self.v.set(True) self.temp = StringVar() #开始站 self.temp2 = StringVar() #目的站 self.start_mon = StringVar() #出发月 self.start_day = StringVar() #出发日 self.start_year = StringVar() #出啊年 self.E_startstation = Entry(self.win, textvariable=self.temp) self.E_endstation = Entry(self.win, textvariable=self.temp2) self.La_startstation = Label(self.win, text="出发站:") self.La_endstation = Label(self.win, text="目的站:") self.La_time = Label(self.win, text="请选择出发时间-年-月-日", fg="blue") self.B_search = Button(self.win, text="搜索") self.R_site = Radiobutton(self.win, text="车票查询", variable=self.v, value=True) self.R_price = Radiobutton(self.win, text="票价查询", variable=self.v, value=False) self.B_buy_tick = Button(self.win, text="购票") self.C_year = Combobox(self.win, textvariable=self.start_year) self.C_mon = Combobox(self.win, textvariable=self.start_mon) self.La_s = Label(self.win, text="--") self.C_day = Combobox(self.win, textvariable=self.start_day) self.S_move = Scrollbar(self.win) self.E_startstation.place(x=70, y=10, width=65, height=30) self.E_endstation.place(x=70, y=60, width=65, height=30) self.La_startstation.place(x=10, y=10, width=50, height=30) self.La_endstation.place(x=10, y=60, width=50, height=30) self.La_time.place(x=10, y=100, width=150, height=30) self.C_year.place(x=10, y=140, width=70, height=30) self.C_mon.place(x=100, y=140, width=50, height=30) self.C_day.place(x=100, y=180, width=50, height=30) self.La_s.place(x=80, y=140, width=20, height=30) self.B_search.place(x=10, y=180, width=50, height=30) self.S_move.place(x=834, y=40, width=30, height=350) self.B_buy_tick.place(x=10, y=260, width=80, height=40) self.R_site.place(x=10, y=230, width=70, height=30) self.R_price.place(x=90, y=230, width=70, height=30) def res_config(self): self.C_year.config(values=[x for x in range(2018, 2020)]) self.C_mon.config(values=["{:02d}".format(x) for x in range(1, 13)]) #时间格式是2018-01-01 self.C_day.config(values=["{:02d}".format(x) for x in range(1, 32)]) self.B_search.config(command=self.search_train_message) self.S_move.config(command=self.tree.yview) self.tree.config(yscrollcommand=self.S_move.set) def add_train_info(self): lis_train = ["C" + str(x) for x in range(0, 15)] tuple_train = tuple(lis_train) self.tree = Treeview(self.win, columns=tuple_train, height=30, show="headings") self.tree.place(x=168, y=40, width=670, height=350) train_info = [ ' 车次 ', ' 出发/到达站', '出发/到达时间', '历时 ', '商/特座', '一等座', '二等座', '高软', '软卧', '动卧', '硬卧', '软座', '硬座', '无座', '其他' ] for i in range(0, len(lis_train)): self.tree.column(lis_train[i], width=len(train_info[i]) * 11, anchor='center') self.tree.heading(lis_train[i], text=train_info[i]) def add_check_button(self): self.v1 = IntVar() self.v2 = IntVar() self.v3 = IntVar() self.v4 = IntVar() self.v5 = IntVar() self.v6 = IntVar() self.v7 = IntVar() self.v1.set("T") self.Check_total = Checkbutton(self.win, text="全部车次", variable=self.v1, onvalue='T') self.Check_total.place(x=168, y=7, width=80, height=30) self.Check_total = Checkbutton(self.win, text="G-高铁", variable=self.v2, onvalue='T') self.Check_total.place(x=258, y=7, width=70, height=30) self.Check_total = Checkbutton(self.win, text="D-动车", variable=self.v3, onvalue='T') self.Check_total.place(x=348, y=7, width=60, height=30) self.Check_total = Checkbutton(self.win, text="Z-直达", variable=self.v4, onvalue='T') self.Check_total.place(x=418, y=7, width=60, height=30) self.Check_total = Checkbutton(self.win, text="T-特快", variable=self.v5, onvalue='T') self.Check_total.place(x=488, y=7, width=60, height=30) self.Check_total = Checkbutton(self.win, text="K-快速", variable=self.v6, onvalue='T') self.Check_total.place(x=568, y=7, width=60, height=30) self.Check_total = Checkbutton(self.win, text="其他", variable=self.v7, onvalue='T') self.Check_total.place(x=648, y=7, width=60, height=30) def get_train_args(self): #输出获得的日期,出发站代码,目的站代码 date = self.start_year.get() + "-" + self.start_mon.get( ) + "-" + self.start_day.get() start_station = self.temp.get() end_station = self.temp2.get() start_station_str = "" end_station_str = "" count1, count2 = 0, 0 with open("res/dict2.txt", mode='r', encoding='utf-8') as f: mes = f.readlines() for i in mes: d = json.loads(i) if start_station in d: start_station_str = d[start_station] else: count1 += 1 if end_station in d: end_station_str = d[end_station] else: count2 += 1 if count1 == len(mes) or count2 == len(mes): messagebox.showwarning(title="友情提示", message="无法找到车站数据") return date, start_station_str, end_station_str def is_leapyear(self): #先判断输入是否是日期,如果是日期执行方法体, a = self.C_year.get() b = self.C_mon.get() c = self.C_day.get() pa_year = '20[\d][\d]' # 2018 if re.compile(pa_year).findall(a) and b in [ "{:02d}".format(x) for x in range(1, 13) ] and c in ["{:02d}".format(x) for x in range(1, 32)]: nowtime = time.localtime() now_time_sp = time.mktime(nowtime) start_time = a + "-" + b + "-" + c + " 23:59:29" #"2018-08-09 23:59:29" start_timestrip = time.strptime(start_time, "%Y-%m-%d %H:%M:%S") start_times = time.mktime(start_timestrip) days = (start_times - now_time_sp) / 60 / 60 / 24 print(days) print(a, b, c) if days > 29: messagebox.showerror(title="警告", message="大于30天无法获取数据") elif days < 0: messagebox.showerror(title="警告", message="小于1天无法获取数据") elif days > 0 and days < 30: if int(a) % 4 == 0 and int(a) % 100 != 0 or int( a) % 400 == 0: #如果是闰年 if (int(b) in (1, 3, 5, 7, 8, 10, 12) and int(c) > 31) or ( (int(b) in (4, 6, 9, 11) and int(c) > 30)) or (int(b) == 2 and int(c) > 29): messagebox.showerror(title="警告", message="你确定这个月有这一天么") else: if (int(b) in (1, 3, 5, 8, 10, 12) and int(c) > 31) or ( (int(b) in (4, 6, 9, 11) and int(c) > 30)) or (int(b) == 2 and int(c) > 28): messagebox.showerror(title="警告", message="你确定这个月有这一天么") else: messagebox.showerror(title="警告", message="请输入正确格式的年:月:日") def manage_date(self): #处理时间,闰年以及当天时间 self.is_leapyear() def change_str(self, mm): for i, j in mm.items(): with open("res/dict.txt", mode='r', encoding='utf-8') as f: mes = f.readlines() for s in mes: d = json.loads(s) if j[0] in d: j[0] = d[j[0]] if j[1] in d: j[1] = d[j[1]] # print(self.new_train_message) #车次信息 non_empty_str = [''] for m, n in mm.items(): mm[m] = ['-' if x in non_empty_str else x for x in n] # 替换''字符为'-' return mm def trans_train_dic(self): #输出出发站-目的站-名字 date, start_station, end_station = self.get_train_args() print(date, start_station, end_station) try: p = Pro_train(date, start_station, end_station) self.train_message = p.get_train_res() # 获得车次信息字典 车次英文 self.train_tick = p.get_tarin_ticket() #获得票价信息 # print(self.train_message) #车次信息 self.new_train_message = self.train_message #复制一份 self.new_train_tick = self.train_tick self.new_train_message = self.change_str(self.new_train_message) self.new_train_tick = self.change_str(self.new_train_tick) return self.new_train_message, self.new_train_tick # 中文字典 except Exception as e: # messagebox.showerror(title="警告",message="无法解析数据,请重新选择") print("错误码:", e.args) def search_train_message(self): self.manage_date() #处理日期-True-transe-view if self.v.get(): self.view_list() else: self.view_price() def clear_tree(self): x = self.tree.get_children() for n in x: self.tree.delete(n) def view_list(self): #显示到网格 # 车次 出发/站 出发到达时间 历时 商务座31 一等座30 二等座29 高软20 软卧22 动卧 硬卧27 软座23 硬座28 无座25 其他21 try: self.clear_tree() self.new_train_message, x = self.trans_train_dic() #生成新车次字典 for i, j in self.new_train_message.items(): self.tree.insert("", "end", values=(i, j[0] + "->" + j[1], j[2] + "->" + j[3], j[4], j[5], j[6], j[7], j[8], j[9], j[10], j[11], j[12], j[13], j[14], j[15])) except Exception as e: # messagebox.showerror(title="警告",message="无法处理数据") print("错误:", e.args) def view_price(self): print("-------票价ok-------") try: self.clear_tree() y, self.new_train_tick = self.trans_train_dic() #生成新车次字典 for i, j in self.new_train_tick.items(): self.tree.insert("", "end", values=(i, j[0] + "->" + j[1], j[2] + "->" + j[3], j[4], j[5], j[6], j[7], j[8], j[9], j[10], j[11], j[12], j[13], j[14], "-")) except Exception as e: # messagebox.showerror(title="警告",message="无法处理数据") print("错误:", e.args)
class Combo(TextWidget): def __init__( self, master, options=[], selected=None, command=None, grid=None, align=None, visible=True, enabled=None, width=None, height=None): """ Creates a Combo :param Container master: The Container (App, Box, etc) the Combo will belong too. :param List option: A list of strings to populate the Combo, defaults to an empty list. :param string selected: The item in the Combo to select, defaults to `None`. :param callback command: The callback function to call when the Combo changes, defaults to `None`. :param List grid: Grid co-ordinates for the widget, required if the master layout is 'grid', defaults to `None`. :param string align: How to align the widget within the grid, defaults to None. :param bool visible: If the widget should be visible, defaults to `True`. :param bool enabled: If the widget should be enabled, defaults to `None`. If `None` the value is inherited from the master. :param int width: The starting width of the widget. Defaults to `None` and will auto size. :param int height: The starting height of the widget. Defaults to `None` and will auto size. """ # Maintain a list of options (as strings, to avoid problems comparing) self._options = [str(x) for x in options] description = "[Combo] object with options " + str(self._options) # Store currently selected item self._selected = StringVar() # Create a tk OptionMenu object within this object if len(self._options) == 0: tk = OptionMenu(master.tk, self._selected, None, command=self._command_callback) else: tk = OptionMenu(master.tk, self._selected, *self._options, command=self._command_callback) # Create the combo menu object self._combo_menu = ComboMenu(tk["menu"]) super(Combo, self).__init__(master, tk, description, grid, align, visible, enabled, width, height) # Remove the thick highlight when the bg is a different color self._set_tk_config("highlightthickness", 0) # Set the selected item if selected is None: # set the first option self._set_option_by_index(0) else: self._set_option(selected) self._default = selected # The command associated with this combo self.update_command(command) # PROPERTIES # ---------------------------------- # The selected text value @property def value(self): """ Sets or returns the option selected in a Combo. """ return self._selected.get() @value.setter def value(self, value): value = str(value) if not self._set_option(value): utils.error_format("Tried to set " + self.description + " to option \"" + str(value) + "\", which does not exist" ) @property def bg(self): """ Sets or returns the background color of the widget. """ return super(Combo, self.__class__).bg.fget(self) @bg.setter def bg(self, value): super(Combo, self.__class__).bg.fset(self, value) self._combo_menu.bg = value @property def text_color(self): """ Sets or returns the text color used by the widget. """ return super(Combo, self.__class__).text_color.fget(self) @text_color.setter def text_color(self, value): super(Combo, self.__class__).text_color.fset(self, value) self._combo_menu.text_color = value @property def text_size(self): """ Sets or returns the text size used by the widget. """ return super(Combo, self.__class__).text_size.fget(self) @text_size.setter def text_size(self, value): super(Combo, self.__class__).text_size.fset(self, value) self._combo_menu.text_size = value @property def font(self): """ Sets or returns the font used by the widget. """ return super(Combo, self.__class__).font.fget(self) @font.setter def font(self, value): super(Combo, self.__class__).font.fset(self, value) self._combo_menu.font = value @property def options(self): """ Returns a list of options in the Combo """ return self._options # METHODS # ------------------------------------------- # Resets the combo box to the original "selected" value from the constructor # (or the first value if no selected value was specified) def select_default(self): """ Resets the combo box to the original "selected" value from the constructor (or the first value if no selected value was specified). """ if self._default is None: if not self._set_option_by_index(0): utils.error_format(self.description + "\n" + "Unable to select default option as the Combo is empty") else: if not self._set_option(self._default): utils.error_format( self.description + "\n" + "Unable to select default option as it doesnt exist in the Combo") def append(self, option): """ Appends a new `option` to the end of the Combo. :param string option: The option to append to the Combo. """ self.insert(len(self._options), option) def insert(self, index, option): """ Insert a new `option` in the Combo at `index`. :param int option: The index of where to insert the option. :param string option: The option to insert into to the Combo. """ option = str(option) self._options.insert(index, option) # if this is the first option, set it. if len(self._options) == 1: self.value = option self._refresh_options() def remove(self, option): """ Removes the first `option` from the Combo. Returns `True` if an item was removed. :param string option: The option to remove from the Combo. """ if option in self._options: if len(self._options) == 1: # this is the last option in the list so clear it self.clear() else: self._options.remove(option) self._refresh_options() # have we just removed the selected option? # if so set it to the first option if option == self.value: self._set_option(self._options[0]) return True else: return False # Clear all options from the box def clear(self): """ Clears all the options in a Combo """ self._options = [] self._combo_menu.tk.delete(0, END) self._selected.set("") def _refresh_options(self): # save which option was selected selected = self.value self._combo_menu.tk.delete(0, END) # Re-add all options # This uses an internal tk method _setit which is a bit naughty for item in self._options: self._combo_menu.tk.add_command(label=item, command=_setit(self._selected, item, self._command_callback)) self.description = "[Combo] object with options " + str(self._options) # set the option which was previously selected self._set_option(selected) def _set_option(self, value): """ Sets a single option in the Combo, returning True if it was able too. """ if len(self._options) > 0: if value in self._options: self._selected.set(value) return True else: return False else: return False def _set_option_by_index(self, index): """ Sets a single option in the Combo by its index, returning True if it was able too. """ if index < len(self._options) - 1: self._selected.set(self._options[index]) return True else: return False def _command_callback(self, value): if self._command: args_expected = utils.no_args_expected(self._command) if args_expected == 0: self._command() elif args_expected == 1: self._command(value) else: utils.error_format("Combo command function must accept either 0 or 1 arguments.\nThe current command has {} arguments.".format(args_expected)) def update_command(self, command): """ Updates the callback command which is called when the Combo changes. Setting to `None` stops the callback. :param callback command: The callback function to call, it can accept 0 or 1 parameters. If it accepts 1 parameter the `value` of the Combo will be passed. """ if command is None: self._command = lambda: None else: self._command = command # DEPRECATED METHODS # -------------------------------------------- # Returns currently selected option def get(self): return self._selected.get() utils.deprecated("Combo get() is deprecated. Please use the value property instead.") # Sets currently selected option (if it exists in the list) def set(self, text): if text in self._options: self._selected.set( str(text) ) else: utils.error_format("Tried to set " + self.description + " to option \"" + str(text) + "\", which does not exist" ) utils.deprecated("Combo set() is deprecated. Please use the value property instead.") # Add an option to the combo def add_option(self, option): self.append(option) self.value = option utils.deprecated("Combo add_option() is deprecated. Please use append() instead.")
class AppGUI: def __init__(self, master, tipo, controller): self.controller = controller self.tipo = tipo self.frame = tk.Frame(master) self.frame.pack() if (self.tipo == 0): self.controller.root_main.iconify() self.frame = tk.Frame(master) self.frame.pack() #Variáveis capturadoras de informação self.vusuario = StringVar() self.vsenha = StringVar() #Botões e entradas self.llogin = tk.Label(self.frame, text="Usuário:") self.lsenha = tk.Label(self.frame, text="Senha:") self.eusuario = tk.Entry(self.frame, textvariable=self.vusuario) self.esenha = tk.Entry(self.frame, textvariable=self.vsenha, show="*") self.btnEntrar = tk.Button(self.frame, text="Entrar") self.btnCadastrar = tk.Button(self.frame, text="Cadastrar") #Adicionar Widgets self.llogin.grid(row=0, column=0) self.lsenha.grid(row=1, column=0) self.eusuario.grid(row=0, column=1) self.esenha.grid(row=1, column=1) self.btnCadastrar.grid(row=2, column=0) self.btnEntrar.grid(row=2, column=1) ##acao do botao para cadastrar - abrirá uma nova janela top.level self.btnCadastrar.bind("<Button>", lambda e: self.cadastrar()) ##acao do botao para entrar - abrira uma nova janela root self.btnEntrar.bind( "<Button>", lambda e: controller.logar(self.vusuario.get(), self.vsenha.get())) if (self.tipo == 1): self.frame = tk.Frame(self.controller.root_main) self.frame.pack() self.lemexecucao = tk.Label(self.frame, text="Em Execucao:") self.lartista = tk.Label(self.frame, text="Artista:") self.btnVerPlaylist = tk.Button(self.frame, text="VerPlaylist") self.btnFavoritar = tk.Button(self.frame, text="Favoritar") self.btnExecutar = tk.Button(self.frame, text="Executar") self.btnPausar = tk.Button(self.frame, text="Pausar") self.btnnPular = tk.Button(self.frame, text="Pular") self.btnVoltar = tk.Button(self.frame, text="Voltar") #Adicionar Widgets self.lemexecucao.grid(row=0, column=0) self.lartista.grid(row=1, column=0) self.btnVerPlaylist.grid(row=2, column=0) self.btnFavoritar.grid(row=2, column=1) self.btnExecutar.grid(row=2, column=2) self.btnPausar.grid(row=3, column=0) self.btnnPular.grid(row=3, column=1) self.btnVoltar.grid(row=3, column=2) self.btnVerPlaylist.bind("<Button>", lambda e: self.abrirPlaylist()) def cadastrar(self): ##deixar comentado, motivo ver comentario na funcao de limpar #self.eusuario['state'] = 'disabled' #self.esenha['state'] = 'disabled' self.controller.root.iconify() self.win = tk.Toplevel() self.win.wm_title("Cadastro") self.win.geometry('400x200') self.frame = tk.Frame(self.win) self.frame.pack() #captura informações para cadastro self.vnome = StringVar() self.vemail = StringVar() self.vidade = StringVar() self.vpais = StringVar() self.vusuario = StringVar() self.vsenha = StringVar() #Botões e campos de entrada self.lusuario = tk.Label(self.frame, text="Usuário:") self.lsenha = tk.Label(self.frame, text="Senha:") self.lnome = tk.Label(self.frame, text="Nome:") self.lemail = tk.Label(self.frame, text="Email:") self.lidade = tk.Label(self.frame, text="Idade:") self.lpais = tk.Label(self.frame, text="País:") self.eusuario = tk.Entry(self.frame, textvariable=self.vusuario) self.esenha = tk.Entry(self.frame, textvariable=self.vsenha, show="*") self.enome = tk.Entry(self.frame, textvariable=self.vnome) self.eemail = tk.Entry(self.frame, textvariable=self.vemail) self.eidade = tk.Entry(self.frame, textvariable=self.vidade) self.epais = tk.Entry(self.frame, textvariable=self.vpais) self.btnTerminar = tk.Button( self.frame, text="Terminar") #Finaliza a operação de cadastro self.lnome.grid(row=0, column=0) self.enome.grid(row=0, column=1) self.lidade.grid(row=1, column=0) self.eidade.grid(row=1, column=1) self.lpais.grid(row=2, column=0) self.epais.grid(row=2, column=1) self.lemail.grid(row=3, column=0) self.eemail.grid(row=3, column=1) self.lusuario.grid(row=4, column=0) self.eusuario.grid(row=4, column=1) self.lsenha.grid(row=5, column=0) self.esenha.grid(row=5, column=1) self.btnTerminar.grid(row=6, column=0) self.btnTerminar.bind("<Button>", lambda e: self.limpar()) def limpar(self): '''Remover os textos dos campos''' self.win.destroy() self.controller.root.deiconify() ## linhas 94 e 95 deveria funcionar para reabilitar os campos loguin e senha da tela root1, mas só desabilita o do loguin. Vou deixar comentado por hora #self.eusuario['state'] = 'normal' #self.esenha['state'] = 'normal' self.vusuario.set("") self.vsenha.set("") #Focus no campo self.eusuario.focus_set() def entrar(self): self.controller.root.iconify() self.controller.root_main.deiconify() MinhatelaPrincipal = AppGUI(self.controller.root_main, 1, self.controller) self.controller.root_main.mainloop() def entrar_erro(self): messagebox.showinfo("Erro", "Dados incorretos") def retornarMainWindow(self): self.win.destroy() self.controller.root_main.deiconify() def abrirPlaylist(self): self.controller.root.iconify() self.controller.root_main.iconify() self.win = tk.Toplevel() self.win.wm_title("Playlist Favoritas") self.win.geometry('400x200') self.frame = tk.Frame(self.win) self.frame.pack() #captura informações para cadastro self.vnome = StringVar() self.vemail = StringVar() self.vidade = StringVar() self.vpais = StringVar() self.vusuario = StringVar() self.vsenha = StringVar() #Botões e campos de entrada self.lusuario = tk.Label(self.frame, text="Usuário:") self.lsenha = tk.Label(self.frame, text="Senha:") self.lnome = tk.Label(self.frame, text="Nome:") self.lemail = tk.Label(self.frame, text="Email:") self.lidade = tk.Label(self.frame, text="Idade:") self.lpais = tk.Label(self.frame, text="País:") self.eusuario = tk.Entry(self.frame, textvariable=self.vusuario) self.esenha = tk.Entry(self.frame, textvariable=self.vsenha, show="*") self.enome = tk.Entry(self.frame, textvariable=self.vnome) self.eemail = tk.Entry(self.frame, textvariable=self.vemail) self.eidade = tk.Entry(self.frame, textvariable=self.vidade) self.epais = tk.Entry(self.frame, textvariable=self.vpais) self.btnRetornar = tk.Button( self.frame, text="Terminar") #Finaliza a operação de cadastro self.lnome.grid(row=0, column=0) self.enome.grid(row=0, column=1) self.lidade.grid(row=1, column=0) self.eidade.grid(row=1, column=1) self.lpais.grid(row=2, column=0) self.epais.grid(row=2, column=1) self.lemail.grid(row=3, column=0) self.eemail.grid(row=3, column=1) self.lusuario.grid(row=4, column=0) self.eusuario.grid(row=4, column=1) self.lsenha.grid(row=5, column=0) self.esenha.grid(row=5, column=1) self.btnRetornar.grid(row=6, column=0) self.btnRetornar.bind("<Button>", lambda e: self.retornarMainWindow()) #Minhatela = AppGUI(root, 0) #root.mainloop()
class NewMorphWindow(Toplevel): def __init__(self, master=None): super().__init__(master=master) self.set_basic() self.set_widgets() def set_basic(self): self.minsize(500, 300) self.maxsize(500, 300) self.title("Operacje morfologiczne") self.protocol("WM_DELETE_WINDOW", lambda: self.cancel()) self.operations = [ "EROZJA", "DYLACJA", "OTWARCIE", "ZAMKNIĘCIE", "SZKIELETYZACJA" ] self.shapes = ["KWADRAT", "ROMB"] self.handleBorder = { "Bez zmian (isolated)": 0, "Odbicie lustrzane (reflect)": 1, "Powielenie skrajnego piksela (replicate)": 2 } def set_widgets(self): self.operationChoice = StringVar(self, self.operations[0]) self.shape = StringVar(self, value=self.shapes[0]) self.size = StringVar(self, value="3") self.borderType = StringVar(self, list(self.handleBorder.keys())[0]) self.operationChoice.trace("w", self.update_preview) self.shape.trace("w", self.update_preview) self.borderType.trace("w", self.update_preview) self.operationList = OptionMenu(self, self.operationChoice) self.shapeList = OptionMenu(self, self.shape) self.sizeSpin = Spinbox(self, justify='center', font=("Helvetica", 15), from_=3, to=9999, textvariable=self.size, command=self.update_preview, state='readonly', increment=2) self.borderList = OptionMenu(self, self.borderType) for oper in self.operations: self.operationList['menu'].add_command( label=oper, command=lambda v=oper: self.operationChoice.set(v)) for sh in self.shapes: self.shapeList['menu'].add_command( label=sh, command=lambda v=sh: self.shape.set(v)) for border in self.handleBorder: self.borderList['menu'].add_command( label=border, command=lambda v=border: self.borderType.set(v)) self.saveButton = Button(self, image=saveIcon, command=self.update_image) self.cancelButton = Button(self, image=closeIcon, command=self.cancel) self.update_preview() self.place_widgets() def update_image(self): self.master.image.cv2Image = copy.deepcopy(self.master.image.copy) self.master.image.morph_operations( self.operationChoice.get(), self.shape.get(), int(self.size.get()), self.handleBorder[self.borderType.get()]) self.master.image.copy = copy.deepcopy(self.master.image.cv2Image) self.master.manager.new_state(self.master.image.cv2Image) self.master.update_visible_image() self.master.update_child_windows() self.destroy() def update_preview(self, *args): self.master.image.cv2Image = copy.deepcopy(self.master.image.copy) self.master.image.morph_operations( self.operationChoice.get(), self.shape.get(), int(self.size.get()), self.handleBorder[self.borderType.get()]) self.master.update_visible_image() self.master.update_child_windows() def place_widgets(self): Label(self, text="Operacja:", font=("Helvetica", 15)).place(x=25, y=25) Label(self, text="Kształt i rozmiar:", font=("Helvetica", 15)).place(x=25, y=85) Label(self, text="Piksele skrajne:", font=("Helvetica", 15)).place(x=25, y=145) self.operationList.place(width=250, height=50, x=225, y=20) self.shapeList.place(width=100, height=50, x=225, y=80) self.sizeSpin.place(width=100, height=50, x=375, y=80) self.borderList.place(width=250, height=50, x=225, y=140) self.saveButton.place(width=40, height=40, x=200, y=255) self.cancelButton.place(width=40, height=40, x=260, y=255) def cancel(self): self.master.image.cv2Image = copy.deepcopy(self.master.image.copy) self.master.update_visible_image() self.master.image.fill_histogram() self.master.update_child_windows() self.destroy()
class PlotterWindow(): def __init__(self, master): # Tkinter parts self.master = master self.master.title("Live Serial Plotter") self.master.resizable(False, False) # Prevent resizing # Serial parts self.ser = None self.IS_SERIAL_CONNECTED = False self.serial_data = [[0 for i in range(MAXINPUTS)] for i in range(NPOINTS)] self.serial_plotline = [] # Figure self.f1 = plt.figure(figsize=PLOTRATIO, dpi=PLOTDPI) self.a1 = self.f1.add_subplot(111) self.a1.grid() self.a1.set_title("Serial Values") self.a1.set_xticklabels([]) self.canvas1 = FigureCanvasTkAgg(self.f1, master) self.canvas1.get_tk_widget().grid(row=0, column=0, columnspan=6, pady=20) # Labels self.npointslabel = Label(master, text='# Points') self.npointslabel.grid(row=1, column=0, sticky='W') self.baudratelabel = Label(master, text="Baud Rate") self.baudratelabel.grid(row=2, column=0, sticky='W') self.portlabel = Label(master, text='Serial Port') self.portlabel.grid(row=3, column=0, sticky='W') self.serialconnectedstringvar = StringVar(master, value='Unconnected') self.serialconnectedlabel = Label( master, textvar=self.serialconnectedstringvar, fg='red', width=15) self.serialconnectedlabel.grid(row=1, column=3) self.numinputslabel = Label(master, text="# Inputs") self.numinputslabel.grid(row=4, column=0, sticky='W') self.currentvallabel = Label(master, text="Most recent:") self.currentvallabel.grid(row=1, column=5) self.currentvalstringvar = StringVar(master, value='None') self.currentval = Label(master, textvar=self.currentvalstringvar) self.currentval.grid(row=2, column=5) self.packageindicator = StringVar(master, value='!') self.packageindicatorlabel = Label(master, textvar=self.packageindicator, font=('times', 20, 'bold')) self.packageindicatorlabel.grid(row=4, column=5) self.packageindicator.set(".") # OptionMenu lists _npoints_list = [10, 25, 50, 75, 100, 250, 500, 750, 1000] # Desired points npoints_list = [str(x) for x in _npoints_list ] # Converting each of these to a string available_ports = FindAllSerialPorts() if len(available_ports ) == 0: # If there are no available ports, print a warning tprint("> Warning: no available ports!") available_ports.append('None') _baud_rates = [ 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600, 115200, 128000, 256000 ] baud_rates = [str(x) for x in _baud_rates] input_num_options = [str(x) for x in range(1, MAXINPUTS + 1)] plotmethods = ['Markers only', 'Line only', 'Both'] # Various ways to display the plotted values # StringVars self.npointsentrystr = StringVar(master, value="250") self.baudrateentrystr = StringVar(master, value="115200") self.portentrystr = StringVar(master, value=available_ports[-1]) self.plotmethodentrystr = StringVar(master, value=plotmethods[1]) self.numinputsentrystr = StringVar(master, value="1") # Using OptionMenu instead: self.plotmethodoptionmenu = OptionMenu(master, self.plotmethodentrystr, *plotmethods) self.plotmethodoptionmenu.grid(row=4, column=2) self.npointsoptionmenu = OptionMenu(master, self.npointsentrystr, *npoints_list) self.npointsoptionmenu.grid(row=1, column=1, sticky='W') self.baudrateoptionmenu = OptionMenu(master, self.baudrateentrystr, *baud_rates) self.baudrateoptionmenu.grid(row=2, column=1, sticky='W') self.portoptionmenu = OptionMenu(master, self.portentrystr, *available_ports) self.portoptionmenu.width = 20 self.portoptionmenu.grid(row=3, column=1, sticky='W') self.numinputsoptionmenu = OptionMenu(master, self.numinputsentrystr, *input_num_options) self.numinputsoptionmenu.grid(row=4, column=1, sticky='W') # Buttons self.show_x_axis = IntVar(master, value=0) self.showxaxischeckbutton = Checkbutton(master, text='Show y=0', variable=self.show_x_axis, onvalue=1, offvalue=0) self.showxaxischeckbutton.grid(row=1, column=2) self.connectbutton = Button(master, text='Connect', command=self.ConnectToSerial) self.connectbutton.grid(row=2, column=3) self.disconnectbutton = Button(master, text='Disconnect', command=self.DisconnectFromSerial) self.disconnectbutton.grid(row=3, column=3) self.refreshserialbutton = Button(master, text='Refresh Ports', command=self.RefreshSerial) self.refreshserialbutton.grid(row=3, column=2) self.exportdatabutton = Button(master, text='Export', command=self.ExportData) self.exportdatabutton.grid(row=4, column=3) self.printrawdata = IntVar(master, value=0) self.printrawbutton = Checkbutton(master, text='Print raw data', variable=self.printrawdata, onvalue=1, offvalue=0) self.printrawbutton.grid(row=2, column=2) self.requirebrackets = IntVar(master, value=1) self.requirebracketsbutton = Checkbutton(master, text='Require brackets', variable=self.requirebrackets, onvalue=1, offvalue=0) self.requirebracketsbutton.grid(row=3, column=5) # ===================================================================== # ========================================================================= # Runs the main loop for Tk(). def mainloop(self): self.master.mainloop() return # ========================================================================= # ========================================================================= # Connects GUI to a COM port based on the user selected port. def ConnectToSerial(self): try: port = self.portentrystr.get() baudrate = int(self.baudrateentrystr.get()) tprint("> Trying to connect to %s at %d" % (port, baudrate)) self.ser = serial.Serial(port, baudrate, timeout=0.1) self.ser.flushInput() except: tprint("> Error") self.ToggleSerialConnectedLabel(False) return -1 tprint("> Success.") self.IS_SERIAL_CONNECTED = True # Set GUI state self.ToggleSerialConnectedLabel(True) # Show the state self.GetSerialValue() # Begin the GetSerialValue() loop return # ========================================================================= # ========================================================================= # Disconnects from whatever serial port is currently active. def DisconnectFromSerial(self): if self.IS_SERIAL_CONNECTED: # Only do this if already connected. self.ser.close() self.ToggleSerialConnectedLabel(False) self.IS_SERIAL_CONNECTED = False return # ========================================================================= # ========================================================================= # Refreshes the list of available serial ports on the option menu. def RefreshSerial(self): new_serial_list = FindAllSerialPorts() tprint("> Refreshing serial port list") if len(new_serial_list) == 0: tprint("> No available serial ports.") return self.portentrystr.set(new_serial_list[-1]) # Set the variable to none self.portoptionmenu['menu'].delete(0, 'end') # Delete the old list for port in new_serial_list: # Refresh: self.portoptionmenu['menu'].add_command(label=port, command=_setit( self.portentrystr, port)) return # ========================================================================= # ========================================================================= # Exports the data to a file associated with the current date and time. def ExportData(self): timestamp = datetime.datetime.now().strftime('%y%m%d_%H%M%S') outfname = 'SessionLogs/SerialSessionLog_%s.csv' % (timestamp) try: hit_data_start = False f = open(outfname, 'w') for sd in self.serial_data: # Check if we have data yet, don't start appending until that point if not hit_data_start: if not any(sd): continue # Skip to the next data point if all values are zeros else: hit_data_start = True wstr = '' for d in sd: wstr += '%f,' % (d) wstr = wstr[:-1] + '\n' f.write(wstr) f.close() tprint("> Successfully exported to %s" % (outfname)) except: tprint("> Error: Unable to export data") return # ========================================================================= # ========================================================================= # Changes the "good data received" indicator. def SetPackageIndicator(self, state): if state == 'good': self.packageindicator.set("!") self.packageindicatorlabel.config(fg='green', font=('times', 20, 'bold')) else: self.packageindicator.set('.') self.packageindicatorlabel.config(fg='black', font=('times', 20, 'bold')) return # ========================================================================= # ========================================================================= # Gets the most recent serial value from connection. IMPORTANT. def GetSerialValue(self): if not self.IS_SERIAL_CONNECTED: tprint("> No connection") return try: # Read data rawdata = self.ser.readline().decode('utf8') if rawdata != '': self.currentvalstringvar.set(str(rawdata[:-1])) self.ser.flushInput() # Clear this out to avoid garbage data self.ser.flushOutput() # Clear this out to avoid garbage data # Parse data x_nonewline = rawdata[:-1] # Ignore the trailing newline if self.printrawdata.get(): # Print the raw data, if desired print(x_nonewline) if self.requirebrackets.get(): if ">" in x_nonewline and "<" in x_nonewline: x = x_nonewline[1:-2] try: npoints = int(self.npointsentrystr.get()) x_split = x.split(' ') # Make sure that every data package is the same length, so it's not a sequence senddata = [] for i in range(MAXINPUTS): try: senddata.append(float(x_split[i])) except: senddata.append( self.serial_data[-1] [i]) # Append the most recent value self.serial_data.append(senddata) self.serial_data = self.serial_data[1:] self.serial_plotline = self.serial_data[-npoints:] # Set the blinker indicator to green! self.SetPackageIndicator('good') self.master.after_idle( self.Plotline) # Once everything's done, plot it! except ValueError: tprint( "> Invalid serial value: Non-floating point detected: %s" % (x)) else: self.SetPackageIndicator('bad') else: x = x_nonewline try: npoints = int(self.npointsentrystr.get()) x_split = x.split(' ') # Make sure that every data package is the same length, so it's not a sequence senddata = [] for i in range(MAXINPUTS): try: senddata.append(float(x_split[i])) except: senddata.append( self.serial_data[-1] [i]) # Append the most recent value self.serial_data.append(senddata) self.serial_data = self.serial_data[1:] self.serial_plotline = self.serial_data[-npoints:] self.master.after_idle(self.Plotline) except ValueError: tprint( "> Invalid serial value: Non-floating point detected: %s" % (x)) except Exception as e: tprint("> Error in GetSerialValue()", e) self.master.after( TIMEDELAY, self.GetSerialValue) # Do it all again: Here's making it the loop return # ========================================================================= # ========================================================================= # Plots the data to the GUI's plot window. def Plotline(self): numpoints = int(self.npointsentrystr.get()) numinputs = int(self.numinputsentrystr.get()) if self.plotmethodentrystr.get() == 'Markers only': plotmethod = '.' elif self.plotmethodentrystr.get() == 'Line only': plotmethod = '-' else: plotmethod = '.-' self.a1.clear() for i in range(numinputs): # Plot each line individually plotline = [x[i] for x in self.serial_plotline] self.a1.plot(plotline, plotmethod, label=str(i)) self.a1.grid() if self.show_x_axis.get(): self.a1.set_ylim(0, 1.125 * np.amax(np.array(self.serial_data))) # Plot formatting parameters ticklabels = np.linspace(numpoints / 10, 0, 5) self.a1.set(xticks=np.linspace(0, numpoints, 5), xticklabels=ticklabels) self.a1.set_xticklabels([]) self.a1.set_ylabel("Serial Value") self.a1.legend(loc=3) self.a1.set_title("Serial Values") self.canvas1.draw() # Actually update the GUI's canvas object return # ========================================================================= # ========================================================================= # Swap out the string label indicating whether serial is connected. def ToggleSerialConnectedLabel(self, connection): if connection: self.serialconnectedstringvar.set('Connected') self.serialconnectedlabel.config(fg='green') else: self.serialconnectedstringvar.set('Unconnected') self.serialconnectedlabel.config(fg='red') return
class GrepDialog(SearchDialogBase): title = "文件内容查找对话框" icon = "Grep" needwrapbutton = 0 def __init__(self, root, engine, flist): SearchDialogBase.__init__(self, root, engine) self.flist = flist self.globvar = StringVar(root) self.recvar = BooleanVar(root) def open(self, text, searchphrase, io=None): SearchDialogBase.open(self, text, searchphrase) if io: path = io.filename or "" else: path = "" dir, base = os.path.split(path) head, tail = os.path.splitext(base) if not tail: tail = ".py" self.globvar.set(os.path.join(dir, "*" + tail)) def create_entries(self): SearchDialogBase.create_entries(self) self.globent = self.make_entry("文件类型:", self.globvar)[0] def create_other_buttons(self): btn = Checkbutton(self.make_frame()[0], variable=self.recvar, text="是否包含子目录") btn.pack(side="top", fill="both") def create_command_buttons(self): SearchDialogBase.create_command_buttons(self) self.make_button("文件中查找", self.default_command, 1) def default_command(self, event=None): prog = self.engine.getprog() if not prog: return path = self.globvar.get() if not path: self.top.bell() return from idlelib.outwin import OutputWindow # leave here! save = sys.stdout try: sys.stdout = OutputWindow(self.flist) self.grep_it(prog, path) finally: sys.stdout = save def grep_it(self, prog, path): dir, base = os.path.split(path) list = self.findfiles(dir, base, self.recvar.get()) list.sort() self.close() pat = self.engine.getpat() print("查找 %r 在 %s ..." % (pat, path)) hits = 0 try: for fn in list: try: with open(fn, errors='replace') as f: for lineno, line in enumerate(f, 1): if line[-1:] == '\n': line = line[:-1] if prog.search(line): sys.stdout.write("%s: %s: %s\n" % (fn, lineno, line)) hits += 1 except OSError as msg: print(msg) print(("查找结果: %s\n" "(跳转: 右击打开目标位置.)" % hits) if hits else "没有发现匹配内容.") except AttributeError: # Tk window has been closed, OutputWindow.text = None, # so in OW.write, OW.text.insert fails. pass def findfiles(self, dir, base, rec): try: names = os.listdir(dir or os.curdir) except OSError as msg: print(msg) return [] list = [] subdirs = [] for name in names: fn = os.path.join(dir, name) if os.path.isdir(fn): subdirs.append(fn) else: if fnmatch.fnmatch(name, base): list.append(fn) if rec: for subdir in subdirs: list.extend(self.findfiles(subdir, base, rec)) return list def close(self, event=None): if self.top: self.top.grab_release() self.top.withdraw()
class Roller(Frame): def __init__(self, group, index): Frame.__init__(self, group) self.group = group self.index = index self.results = [0] self.history = [] self.name = StringVar() self.dice_qty = IntVar() self.die_faces = IntVar() self.modifier = IntVar() self.finalmod = IntVar() self.results_text = StringVar() self.name.trace('w', self.group.mainframe.set_unsaved_title) self.dice_qty.trace('w', self.group.mainframe.set_unsaved_title) self.die_faces.trace('w', self.group.mainframe.set_unsaved_title) self.modifier.trace('w', self.group.mainframe.set_unsaved_title) self.finalmod.trace('w', self.group.mainframe.set_unsaved_title) self.results_text.trace('w', self.group.mainframe.set_unsaved_title) default_font = ('Courier', 14) self.menu_btn = Menubutton(self, bd=1, relief='solid', font=('Courier', 8), text='\u25e2', takefocus=1, highlightthickness=1) self.name_entry = Entry(self, bd=1, relief='solid', font=('Verdana', 12), width=16, textvariable=self.name) self.dice_qty_spin = NumericSpinner(self, self.dice_qty, 1, 99, callback=self.reset, initial=1) self.die_faces_spin = NumericSpinner( self, self.die_faces, 2, 100, interval=self.group.mainframe.allow_odd.get(), initial=10) self.modifier_spin = NumericSpinner(self, self.modifier, -99, 100, callback=self.apply_modifiers) self.finalmod_spin = NumericSpinner(self, self.finalmod, -99, 100, callback=self.apply_modifiers) self.dice_lbl = Label(self, text=' d', font=default_font) self.modifier_lbl = Label(self, text='\u002b', font=default_font) self.finalmod_lbl = Label(self, text='\u002b', font=default_font) self.roll_btn = Button(self, bd=0, image=self.group.roll_img, command=lambda: self.roll(single=True)) self.results_entry = Entry(self, bd=0, relief='solid', font=default_font, width=0, textvariable=self.results_text, state='readonly', justify='center') self.menu_btn.config(menu=self.create_menu()) self.menu_btn.grid(row=index, column=0, padx=(4, 0)) self.name_entry.grid(row=index, column=1, padx=(4, 0)) self.dice_qty_spin.grid(row=index, column=2, padx=(4, 0)) self.dice_lbl.grid(row=index, column=3, padx=(0, 0)) self.die_faces_spin.grid(row=index, column=4, padx=(0, 0)) self.modifier_lbl.grid(row=index, column=5, padx=(6, 6)) self.modifier_spin.grid(row=index, column=6, padx=(0, 0)) self.roll_btn.grid(row=index, column=7, padx=(8, 0)) self.results_entry.grid(row=index, column=8, padx=(8, 0)) self.finalmod_lbl.grid(row=index, column=9, padx=(6, 6)) self.finalmod_spin.grid(row=index, column=10, padx=(0, 4)) self.name.set('Roller {}'.format(len(self.group.rollers) + 1)) self.die_faces.set(10) self.results_text.set('0 = 0') self.grid(row=index, sticky='w', pady=4) def create_menu(self): menu = Menu(self.menu_btn, tearoff=0, postcommand=self.group.maintain_roller_indices) menu.add_command(label='Add', underline=0, command=self.add_roller) menu.add_command(label='Clone', underline=0, command=lambda: self.add_roller(clone=True)) menu.add_command(label='Up', underline=0, command=lambda: self.move_roller(offset=-1)) menu.add_command(label='Down', underline=0, command=lambda: self.move_roller(offset=1)) menu.add_separator() # ------ menu.add_command(label='Remove', underline=0, command=self.remove_roller) return menu def create_hist_record(self): record = { 'dice_qty': self.dice_qty.get(), 'die_faces': self.die_faces.get(), 'modifier': self.modifier.get(), 'results_text': self.results_text.get(), 'finalmod': self.finalmod.get(), 'timestamp': str(dt.now().time())[:8], 'results': self.results } return record def add_roller(self, clone=False): destination_index = self.index + 1 roller = Roller(self.group, destination_index) self.group.rollers.insert(roller.index, roller) for i in range(destination_index, len(self.group.rollers)): self.group.rollers[i].grid(row=i + 1) if clone: roller.name.set(self.name.get()) roller.dice_qty.set(self.dice_qty.get()) roller.die_faces.set(self.die_faces.get()) roller.modifier.set(self.modifier.get()) roller.finalmod.set(self.finalmod.get()) roller.reset() for h in self.history: record = roller.create_hist_record() record['timestamp'] = h['timestamp'] roller.history.append(record) roller.apply_modifiers() for r in self.group.rollers: r.lift() self.group.mainframe.editmenu.entryconfigure( self.group.mainframe.editmenu.index('end'), command=lambda: self.add_roller(clone=clone)) self.group.mainframe.bind_all('<Control-r>', lambda e: self.add_roller(clone=clone)) def move_roller(self, offset=0, destination_index=0): if not destination_index: destination_index = self.index + offset if destination_index >= 0: roller = self.group.rollers.pop(self.index) self.group.rollers.insert(destination_index, roller) self.group.maintain_roller_indices() self.name.set(self.name.get()) self.group.mainframe.editmenu.entryconfigure( self.group.mainframe.editmenu.index('end'), command=lambda: self.move_roller(offset=offset)) self.group.mainframe.bind_all( '<Control-r>', lambda e: self.move_roller(offset=offset)) def remove_roller(self): if len(self.group.rollers) > 1: self.grid_remove() self.group.rollers.remove(self) self.name.set('') def reset(self, loading=False): self.results = [0 for i in range(self.dice_qty.get())] self.dice_qty_spin.step(0) self.die_faces_spin.step(0) self.modifier_spin.step(0) self.finalmod_spin.step(0) if not loading: self.apply_modifiers() self.group.maintain_result_widths() def roll(self, single=False): rolls = self.dice_qty.get() sides = self.die_faces.get() if self.group.mainframe.allow_odd.get() % 2 == 0 and sides % 2 != 0: self.die_faces.set(sides - 1) sides -= 1 mod = self.modifier.get() fmod = self.finalmod.get() max_roll = sides min_roll = 1 results = [] if self.group.mainframe.use_random_org.get(): url = 'https://www.random.org/integers/?col={0}&num={0}&min={1}&max={2}&base=10&format=plain&rnd=new' url = url.format(rolls, min_roll, max_roll) try: resp = urlopen(url) results.extend([ int(x) for x in str(resp.read().rstrip(), encoding='utf8').split('\t') ]) sleep(0.1) except: print('Failed to use random.org, falling back to CSPRNG!') if not results: csprng = SystemRandom() for i in range(rolls): roll = csprng.randint(min_roll, sides) results.append(roll) self.results = [] for n in results: if n == max_roll: self.results.append(n * CRIT) elif n == min_roll: self.results.append(n * FAIL) else: self.results.append(n) self.apply_modifiers(True) self.history.append(self.create_hist_record()) hist_index = len(self.history) - 1 if single: for roller in self.group.rollers: if roller is not self: roller.history.append(roller.create_hist_record()) self.group.navigate_history(desired_index=hist_index) self.group.hist_index = hist_index self.name.set(self.name.get()) self.group.mainframe.editmenu.entryconfigure( self.group.mainframe.editmenu.index('end'), command=lambda: self.roll(single=single)) self.group.mainframe.bind_all('<Control-r>', lambda e: self.roll(single=single)) def apply_modifiers(self, rolling=False): fmod = self.finalmod.get() dmod = self.modifier.get() dqty = self.dice_qty.get() formatted_results = [] total = 0 for n in self.results: if n > CRIT: n = int(n / CRIT) n = n + dmod formatted_results.append('\u25b2{}'.format(str(n))) elif 0 < n < 1: n = int(n / FAIL) n = n + dmod formatted_results.append('\u25bc{}'.format(str(n))) else: n = n + dmod formatted_results.append(str(n)) total += n s = ' + '.join(formatted_results) s = '{} = {}'.format(total + fmod, s) if not rolling and self.history: self.history[self.group.hist_index]['modifier'] = dmod self.history[self.group.hist_index]['finalmod'] = fmod self.history[self.group.hist_index]['results_text'] = s self.results_text.set(s) self.group.maintain_result_widths()
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)
from tkinter import Tk, Entry, StringVar, Label root = Tk() # text control variable sValue = StringVar() t1 = Label(root, text='Type in some text here!') t1.pack() x = Entry(root, textvariable=sValue) x.pack() root.mainloop() print(sValue.get())