class model_select(Frame): def __init__(self,controller,model_list,current_model,master,*args,**kwargs): self.controller = controller self.model_list = model_list self.current_model = current_model # Dibujar widget super().__init__(master, *args, **kwargs) self.listbox = Listbox(self, exportselection=False) self.listbox.bind('<<ListboxSelect>>', self.selection) self.listbox.pack() for item in self.model_list: self.listbox.insert(END, item) self.listbox.select_set(0) self.listbox.event_generate("<<ListboxSelect>>") def selection(self,x): w = x.widget index = int(w.curselection()[0]) value = w.get(index) print(value) # Send message to interface to load another model f_path = os.path.join(config_folder, value) self.current_model.change_model(f_path) self.controller.event_change_model(self.current_model) pass
def openStats(handler): statsApi = get( "https://raw.githubusercontent.com/revoxhere/duco-statistics/master/api.json", data=None) if statsApi.status_code == 200: #Check for reponse statsApi = (statsApi.json()) print(statsApi) statsWindow = Toplevel() statsWindow.resizable(False, False) statsWindow.title("Duino-Coin Wallet - Stats") statsWindow.configure(background=backgroundColor) statsWindow.transient([root]) textFont3 = Font(statsWindow, size=14, weight="bold") textFont = Font(statsWindow, size=12, weight="normal") Label(statsWindow, text="Duco Statistics - WIP", background=backgroundColor, foreground=foregroundColor, font=textFont3).grid(row=0, column=0) Active_workers_listbox = Listbox(statsWindow, exportselection=False, background=backgroundColor, foreground=foregroundColor, selectbackground="#7bed9f", border="0", font=textFont, width="20", height="13") Active_workers_listbox.grid(row=1, column=0, sticky=W) i = 0 for worker in statsApi['Active workers']: Active_workers_listbox.insert(i, worker) i += 1 Active_workers_listbox.select_set(32) Active_workers_listbox.event_generate("<<ListboxSelect>>") Top_10_listbox = Listbox(statsWindow, exportselection=False, background=backgroundColor, foreground=foregroundColor, selectbackground="#7bed9f", border="0", font=textFont, width="33", height="13") Top_10_listbox.grid(row=1, column=1, sticky=W) i = 0 for rich in statsApi['Top 10 richest miners']: Top_10_listbox.insert(i, statsApi['Top 10 richest miners'][i]) i += 1 Top_10_listbox.select_set(32) Top_10_listbox.event_generate("<<ListboxSelect>>") statsWindow.mainloop()
class HelpWindow(Toplevel): def __init__(self, master=None): super().__init__(master) self.root = master self.title = 'Help' self.list = Listbox(self) self.list.pack(side="left", fill="y") self.text = scrolledtext.ScrolledText(self, wrap=WORD) self.text.pack(side="right", fill="both", expand=True) self.images = [] self.load_list() self.list.bind('<<ListboxSelect>>', self.list_click) self.list.select_set(0) self.list_click(None) def load_list(self): self.files = {} path = os.path.dirname(os.path.realpath(__file__)) file_path = os.path.join(path, 'index.json') f = open(file_path, 'rt') self.files = json.loads(f.read()) for counter, entry in enumerate(self.files['files']): self.list.insert(counter, entry['name']) f.close() def list_click(self, event): index = self.list.curselection()[0] item = self.files['files'][index] path = os.path.dirname(os.path.realpath(__file__)) fileName = os.path.normpath(os.path.join(path, item['fileName'])) self.render_file(fileName) def render_file(self, fileName): path = os.path.dirname(os.path.realpath(__file__)) f = open(os.path.join(fileName), 'rt') buffer = f.read() f.close() parser = MarkdownParser() tokens = parser.parse(buffer) renderer = MarkdownRenderTk(self.text) renderer.render(tokens, os.path.normpath(os.path.join(path, '../res')), self.images, self.link_click) def link_click(self, url, title): if (url.startswith('http:') or url.startswith('https:')): # Open a web browser with that link. webbrowser.open(url) else: # Open a markdown file. path = os.path.dirname(os.path.realpath(__file__)) fileName = os.path.normpath(os.path.join(path, url)) self.render_file(fileName)
class PRGListBox(Frame): def __init__(self, master=None,**args): Frame.__init__(self, master,**args) scrollbar = Scrollbar(self, orient=VERTICAL) #нужен для отображения длинных списков scrollbar.unbind("<Key-Up>") scrollbar.unbind("<Key-Down>") scrollbar.unbind("<Key-Left>") scrollbar.unbind("<Key-Right>") scrollbar.pack(side=RIGHT, fill=Y) self.lst = Listbox(self, yscrollcommand=scrollbar.set, bg="grey", selectmode=SINGLE) self.lst.insert(END,"Hide All") self.lst.insert(END,"Show All") self.lst.select_set(0) self.lst.pack(side=LEFT, fill=BOTH, expand=1) scrollbar.config(command=self.lst.yview)
class mask_select(Frame): def __init__(self, controller, current_model : model_manager_obj, master, *args, **kwargs): self.controller = controller super().__init__(master, *args, **kwargs) self.listbox = Listbox(self, exportselection=False) self.listbox.pack(fill="both", expand=True) self.listbox.bind("<<ListboxSelect>>",self.selection) Label(self,text="New mask file: ").pack() self.entry_text = StringVar() Entry(self,textvariable=self.entry_text).pack() Button(self,text='Create',command=self.add_new).pack() self.update_model(current_model) def update_model(self, current_model): self.model = current_model self.mask_file_list = self.model.get_mask_file_list() self.current_mask_file=self.model.get_current_mask_file() self.listbox.delete(0, END) for item in self.mask_file_list: self.listbox.insert(END, item) self.listbox.select_set(0) self.listbox.event_generate("<<ListboxSelect>>") def selection(self,event): w = event.widget index = int(w.curselection()[0]) value = w.get(index) selected = value self.controller.event_change_mask_file(selected) pass def add_new(self): new = self.entry_text.get() self.controller.event_add_mask_file(new) pass
class ReloadOption(Toplevel): def __init__(self): super().__init__() self.title('重载设置') self.reload_mode = None self.label = Label(self, text="请选择重新加载的范围:") self.lb = Listbox(self, width=40) self.fm = Frame(self) self.ok = Button(self.fm, text="重载", command=self.select_mode) self.cancel = Button(self.fm, text="取消", command=self.destroy) for item in ['最近一周', '最近一个月', '最近三个月', '最近半年', '最近一年', '全部重载']: self.lb.insert(END, item) self.lb.select_set(5) self.label.pack(side='top') self.lb.pack(side='top', fill='both', expand='YES') self.fm.pack(side='top') self.ok.pack(side='left') self.cancel.pack(side='right') def select_mode(self): self.reload_mode = self.lb.get(self.lb.curselection()) self.destroy()
class GuiTestManager(Tk): """Manager for GUI tests. Use `add_test` method to add a test class.""" def __init__(self): """Initialise manager.""" Tk.__init__(self) self.title("GUI Test Manager") self.geometry("400x300") ## Dictionary of Toplevel tests who are current active. self.active_tests = {} ## List of all available test classes. self.all_tests = [] # Create widgets to show list of available tests. Label(self, text="Available Tests", font=("Comic Sans MS", "24")).pack(padx=3, pady=3) Label(self, text="Click a test to open it, and again to close it.", font=["Comic Sans MS"]).pack() # Create container for listbox and scrollbar. list_frame = Frame(self) list_frame.pack(fill="both", expand=1, padx=3, pady=3) # Add scrollbar for Listbox. list_scrollbar = Scrollbar(list_frame, orient="vertical") list_scrollbar.pack(side="right", fill="y") # Create Listbox next to scrollbar. self.all_tests_list = Listbox(list_frame, selectmode="multiple", yscrollcommand=list_scrollbar.set, selectborderwidth=5, font=("Comic Sans MS", "16", "italic"), activestyle="none", takefocus=1, cursor="pirate") # Bind the event for 0ms after a click, so the listbox can process first. self.all_tests_list.bind( "<ButtonPress-1>", lambda e: self.after(0, lambda e=e: self.on_test_list_pressed(e))) self.all_tests_list.pack(side="left", fill="both", expand=1) # Link scrollbar and listbox scroll commands. list_scrollbar.config(command=self.all_tests_list.yview) # Perform initial refresh. self.refresh_available() def add_test(self, test_class): """ Add a GUI test class to the test manager. Will do nothing if already added this test. """ if test_class in self.all_tests: return self.all_tests.append(test_class) self.refresh_available() def refresh_available(self): """Refresh list of available tests.""" # Delete old options. old_selection = self.all_tests_list.curselection() self.all_tests_list.delete(0, "end") # Show new options in Listbox from set. for test_class in self.all_tests: self.all_tests_list.insert("end", test_class.get_test_name()) # Maintain previous selection. for i in old_selection: self.all_tests_list.select_set(i) def on_test_list_pressed(self, event): """Called when mouse button 1 pressed on all_tests_list""" # All selected indexes. now_selected = set(self.all_tests_list.curselection()) # Check all options in Listbox. for i, test_class in enumerate(self.all_tests): if i in now_selected and i not in self.active_tests: # Index has been newly selected. Make the widget. new_wgt = test_class(self) new_wgt.protocol("WM_DELETE_WINDOW", lambda i=i: self.on_toplevel_destroyed(i)) self.active_tests[i] = new_wgt elif i not in now_selected and i in self.active_tests: # Index has been newly deselected. Destroy the widget. self.active_tests.pop(i).destroy() def on_toplevel_destroyed(self, index): """Called when initialised test window is manually destroyed.""" self.active_tests.pop(index).destroy() self.all_tests_list.select_clear(index)
class PCRLibrarianApp(Tk): """ Main window for thePCR Librarian app """ def __init__(self): super(PCRLibrarianApp, self).__init__() # Screen metrics sw = self.winfo_screenwidth() sh = self.winfo_screenheight() # TODO Position and size main window self.title("PCR Librarian") # ttk theme # s = ttk.Style() # s.theme_use('classic') self.background_color = "#ffffff" self.highlight_color = "#e0e0e0" # Create window widgets self._create_widgets(sw, sh) # Size the main window according to its contents self.update() w = self.winfo_width() h = self.winfo_height() # Centered x = int((sw - w) / 2) y = int((sh - h) / 2) # width x height + x + y geo = "{0}x{1}+{2}+{3}".format(w, h, x, y) self.geometry(geo) # self.resizable(width=True, height=True) self.resizable(width=True, height=False) # Handle app exit self.protocol("WM_DELETE_WINDOW", self._on_close) # Restore last used directory self._set_directory(Configuration.get_last_recent()) def _create_widgets(self, sw, sh): """ Create the UI widgets :param sw: Screen width :param sh: Screen height :return: """ MIN_WIDTH = 100 # Create a menu bar for the current OS self._create_menu() # Control/widget experimentation self.config(padx=10) self.config(pady=10) # Around control map directory widgets self._ctrl_frame = LabelFrame(master=self, padx=10, pady=10, text="Control Map Directory") self._ctrl_frame.grid(row=0, column=0, sticky="ew") # Container for action buttons self._button_frame = Frame(master=self, bd=5, padx=5, pady=5) self._button_frame.grid(row=2, column=0, pady=5) self.columnconfigure(0, weight=1, minsize=MIN_WIDTH) self._ctrl_frame.columnconfigure(0, weight=1) # Control frame row tracker r = 0 # Directory entry self._ent_directory = Entry(master=self._ctrl_frame, width=MIN_WIDTH) self._ent_directory.grid(row=r, column=0, sticky="ew") r += 1 # Frame for directory widgets self._fr_dir = Frame(master=self._ctrl_frame) # Select a directory self._btn_dir_button = Button(master=self._fr_dir, text="Select Control Map Directory", command=self._on_select_directory) self._btn_dir_button.grid(row=0, column=0, padx=5, pady=5) # Recently used directories self._cb_recent_dirs = Combobox(master=self._fr_dir, width=50, values=Configuration.get_recent()) self._cb_recent_dirs.grid(row=0, column=1, padx=5, pady=5) self._cb_recent_dirs.bind("<<ComboboxSelected>>", self._on_recent_directory) self._fr_dir.grid(row=r, column=0, padx=10) r += 1 # Control map file listbox with scrollbar self._lb_frame = LabelFrame(self._ctrl_frame, text="Control Map Files", pady=5, padx=5) self._lb_scrollbar = Scrollbar(self._lb_frame, orient=tkinter.VERTICAL) self._lb_filelist = Listbox(master=self._lb_frame, width=100) self._lb_scrollbar.config(command=self._lb_filelist.yview) self._lb_scrollbar.pack(side=tkinter.RIGHT, fill=tkinter.Y) self._lb_filelist.pack() self._lb_frame.grid(row=r, column=0, pady=5) r += 1 # Action buttons are inside the button frame on one row self._btn_receive_current_button = Button( master=self._button_frame, text="Receive Current Map", state=tkinter.DISABLED, command=self._on_receive_current_map) self._btn_receive_current_button.grid(row=0, column=0, padx=5) self._btn_receive_all_button = Button( master=self._button_frame, text="Receive All Maps", state=tkinter.DISABLED, command=self._on_receive_all_maps) self._btn_receive_all_button.grid(row=0, column=1, padx=5) self._btn_send_button = Button(master=self._button_frame, text="Send Control Map Files", state=tkinter.DISABLED, command=self._on_send) self._btn_send_button.grid(row=0, column=2, padx=5) self._btn_quit_button = Button(master=self._button_frame, text="Quit", command=self._on_close) self._btn_quit_button.grid(row=0, column=3, padx=5) # MIDI in/out ports listboxes self._lb_midiports_frame = LabelFrame(self, text="MIDI Ports", pady=5, padx=5) self._lbl_inports = Label(master=self._lb_midiports_frame, text="In") self._lb_midiin_ports = Listbox(master=self._lb_midiports_frame, width=30, height=5, selectmode=tkinter.SINGLE, exportselection=0) self._lbl_inports.grid(row=0, column=0) self._lb_midiin_ports.grid(row=1, column=0, padx=5, pady=5) self._lbl_outports = Label(master=self._lb_midiports_frame, text="Out") self._lb_midiout_ports = Listbox(master=self._lb_midiports_frame, width=30, height=5, selectmode=tkinter.SINGLE, exportselection=0) self._lbl_outports.grid(row=0, column=1) self._lb_midiout_ports.grid(row=1, column=1, padx=5, pady=5) self._lb_midiports_frame.grid(row=1, column=0, pady=5) # Populate midin ports listbox self._in_ports = get_midiin_ports() for p in self._in_ports: self._lb_midiin_ports.insert(tkinter.END, p) # Populate midout ports listbox self._out_ports = get_midiout_ports() for p in self._out_ports: self._lb_midiout_ports.insert(tkinter.END, p) # Minimize the height of the ports listboxes max_height = max(len(self._in_ports), len(self._out_ports)) self._lb_midiin_ports.config(height=max_height) self._lb_midiout_ports.config(height=max_height) # Default midi port selections self._lb_midiin_ports.select_set(0) self._lb_midiout_ports.select_set(0) # Status bar self._v_statusbar = StringVar(value="Select control map directory") self._lbl_statusbar = Label(master=self, textvariable=self._v_statusbar, bd=5, relief=tkinter.RIDGE, anchor=tkinter.W) self._lbl_statusbar.grid(row=3, column=0, pady=5, padx=5, sticky="ew") # Put the focus in the directory text box self._ent_directory.focus_set() def _create_menu(self): # will return x11 (Linux), win32 or aqua (macOS) gfx_platform = self.tk.call('tk', 'windowingsystem') # App menu bar self._menu_bar = Menu(self) if gfx_platform == "aqua": # macOS app menu covering things specific to macOS X self._appmenu = Menu(self._menu_bar, name='apple') self._appmenu.add_command(label='About PCR Librarian', command=self._show_about) self._appmenu.add_separator() self._menu_bar.add_cascade(menu=self._appmenu, label='PCRLibrarian') self.createcommand('tk::mac::ShowPreferences', self._show_preferences) filemenu = Menu(self._menu_bar, tearoff=0) filemenu.add_command(label="Clear recent directories list", command=self._on_clear_recent) self._menu_bar.add_cascade(label="File", menu=filemenu) elif gfx_platform in ["win32", "x11"]: # Build a menu for Windows or Linux filemenu = Menu(self._menu_bar, tearoff=0) filemenu.add_command(label="Clear recent directories list", command=self._on_clear_recent) filemenu.add_separator() filemenu.add_command(label="Exit", command=self._on_close) self._menu_bar.add_cascade(label="File", menu=filemenu) helpmenu = Menu(self._menu_bar, tearoff=0) helpmenu.add_command(label="About", command=self._show_about) self._menu_bar.add_cascade(label="Help", menu=helpmenu) self.config(menu=self._menu_bar) def _set_statusbar(self, text): """ Update the status bar :param text: :return: """ self._v_statusbar.set(text) # Force the widget to update now self._lbl_statusbar.update() def _on_recent_directory(self, event=None): directory = self._cb_recent_dirs.get() self._set_directory(directory) self._set_statusbar("Ready") def _on_select_directory(self): """ Select a directory as the source or target of control map(s) :return: """ directory = filedialog.askdirectory( initialdir=os.getcwd(), title="Select source/target directory") self._set_directory(directory) self._set_statusbar("Ready") def _on_clear_recent(self): Configuration.clear_recent() self._cb_recent_dirs.config(values=Configuration.get_recent()) def _set_directory(self, directory): if directory: Configuration.set_recent(directory) self._ent_directory.delete(0, tkinter.END) self._ent_directory.insert(0, directory) self._load_files() self._btn_receive_current_button["state"] = tkinter.NORMAL self._btn_receive_all_button["state"] = tkinter.NORMAL self._fill_files_listbox() self._cb_recent_dirs.config(values=Configuration.get_recent()) def _on_send(self): """ Send control map(s). Sends all .syx files from selected directory. :return: """ selected_port = self._lb_midiout_ports.curselection() dlg = SendDlg(self, title="Send Control Map Sysex Files", port=selected_port[0], files=self._files) def _on_receive_current_map(self): self._set_statusbar("Ready to receive current control map") self._on_receive_control_maps(ReceiveDlg.SINGLE) def _on_receive_all_maps(self): self._set_statusbar("Ready to receive all 15 control maps") self._on_receive_control_maps(ReceiveDlg.ALL) def _on_receive_control_maps(self, count): # Delete existing .syx files self._delete_existing_files() selected_port = self._lb_midiin_ports.curselection() # Modal dialog box for receiving sysex messages from PCR dlg = ReceiveDlg(self, title="Receive Current Control Map", port=selected_port[0], dir=self._ent_directory.get(), control_map=count) dlg.begin_modal() if dlg.result: self._set_statusbar("Current control map(s) received") else: self._set_statusbar("Canceled") self._load_files() self._fill_files_listbox() del dlg def _delete_existing_files(self): """ Delete existing .syx files :return: """ for file in self._files: os.remove(file) self._files.clear() self._fill_files_listbox() def _load_files(self): """ Load all of the .syx files in the selected directory :return: """ self._files = [] directory = self._ent_directory.get() self._files.extend( sorted([ os.path.join(directory, fn) for fn in os.listdir(directory) if fn.lower().endswith('.syx') ])) if len(self._files) >= 50: self._btn_send_button["state"] = tkinter.NORMAL else: self._btn_send_button["state"] = tkinter.DISABLED def _fill_files_listbox(self): """ Load the files listbox with all of the .syx files in the selected diretory :return: """ self._lb_filelist.delete(0, tkinter.END) for f in self._files: self._lb_filelist.insert(tkinter.END, f) def _on_close(self): """ App is closing. Warn user if unsaved changes. :return: """ print(self._ent_directory.get()) # Save the directory setting? Configuration.set_last_recent(self._ent_directory.get()) # Essentially, this terminates the app by destroying the main window self.destroy() return True def _show_about(self): about_text = \ "© 2020 by Dave Hocker\n" + \ "\n" + \ "Source: https://github.com/dhocker/pcr_librarian\n" + \ "License: GNU General Public License v3\n" + \ "as published by the Free Software Foundation, Inc. " # Locate logo image file cwd = os.path.realpath( os.path.abspath( os.path.split(inspect.getfile(inspect.currentframe()))[0])) if os.path.exists(cwd + "/pcr_librarian.gif"): image_path = cwd + "/pcr_librarian.gif" elif os.path.exists(cwd + "/resources/pcr_librarian.gif"): image_path = cwd + "/resources/pcr_librarian.gif" else: image_path = "pcr_librarian.gif" # This is a modal message box mb = TextMessageBox(self, title="About PCR Librarian", text=about_text, heading="PCR Librarian {}".format(app_version()), image=image_path, width=150, height=110, orient=tkinter.HORIZONTAL) mb.show() self.wait_window(window=mb) def _show_preferences(self): tkinter.messagebox.showinfo("Preferences for PCR Librarian", "None currently defined")
class SearchResultsWindow(BaseListMenu): # Window title TITLE = 'Search Results' def __init__(self, manga_scraper_obj: MangaReaderScraper): # call parent super().__init__(title=self.TITLE) # listbox self.list_box = Listbox(self.frame, width=50, selectmode='single', yscrollcommand=self.scrollbar.set) # add data to listbox self.list_box.insert('end', *manga_scraper_obj._text_list_of_series) # default selection to first index self.list_box.select_set(0) # set scrollbar view to listbox self.scrollbar.config(command=self.list_box.yview) # pack scrollbar self.scrollbar.pack(side='right', fill='y') # set default icon self.iconbitmap(ICON_PATH) # pack frame self.frame.pack() # pack list box self.list_box.pack(pady=15) # inner method for when ok button is clicked def ok_btn_click(self, manga_scraper_obj, series_chosen): self.check(manga_scraper_obj, series_chosen) # OK Button self.ok_btn = Button(self, text='OK', command=lambda: ok_btn_click( self, manga_scraper_obj=manga_scraper_obj, series_chosen=self.list_box.selection_get())) self.ok_btn.pack(side='left', padx=(80, 10), pady=10) # Cancel Button self.cancel_btn = Button(self, text='Cancel', command=lambda: self.destroy()) self.cancel_btn.pack(side='right', padx=(10, 80), pady=10) def check(self, manga_scraper_obj, series_chosen): if series_chosen is not None: # Set series attribute for manga scraper manga_scraper_obj.series = series_chosen # Initialize chapter list window chapter_results = ChapterListWindow( prior_window=self, manga_scraper_obj=manga_scraper_obj) chapter_results.focus_force() self.grab_release() chapter_results.grab_set() else: # Notify that a series hasn't been selected yet. messagebox.showinfo(title='Please select', message='No series selected.')
class FileChoice(object): def __init__(self, master=None, title=None, prefix=None, list=[], start='', ext="txt", new=False): self.master = master self.value = None self.prefix = prefix self.list = list if prefix and start: self.start = relpath(start, prefix) else: self.start = start self.ext = ext self.new = new self.modalPane = Toplevel(self.master, highlightbackground=BGCOLOR, background=BGCOLOR) if master: logger.debug('winfo: {0}, {1}; {2}, {3}'.format( master.winfo_rootx(), type(master.winfo_rootx()), master.winfo_rooty(), type(master.winfo_rooty()))) self.modalPane.geometry( "+%d+%d" % (master.winfo_rootx() + 50, master.winfo_rooty() + 50)) self.modalPane.transient(self.master) self.modalPane.grab_set() self.modalPane.bind("<Return>", self._choose) self.modalPane.bind("<Escape>", self._cancel) if title: self.modalPane.title(title) if new: nameFrame = Frame(self.modalPane, highlightbackground=BGCOLOR, background=BGCOLOR) nameFrame.pack(side="top", padx=18, pady=2, fill="x") nameLabel = Label(nameFrame, text=_("file:"), bd=1, relief="flat", anchor="w", padx=0, pady=0, highlightbackground=BGCOLOR, background=BGCOLOR) nameLabel.pack(side="left") self.fileName = StringVar(self.modalPane) self.fileName.set("untitled.{0}".format(ext)) self.fileName.trace_variable("w", self.onSelect) self.fname = Entry(nameFrame, textvariable=self.fileName, bd=1, highlightbackground=BGCOLOR) self.fname.pack(side="left", fill="x", expand=1, padx=0, pady=0) self.fname.icursor(END) self.fname.bind("<Up>", self.cursorUp) self.fname.bind("<Down>", self.cursorDown) filterFrame = Frame(self.modalPane, highlightbackground=BGCOLOR, background=BGCOLOR) filterFrame.pack(side="top", padx=18, pady=4, fill="x") filterLabel = Label(filterFrame, text=_("filter:"), bd=1, relief="flat", anchor="w", padx=0, pady=0, highlightbackground=BGCOLOR, background=BGCOLOR) filterLabel.pack(side="left") self.filterValue = StringVar(self.modalPane) self.filterValue.set("") self.filterValue.trace_variable("w", self.setMatching) self.fltr = Entry(filterFrame, textvariable=self.filterValue, bd=1, highlightbackground=BGCOLOR) self.fltr.pack(side="left", fill="x", expand=1, padx=0, pady=0) self.fltr.icursor(END) prefixFrame = Frame(self.modalPane, highlightbackground=BGCOLOR, background=BGCOLOR) prefixFrame.pack(side="top", padx=8, pady=2, fill="x") self.prefixLabel = Label(prefixFrame, text=_("{0}:").format(prefix), bd=1, highlightbackground=BGCOLOR, background=BGCOLOR) self.prefixLabel.pack(side="left", expand=0, padx=0, pady=0) buttonFrame = Frame(self.modalPane, highlightbackground=BGCOLOR, background=BGCOLOR) buttonFrame.pack(side="bottom", padx=10, pady=2) chooseButton = Button(buttonFrame, text="Choose", command=self._choose, highlightbackground=BGCOLOR, background=BGCOLOR, pady=2) chooseButton.pack(side="right", padx=10) cancelButton = Button(buttonFrame, text="Cancel", command=self._cancel, highlightbackground=BGCOLOR, background=BGCOLOR, pady=2) cancelButton.pack(side="left") selectionFrame = Frame(self.modalPane, highlightbackground=BGCOLOR, background=BGCOLOR) selectionFrame.pack(side="bottom", padx=8, pady=2, fill="x") self.selectionValue = StringVar(self.modalPane) self.selectionValue.set("") self.selection = Label(selectionFrame, textvariable=self.selectionValue, bd=1, highlightbackground=BGCOLOR, background=BGCOLOR) self.selection.pack(side="left", fill="x", expand=1, padx=0, pady=0) listFrame = Frame(self.modalPane, highlightbackground=BGCOLOR, background=BGCOLOR, width=40) listFrame.pack(side="top", fill="both", expand=1, padx=5, pady=2) scrollBar = Scrollbar(listFrame, width=8) scrollBar.pack(side="right", fill="y") self.listBox = Listbox(listFrame, selectmode=BROWSE, width=36) self.listBox.pack(side="left", fill="both", expand=1, ipadx=4, padx=2, pady=0) self.listBox.bind('<<ListboxSelect>>', self.onSelect) self.listBox.bind("<Double-1>", self._choose) self.modalPane.bind("<Return>", self._choose) self.modalPane.bind("<Escape>", self._cancel) # self.modalPane.bind("<Up>", self.cursorUp) # self.modalPane.bind("<Down>", self.cursorDown) self.fltr.bind("<Up>", self.cursorUp) self.fltr.bind("<Down>", self.cursorDown) scrollBar.config(command=self.listBox.yview) self.listBox.config(yscrollcommand=scrollBar.set) self.setMatching() def ignore(self, e=None): return "break" def onSelect(self, *args): # Note here that Tkinter passes an event object to onselect() if self.listBox.curselection(): firstIndex = self.listBox.curselection()[0] value = self.matches[int(firstIndex)] r = value[1] p = os.path.join(self.prefix, r) if self.new: if os.path.isfile(p): p = os.path.split(p)[0] r = os.path.split(r)[0] f = self.fileName.get() r = os.path.join(r, f) p = os.path.join(p, f) self.selectionValue.set(r) self.value = p return "break" def cursorUp(self, event=None): cursel = int(self.listBox.curselection()[0]) newsel = max(0, cursel - 1) self.listBox.select_clear(cursel) self.listBox.select_set(newsel) self.listBox.see(newsel) self.onSelect() return "break" def cursorDown(self, event=None): cursel = int(self.listBox.curselection()[0]) newsel = min(len(self.list) - 1, cursel + 1) self.listBox.select_clear(cursel) self.listBox.select_set(newsel) self.listBox.see(newsel) self.onSelect() return "break" def setMatching(self, *args): # disabled = "#BADEC3" # disabled = "#91CC9E" disabled = "#62B374" match = self.filterValue.get() if match: self.matches = matches = [ x for x in self.list if x and match.lower() in x[1].lower() ] else: self.matches = matches = self.list self.listBox.delete(0, END) index = 0 init_index = 0 for item in matches: if type(item) is tuple: # only show the label # (label, value, disabled)FF self.listBox.insert(END, item[0]) if self.new: if not item[-1]: self.listBox.itemconfig(index, fg=disabled) else: self.listBox.itemconfig(index, fg="blue") if self.start and item[1] == self.start: init_index = index else: if item[-1]: self.listBox.itemconfig(index, fg=disabled) else: self.listBox.itemconfig(index, fg="blue") if self.start and item[1] == self.start: init_index = index # elif files: else: self.listBox.insert(END, item) index += 1 self.listBox.select_set(init_index) self.listBox.see(init_index) self.fltr.focus_set() self.onSelect() def _choose(self, event=None): try: if self.listBox.curselection(): firstIndex = self.listBox.curselection()[0] if self.new: if not self.value or os.path.isfile(self.value): return else: tup = self.matches[int(firstIndex)] if tup[-1]: return self.value = os.path.join(self.prefix, tup[1]) else: return except IndexError: self.value = None self.modalPane.destroy() def _cancel(self, event=None): self.value = None self.modalPane.destroy() def returnValue(self): self.master.wait_window(self.modalPane) return self.value
class Window2(Frame): def __init__(self, parent, context): super(Window2, self).__init__(parent.Frame) context.add_observer(self) self.parent = parent self.context = context self.controller = parent.controller self._initialize() self.build() def _initialize(self): self.id = 'task' #画面遷移の順番を示す指示物 self.unit_name_list = [] def update(self, msg): self._gid = msg['gid'] self.unit_name_list = _global_group[msg['gid'] - 1] self._update_unit_name_list() self.task_lbx.delete(0, END) def convert(self): units = self._task_box.get(0, END) if not units: self.context.notify('root', 'info', "처리할 작업이 없습니다.") return working_dir = self.context.get('directory') if not working_dir: self.context.directory() working_dir = self.context.get('directory') if not working_dir: messagebox.showwarning("경고", '작업디렉토리가 설정되어 있지 않습니다.') return # html변환여부 체크옵션 _html = self.context.get('html') _gid = self._gid try: self.controller.convert(working_dir, _html, units, _gid) self.context.notify('root', 'info', "작업완료") messagebox.showinfo("알림", message="작업이 완료되었습니다.") except Exception as e: print(e) messagebox.showerror('포맷오류', '잘못된 포맷을 적용하였습니다.') self.context.notify('root', 'info', "작업오류") def build(self): componets = self.component_list() tasks = self.task_list() componets.pack(side="left", fill='y') componets.config(bg='steel blue3') tasks.pack(side='right', fill='both', expand=True) tasks.config(bg='light grey', padx=3) def _update_unit_name_list(self): self._list.delete(0, END) for i, name in enumerate(self.unit_name_list): self._list.insert(i, name) def component_list(self): #sandy brown fr1 = Frame(self) scrollbar = Scrollbar(fr1) scrollbar.pack(side="right", fill="y") self._list = Listbox(fr1, bg="dim grey", fg="white", width=20, yscrollcommand=scrollbar.set) mb1 = Menubutton(fr1, text='선택메뉴', relief='flat', bg='steel blue3') mb1.menu = Menu(mb1, tearoff=0) mb1['menu'] = mb1.menu mb1.menu.add_command(label='등록', command=self.choose_all) mb1.pack(side='bottom') mb1.menu.add_command(label='선택', command=lambda: self._list.select_set(0, END)) mb1.menu.add_command( label='해제', command=lambda: self._list.selection_clear(0, 'end')) self._list.pack(anchor="center", fill="both", expand=True, padx=3, pady=3) scrollbar.config(command=self._list.yview) self._list.config(highlightcolor='green', font=('나눔고딕', 10), activestyle='none', selectmode='extended') self._list.bind('<<ListboxSelect>>', self.select_item) self._list.bind('<Button-3>', self.sub_menu1) self._list.exportselection = 0 return fr1 def select_item(self, event): self.clear_submenu() widget = event.widget #print("select item",widget.curselection()) # if isinstance(widget,Listbox): v = widget.curselection() t = [widget.get(i) for i in v] self.context.notify('root', 'info', t) def clear_submenu(self): if hasattr(self, 'sub_fr'): self.sub_fr.destroy() def _setActivate(self, obj, index): obj.selection_set(index) # obj.see(index) # obj.activate(index) # obj.selection_anchor(index) def sub_menu1(self, event): self.clear_submenu() x, y = event.x, event.y self._setActivate(self._list, self._list.nearest(y)) self.sub_fr = Frame(self, height=10) b1 = Button(self.sub_fr, text='reg', command=self.choose_task, relief='flat') b1.pack(side='top', fill='both') self.sub_fr.place(x=x + 15, y=y) def choose_all(self): self.clear_submenu() for el in self._list.get(0, END): if not self._isduplicate(el): self._task_box.insert(END, el) def choose_task(self): self.clear_submenu() ixs = self._list.curselection() for ix in ixs: el = self._list.get(ix) if not self._isduplicate(el): self._task_box.insert(END, el) def _isduplicate(self, txt): for v in list(self._task_box.get(0, 'end')): if v == txt: return True return False def task_list(self): fr = Frame(self) fr_top = Frame(fr) task_lbx = Listbox(fr_top) task_lbx.pack(anchor="center", fill="both", expand=True, padx=3, pady=3) self._task_box = task_lbx fr_bot = Frame(fr, height='2') b1 = Menubutton(fr_bot, text='실행메뉴') b1.menu = Menu(b1, tearoff=0) b1['menu'] = b1.menu b1.menu.add_command(label='실행', command=self.convert) b1.menu.add_command(label='비우기', command=self.delete_task_item) b1.pack() fr_top.pack(side='top', fill='both', expand=True) fr_bot.pack(side='bottom', fill='x') task_lbx.config(highlightcolor='green', font=('굴림체', 10), activestyle='none', selectmode='extended') self.task_lbx = task_lbx return fr def delete_task_item(self): v = self.task_lbx.curselection() #print(v) if not v: self.task_lbx.delete(0, END) elif len(v) == 1: self.task_lbx.delete(v) else: self.task_lbx.delete(v[0], v[-1])
def initUI(self): self.master.title("Py Docker Interface Manager") #################### # used functions #################### def getDirectories(event): # current directory that we are looking for information.see("end") def systemprune(): message = messagebox.askokcancel( "Warning", "Would you like to perform a system prune?") if message: sysPrune(information) def inspect(): if getWarnings(): for message in getWarnings(): information.insert("end", message, "warning") index = area.curselection() inspectProject(information, area.get(index)) # checking if composer exists information.insert("end", checkIfComposerExists(area.get(index)), "notice") information.see("end") def clearConsole(): message = messagebox.askokcancel("Warning", "Clear the console?") if message: information.delete(1.0, "end") def buildProject(): index = area.curselection() if len(getDockerfiles(area.get(index))) > 1: message = messagebox.askokcancel( "Attention!", "More than one Dockerfiles found. Build all?") if message: buildDockerfiles(information, getDockerfiles(area.get(index)), area.get(index), True) else: buildDockerfiles(information, getDockerfiles(area.get(index)), area.get(index), False) else: buildDockerfiles(information, getDockerfiles(area.get(index)), area.get(index), False) def runProject(): message = messagebox.askokcancel("Attention!", "Start the current project?") if message: index = area.curselection() foldername = area.get(index) runTheProject(information, foldername, checkIfComposerExistsBool(foldername)) def removeContainers(): message = messagebox.askokcancel( "Attention!", "Removing the containers for the current project?") project = area.get(area.curselection()) if message: removeProject(information, project) #################### # sidebar area #################### sidebar = Frame(self.master, width=200, height=500, relief='flat', borderwidth=2) sidebar.pack(expand=False, fill='both', side='right', anchor='ne') ### Inspect Button abtn = Button(sidebar, text="Inspect", command=inspect) abtn.grid(row=0, column=0, pady=2) ### Build button abtn = Button(sidebar, text="Build", command=buildProject) abtn.grid(row=1, column=0, pady=2) ### Run button cbtn = Button(sidebar, text="Run", command=runProject) cbtn.grid(row=2, column=0, pady=2) ### Remove containers button settingsbtn = Button(sidebar, text="Remove", command=removeContainers) settingsbtn.grid(row=3, column=0, pady=2) ### System Prune button cbtn = Button(sidebar, text="Prune", command=systemprune) cbtn.grid(row=4, column=0, pady=2) ### Clear Button hbtn = Button(sidebar, text="Clear", command=clearConsole) hbtn.grid(row=5, column=0, padx=5, pady=2) ### Close button obtn = Button(sidebar, text="Close", command=self.closeWindow) obtn.grid(row=6, column=0, pady=2) #################### # main content area #################### main_content = Frame(self.master, relief='flat') main_content.pack(expand=True, fill='both', side='left') lbl = Label(main_content, text="Projects") lbl.grid(sticky=W, pady=4, padx=5) ### Directories list area = Listbox(main_content, width=60) for directory in getDirs("../"): area.insert(1, directory) area.select_set(0) area.grid(row=1, column=0, rowspan=4, padx=5, sticky=E + W + N + S) area.bind('<ButtonRelease-1>', getDirectories) #information area information = Text(main_content, width=60, height=15) information.tag_config('warning', foreground="red") information.tag_config('notice', foreground="white", background="blue") information.tag_config('inspect', foreground="black", background="lightgray") information.tag_config('danger', foreground="white", background="red") information.grid(row=6, column=0, pady=10, padx=5, sticky=E + W + S + N) #### Output area lb2 = Label(main_content, text="Output >>>") lb2.grid(sticky=W, row=7, column=0, pady=4, padx=5)
class index_select(Frame): def __init__(self,controller,current_model,master,*args,**kwargs): self.controller = controller self.current_model = current_model self.filtered_list = None self.saved_selection = None from tkinter import EXTENDED,Scrollbar,Y #dibujar widget super().__init__(master, *args, **kwargs) f_st=Frame(self) Label(f_st,text="Current_index: ").pack() Label(f_st, text="Current_filter: ").pack() f_st.pack() frame_index_listbox = Frame(self) self.listbox = Listbox(frame_index_listbox, exportselection=False,selectmode=EXTENDED) self.listbox.pack(side=LEFT) scrollbar = Scrollbar(frame_index_listbox) scrollbar.pack(side=LEFT, fill=Y) frame_index_listbox.pack() # attach listbox to scrollbar self.listbox.config(yscrollcommand=scrollbar.set) scrollbar.config(command=self.listbox.yview) f=Frame(self) Label(f,text="Filtro: ").pack(side=LEFT) self.entry_w = Entry(f) self.entry_w.pack(side=LEFT) f.pack() f2=Frame(self) Button(f2, text='Filter',command=self.filter_indexs).pack(side=LEFT) Button(f2,text='Clean Filter',command=self.clean_filter).pack(side=LEFT) Button(f2, text='Export sel for gen',command=self.export_selection).pack(side=LEFT) f2.pack() f3=Frame(self) Button(self, text='<<',command=self.next_prev(-1)).pack(side=LEFT) Button(self, text='>>',command=self.next_prev(1)).pack(side=LEFT) f3.pack() self.update_model(current_model) self.listbox.select_set(0) self.listbox.event_generate("<<ListboxSelect>>") self.listbox.bind('<<ListboxSelect>>', self.selection) def filter_indexs(self): import random path_filter = self.entry_w.get() with open(path_filter,'r') as f: indexs_list_str = f.read().strip() random.seed(3) indexs_list = list(set(indexs_list_str.split('\n'))) print(len(indexs_list)) random.shuffle(indexs_list) self.filtered_list = indexs_list self.listbox.delete(0, END) for item in indexs_list: self.listbox.insert(END, item) def clean_filter(self): self.filtered_list = None self.update_model(self.current_model) self.listbox.delete(0, END) for item in sorted(self.index_list): self.listbox.insert(END, item) self.saved_selection = None def export_selection(self): sel_files_folder = os.path.join('config_files','select_files') os.makedirs(sel_files_folder,exist_ok=True) sel_list = self.listbox.curselection() index_list = [self.listbox.get(ind) for ind in sel_list] print("Exporting list for image generator. List: {0}".format(index_list)) now_s = now_string() out_selection_file = {'index_list' : index_list, 'train_result_path': self.current_model.current_config_file, 'details' : '', 'mask_file' : self.current_model.current_mask_file} sel_file_name = "{0}_{1}_{2}_selection.json".format(self.current_model.classifier_key,self.current_model.dataset_key,now_s) sel_path = os.path.join(sel_files_folder,sel_file_name) with open(sel_path,'w') as f: json.dump(out_selection_file,f) print("Select in {0}".format(sel_path)) def update_model(self, current_model): self.model = current_model self.index_list = self.model.get_index_list() self.current_index = self.model.get_current_index() self.mask_list = self.model.get_current_mask_index_list() indexs_list = self.filtered_list if self.filtered_list else sorted(self.index_list) self.listbox.delete(0, END) for item in indexs_list: self.listbox.insert(END, item) if self.saved_selection: ind,ypos = self.saved_selection self.listbox.selection_set(ind) self.listbox.yview_moveto(ypos[0]) # go back to that position def next_prev(self,x): def selection(): ind_l = self.index_list.index(self.current_index) n = len(self.index_list) n_ind_l = (ind_l+x) % n next = self.index_list[n_ind_l] self.current_index = next self.listbox.selection_clear(0, END) self.listbox.select_set(n_ind_l) self.controller.event_change_index(next) return selection def selection(self,event): w = event.widget index = int(w.curselection()[0]) value = w.get(index) print("v: {0}".format(value)) selected_index = value self.current_index = selected_index self.controller.event_change_index(selected_index) self.saved_selection = (index,self.listbox.yview()) pass
class GridGUI(object): """ tkGridGUI builds a python Tkinter GUI graphic user interface using the grid geometry manager. """ def __init__(self, MainWin): """Inits Tkinter window of GridGUI.""" self.root = MainWin #MainWin.geometry("800x600") #You want the size of the app to be 500x500 MainWin.geometry( '+10+30' ) try: style = Style(self.root) if "win" == platform[:3]: style.theme_use('vista') elif "darwin" in platform: style.theme_use('clam') else: style.theme_use('clam') bg = style.lookup("TLabel", "background") self.root.configure(bg=bg) except: print("OOPS... failed to set style.theme_use... Let's press on.") self.MainWin = MainWin MainWin.protocol('WM_DELETE_WINDOW', self.cleanupOnQuit) MainWin.allow_subWindows_to_close = 0 self.add_menu_to_MainWin() topFrame = Frame( MainWin ) # frame for controls #topFrame = tx.ScrolledWindow( MainWin ) frame1 = LabelFrame(topFrame, text="Widgets") self.place_widget_selection_listbox( frame1 ) frame1.pack(anchor=NW, side=LEFT) frame2 = Frame( topFrame ) # frame for radio buttons self.place_gui_definition_controls( frame2, MainWin ) frame2.pack(anchor=N, side=LEFT) self.grid_frame = Frame(topFrame) self.grid_notebook = NotebookGridDes(self, self.grid_frame, MainWin, num_cols=5, num_rows=8) self.grid_frame.pack(anchor=N, side=LEFT) topFrame.pack(fill=BOTH, expand=Y) # make a Status Bar statframe = Frame(MainWin) MainWin.statusMessage = StringVar() MainWin.statusMessage.set('Welcome to TkGridGUI') self.statusbar = Label(statframe, textvariable=MainWin.statusMessage, relief=SUNKEN, anchor=W) self.statusbar.pack(anchor=SW, fill=X, side=BOTTOM) statframe.pack(anchor=SW, fill=X, side=BOTTOM) # Initialize some GridGUI parameters self.current_fileFullName = '' # no file for now self.current_filePath = '' # no file for now self.current_fileName = '' # no file for now self.target_app = TargetTkAppDef( name='myApp') self.PreviewWin = None # need to initialize later self.Listbox_1_Click( 'FromInit' ) # execute selection logic self.in_reading_mode = False # when True, suppresses some automatic trace actions. if len( sys.argv ) == 2: fName = sys.argv[1] if fName.find('.')<0: fName += '.def' fullpath = os.path.abspath(fName) if os.path.isfile( fullpath ): # if file exists, read it as a definition file self.openFile( fName=fullpath ) else: self.MainWin.statusMessage.set('file "%s" does not exist'%fName) self.grid_notebook.notebook.bind("<<NotebookTabChanged>>", self.tab_of_notebook_changed) self.mouse_location = '' self.MainWin.bind("<Enter>", self.onMainWindowEnter) def onMainWindowEnter(self, event): """Only track Enter... Want last known location.""" #if self.mouse_location != 'main_window': # print('mouse_location = main_window') self.mouse_location = 'main_window' def refresh_preview_win(self, allow_destroy_children=True): """ Place all of the widgets from grid_notebook onto PreviewWin. May need to delete and rebuild current widgets on PreviewWin. """ if self.PreviewWin is None: self.PreviewWin = PreviewWin( self.MainWin, grid_gui=self ) self.target_app.set_PreviewWin( self.PreviewWin ) self.target_app.set_Notebook( self.grid_notebook ) else: if allow_destroy_children: self.PreviewWin.destroy_all_children() self.target_app.destroy_all_preview_widgets() widgetL = self.grid_notebook.make_complete_list_of_widgets() #print("========== PreviewWin Widget Info.") for w in widgetL: #print( w ) (widget_type, widget_name, tab_label, row_target, col_target) = w self.target_app.maybe_add_component( widget_type=widget_type, widget_name=widget_name, tab_label=tab_label, row=row_target, col=col_target) self.target_app.show_preview() #print("="*55) #print('ref crc_reference =',self.target_app.crc_reference, 'current =', self.target_app.get_model_crc() ) def add_menu_to_MainWin(self): # make menus self.menuBar = Menu(self.MainWin, relief = 'raised', bd=2) # create file pulldown menu fileMenu = Menu(self.menuBar, tearoff=0) fileMenu.add('command', label = 'New', command=self.newForm, underline=0,accelerator="Ctrl+N") fileMenu.add('command', label = 'Open', command=self.openFile, underline=0,accelerator="Ctrl+O") fileMenu.add('command', label = 'Save', command=self.saveasFile, underline=0,accelerator="Ctrl+S") #fileMenu.add('command', label = 'SaveAs', command = self.saveasFile) fileMenu.add('command', label = 'Exit', command=self.cleanupOnQuit, underline=0,accelerator="Ctrl+X") self.menuBar.add('cascade', label="File", menu=fileMenu) # create options pulldown menu optMenu = Menu(self.menuBar, tearoff=0) optMenu.add('command', label = 'Font to Clipboard', command =self.FontPickButton_Select, underline=0,accelerator="Ctrl+F") optMenu.add('command', label = 'Color to Clipboard', command = self.ColorPickButton_Select, underline=0,accelerator="Ctrl+C") optMenu.add('command', label = 'Named Color to Clipboard', command = self.NamedColorPickButton_Select, underline=0,accelerator="Ctrl+K") self.menuBar.add('cascade', label="Options", menu=optMenu) # bind accelerator keys (need lambda since functions don't have "event" parameter) self.root.bind("<Control-N>", lambda event: self.newForm()) self.root.bind("<Control-n>", lambda event: self.newForm()) self.root.bind("<Control-O>", lambda event: self.openFile()) self.root.bind("<Control-o>", lambda event: self.openFile()) self.root.bind("<Control-S>", lambda event: self.saveasFile()) self.root.bind("<Control-s>", lambda event: self.saveasFile()) self.root.bind("<Control-X>", lambda event: self.cleanupOnQuit()) self.root.bind("<Control-x>", lambda event: self.cleanupOnQuit()) self.root.bind("<Control-F>", self.FontPickButton_Click) self.root.bind("<Control-f>", self.FontPickButton_Click) self.root.bind("<Control-C>", self.ColorPickButton_Click) self.root.bind("<Control-c>", self.ColorPickButton_Click) self.root.bind("<Control-K>", self.NamedColorPickButton_Click) self.root.bind("<Control-k>", self.NamedColorPickButton_Click) # create About menu self.menuBar.add('command', label="About", command = self.About) # create Help menu self.menuBar.add('command', label="Help", command = self.Help) self.root.config(menu=self.menuBar) def mainOrDialog_Callback(self, varName, index, mode): #print( "mainOrDialog_Callback varName, index, mode",varName, index, mode ) #print( " new StringVar value =",self.MainWin.mainOrDialog.get() ) self.refresh_preview_win() if self.MainWin.mainOrDialog.get() == 'dialog': if self.MainWin.hideOkChkBox_StringVar.get() == "yes": self.PreviewWin.remove_mock_OK_Cancel_Buttons() else: self.PreviewWin.add_mock_OK_Cancel_Buttons() else: self.PreviewWin.remove_mock_OK_Cancel_Buttons() def place_gui_definition_controls(self, frame2, MainWin ): # show option for Main Window or Dialog MainWin.mainOrDialog=StringVar() lbframe = LabelFrame(frame2, text="GUI Type") lbframe.pack(anchor=W) b = Radiobutton(lbframe, text="Main Window", value='main', variable=MainWin.mainOrDialog) b.pack(anchor=W) b = Radiobutton(lbframe, text="Dialog", value='dialog', variable=MainWin.mainOrDialog) b.pack(anchor=W) MainWin.mainOrDialog.set('main') self.mainOrDialog_traceName = MainWin.mainOrDialog.trace_variable("w", self.mainOrDialog_Callback) MainWin.hideOkChkBox = Checkbutton(lbframe, text="Hide OK Btn", width="15") MainWin.hideOkChkBox.pack(anchor=E, side=TOP) MainWin.hideOkChkBox_StringVar = StringVar() MainWin.hideOkChkBox_StringVar.set("no") MainWin.hideOkChkBox.configure(variable=MainWin.hideOkChkBox_StringVar, onvalue="yes", offvalue="no") self.hideOkChkBox_traceName = MainWin.hideOkChkBox_StringVar.trace_variable("w", self.hideOkChkBox_Callback) # show checkbox for menu and status bar lbframe = LabelFrame(frame2, text="Window Options") lbframe.pack(anchor=W) MainWin.menuChkBox = Checkbutton(lbframe, text="Main Menu", width="15") MainWin.menuChkBox.pack(anchor=W, side=TOP) MainWin.menuChkBox_StringVar = StringVar() MainWin.menuChkBox_StringVar.set("no") MainWin.menuChkBox.configure(variable=MainWin.menuChkBox_StringVar, onvalue="yes", offvalue="no") self.menuChkBox_traceName = MainWin.menuChkBox_StringVar.trace_variable("w", self.menuChkBox_Callback) MainWin.statusBarChkBox = Checkbutton(lbframe, text="Status Bar", width="15") MainWin.statusBarChkBox.pack(anchor=W, side=TOP) MainWin.statusBarChkBox_StringVar = StringVar() MainWin.statusBarChkBox_StringVar.set("no") MainWin.statusBarChkBox.configure(variable=MainWin.statusBarChkBox_StringVar, onvalue="yes", offvalue="no") self.statusBarChkBox_traceName = MainWin.statusBarChkBox_StringVar.trace_variable("w", self.statusBarChkBox_Callback) MainWin.resizableChkBox = Checkbutton(lbframe, text="Resizable", width="15") MainWin.resizableChkBox.pack(anchor=W, side=TOP) MainWin.resizableChkBox_StringVar = StringVar() MainWin.resizableChkBox_StringVar.set("yes") MainWin.resizableChkBox.configure(variable=MainWin.resizableChkBox_StringVar, onvalue="yes", offvalue="no") self.resizableChkBox_traceName = MainWin.resizableChkBox_StringVar.trace_variable("w", self.resizableChkBox_Callback) # show choices for standard dialogs lbframe = LabelFrame(frame2, text="Standard Dialogs") lbframe.pack(anchor=W) MainWin.stdDialMessChkBox = Checkbutton(lbframe, text="Messages", width="15") MainWin.stdDialMessChkBox.pack(anchor=E, side=TOP) MainWin.stdDialMessChkBox_StringVar = StringVar() MainWin.stdDialMessChkBox_StringVar.set("no") MainWin.stdDialMessChkBox.configure(variable=MainWin.stdDialMessChkBox_StringVar, onvalue="yes", offvalue="no") MainWin.stdDialColorChkBox = Checkbutton(lbframe, text="Color Choose", width="15") MainWin.stdDialColorChkBox.pack(anchor=E, side=TOP) MainWin.stdDialColorChkBox_StringVar = StringVar() MainWin.stdDialColorChkBox_StringVar.set("no") MainWin.stdDialColorChkBox.configure(variable=MainWin.stdDialColorChkBox_StringVar, onvalue="yes", offvalue="no") MainWin.stdDialFileChkBox = Checkbutton(lbframe, text="File Open/Save", width="15") MainWin.stdDialFileChkBox.pack(anchor=E, side=TOP) MainWin.stdDialFileChkBox_StringVar = StringVar() MainWin.stdDialFileChkBox_StringVar.set("no") MainWin.stdDialFileChkBox.configure(variable=MainWin.stdDialFileChkBox_StringVar, onvalue="yes", offvalue="no") MainWin.stdAlarmChkBox = Checkbutton(lbframe, text="Alarm Handler", width="15") MainWin.stdAlarmChkBox.pack(anchor=E, side=TOP) MainWin.stdAlarmChkBox_StringVar = StringVar() MainWin.stdAlarmChkBox_StringVar.set("no") MainWin.stdAlarmChkBox.configure(variable=MainWin.stdAlarmChkBox_StringVar, onvalue="yes", offvalue="no") # put color picker button self.ColorPickButton = Button(frame2, text="Put Color on Clipboard", width=18) self.ColorPickButton.pack(anchor=W, side=TOP) self.ColorPickButton.bind("<ButtonRelease-1>", self.ColorPickButton_Click) # put color picker button self.ColorPickButton = Button(frame2, text=" --> Named Color", width=18) self.ColorPickButton.pack(anchor=W, side=TOP) self.ColorPickButton.bind("<ButtonRelease-1>", self.NamedColorPickButton_Click) # put Font picker button self.FontPickButton = Button(frame2, text="Put Font on Clipboard", width=18) self.FontPickButton.pack(anchor=W, side=TOP) self.FontPickButton.bind("<ButtonRelease-1>", self.FontPickButton_Click) # put All widgets on notebook #self.PlaceAllWidgetsButton = Button(frame2, text="Debug All Widgets", width=18) #self.PlaceAllWidgetsButton.pack(anchor=W, side=TOP) #self.PlaceAllWidgetsButton.bind("<ButtonRelease-1>", self.PlaceAllWidgetsButton_Click) # append new row or column to current notebook tab add_frame = Frame( frame2 ) self.AddNewRowButton = Button(add_frame, text="Add Row", width=8) self.AddNewRowButton.pack(anchor=W, side=LEFT) self.AddNewRowButton.bind("<ButtonRelease-1>", self.AddNewRowButton_Click) self.AddNewColButton = Button(add_frame, text="Add Col", width=8) self.AddNewColButton.pack(anchor=W, side=LEFT) self.AddNewColButton.bind("<ButtonRelease-1>", self.AddNewColButton_Click) add_frame.pack(anchor=W, side=TOP) # dup_widget_label can be used for set_placement_widget_label, or widget duplication self.dup_widget_label_desc = Label(frame2, width=16) self.dup_widget_label_desc["text" ] = "\nduplicate widget\nand its properties" self.dup_widget_label_desc.pack(anchor=W) self.dup_widget_label = Label(frame2, width=16) self.dup_widget_label["text" ] = "\n\n" self.dup_widget_label["font" ] = ("Courier", 8, "normal") self.dup_widget_label["relief"] = "groove" self.dup_widget_label.pack(anchor=W) self.dup_widget_label_plain_bg = self.dup_widget_label["background"] self.dup_widget_label["background"] = "#FFFACD" # lemonchiffon # Refresh Preview Window #self.PlaceAllWidgetsButton = Button(frame2, text="Refresh Preview", width=18) #self.PlaceAllWidgetsButton.pack(anchor=W, side=TOP) #self.PlaceAllWidgetsButton.bind("<ButtonRelease-1>", self.GeneralDebugButton_Click) def GeneralDebugButton_Click(self, event): self.grid_notebook.repaint_all_labels() self.refresh_preview_win() def AddNewRowButton_Click(self, event): self.grid_notebook.append_row() def AddNewColButton_Click(self, event): self.grid_notebook.append_column() def PlaceAllWidgetsButton_Click(self, event): """As DEBUG TOOL, show all widgets in Notebook""" saved_sel = self.MainWin.placementWidgetType_svar.get() saved_tab = self.grid_notebook.current_tab_label() row = 1 # row_interface col = 1 # col_interface self.grid_notebook.set_current_tab_by_label( "Main" ) for wname, wcolor in CONTROLS: self.MainWin.placementWidgetType_svar.set( wname ) event.widget = self.grid_notebook.interface_gridBoxWidgetD[("Main", row, col)]# row_interface, col_interface self.grid_notebook.onGridBoxClicked( event ) if wname in ContainerControlsL: new_tab_name = wname + "_%i"%(CONTROL_NEXT_NUMBER_D[wname] -1,) self.grid_notebook.set_current_tab_by_label( new_tab_name ) # place some widgets on ContainerControlsL tab if wname == 'RadioGroup': self.MainWin.placementWidgetType_svar.set( "Label" ) event.widget = self.grid_notebook.interface_gridBoxWidgetD[(new_tab_name, 2, 2)]# row_interface, col_interface self.grid_notebook.onGridBoxClicked( event ) for n_radio in range(3): self.MainWin.placementWidgetType_svar.set( "Radiobutton" ) event.widget = self.grid_notebook.interface_gridBoxWidgetD[(new_tab_name, 3+n_radio, 2)]# row_interface, col_interface self.grid_notebook.onGridBoxClicked( event ) else: self.MainWin.placementWidgetType_svar.set( "Button" ) event.widget = self.grid_notebook.interface_gridBoxWidgetD[(new_tab_name, 2, 2)]# row_interface, col_interface self.grid_notebook.onGridBoxClicked( event ) self.MainWin.placementWidgetType_svar.set( "Label" ) event.widget = self.grid_notebook.interface_gridBoxWidgetD[(new_tab_name, 3, 2)]# row_interface, col_interface self.grid_notebook.onGridBoxClicked( event ) self.MainWin.placementWidgetType_svar.set( "Entry" ) event.widget = self.grid_notebook.interface_gridBoxWidgetD[(new_tab_name, 4, 2)]# row_interface, col_interface self.grid_notebook.onGridBoxClicked( event ) # restore notebook to Main tab self.grid_notebook.set_current_tab_by_label( "Main" ) col += 1 if col % 5 == 0: col = 1 row += 1 # Return Listbox_1 selection to original value self.MainWin.placementWidgetType_svar.set( saved_sel ) self.grid_notebook.set_current_tab_by_label( saved_tab ) def set_status_msg(self, msg): self.MainWin.statusMessage.set( msg ) def gray_out_listbox(self, omit_list=None): """if omit_list is None, gray all.""" if omit_list is None: omit_list = [] n = -1 for index, (wname, wcolor) in enumerate(CONTROLS): if wname in omit_list: self.Listbox_1.itemconfig(index, fg="black") n = index else: self.Listbox_1.itemconfig(index, fg="gray") self.Listbox_1.selection_clear(index) if n >= 0: self.Listbox_1.selection_set(n) self.Listbox_1_Click( 'FromGrayOut' ) # event is not used in Listbox_1_Click def restore_black_listbox(self): """Make sure all listbox options show up for all other tabs.""" n = 0 for i in self.Listbox_1.curselection(): n = i break # set to 1st value encountered for index, (wname, wcolor) in enumerate(CONTROLS): self.Listbox_1.itemconfig(index, fg="black") self.Listbox_1.selection_clear(index) self.Listbox_1.selection_set(n) self.Listbox_1_Click( 'FromRestoreBlack' ) # event is not used in Listbox_1_Click def select_preview_tab(self, tab_name_inp): if not self.PreviewWin: self.refresh_preview_win() # make PreviewWin if not already done. tab_comp = self.target_app.compObjD[tab_name_inp] notebook_name = tab_comp.tab_label nb_obj = self.target_app.compObjD[ notebook_name ] # get index of tab on preview_win for itab, (row, col, tab_name, tab_label) in enumerate( nb_obj.tab_nameL ): if tab_name_inp == tab_name: nb_obj.pw_widget.native_widget.select( itab ) #print('grid_gui.tab_of_notebook_changed: set PreviewWin Tab to:', itab) break def tab_of_notebook_changed(self, event): if self.mouse_location == 'preview_win': return # look at the dup widget to see if it's a full widget duplication s_dup = self.dup_widget_label["text"].strip() if s_dup and s_dup.startswith('('): # i.e. widget has a (row,col) position saved_dup_text_on_tab_change = self.dup_widget_label["text"] saved_dup_bg_on_tab_change = self.dup_widget_label["background"] else: saved_dup_text_on_tab_change = '' saved_dup_bg_on_tab_change = '' nb = self.grid_notebook.notebook #i = nb.index(nb.select()) nb_tab_label = nb.tab(nb.select(), "text") #print("GridGUI Notebook Tab Set to:", nb_tab_label ) self.Listbox_1.config( state=NORMAL ) # gray out some listbox options for RadioGroup if nb_tab_label.startswith('RadioGroup'): self.gray_out_listbox( omit_list=("Radiobutton","Label") ) elif nb_tab_label.startswith('Notebook'): #print('=========> Need to add Notebook logic.') self.gray_out_listbox( omit_list=None ) self.set_placement_widget_label( 'Tab' ) self.set_status_msg( "Only Tabs can be added to Notebook" ) else: # Make sure all listbox options show up for all other tabs. self.restore_black_listbox() if saved_dup_text_on_tab_change: self.dup_widget_label["text" ] = saved_dup_text_on_tab_change self.dup_widget_label["background"] = saved_dup_bg_on_tab_change self.dup_widget_label_desc["text" ] = "\nduplicate widget\nand its properties" # Cause PreviewWin to switch to same Tab if nb_tab_label in self.target_app.compObjD: # i.e. the tab is in the TargetTkAppDef w = self.target_app.compObjD[ nb_tab_label ] treeL = w.get_tab_label_tree() #print('New widget tab_label_tree =', treeL ) for name in treeL: if name.startswith('Tab_'): self.select_preview_tab( name ) # nb_tab_label is tab_name def place_widget_selection_listbox(self, frame1): """frame1 in topFrame contains Widgets selection ListBox""" self.MainWin.placementWidgetType_svar=StringVar() self.MainWin.placementWidgetType_svar.set('Button') # Notebooks handled seperately self.Listbox_1 = Listbox(frame1,width=15 ,height=str(len(CONTROLS)), selectmode='single')#, selectmode="extended") self.Listbox_1.bind("<ButtonRelease-1>", self.Listbox_1_Click) for wname, wcolor in CONTROLS: #b = Radiobutton(frame1, text=text, value=cont, variable=self.MainWin.placementWidgetType_svar) #b.pack(anchor=W) #print("inserting wname into Listbox_1 "+wname) self.Listbox_1.insert(END, wname) self.Listbox_1.pack(anchor=W) self.Listbox_1.select_set(0) # make Top Item highlighted def cleanupOnQuit(self): if self.target_app.model_has_changed(): dialog = maybe_save_dialog(self.MainWin, "Save Before Exit?") if (dialog.result is not None) and ( dialog.result['save_file'] == "yes"): self.saveasFile() return else: # ignore any other warnings self.target_app.reset_crc_reference() # for detecting changes to model #print( 'Doing final cleanup before quitting' ) self.MainWin.allow_subWindows_to_close = 1 self.MainWin.destroy() def set_duplication_widget_label(self, label_obj): """Given the widget Label object, set up for making duplicates.""" self.dup_widget_label["text" ] = label_obj["text"] self.dup_widget_label["background"] = label_obj["background"] self.dup_widget_label_desc["text" ] = "\nduplicate widget\nand its properties" def set_placement_widget_label(self, widget_type): """Sets dup_widget_label for a simple Place of widget_type.""" self.dup_widget_label["text" ] = "\n%s\n"%widget_type #self.dup_widget_label["background"] = self.dup_widget_label_plain_bg # "#FFFACD" # lemonchiffon self.dup_widget_label["background"] = CONTROL_COLOR_D[widget_type] self.dup_widget_label_desc["text" ] = "\n\nPlace %s"%widget_type self.grid_notebook.dup_source_widget_name = '' # not a dup_widget_label event so no dup_source_widget_name def Listbox_1_Click(self, event): #click method for component ID=1 val = 'Button' for i in self.Listbox_1.curselection(): val = self.Listbox_1.get(i)# .lower() self.set_status_msg("Selected Widget: "+ val ) self.MainWin.placementWidgetType_svar.set(val) tab_label = self.grid_notebook.current_tab_label() if not tab_label.startswith('Notebook'): # set duplicate widget text and background to indicate normal placement self.set_placement_widget_label( val ) def hideOkChkBox_Callback(self, varName, index, mode): #print( 'Hide OK Button in Dialog =',self.MainWin.hideOkChkBox_StringVar.get(), end="\n") try: self.target_app.setSpecialOption('hideokbutton', self.MainWin.hideOkChkBox_StringVar.get()) except: pass if self.MainWin.hideOkChkBox_StringVar.get() == "yes": self.PreviewWin.remove_mock_OK_Cancel_Buttons() else: self.PreviewWin.add_mock_OK_Cancel_Buttons() def menuChkBox_Callback(self, varName, index, mode): #print( 'make menu =',self.MainWin.menuChkBox_StringVar.get(), end="\n") try: self.target_app.setSpecialOption('hasmenu', self.MainWin.menuChkBox_StringVar.get()) #print('Setting Menu "hasmenu" Option To:',self.MainWin.menuChkBox_StringVar.get()) except: print('WARNING... Failed To Properly Set "hasmenu" Option.') if not self.in_reading_mode: if self.MainWin.menuChkBox_StringVar.get()=='yes' and self.target_app: dialog = Menumaker(self.MainWin, "Define Menu Structure", self.target_app.getSpecialOption('menu')) #print( dialog.result, end="\n") if type(dialog.result) == type({}): add_menu_ctrl_keys = dialog.result.get('add_menu_ctrl_keys','yes') self.target_app.setSpecialOption('add_menu_ctrl_keys', add_menu_ctrl_keys) menuStr = dialog.result.get('menu','').strip() if len( menuStr ) > 0: self.target_app.setSpecialOption('menu',menuStr) #print( 'Recording new Menu Definition', end="\n") if not self.PreviewWin: self.refresh_preview_win() # make PreviewWin if not already done. # delete menuBar if self.MainWin.menuChkBox_StringVar.get()=='no' and self.target_app: if (self.PreviewWin is not None): if self.PreviewWin.menuBar: self.PreviewWin.delete_menu() # create menuBar if self.MainWin.menuChkBox_StringVar.get()=='yes' and self.target_app: if (self.PreviewWin is not None): if self.PreviewWin.menuBar: self.PreviewWin.delete_menu() # delete so menuBar can be recreated menuL = buildMenuSource( self.target_app.getSpecialOption( 'menu' ) ) menuSrcL = getMenuSource( menuL, rootName='self' ) self.PreviewWin.add_menu( menuSrcL ) self.refresh_preview_win() # redraw the form window showing menu state. def statusBarChkBox_Callback(self, varName, index, mode): #print( 'Status Bar =',self.MainWin.statusBarChkBox_StringVar.get(), end="\n") try: self.target_app.setSpecialOption('hasstatusbar', self.MainWin.statusBarChkBox_StringVar.get()) except: pass if not self.PreviewWin: self.refresh_preview_win() # make PreviewWin if not already done. # add statusbar to PreviewWin if self.MainWin.statusBarChkBox_StringVar.get()=='yes' and self.target_app: if (self.PreviewWin is not None): if not self.PreviewWin.statusbar: self.PreviewWin.add_mock_statusbar() # remove statusbar from PreviewWin if self.MainWin.statusBarChkBox_StringVar.get()=='no' and self.target_app: if (self.PreviewWin is not None): if self.PreviewWin.statusbar: self.PreviewWin.remove_mock_statusbar() self.refresh_preview_win() # redraw the form window showing menu state. def resizableChkBox_Callback(self, varName, index, mode): #print( 'Status Bar =',self.MainWin.resizableChkBox_StringVar.get(), end="\n") try: self.target_app.setSpecialOption('resizable', self.MainWin.resizableChkBox_StringVar.get()) except: pass self.refresh_preview_win() # redraw the form window showing menu state. def ColorPickButton_Click(self, event): #put selected color on clipboard self.ColorPickButton_Select() def ColorPickButton_Select(self): #put selected color on clipboard self.set_status_msg('Place Selected Color on Clipboard') ctup,cstr = tkinter.colorchooser.askcolor(title='Place Selected Color on Clipboard') if cstr != None: self.set_status_msg('%s is on Clipboard'%cstr) self.ColorPickButton.clipboard_clear() self.ColorPickButton.clipboard_append(cstr) #print( 'color chosen=',cstr, end="\n") def NamedColorPickButton_Click(self, event): #put selected color on clipboard self.NamedColorPickButton_Select() def NamedColorPickButton_Select(self): #put selected color on clipboard self.set_status_msg('Place Named Color on Clipboard') dialog = named_color_picker(self.MainWin, title="Place Named Color on Clipboard") if dialog.result is not None: (_, _, _, _, _, _, cstr, name) = dialog.result["named_color"] self.set_status_msg('%s %s is on Clipboard'%(name, cstr) ) self.ColorPickButton.clipboard_clear() self.ColorPickButton.clipboard_append(cstr) def FontPickButton_Click(self, event): self.FontPickButton_Select() def FontPickButton_Select(self): self.set_status_msg('Place Selected Font on Clipboard') dialog = get_cross_platform_font(self.MainWin, title="Get Font") if dialog.result is not None: font_str = dialog.result['full_font_str'] # for example: Comic\ Sans\ MS 20 bold roman self.set_status_msg('%s is on Clipboard'%font_str) self.ColorPickButton.clipboard_clear() self.ColorPickButton.clipboard_append(font_str) #print( 'font chosen=',font_str, end="\n") def Help(self): usage = """ Basic Usage: Select Widget in Listbox with Left Click. Place Widget with Left Click in grid. Edit Widget: Right Click Widget in Grid or Preview Window. Move Widget: Left Button Drag and Drop in Grid. Duplicate Widget: Left Click Widget in Grid. Left Click in grid to place the duplicate. Insert Row or Column Left Click on "+" control. Add Weight to row or column Left Click "wt" control. Container Widgets Select Grid Tab for Main, Frames, RadioGroups etc. """ myshowinfo(self.MainWin, title="Help for TkGridGUI", dialogOptions={'info':usage, 'bg':'#EAFFFE'}) def About(self): tkinter.messagebox.showinfo( "About TkGridGUI v(%s)"%__version__, "TkGridGUI v(%s) is:\n\n"%__version__+\ "A quick approach to\n"+\ "building Tkinter applications.\n"+\ "Written by Charlie Taylor\n" ) def newForm(self): #print( "New Form" ) if self.target_app.model_has_changed(): dialog = maybe_save_dialog(self.MainWin, "Save Current File?") if (dialog.result is not None) and ( dialog.result['save_file'] == "yes" ): self.saveasFile() return self.current_fileFullName = '' # no file for now # leave path alone... self.current_filePath = '' # no file for now self.current_fileName = '' # no file for now self.MainWin.title( 'TkGridGUI: ' + self.current_fileName ) if self.PreviewWin: self.PreviewWin.delete_menu() self.PreviewWin.remove_mock_statusbar() self.target_app.reinitialize() self.grid_notebook.initialize_NotebookGridDes() self.grid_notebook.notebook.bind("<<NotebookTabChanged>>", self.tab_of_notebook_changed) self.refresh_preview_win() # ignore any other warnings self.target_app.reset_crc_reference() # for detecting changes to model def openFile(self, fName=None): #print( 'Open File' ) if self.target_app.model_has_changed(): dialog = maybe_save_dialog(self.MainWin, "Save Current File?") if (dialog.result is not None) and (dialog.result['save_file'] == "yes"): self.saveasFile() return else: # ignore any other warnings self.target_app.reset_crc_reference() # for detecting changes to model self.in_reading_mode = True # when True, suppresses some automatic trace actions. if fName is None: if self.current_filePath: initialdir = self.current_filePath else: initialdir = '.' filetypes = [ ('tkGridGUI definition','*.def'), ('Any File','*.*')] self.pathopen = tkinter.filedialog.askopenfilename(parent=self.MainWin, title='Open tkGridGUI file', filetypes=filetypes, initialdir=initialdir) #print('self.pathopen =',self.pathopen) else: self.pathopen = os.path.abspath(fName) if self.pathopen: self.newForm() # clean up any leftovers from another job full_fname = os.path.abspath( self.pathopen ) head,tail = os.path.split( full_fname ) self.current_fileFullName = full_fname self.current_filePath = head self.current_fileName = tail self.target_app.readAppDefFile( self.pathopen ) #'hasmenu':'no', self.MainWin.menuChkBox_StringVar.set( self.target_app.getSpecialOption( 'hasmenu' ) ) #'hasstatusbar':'no', self.MainWin.statusBarChkBox_StringVar.set( self.target_app.getSpecialOption( 'hasstatusbar' ) ) #'resizable':'no' self.MainWin.resizableChkBox_StringVar.set( self.target_app.getSpecialOption( 'resizable' ) ) #'hideokbutton':'no' self.MainWin.hideOkChkBox_StringVar.set( self.target_app.getSpecialOption( 'hideokbutton' ) ) #'guitype':'main', self.MainWin.mainOrDialog.set( self.target_app.getSpecialOption( 'guitype' ) ) #'hasstddialmess':'no', self.MainWin.stdDialMessChkBox_StringVar.set( self.target_app.getSpecialOption( 'hasstddialmess' ) ) #'hasstddialcolor':'no', self.MainWin.stdDialColorChkBox_StringVar.set( self.target_app.getSpecialOption( 'hasstddialcolor' ) ) #'hasstddialfile':'no', self.MainWin.stdDialFileChkBox_StringVar.set( self.target_app.getSpecialOption( 'hasstddialfile' ) ) #'hasstdalarm':'no', self.MainWin.stdAlarmChkBox_StringVar.set( self.target_app.getSpecialOption( 'hasstdalarm' ) ) #for key,val in self.target_app.app_attrD.items(): # print('%20s %s'%(key, str(val).replace('\t',' '))) widgetL = [(c.widget_type, widget_name, c.tab_label, c.row, c.col) for widget_name,c in list(self.target_app.compObjD.items())] self.grid_notebook.set_complete_list_of_widgets( widgetL ) if not self.PreviewWin: self.refresh_preview_win() # make PreviewWin if not already done. # maybe create menuBar if self.MainWin.menuChkBox_StringVar.get()=='yes' and self.target_app: if (self.PreviewWin is not None): if self.PreviewWin.menuBar: self.PreviewWin.delete_menu() # delete so menuBar can be recreated menuL = buildMenuSource( self.target_app.getSpecialOption( 'menu' ) ) menuSrcL = getMenuSource( menuL, rootName='self' ) self.PreviewWin.add_menu( menuSrcL ) # maybe add statusbar to PreviewWin if self.MainWin.statusBarChkBox_StringVar.get()=='yes' and self.target_app: if (self.PreviewWin is not None): if not self.PreviewWin.statusbar: self.PreviewWin.add_mock_statusbar() if self.PreviewWin: w = self.target_app.getSpecialOption( 'width' ) h = self.target_app.getSpecialOption( 'height' ) x = self.target_app.getSpecialOption( 'x' ) y = self.target_app.getSpecialOption( 'y' ) if self.PreviewWin.statusbar: y += 30 self.PreviewWin.geometry( '%ix%i+%i+%i'%(w,h,x,y)) #self.PreviewWin.geometry( '' ) # allow to resize after set to x,y self.PreviewWin.update_idletasks() self.MainWin.title( 'TkGridGUI: ' + self.current_fileName ) self.target_app.reset_crc_reference() # for detecting changes to model self.in_reading_mode = False # when True, suppresses some automatic trace actions. self.refresh_preview_win() # redraw the form window showing menu state self.grid_notebook.notebook.bind("<<NotebookTabChanged>>", self.tab_of_notebook_changed) def saveasFile(self): #print( 'Save File to Disk' ) self.set_status_msg('Save File to Disk') filetypes = [ ('TkGridGUI','*.def'), ('Any File','*.*')] if self.current_fileName: fname = self.current_fileName else: fname = '' if self.current_filePath: initialdir = self.current_filePath else: initialdir = '.' fsave = tkinter.filedialog.asksaveasfilename(parent=self.MainWin, title='Saving TkGridGUI Definition File', initialfile=fname, filetypes=filetypes, initialdir=initialdir) if fsave: if not fsave.lower().endswith('.def'): fsave += '.def' full_fname = os.path.abspath( fsave ) head,tail = os.path.split( full_fname ) self.current_fileFullName = full_fname self.current_filePath = head self.current_fileName = tail # set values in target_app #'hasmenu':'no', self.target_app.setSpecialOption( 'hasmenu', self.MainWin.menuChkBox_StringVar.get() ) #'hasstatusbar':'no', self.target_app.setSpecialOption( 'hasstatusbar' , self.MainWin.statusBarChkBox_StringVar.get() ) #'resizable':'no' self.target_app.setSpecialOption( 'resizable', self.MainWin.resizableChkBox_StringVar.get() ) #'guitype':'main', self.target_app.setSpecialOption( 'guitype', self.MainWin.mainOrDialog.get() ) #'hideokbutton':'no' self.target_app.setSpecialOption( 'hideokbutton', self.MainWin.hideOkChkBox_StringVar.get() ) #'hasstddialmess':'no', self.target_app.setSpecialOption( 'hasstddialmess', self.MainWin.stdDialMessChkBox_StringVar.get() ) #'hasstddialcolor':'no', self.target_app.setSpecialOption( 'hasstddialcolor', self.MainWin.stdDialColorChkBox_StringVar.get() ) #'hasstddialfile':'no', self.target_app.setSpecialOption( 'hasstddialfile', self.MainWin.stdDialFileChkBox_StringVar.get() ) #'hasstdalarm':'no', self.target_app.setSpecialOption( 'hasstdalarm', self.MainWin.stdAlarmChkBox_StringVar.get() ) # first save *.def file if self.target_app.saveAppDefFile( savePathName=self.current_fileFullName ): # if that goes OK, then save *.py file self.MainWin.title( 'TkGridGUI: ' + self.current_fileName ) sf = FormSource( self.target_app, self.MainWin, self ) sf.saveToFile() # save *.py file head, tail = os.path.split( sf.sourceFile.pathopen ) self.set_status_msg('Saved File: "%s" and "%s" in "%s"'%(self.current_fileName, tail, head) ) self.target_app.reset_crc_reference() # for detecting changes to model else: self.set_status_msg("WARNING... *.def file save failed. NO SAVE PERFORMED.")
class HoursBankGUI(): def __init__(self, window): # define the window self.window = window window.title("Hours Management Tool") # define the size of the main window window.geometry('{}x{}'.format(700, 500)) self.window.grid_rowconfigure(1, weight=1) self.window.grid_columnconfigure(0, weight=1) # pretends the window from being resized self.window.resizable(0, 0) # font test # appHighlightFont = font.Font(family='Helvetica', size=12, weight='bold') # define the panels ############################################################################## # LEFT PANEL # This panel houses the list box which allows the user to select the employee self.leftFrame = Frame(self.window, bg="white", width=300, height=500, pady=3, borderwidth=1, relief="solid") self.leftFrame.grid(row=0, sticky="nsw") # keep the frame the same size even if the widgets chnage size self.leftFrame.grid_propagate(False) # label self.listLabel = Label(self.leftFrame, text="Select User", bg="white", font="Ariel") self.listLabel.grid(row=0, sticky="nwe") # Listbox self.list_box = Listbox(self.leftFrame, width=23, height=18, bg="white", font=("Ariel", 14)) self.list_box.grid(row=1, sticky="wes", padx=10, pady=20) # scroll Bar self.scrollbar = Scrollbar(self.leftFrame) self.list_box.config(yscrollcommand=self.scrollbar.set) self.scrollbar.config(command=self.list_box.yview) self.scrollbar.grid(column=2, row=1, sticky="ns") # fire an event when a employee in the list box is selected self.list_box.bind('<<ListboxSelect>>', self.showDetailsLive) # RIGHT PANEL TOP # When a user clicks on an employee in the employee list box then their details will be shown in the panel self.rightFrame1 = Frame(self.window, bg="white", width=400, height=300, relief="solid", borderwidth=1, padx=20, pady=5) self.rightFrame1.grid(row=0, sticky="ne") # keep the frame the same size even if the widgets change size self.rightFrame1.grid_propagate(False) # Label Widgets for the right top Frame self.details_title = Label(self.rightFrame1, text="Employee Details", font="Ariel", bg="white") self.details_title.grid(row=0, column=0, columnspan=4, sticky="nw") self.name_label = Label(self.rightFrame1, text="Name", font="Arial", bg="white") self.name_label.grid(row=3, column=1, sticky="w") self.ID_label = Label(self.rightFrame1, text="ID", font="Arial", bg="white") self.ID_label.grid(row=2, column=1, sticky="w") self.Rate_label = Label(self.rightFrame1, text="Rate", font="Arial", bg="white") self.Rate_label.grid(row=4, column=1, sticky="w") self.Hol_Rate_label = Label(self.rightFrame1, text="Holiday Rate", font="Arial", bg="white") self.Hol_Rate_label.grid(row=5, column=1, sticky="w") self.Banked_Hours_label = Label(self.rightFrame1, text="Banked Hours", font="Arial", bg="white") self.Banked_Hours_label.grid(row=6, column=1, sticky="w") self.Banked_Salary_label = Label(self.rightFrame1, text="Banked Salary", font="Arial", bg="white") self.Banked_Salary_label.grid(row=7, column=1, sticky="w") # RIGHT BOTTOM PANEL # This panel contains the buttons the user can select to perform operations on the employees data self.rightFrame2 = Frame(self.window, bg="white", width=400, height=200) self.rightFrame2.grid(row=0, sticky="se") # organises the grid of the panel to look good self.rightFrame2.grid_propagate( False) #Stops the frame resizing to widget self.rightFrame2.grid_columnconfigure(0, weight=1) self.rightFrame2.grid_columnconfigure(1, weight=1) self.rightFrame2.grid_rowconfigure(0, weight=1) self.rightFrame2.grid_rowconfigure(1, weight=1) self.rightFrame2.grid_rowconfigure(2, weight=1) # Define the buttons of the bottom right panel self.add_user_button = Button(self.rightFrame2, text="New Employee", font="Arial", relief="groove", command=self.addTodB) self.add_user_button.grid(row=0, column=0, sticky="nsew") self.add_hours_button = Button(self.rightFrame2, text="Add Hours", font="Arial", relief="groove", command=lambda: self.ChangeHours(False)) self.add_hours_button.grid(row=0, column=1, sticky="nsew") self.delete_employee_button = Button(self.rightFrame2, text="Delete Employee", relief="groove", font="Arial", command=self.deleteUser) self.delete_employee_button.grid(row=1, column=0, sticky="nsew") self.edit_user_info_bt = Button(self.rightFrame2, text="Edit Employee", relief="groove", font="Arial", command=self.editEmployeeDetials) self.edit_user_info_bt.grid(row=1, column=1, sticky="nsew") self.remove_hours_btn = Button(self.rightFrame2, text="Remove Hours", relief="groove", font="Arial", command=lambda: self.ChangeHours(True)) self.remove_hours_btn.grid(row=2, column=0, sticky="nsew") self.number = 0 # check if there are any employees in the database # if there is not then display no employees in the list list_box # If there are then display the employees dbList = dbFunctionsV2.getAllUsers() print(dbList) if len(dbList) > 0: # lets get a list of employees and display them self.viewAll() self.list_box.selection_set(0) self.showDetails(self.list_box.curselection()[0]) else: self.list_box.insert(END, "No Employees in Database") # When a item in the list is clicked then show the data in the RIGHT TOP FRAME def showDetailsLive(self, event): # get list item number index = self.list_box.curselection()[0] # pass to showDetails function self.showDetails(index) # gets the information of the employee selected in the listbox and loads it into the right panel def showDetails(self, index): #get tme employee details from the selection name = self.names[index] ID = self.IDs[index] rate = self.rates[index] hol_rate = self.hol_rate[index] banked_hours = self.banked_hours[index] banked_salary = round(self.banked_salary[index], 2) #note event is passed but is not needed print("Hello dynamic label") try: # if the labels have already been created than destroy them so that another employees details can be # displayed self.employee_name.destroy() self.employee_ID.destroy() self.employee_rate.destroy() self.employee_hol_rate.destroy() self.employee_banked_hours.destroy() self.employee_banked_salary.destroy() print("Destroyed") # Now display the newly selected employees details in the right top panel # name self.employee_name = Label(self.rightFrame1, text=name, font="Ariel", bg="white") self.employee_name.grid(row=3, column=2, sticky="w") # ID self.employee_ID = Label(self.rightFrame1, text=ID, font="Ariel", bg="white") self.employee_ID.grid(row=2, column=2, sticky="w") # Rate self.employee_rate = Label(self.rightFrame1, text="£ {} per hour".format(rate), font="Ariel", bg="white") self.employee_rate.grid(row=4, column=2, sticky="w") # holiday Hours self.employee_hol_rate = Label( self.rightFrame1, text="£ {} per hour".format(hol_rate), font="Ariel", bg="white") self.employee_hol_rate.grid(row=5, column=2, sticky="w") # non holiday hours self.employee_banked_hours = Label(self.rightFrame1, text=banked_hours, font="Ariel", bg="white") self.employee_banked_hours.grid(row=6, column=2, sticky="w") # total hours self.employee_banked_salary = Label( self.rightFrame1, text="£ {}".format(banked_salary), font="Ariel", bg="white") self.employee_banked_salary.grid(row=7, column=2, sticky="w") except: # If it the first employee to be selected since the program was opened then you do not need to deastroy the # labels print("First Time") # name self.employee_name = Label(self.rightFrame1, text=name, font="Ariel", bg="white") self.employee_name.grid(row=3, column=2, sticky="w") # ID self.employee_ID = Label(self.rightFrame1, text=ID, font="Ariel", bg="white") self.employee_ID.grid(row=2, column=2, sticky="w") # Rate self.employee_rate = Label(self.rightFrame1, text="£ {} per hour".format(rate), font="Ariel", bg="white") self.employee_rate.grid(row=4, column=2, sticky="w") # holiday Hours self.employee_hol_rate = Label( self.rightFrame1, text="£ {} per hour".format(hol_rate), font="Ariel", bg="white") self.employee_hol_rate.grid(row=5, column=2, sticky="w") # non holiday hours self.employee_banked_hours = Label(self.rightFrame1, text=banked_hours, font="Ariel", bg="white") self.employee_banked_hours.grid(row=6, column=2, sticky="w") # total hours self.employee_banked_salary = Label( self.rightFrame1, text="£ {}".format(banked_salary), font="Ariel", bg="white") self.employee_banked_salary.grid(row=7, column=2, sticky="w") # When a window that has been previously called by the user e.g. new employee has been closed this function is # called. It grabs all the employees from the database and displays them in the list box (especially good if a new # employee has just been added). It then sets the previous selection in the listbox to the current selction and # grabs the data from the database and displays it in the top right panel def destroyTest(self, event): print("Testing Destroyed") self.viewAll() # self.showDetails(True) self.showDetails(self.currentSelectionIndex) self.list_box.select_set(self.currentSelectionIndex) # This function calls to the database and gets all the employee data from the database. It then puts thsi information # into lists, it then creates a list of lists and returns that to the caller def getLatestData(self): usersList = dbFunctionsV2.getAllUsers() self.names = [] self.IDs = [] self.rates = [] self.hol_rate = [] self.banked_hours = [] self.banked_salary = [] # put that into some List for a in usersList: self.names.append(a[1]) self.IDs.append(a[0]) self.rates.append(a[2]) self.hol_rate.append(a[3]) self.banked_hours.append(a[4]) self.banked_salary.append(a[5]) return (self.names, self.IDs, self.rates, self.hol_rate, self.banked_hours, self.banked_salary) # This function displays all the employees in the database into the list box def viewAll(self): # clear the list first self.list_box.delete(0, END) # get a list of the users from the database self.getLatestData() # the emumerate function gets the index from the list value, this index # is then used to get the corresponding ID value # This loop puts the employee name and ID into the list box for the user to select for (i, e) in enumerate(self.names): self.list_box.insert(END, "{} {}".format(self.IDs[i], e)) # function that was used for some basic testing def add(self): self.number = self.number + 1 #print(self.number) # function that was used for some basic testing def printNumber(self): return self.number # This function is called when the new Employee button is pressed in the bottom right panel def addTodB(self): # Get the value from the list_box selected = self.list_box.curselection() if selected: print(selected) for index in selected: print(self.list_box.get(index)) name = self.list_box.get(index) else: name = "No Name" print("Open New Window") # Toplevel creates a window dependent on the Tk window root = Toplevel(self.window) # creates an instance of the UGUI class which opens the window to add an new employee userUpdateGUI = UGUI(root, name) # When the new employee window is closed the destroyNewUserWindow function is called root.bind("<Destroy>", self.destroyNewUserWindow) # When the add new employee window is closed this function is called # It selects the last employee in the listbox, which should be the new user and then shows their details def destroyNewUserWindow(self, message): self.viewAll() # self the last last item in the list which is the new users self.list_box.selection_set(len(self.names) - 1) print(len(self.names)) self.showDetails(self.list_box.curselection()[0]) # This functions deletes the employee that is selected in the listbox def deleteUser(self): print("Are you sure???") # get the ID of the current employee selected currentID = str(self.IDs[self.list_box.curselection()[0]]) # check is the user meant to hit the cancel button answer = messagebox.askyesno( "Delete", "Are you user you want to delete employee {}?".format(currentID)) # if the user does not want to delete the user than exit without deleting if not answer: return # call the database delete function passing the employee to be deleted ID dbFunctionsV2.deleteUser(currentID) # display the updated list of employees self.viewAll() # if there are no employees left in the database need to blank the details labels in the # right top panel print("Length of ID Array: ", len(self.IDs)) if len(self.IDs) == 0: self.employee_name.destroy() self.employee_ID.destroy() self.employee_rate.destroy() self.employee_hol_rate.destroy() self.employee_banked_hours.destroy() self.employee_banked_salary.destroy() else: # select first item in list self.list_box.selection_set(0) # show data for current selection self.showDetails(self.list_box.curselection()[0]) # this function is called when the employee details are to be editted def editEmployeeDetials(self): # get the details of the current selected employee BankedHours = float(self.banked_hours[self.list_box.curselection()[0]]) BankedSalary = float( self.banked_salary[self.list_box.curselection()[0]]) currentID = self.IDs[self.list_box.curselection()[0]] rate = float(self.rates[self.list_box.curselection()[0]]) hol_rate = float(self.hol_rate[self.list_box.curselection()[0]]) currentName = self.names[self.list_box.curselection()[0]] root = Toplevel(self.window) # create an instance of the editEmployeeDetails class and pass the employees details to it # this will launch an edit employee window for the user newWindow = editEmployeeDetails(root, currentID, currentName, rate, hol_rate) # save the position of the current selected employee in the list box self.currentSelectionIndex = self.list_box.curselection()[0] # When the window for the edit employee is closed run detroyTest function root.bind("<Destroy>", self.destroyTest) def finish(self): self.window.destroy() # this function is called when the user wants to add or subtract hours from the employees Hours Bank. # when the add hours button is pressed this function is called with remove = False, if the remove hours # button is pressed then remove = True. def ChangeHours(self, remove): # get the data for the selected employee BankedHours = float(self.banked_hours[self.list_box.curselection()[0]]) BankedSalary = float( self.banked_salary[self.list_box.curselection()[0]]) currentID = self.IDs[self.list_box.curselection()[0]] rate = float(self.rates[self.list_box.curselection()[0]]) hol_rate = float(self.hol_rate[self.list_box.curselection()[0]]) #if remove True then remove hours, if false then add hours # open a new window root = Toplevel(self.window) # create an instance of the class ChnageHoursWindow where the change hours window is launched ChangeHours = ChangeHoursWindow(root, BankedHours, BankedSalary, currentID, rate, hol_rate, remove) # have the slection in the list box that the user make` self.currentSelectionIndex = self.list_box.curselection()[0] # when the window to change hours is destroyed run the destroyTest function root.bind("<Destroy>", self.destroyTest)
class ChooseFilesPage(Frame): """Page for output files choice""" def __init__(self, parent, controller, *files): """ Arguments: `parent` (Frame): Parent page `controller` (Tk): Main controller page `files` (list): Available .out files """ super().__init__(parent) self.controller = controller self.files = sorted(files[0][0]) self.init_UI() # Create main GUI window def init_UI(self): txt = "Select the file(s) you want to post-process" label = Label(self, text=txt, font=LARGE_FONT) label.grid(row=0, columnspan=2, sticky='w') label_entry = Label(self, text='Filter:') label_entry.grid(row=1, column=0, sticky='w') self.search_var = StringVar() self.search_var.trace("w", lambda name, index, mode: self.update_list()) self.entry = Entry(self, textvariable=self.search_var, width=13) self.entry.grid(row=1, column=1, sticky='w') self.lbox = Listbox(self, width=45, height=15, selectmode='multiple') self.lbox.grid(row=2, columnspan=2) bu = ttk.Button(self, text='Select all', command=self.select_all) bu.grid(row=3, columnspan=2, sticky='w') bu = ttk.Button(self, text='Unselect all', command=self.unselect_all) bu.grid(row=4, columnspan=2, sticky='w') txt = "Display selected files" # Command allowing comunication to controller (Tk), calling # raise_displayer_files method with selected files in self.data cmd = partial(self.controller.raise_displayer_files) bu = ttk.Button(self, text=txt, command=cmd) bu.grid(row=5, columnspan=2, sticky='w') # update_list needs to be called here to populate the listbox self.update_list() def update_list(self): """ Update the list while doing the search with the filter Warning: the selection is reset when the listbox is updated! """ search_term = self.search_var.get() # Generic list to populate the listbox lbox_list = self.files self.lbox.delete(0, END) for item in lbox_list: if search_term.lower() in item.lower(): self.lbox.insert(END, item) def select_all(self): """Select all the file names""" self.lbox.select_set(0, END) def unselect_all(self): """Unselect all the file names""" self.lbox.select_clear(0, END)
class LintGui(object): """Build and control a window to interact with pylint""" def __init__(self, root=None): """init""" self.root = root or Tk() self.root.title('Pylint') #reporter self.reporter = None #message queue for output from reporter self.msg_queue = queue.Queue() self.msgs = [] self.visible_msgs = [] self.filenames = [] self.rating = StringVar() self.tabs = {} self.report_stream = BasicStream(self) #gui objects self.lb_messages = None self.showhistory = None self.results = None self.btnRun = None self.information_box = None self.convention_box = None self.refactor_box = None self.warning_box = None self.error_box = None self.fatal_box = None self.txtModule = None self.status = None self.msg_type_dict = None self.init_gui() def init_gui(self): """init helper""" #setting up frames top_frame = Frame(self.root) mid_frame = Frame(self.root) radio_frame = Frame(self.root) res_frame = Frame(self.root) msg_frame = Frame(self.root) check_frame = Frame(self.root) history_frame = Frame(self.root) btn_frame = Frame(self.root) rating_frame = Frame(self.root) top_frame.pack(side=TOP, fill=X) mid_frame.pack(side=TOP, fill=X) history_frame.pack(side=TOP, fill=BOTH, expand=True) radio_frame.pack(side=TOP, fill=BOTH, expand=True) rating_frame.pack(side=TOP, fill=BOTH, expand=True) res_frame.pack(side=TOP, fill=BOTH, expand=True) check_frame.pack(side=TOP, fill=BOTH, expand=True) msg_frame.pack(side=TOP, fill=BOTH, expand=True) btn_frame.pack(side=TOP, fill=X) # Binding F5 application-wide to run lint self.root.bind('<F5>', self.run_lint) #Message ListBox rightscrollbar = Scrollbar(msg_frame) rightscrollbar.pack(side=RIGHT, fill=Y) bottomscrollbar = Scrollbar(msg_frame, orient=HORIZONTAL) bottomscrollbar.pack(side=BOTTOM, fill=X) self.lb_messages = Listbox(msg_frame, yscrollcommand=rightscrollbar.set, xscrollcommand=bottomscrollbar.set, bg="white") self.lb_messages.bind("<Double-Button-1>", self.show_sourcefile) self.lb_messages.pack(expand=True, fill=BOTH) rightscrollbar.config(command=self.lb_messages.yview) bottomscrollbar.config(command=self.lb_messages.xview) #History ListBoxes rightscrollbar2 = Scrollbar(history_frame) rightscrollbar2.pack(side=RIGHT, fill=Y) bottomscrollbar2 = Scrollbar(history_frame, orient=HORIZONTAL) bottomscrollbar2.pack(side=BOTTOM, fill=X) self.showhistory = Listbox(history_frame, yscrollcommand=rightscrollbar2.set, xscrollcommand=bottomscrollbar2.set, bg="white") self.showhistory.pack(expand=True, fill=BOTH) rightscrollbar2.config(command=self.showhistory.yview) bottomscrollbar2.config(command=self.showhistory.xview) self.showhistory.bind('<Double-Button-1>', self.select_recent_file) self.set_history_window() #status bar self.status = Label(self.root, text="", bd=1, relief=SUNKEN, anchor=W) self.status.pack(side=BOTTOM, fill=X) #labelbl_ratingls lbl_rating_label = Label(rating_frame, text='Rating:') lbl_rating_label.pack(side=LEFT) lbl_rating = Label(rating_frame, textvariable=self.rating) lbl_rating.pack(side=LEFT) Label(mid_frame, text='Recently Used:').pack(side=LEFT) Label(top_frame, text='Module or package').pack(side=LEFT) #file textbox self.txt_module = Entry(top_frame, background='white') self.txt_module.bind('<Return>', self.run_lint) self.txt_module.pack(side=LEFT, expand=True, fill=X) #results box rightscrollbar = Scrollbar(res_frame) rightscrollbar.pack(side=RIGHT, fill=Y) bottomscrollbar = Scrollbar(res_frame, orient=HORIZONTAL) bottomscrollbar.pack(side=BOTTOM, fill=X) self.results = Listbox(res_frame, yscrollcommand=rightscrollbar.set, xscrollcommand=bottomscrollbar.set, bg="white", font="Courier") self.results.pack(expand=True, fill=BOTH, side=BOTTOM) rightscrollbar.config(command=self.results.yview) bottomscrollbar.config(command=self.results.xview) #buttons Button(top_frame, text='Open', command=self.file_open).pack(side=LEFT) Button(top_frame, text='Open Package', command=(lambda: self.file_open(package=True))).pack(side=LEFT) self.btnRun = Button(top_frame, text='Run', command=self.run_lint) self.btnRun.pack(side=LEFT) Button(btn_frame, text='Quit', command=self.quit).pack(side=BOTTOM) #radio buttons self.information_box = IntVar() self.convention_box = IntVar() self.refactor_box = IntVar() self.warning_box = IntVar() self.error_box = IntVar() self.fatal_box = IntVar() i = Checkbutton(check_frame, text="Information", fg=COLORS['(I)'], variable=self.information_box, command=self.refresh_msg_window) c = Checkbutton(check_frame, text="Convention", fg=COLORS['(C)'], variable=self.convention_box, command=self.refresh_msg_window) r = Checkbutton(check_frame, text="Refactor", fg=COLORS['(R)'], variable=self.refactor_box, command=self.refresh_msg_window) w = Checkbutton(check_frame, text="Warning", fg=COLORS['(W)'], variable=self.warning_box, command=self.refresh_msg_window) e = Checkbutton(check_frame, text="Error", fg=COLORS['(E)'], variable=self.error_box, command=self.refresh_msg_window) f = Checkbutton(check_frame, text="Fatal", fg=COLORS['(F)'], variable=self.fatal_box, command=self.refresh_msg_window) i.select() c.select() r.select() w.select() e.select() f.select() i.pack(side=LEFT) c.pack(side=LEFT) r.pack(side=LEFT) w.pack(side=LEFT) e.pack(side=LEFT) f.pack(side=LEFT) #check boxes self.box = StringVar() # XXX should be generated report = Radiobutton( radio_frame, text="Report", variable=self.box, value="Report", command=self.refresh_results_window) raw_met = Radiobutton( radio_frame, text="Raw metrics", variable=self.box, value="Raw metrics", command=self.refresh_results_window) dup = Radiobutton( radio_frame, text="Duplication", variable=self.box, value="Duplication", command=self.refresh_results_window) ext = Radiobutton( radio_frame, text="External dependencies", variable=self.box, value="External dependencies", command=self.refresh_results_window) stat = Radiobutton( radio_frame, text="Statistics by type", variable=self.box, value="Statistics by type", command=self.refresh_results_window) msg_cat = Radiobutton( radio_frame, text="Messages by category", variable=self.box, value="Messages by category", command=self.refresh_results_window) msg = Radiobutton( radio_frame, text="Messages", variable=self.box, value="Messages", command=self.refresh_results_window) source_file = Radiobutton( radio_frame, text="Source File", variable=self.box, value="Source File", command=self.refresh_results_window) report.select() report.grid(column=0, row=0, sticky=W) raw_met.grid(column=1, row=0, sticky=W) dup.grid(column=2, row=0, sticky=W) msg.grid(column=3, row=0, sticky=W) stat.grid(column=0, row=1, sticky=W) msg_cat.grid(column=1, row=1, sticky=W) ext.grid(column=2, row=1, sticky=W) source_file.grid(column=3, row=1, sticky=W) #dictionary for check boxes and associated error term self.msg_type_dict = { 'I': lambda: self.information_box.get() == 1, 'C': lambda: self.convention_box.get() == 1, 'R': lambda: self.refactor_box.get() == 1, 'E': lambda: self.error_box.get() == 1, 'W': lambda: self.warning_box.get() == 1, 'F': lambda: self.fatal_box.get() == 1 } self.txt_module.focus_set() def select_recent_file(self, event): """adds the selected file in the history listbox to the Module box""" if not self.showhistory.size(): return selected = self.showhistory.curselection() item = self.showhistory.get(selected) #update module self.txt_module.delete(0, END) self.txt_module.insert(0, item) def refresh_msg_window(self): """refresh the message window with current output""" #clear the window self.lb_messages.delete(0, END) self.visible_msgs = [] for msg in self.msgs: if self.msg_type_dict.get(msg.C)(): self.visible_msgs.append(msg) msg_str = convert_to_string(msg) self.lb_messages.insert(END, msg_str) fg_color = COLORS.get(msg_str[:3], 'black') self.lb_messages.itemconfigure(END, fg=fg_color) def refresh_results_window(self): """refresh the results window with current output""" #clear the window self.results.delete(0, END) try: for res in self.tabs[self.box.get()]: self.results.insert(END, res) except: pass def process_incoming(self): """process the incoming messages from running pylint""" while self.msg_queue.qsize(): try: msg = self.msg_queue.get(0) if msg == "DONE": self.report_stream.output_contents() return False #adding message to list of msgs self.msgs.append(msg) #displaying msg if message type is selected in check box if self.msg_type_dict.get(msg.C)(): self.visible_msgs.append(msg) msg_str = convert_to_string(msg) self.lb_messages.insert(END, msg_str) fg_color = COLORS.get(msg_str[:3], 'black') self.lb_messages.itemconfigure(END, fg=fg_color) except queue.Empty: pass return True def periodic_call(self): """determine when to unlock the run button""" if self.process_incoming(): self.root.after(100, self.periodic_call) else: #enabling button so it can be run again self.btnRun.config(state=NORMAL) def mainloop(self): """launch the mainloop of the application""" self.root.mainloop() def quit(self, _=None): """quit the application""" self.root.quit() def halt(self): """program halt placeholder""" return def file_open(self, package=False, _=None): """launch a file browser""" if not package: filename = askopenfilename(parent=self.root, filetypes=[('pythonfiles', '*.py'), ('allfiles', '*')], title='Select Module') else: filename = askdirectory(title="Select A Folder", mustexist=1) if filename == (): return self.txt_module.delete(0, END) self.txt_module.insert(0, filename) def update_filenames(self): """update the list of recent filenames""" filename = self.txt_module.get() if not filename: filename = os.getcwd() if filename+'\n' in self.filenames: index = self.filenames.index(filename+'\n') self.filenames.pop(index) #ensure only 10 most recent are stored if len(self.filenames) == 10: self.filenames.pop() self.filenames.insert(0, filename+'\n') def set_history_window(self): """update the history window with info from the history file""" #clear the window self.showhistory.delete(0, END) # keep the last 10 most recent files try: view_history = open(HOME+HISTORY, 'r') for hist in view_history.readlines(): if not hist in self.filenames: self.filenames.append(hist) self.showhistory.insert(END, hist.split('\n')[0]) view_history.close() except IOError: # do nothing since history file will be created later return def run_lint(self, _=None): """launches pylint""" self.update_filenames() self.root.configure(cursor='watch') self.reporter = GUIReporter(self, output=self.report_stream) module = self.txt_module.get() if not module: module = os.getcwd() #cleaning up msgs and windows self.msgs = [] self.visible_msgs = [] self.lb_messages.delete(0, END) self.tabs = {} self.results.delete(0, END) self.btnRun.config(state=DISABLED) #setting up a worker thread to run pylint worker = Thread(target=lint_thread, args=(module, self.reporter, self,)) self.periodic_call() worker.start() # Overwrite the .pylint-gui-history file with all the new recently added files # in order from filenames but only save last 10 files write_history = open(HOME+HISTORY, 'w') write_history.writelines(self.filenames) write_history.close() self.set_history_window() self.root.configure(cursor='') def show_sourcefile(self, event=None): selected = self.lb_messages.curselection() if not selected: return msg = self.visible_msgs[int(selected[0])] scroll = msg.line - 3 if scroll < 0: scroll = 0 self.tabs["Source File"] = open(msg.path, "r").readlines() self.box.set("Source File") self.refresh_results_window() self.results.yview(scroll) self.results.select_set(msg.line - 1)
def openStats(handler): statsApi = get( "https://raw.githubusercontent.com/revoxhere/duco-statistics/master/api.json", data=None) if statsApi.status_code == 200: #Check for reponse statsApi = (statsApi.json()) print(statsApi) statsWindow = Toplevel() statsWindow.resizable(False, False) statsWindow.title("Duino-Coin Wallet - Stats") statsWindow.configure(background=backgroundColor) statsWindow.transient([root]) textFont3 = Font(statsWindow, size=14, weight="bold") textFont = Font(statsWindow, size=12, weight="normal") Label(statsWindow, text="Duco Statistics", background=backgroundColor, foreground=foregroundColor, font=textFont3).grid(row=0, column=0) i = 3 i2 = 3 for key in statsApi.keys(): if str(key) == 'Active workers' or str( key) == 'Top 10 richest miners' or str( key) == 'Total supply' or str( key) == 'Full last block hash' or str( key) == 'GitHub API file update count' or str( key) == 'Diff increases per': pass else: if len(statsApi.get(str(key))) > 8: Label(statsWindow, text=f"{key}: {statsApi.get(str(key))}", background=backgroundColor, foreground=foregroundColor, font=textFont).grid(row=i2, column=1, sticky=W) i2 += 1 else: Label(statsWindow, text=f"{key}: {statsApi.get(str(key))}", background=backgroundColor, foreground=foregroundColor, font=textFont).grid(row=i, column=0, sticky=W) i += 1 Active_workers_listbox = Listbox(statsWindow, exportselection=False, background=backgroundColor, foreground=foregroundColor, selectbackground="#7bed9f", border="0", font=textFont, width="20", height="13") Active_workers_listbox.grid(row=1, column=0, sticky=W) i = 0 for worker in (statsApi['Active workers']).split(', '): Active_workers_listbox.insert(i, worker) i = i + 1 Active_workers_listbox.select_set(32) Active_workers_listbox.event_generate("<<ListboxSelect>>") Top_10_listbox = Listbox(statsWindow, exportselection=False, background=backgroundColor, foreground=foregroundColor, selectbackground="#7bed9f", border="0", font=textFont, width="33", height="13") Top_10_listbox.grid(row=1, column=1, sticky=W) i = 0 for rich in (statsApi['Top 10 richest miners']).split(', '): Top_10_listbox.insert(i, rich) i = i + 1 Top_10_listbox.select_set(32) Top_10_listbox.event_generate("<<ListboxSelect>>") statsWindow.mainloop()
class AlbumsPanel(Frame): def __init__(self, parent, albumsController: IAlbumsController): super().__init__(parent) self.albumsController = albumsController self.albumList: List[AlbumDb] = [] self.selectedAlbumName: str = None self.musicFromDisc: List[Music] = [] self.displayedMusicOnComputer = None self.displayedMusicInAlbum = None self.__initView() def __initView(self): self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(3, weight=1) self.albumsListBox = Listbox(self, exportselection=0) self.albumsListBox.grid(row=0, column=0, sticky='WE', padx=(10, 0), pady=10) self.albumsListBox.bind('<Double-1>', self.__albumDoubleClicked) self.albumsListBox.bind("<<ListboxSelect>>", self.__albumSelected) albumsScrollbar = Scrollbar(self, command=self.albumsListBox.yview) albumsScrollbar.grid(row=0, column=1, sticky='NS', padx=(0, 10), pady=10) self.albumsListBox.configure(yscrollcommand=albumsScrollbar.set) ###################################################################################################### buttonsFrame = Frame(self) buttonsFrame.grid(row=1, column=0, sticky='W', padx=10) self.albumDeleteButton = Button(buttonsFrame, text=ALBUM_DELETE_TEXT, command=self.__deleteAlbum) self.albumDeleteButton.grid(row=0, column=0, padx=5) self.albumExportButton = Button(buttonsFrame, text=ALBUM_EXPORT_TEXT, command=self.__exportAlbumClicked) self.albumExportButton.grid(row=0, column=1, padx=5) self.albumImportButton = Button(buttonsFrame, text=ALBUM_IMPORT_TEXT, command=self.__importAlbumClicked) self.albumImportButton.grid(row=0, column=2, padx=5) ###################################################################################################### createFrame = Frame(self) createFrame.grid(row=2, column=0, sticky='W', padx=10) label = Label(createFrame, text=ALBUM_CREATE_LABEL_TEXT) label.grid(row=0, column=0) self.createAlbumNameEntry = Entry(createFrame) self.createAlbumNameEntry.grid(row=0, column=1) self.createAlbumButton = Button(createFrame, text=ALBUM_CREATE_BUTTON_TEXT, command=self.__createAlbum) self.createAlbumButton.grid(row=0, column=2) ###################################################################################################### # Music on computer musicFrame = Frame(self, padx=10, pady=10) musicFrame.grid(row=3, column=0, columnspan=2, sticky='WENS') musicFrame.grid_columnconfigure(0, weight=1) musicFrame.grid_columnconfigure(3, weight=1) musicFrame.grid_rowconfigure(1, weight=1) label = Label(musicFrame, text=MUSIC_ON_COMPUTER_TEXT) label.grid(row=0, column=0, sticky='W') self.musicOnComputerListBox = Listbox(musicFrame) self.musicOnComputerListBox.grid(row=1, column=0, sticky='WENS') musicOnComputerScrollbar = Scrollbar(musicFrame, command=self.musicOnComputerListBox.yview) musicOnComputerScrollbar.grid(row=1, column=1, sticky='NS') self.musicOnComputerListBox.configure(yscrollcommand=musicOnComputerScrollbar.set) ###################################################################################################### buttonFrame = Frame(musicFrame, padx=10) buttonFrame.grid(row=1, column=2) self.removeFromAlbumButton = Button(buttonFrame, text='<<', command=self.__removeMusicFromAlbumClicked) self.removeFromAlbumButton.grid(row=0, column=0) self.addToAlbumButton = Button(buttonFrame, text='>>', command=self.__addMusicToAlbumClicked) self.addToAlbumButton.grid(row=1, column=0) ###################################################################################################### #Music in album label = Label(musicFrame, text=MUSIC_IN_ALBUM_TEXT) label.grid(row=0, column=3, sticky='W') self.musicInAlbumListBox = Listbox(musicFrame) self.musicInAlbumListBox.grid(row=1, column=3, sticky='WENS') musicInAlbumScrollbar = Scrollbar(musicFrame, command=self.musicInAlbumListBox.yview) musicInAlbumScrollbar.grid(row=1, column=4, sticky='NS') self.musicInAlbumListBox.configure(yscrollcommand=musicInAlbumScrollbar.set) ###################################################################################################### def displayAlbums(self, albums: List[AlbumDb], musicFromDisc: List[Music]): self.albumList = albums self.musicFromDisc = musicFromDisc self.albumsListBox.delete(0, 'end') for i in range(len(self.albumList)): a = self.albumList[i] self.albumsListBox.insert(i, a.name) if self.selectedAlbumName is not None: selectedIndex = -1 for i in range(len(self.albumList)): if self.albumList[i].name == self.selectedAlbumName: selectedIndex = i break if selectedIndex >= 0: self.albumsListBox.select_set(selectedIndex) self.albumsListBox.event_generate("<<ListboxSelect>>") def __deleteAlbum(self): selection = self.albumsListBox.curselection() if len(selection) <= 0: messagebox.showwarning('Warning', DELETE_ALBUM_SELECT_TEXT) return self.albumsListBox.selection_clear(0, END) self.albumsListBox.event_generate("<<ListboxSelect>>") album = self.albumList[selection[0]] self.albumsController.deleteAlbum(album.name) def __createAlbum(self): name = self.createAlbumNameEntry.get() if name is None or name == '': messagebox.showwarning('Warning', CRATE_ALBUM_INSERT_NAME_TEXT) return self.albumsController.createAlbum(name) def __albumSelected(self, event): self.musicOnComputerListBox.delete(0, 'end') self.musicInAlbumListBox.delete(0, 'end') selection = self.albumsListBox.curselection() if len(selection) <= 0: return selectedAlbum = self.albumList[selection[0]] self.selectedAlbumName = selectedAlbum.name self.__lisMusicOnComputer(selectedAlbum) self.__lisMusicInAlbum(selectedAlbum) def __lisMusicOnComputer(self, album): musicInAlbum = set() for m in album.music: musicInAlbum.add(m.path) if self.musicFromDisc is None: return music = self.musicFromDisc.copy() music = filter(lambda m: m.path not in musicInAlbum, music) self.displayedMusicOnComputer = list(music) i = 0 for m in self.displayedMusicOnComputer: self.musicOnComputerListBox.insert(i, m.filename) i = i + 1 def __lisMusicInAlbum(self, album): musicOnDisc = set() if self.musicFromDisc is not None: for m in self.musicFromDisc: musicOnDisc.add(m.path) self.displayedMusicInAlbum = list(album.music) i = 0 for m in self.displayedMusicInAlbum: description = os.path.basename(m.path) if m.path not in musicOnDisc: description = '<missing> ' + m.path self.musicInAlbumListBox.insert(i, description) i = i + 1 def __addMusicToAlbumClicked(self): selection = self.albumsListBox.curselection() if len(selection) <= 0: return selectedAlbum = self.albumList[selection[0]] selection = self.musicOnComputerListBox.curselection() if len(selection) <= 0: messagebox.showwarning('Warning', ADD_TO_ALBUM_SELECT_TEXT) return selectedMusic = self.displayedMusicOnComputer[selection[0]] self.albumsController.addMusicToAlbum(selectedAlbum.name, selectedMusic.path) def __removeMusicFromAlbumClicked(self): selection = self.albumsListBox.curselection() if len(selection) <= 0: return selectedAlbum = self.albumList[selection[0]] selection = self.musicInAlbumListBox.curselection() if len(selection) <= 0: messagebox.showwarning('Warning', REMOVE_FROM_ALBUM_SELECT_TEXT) return selectedMusic = self.displayedMusicInAlbum[selection[0]] self.albumsController.removeMusicFromAlbum(selectedAlbum.name, selectedMusic.path) def __exportAlbumClicked(self): selection = self.albumsListBox.curselection() if len(selection) <= 0: messagebox.showwarning('Warning', EXPORT_ALBUM_SELECT_TEXT) return selectedAlbum = self.albumList[selection[0]] self.albumsController.exportAlbum(selectedAlbum.name) def __importAlbumClicked(self): self.albumsController.importAlbum() def __albumDoubleClicked(self, event): album = self.albumList[self.albumsListBox.curselection()[0]] self.albumsController.addAlbumToQueue(album)
class ImageZip(Frame): def __init__(self, parent): # Bind Frame to self and begin UI Frame.__init__(self, parent) self.parent = parent self.onGetZipResults = {} self.imagetypes = [("Image file", "*.jpg"), ("Image file", "*.jpeg"), ("Image file", "*.jfif"), ("Image file", "*.jpe"), ("Image file", "*.jfi"), ("Image file", "*.jif")] self.initUI() def initUI(self): # Creating UI elements and action calls self.parent.title("JPEG 2 Zip Code") self.pack(fill=BOTH, expand=True) # Menu menubar = Menu(self.parent) fileMenu = Menu(menubar, tearoff=False) fileMenu.add_command(label="Open File(s)", command=self.onOpenFile) fileMenu.add_command(label="Exit", command=self.parent.quit) menubar.add_cascade(label="File", menu=fileMenu) self.editMenu = Menu(menubar, tearoff=False) self.editMenu.add_command(label="Select All", command=self.onSelectAll) self.editMenu.add_command(label="Deselect All", command=self.onDeselectAll) menubar.add_cascade(label="Edit", menu=self.editMenu) self.actionMenu = Menu(menubar, tearoff=False) self.actionMenu.add_command(label="Get ZIP Codes", command=self.onGetZIP) menubar.add_cascade(label="Action", menu=self.actionMenu) self.parent.config(menu=menubar) self.menuItemAccess( False) # Disable unneeded menu items until files loaded # Listbox which will hold opened file names and allow selection self.listboxFiles = Listbox(self.parent, selectmode=EXTENDED) self.listboxFiles.pack(fill=BOTH, expand=True) def onDeselectAll(self): self.listboxFiles.select_clear(0, END) def onSelectAll(self): self.listboxFiles.select_set(0, END) # Takes in boolean, TRUE = allow access, FALSE = disable access def menuItemAccess(self, viewable): if viewable == True: self.editMenu.entryconfig(0, state=NORMAL) self.editMenu.entryconfig(1, state=NORMAL) self.actionMenu.entryconfig(0, state=NORMAL) if viewable == False: self.editMenu.entryconfig(0, state=DISABLED) self.editMenu.entryconfig(1, state=DISABLED) self.actionMenu.entryconfig(0, state=DISABLED) def badImageDialog(self, badimagefiles): # Takes in a list of files and produces a warning dialog fileerrors = "" for file in badimagefiles: fileerrors += str(file) + '\n' messagebox.showwarning( "Error Loading All Images", "Not all images were found to be valid. The following files will not be loaded...\n" + fileerrors) def onGetZIP(self): # Produces GPS, then ZIP codes for all selected files in the UI. geolocator = Nominatim(user_agent="JPEG2ZIP") selectedfiles = self.listboxFiles.curselection() for item in selectedfiles: currentFile = self.listboxFiles.get(item) currentGPS = getEXIF().load(currentFile) print(currentGPS) try: temp = geolocator.reverse(currentGPS) currentZIP = temp.raw['address']['postcode'] except: # If ZIP code not found or coords are (0.0, 0.0) currentZIP = "Error" # Unused right now but still saved. # Adds {index: FileName, GPS Coords, ZIP code} to dictionary self.onGetZipResults.update( {item: (currentFile, getEXIF().load(currentFile), currentZIP)}) #Update UI self.listboxFiles.delete(item) self.listboxFiles.insert(item, currentFile + ' ' + currentZIP) #print(self.onGetZipResults) def onOpenFile(self): # TODO: Grab and display thumbnails with file name. fl = filedialog.askopenfilenames(filetypes=self.imagetypes) # Image validity check and update UI with file names print('Opening...') badimagefiles = [] if fl != '': for file in fl: if (self.isValidJPEG(file) == True): # is valid print('\t' + file) self.listboxFiles.insert(END, file) if (self.isValidJPEG(file) == False): # is invalid badimagefiles.append(file) if len(badimagefiles) > 0: # push bad images to dialog box self.badImageDialog(badimagefiles) # Enable Menu items self.menuItemAccess(True) def isValidJPEG(self, imageFile): # TODO: use library to check validity of image. No need to reinvent the wheel. try: data = open(imageFile, 'rb').read(11) #read first 11 bytes # All JPEG image files start off with SOI '0xff 0xd8'. # This is slightly unnecessary. See TODO above. if data[:2] != b'\xff\xd8': #Bad SOI return False return True except: print("Image Validation Error: Unable to open image " + imageFile) # sanity check (print to console) return False
class InstanceEditor(Toplevel): def __init__(self): Toplevel.__init__(self) self.focus_set() self.grab_set() self.result = None self.module_data = None self.mod_applis = None self.title(ugettext("Instance editor")) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self.ntbk = ttk.Notebook(self) self.ntbk.grid(row=0, column=0, columnspan=1, sticky=(N, S, E, W)) self.frm_general = Frame(self.ntbk, width=350, height=150) self.frm_general.grid_columnconfigure(0, weight=0) self.frm_general.grid_columnconfigure(1, weight=1) self._general_tabs() self.ntbk.add(self.frm_general, text=ugettext('General')) self.frm_database = Frame(self.ntbk, width=350, height=150) self.frm_database.grid_columnconfigure(0, weight=0) self.frm_database.grid_columnconfigure(1, weight=1) self._database_tabs() self.ntbk.add(self.frm_database, text=ugettext('Database')) btnframe = Frame(self, bd=1) btnframe.grid(row=1, column=0, columnspan=1) Button(btnframe, text=ugettext("OK"), width=10, command=self.apply).grid( row=0, column=0, sticky=(N, S, E)) Button(btnframe, text=ugettext("Cancel"), width=10, command=self.destroy).grid( row=0, column=1, sticky=(N, S, W)) def _database_tabs(self): Label(self.frm_database, text=ugettext("Type")).grid( row=0, column=0, sticky=(N, W), padx=5, pady=3) self.typedb = ttk.Combobox( self.frm_database, textvariable=StringVar(), state=READLONY) self.typedb.bind("<<ComboboxSelected>>", self.typedb_selection) self.typedb.grid(row=0, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_database, text=ugettext("Name")).grid( row=1, column=0, sticky=(N, W), padx=5, pady=3) self.namedb = Entry(self.frm_database) self.namedb.grid(row=1, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_database, text=ugettext("User")).grid( row=2, column=0, sticky=(N, W), padx=5, pady=3) self.userdb = Entry(self.frm_database) self.userdb.grid(row=2, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_database, text=ugettext("Password")).grid( row=3, column=0, sticky=(N, W), padx=5, pady=3) self.pwddb = Entry(self.frm_database) self.pwddb.grid(row=3, column=1, sticky=(N, S, E, W), padx=5, pady=3) def _general_tabs(self): Label(self.frm_general, text=ugettext("Name")).grid( row=0, column=0, sticky=(N, W), padx=5, pady=3) self.name = Entry(self.frm_general) self.name.grid(row=0, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_general, text=ugettext("Appli")).grid( row=1, column=0, sticky=(N, W), padx=5, pady=3) self.applis = ttk.Combobox( self.frm_general, textvariable=StringVar(), state=READLONY) self.applis.bind("<<ComboboxSelected>>", self.appli_selection) self.applis.grid(row=1, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_general, text=ugettext("Modules")).grid( row=2, column=0, sticky=(N, W), padx=5, pady=3) self.modules = Listbox(self.frm_general, selectmode=EXTENDED) self.modules.configure(exportselection=False) self.modules.grid(row=2, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_general, text=ugettext("Language")).grid( row=3, column=0, sticky=(N, W), padx=5, pady=3) self.language = ttk.Combobox( self.frm_general, textvariable=StringVar(), state=READLONY) self.language.grid( row=3, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_general, text=ugettext("CORE-connectmode") ).grid(row=4, column=0, sticky=(N, W), padx=5, pady=3) self.mode = ttk.Combobox( self.frm_general, textvariable=StringVar(), state=READLONY) self.mode.bind("<<ComboboxSelected>>", self.mode_selection) self.mode.grid(row=4, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_general, text=ugettext("Password")).grid( row=5, column=0, sticky=(N, W), padx=5, pady=3) self.password = Entry(self.frm_general, show="*") self.password.grid( row=5, column=1, sticky=(N, S, E, W), padx=5, pady=3) def typedb_selection(self, event): visible = list(self.typedb[VALUES]).index(self.typedb.get()) != 0 for child_cmp in self.frm_database.winfo_children()[2:]: if visible: child_cmp.config(state=NORMAL) else: child_cmp.config(state=DISABLED) def appli_selection(self, event): if self.applis.get() != '': appli_id = list(self.applis[VALUES]).index(self.applis.get()) luct_glo = LucteriosGlobal() current_inst_names = luct_glo.listing() appli_root_name = self.mod_applis[appli_id][0].split('.')[-1] default_name_idx = 1 while appli_root_name + six.text_type(default_name_idx) in current_inst_names: default_name_idx += 1 self.name.delete(0, END) self.name.insert( 0, appli_root_name + six.text_type(default_name_idx)) mod_depended = self.mod_applis[appli_id][2] self.modules.select_clear(0, self.modules.size()) for mod_idx in range(len(self.module_data)): current_mod = self.module_data[mod_idx] if current_mod in mod_depended: self.modules.selection_set(mod_idx) def mode_selection(self, event): visible = list(self.mode[VALUES]).index(self.mode.get()) != 2 for child_cmp in self.frm_general.winfo_children()[-2:]: if visible: child_cmp.config(state=NORMAL) else: child_cmp.config(state=DISABLED) def apply(self): from lucterios.framework.settings import DEFAULT_LANGUAGES, get_locale_lang if self.name.get() == '': showerror(ugettext("Instance editor"), ugettext("Name empty!")) return if self.applis.get() == '': showerror(ugettext("Instance editor"), ugettext("No application!")) return db_param = "%s:name=%s,user=%s,password=%s" % ( self.typedb.get(), self.namedb.get(), self.userdb.get(), self.pwddb.get()) security = "MODE=%s" % list( self.mode[VALUES]).index(self.mode.get()) if self.password.get() != '': security += ",PASSWORD=%s" % self.password.get() module_list = [ self.module_data[int(item)] for item in self.modules.curselection()] appli_id = list(self.applis[VALUES]).index(self.applis.get()) current_lang = get_locale_lang() for lang in DEFAULT_LANGUAGES: if lang[1] == self.language.get(): current_lang = lang[0] self.result = (self.name.get(), self.mod_applis[appli_id][ 0], ",".join(module_list), security, db_param, current_lang) self.destroy() def _load_current_data(self, instance_name): from lucterios.framework.settings import DEFAULT_LANGUAGES, get_locale_lang lct_inst = LucteriosInstance(instance_name) lct_inst.read() self.name.delete(0, END) self.name.insert(0, lct_inst.name) self.name.config(state=DISABLED) applis_id = 0 for appli_iter in range(len(self.mod_applis)): if self.mod_applis[appli_iter][0] == lct_inst.appli_name: applis_id = appli_iter break self.applis.current(applis_id) if lct_inst.extra['']['mode'] is not None: self.mode.current(lct_inst.extra['']['mode'][0]) else: self.mode.current(2) self.mode_selection(None) typedb_index = 0 for typedb_idx in range(len(self.typedb[VALUES])): if self.typedb[VALUES][typedb_idx].lower() == lct_inst.database[0].lower(): typedb_index = typedb_idx break self.typedb.current(typedb_index) self.typedb.config(state=DISABLED) self.typedb_selection(None) self.namedb.delete(0, END) if 'name' in lct_inst.database[1].keys(): self.namedb.insert(0, lct_inst.database[1]['name']) self.userdb.delete(0, END) if 'user' in lct_inst.database[1].keys(): self.userdb.insert(0, lct_inst.database[1]['user']) self.pwddb.delete(0, END) if 'password' in lct_inst.database[1].keys(): self.pwddb.insert(0, lct_inst.database[1]['password']) self.modules.select_clear(0, self.modules.size()) for mod_idx in range(len(self.module_data)): current_mod = self.module_data[mod_idx] if current_mod in lct_inst.modules: self.modules.select_set(mod_idx) current_lang = get_locale_lang() if 'LANGUAGE_CODE' in lct_inst.extra.keys(): current_lang = lct_inst.extra['LANGUAGE_CODE'] for lang in DEFAULT_LANGUAGES: if lang[0] == current_lang: self.language.current(self.language[VALUES].index(lang[1])) def execute(self, instance_name=None): from lucterios.framework.settings import DEFAULT_LANGUAGES, get_locale_lang self.mode[VALUES] = [ugettext( "CORE-connectmode.0"), ugettext("CORE-connectmode.1"), ugettext("CORE-connectmode.2")] self.language[VALUES] = [lang[1] for lang in DEFAULT_LANGUAGES] self.typedb[VALUES] = ["SQLite", "MySQL", "PostgreSQL"] lct_glob = LucteriosGlobal() _, self.mod_applis, mod_modules = lct_glob.installed() self.mod_applis.sort(key=lambda item: get_module_title(item[0])) self.modules.delete(0, END) self.module_data = [] module_list = [] for mod_module_item in mod_modules: module_list.append( (get_module_title(mod_module_item[0]), mod_module_item[0])) module_list.sort(key=lambda module: module[0]) for module_title, module_name in module_list: self.modules.insert(END, module_title) self.module_data.append(module_name) appli_list = [] for mod_appli_item in self.mod_applis: appli_list.append(get_module_title(mod_appli_item[0])) self.applis[VALUES] = appli_list if instance_name is not None: self._load_current_data(instance_name) else: self.typedb.current(0) self.mode.current(2) if len(appli_list) > 0: self.applis.current(0) self.appli_selection(None) self.mode_selection(None) self.typedb_selection(None) for lang in DEFAULT_LANGUAGES: if lang[0] == get_locale_lang(): self.language.current(self.language[VALUES].index(lang[1])) center(self)
class InstanceEditor(Toplevel, EditorInstance): def __init__(self): Toplevel.__init__(self) EditorInstance.__init__(self) self.focus_set() self.grab_set() self.result = None self.module_data = None self.mod_applis = None self.title(ugettext("Instance editor")) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self.ntbk = ttk.Notebook(self) self.ntbk.grid(row=0, column=0, columnspan=1, sticky=(N, S, E, W)) self.frm_general = Frame(self.ntbk, width=350, height=150) self.frm_general.grid_columnconfigure(0, weight=0) self.frm_general.grid_columnconfigure(1, weight=1) self._general_tabs() self.ntbk.add(self.frm_general, text=ugettext('General')) self.frm_database = Frame(self.ntbk, width=350, height=150) self.frm_database.grid_columnconfigure(0, weight=0) self.frm_database.grid_columnconfigure(1, weight=1) self._database_tabs() self.ntbk.add(self.frm_database, text=ugettext('Database')) btnframe = Frame(self, bd=1) btnframe.grid(row=1, column=0, columnspan=1) Button(btnframe, text=ugettext("OK"), width=10, command=self.apply).grid(row=0, column=0, sticky=(N, S, E)) Button(btnframe, text=ugettext("Cancel"), width=10, command=self.destroy).grid(row=0, column=1, sticky=(N, S, W)) def _database_tabs(self): Label(self.frm_database, text=ugettext("Type")).grid(row=0, column=0, sticky=(N, W), padx=5, pady=3) self.typedb = ttk.Combobox(self.frm_database, textvariable=StringVar(), state=READLONY) self.typedb.bind("<<ComboboxSelected>>", self.typedb_selection) self.typedb.grid(row=0, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_database, text=ugettext("Name")).grid(row=1, column=0, sticky=(N, W), padx=5, pady=3) self.namedb = Entry(self.frm_database) self.namedb.grid(row=1, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_database, text=ugettext("User")).grid(row=2, column=0, sticky=(N, W), padx=5, pady=3) self.userdb = Entry(self.frm_database) self.userdb.grid(row=2, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_database, text=ugettext("Password")).grid(row=3, column=0, sticky=(N, W), padx=5, pady=3) self.pwddb = Entry(self.frm_database) self.pwddb.grid(row=3, column=1, sticky=(N, S, E, W), padx=5, pady=3) def _general_tabs(self): Label(self.frm_general, text=ugettext("Name")).grid(row=0, column=0, sticky=(N, W), padx=5, pady=3) self.name = Entry(self.frm_general) self.name.grid(row=0, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_general, text=ugettext("Appli")).grid(row=1, column=0, sticky=(N, W), padx=5, pady=3) self.applis = ttk.Combobox(self.frm_general, textvariable=StringVar(), state=READLONY) self.applis.bind("<<ComboboxSelected>>", self.appli_selection) self.applis.grid(row=1, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_general, text=ugettext("Modules")).grid(row=2, column=0, sticky=(N, W), padx=5, pady=3) self.modules = Listbox(self.frm_general, selectmode=EXTENDED) self.modules.configure(exportselection=False) self.modules.grid(row=2, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_general, text=ugettext("Language")).grid(row=3, column=0, sticky=(N, W), padx=5, pady=3) self.language = ttk.Combobox(self.frm_general, textvariable=StringVar(), state=READLONY) self.language.grid(row=3, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_general, text=ugettext("CORE-connectmode")).grid(row=4, column=0, sticky=(N, W), padx=5, pady=3) self.mode = ttk.Combobox(self.frm_general, textvariable=StringVar(), state=READLONY) self.mode.bind("<<ComboboxSelected>>", self.mode_selection) self.mode.grid(row=4, column=1, sticky=(N, S, E, W), padx=5, pady=3) Label(self.frm_general, text=ugettext("Password")).grid(row=5, column=0, sticky=(N, W), padx=5, pady=3) self.password = Entry(self.frm_general, show="*") self.password.grid(row=5, column=1, sticky=(N, S, E, W), padx=5, pady=3) def typedb_selection(self, event): visible = list(self.typedb[VALUES]).index(self.typedb.get()) != 0 for child_cmp in self.frm_database.winfo_children()[2:]: if visible: child_cmp.config(state=NORMAL) else: child_cmp.config(state=DISABLED) def appli_selection(self, event): if self.applis.get() != '': appli_id = list(self.applis[VALUES]).index(self.applis.get()) luct_glo = LucteriosGlobal() current_inst_names = luct_glo.listing() appli_root_name = self.mod_applis[appli_id][0].split('.')[-1] default_name_idx = 1 while appli_root_name + six.text_type( default_name_idx) in current_inst_names: default_name_idx += 1 self.name.delete(0, END) self.name.insert(0, appli_root_name + six.text_type(default_name_idx)) mod_depended = self.mod_applis[appli_id][2] self.modules.select_clear(0, self.modules.size()) for mod_idx in range(len(self.module_data)): current_mod = self.module_data[mod_idx] if current_mod in mod_depended: self.modules.selection_set(mod_idx) def mode_selection(self, event): visible = list(self.mode[VALUES]).index(self.mode.get()) != 2 for child_cmp in self.frm_general.winfo_children()[-2:]: if visible: child_cmp.config(state=NORMAL) else: child_cmp.config(state=DISABLED) def apply(self): from lucterios.framework.settings import DEFAULT_LANGUAGES, get_locale_lang if self.is_new_instance and ( (self.name.get() == '') or (self.name_rull.match(self.name.get()) is None)): showerror(ugettext("Instance editor"), ugettext("Name invalid!")) return if self.applis.get() == '': showerror(ugettext("Instance editor"), ugettext("No application!")) return db_param = "%s:name=%s,user=%s,password=%s" % ( self.typedb.get(), self.namedb.get(), self.userdb.get(), self.pwddb.get()) security = "MODE=%s" % list(self.mode[VALUES]).index(self.mode.get()) if self.password.get() != '': security += ",PASSWORD=%s" % self.password.get() module_list = [ self.module_data[int(item)] for item in self.modules.curselection() ] appli_id = list(self.applis[VALUES]).index(self.applis.get()) current_lang = get_locale_lang() for lang in DEFAULT_LANGUAGES: if lang[1] == self.language.get(): current_lang = lang[0] self.result = (self.name.get(), self.mod_applis[appli_id][0], ",".join(module_list), security, db_param, current_lang) self.destroy() def _load_current_data(self, instance_name): from lucterios.framework.settings import DEFAULT_LANGUAGES lct_inst, applis_id, mode_id, typedb_index, current_lang = self._get_instance_elements( instance_name) self.is_new_instance = False self.name.delete(0, END) self.name.insert(0, lct_inst.name) self.name.config(state=DISABLED) self.applis.current(applis_id) self.mode.current(mode_id) self.mode_selection(None) self.typedb.current(typedb_index) self.typedb.config(state=DISABLED) self.typedb_selection(None) self.namedb.delete(0, END) if 'name' in lct_inst.database[1].keys(): self.namedb.insert(0, lct_inst.database[1]['name']) self.userdb.delete(0, END) if 'user' in lct_inst.database[1].keys(): self.userdb.insert(0, lct_inst.database[1]['user']) self.pwddb.delete(0, END) if 'password' in lct_inst.database[1].keys(): self.pwddb.insert(0, lct_inst.database[1]['password']) self.modules.select_clear(0, self.modules.size()) for mod_idx in range(len(self.module_data)): current_mod = self.module_data[mod_idx] if current_mod in lct_inst.modules: self.modules.select_set(mod_idx) for lang in DEFAULT_LANGUAGES: if lang[0] == current_lang: self.language.current(self.language[VALUES].index(lang[1])) def execute(self, instance_name=None): from lucterios.framework.settings import DEFAULT_LANGUAGES, get_locale_lang self._define_values() self.module_data = [] self.modules.delete(0, END) for module_title, module_name in self.module_list: self.modules.insert(END, module_title) self.module_data.append(module_name) self.mode[VALUES] = self.mode_values self.language[VALUES] = self.lang_values self.typedb[VALUES] = self.dbtype_values self.applis[VALUES] = self.appli_list if instance_name is not None: self._load_current_data(instance_name) else: self.typedb.current(0) self.mode.current(2) if len(self.appli_list) > 0: self.applis.current(0) self.appli_selection(None) self.mode_selection(None) self.typedb_selection(None) for lang in DEFAULT_LANGUAGES: if lang[0] == get_locale_lang(): self.language.current(self.language[VALUES].index(lang[1])) center(self)
class SettingsFrame(Frame): """ Frame inheritance class for application settings and controls. """ def __init__(self, app, *args, **kwargs): """ Constructor """ self.__app = app # Reference to main application class self.__master = self.__app.get_master() # Reference to root class (Tk) Frame.__init__(self, self.__master, *args, **kwargs) # Initialise up key variables self._image_num = 0 self._image_name = "image" self._settype = StringVar() self._zoom = DoubleVar() self._radius = DoubleVar() self._exponent = IntVar() self._zx_off = DoubleVar() self._zy_off = DoubleVar() self._cx_off = DoubleVar() self._cy_off = DoubleVar() self._maxiter = IntVar() self._zx_coord = DoubleVar() self._zy_coord = DoubleVar() self._theme = StringVar() self._shift = IntVar() self._themes = None self._filename = StringVar() self._filepath = None self._frames = IntVar() self._zoominc = DoubleVar() self._autoiter = IntVar() self._autosave = IntVar() self._validsettings = True self.body() def body(self): """ Set up frame and widgets. """ # Create settings panel widgets # pylint: disable=W0108 self.lbl_settype = Label(self, text=LBLMODE) self.spn_settype = Spinbox( self, values=("BurningShip", "Tricorn", "Julia", "Mandelbrot"), width=8, bg=GOOD, wrap=True, textvariable=self._settype, ) self.lbl_zoom = Label(self, text=LBLZOOM) self.ent_zoom = Entry( self, border=2, relief="sunken", width=12, bg=GOOD, justify=RIGHT, textvariable=self._zoom, ) self.lbl_zoominc = Label(self, text=LBLZOOMINC, justify=LEFT) self.ent_zoominc = Entry(self, width=5, border=2, bg=GOOD, justify=RIGHT, textvariable=self._zoominc) self.lbl_zx_off = Label(self, text=LBLZXOFF) self.ent_zx_off = Entry( self, border=2, relief="sunken", width=12, bg=GOOD, justify=RIGHT, textvariable=self._zx_off, ) self.lbl_zy_off = Label(self, text=LBLZYOFF) self.ent_zy_off = Entry( self, border=2, relief="sunken", width=12, bg=GOOD, justify=RIGHT, textvariable=self._zy_off, ) self.lbl_cx_off = Label(self, text=LBLCX) self.ent_cx_off = Entry( self, border=2, relief="sunken", width=12, bg=GOOD, justify=RIGHT, textvariable=self._cx_off, state=DISABLED, ) self.lbl_cy_off = Label(self, text=LBLCY) self.ent_cy_off = Entry( self, border=2, relief="sunken", width=12, bg=GOOD, justify=RIGHT, textvariable=self._cy_off, state=DISABLED, ) self.lbl_niter = Label(self, text=LBLITER, justify=LEFT) self.ent_maxiter = Entry( self, border=2, relief="sunken", bg=GOOD, width=8, justify=RIGHT, textvariable=self._maxiter, ) self.chk_autoiter = Checkbutton(self, text="Auto", variable=self._autoiter, onvalue=1, offvalue=0) self.lbl_theme = Label(self, text=LBLTHEME, justify=LEFT) self.lbl_radius = Label(self, text=LBLRAD, justify=LEFT) self.ent_radius = Entry( self, border=2, relief="sunken", bg=GOOD, width=8, justify=RIGHT, textvariable=self._radius, ) self.lbl_exp = Label(self, text=LBLEXP) self.spn_exp = Spinbox( self, border=2, relief="sunken", bg=GOOD, width=4, from_=2, to=20, wrap=True, textvariable=self._exponent, ) self.sep_1 = ttk.Separator( self, orient=HORIZONTAL, ) self.lbx_theme = Listbox( self, border=2, relief="sunken", bg=GOOD, width=6, height=5, justify=LEFT, exportselection=False, ) self.lbl_shift = Label(self, text=LBLSHIFT, justify=LEFT) self.scl_shift = Scale( self, from_=0, to=100, orient=HORIZONTAL, variable=self._shift, border=2, relief="sunken", sliderlength=20, troughcolor=GOOD, ) self.scrollbar = Scrollbar(self, orient=VERTICAL) self.lbx_theme.config(yscrollcommand=self.scrollbar.set) self.scrollbar.config(command=self.lbx_theme.yview) self.lbx_theme.select_set(0) self.lbx_theme.event_generate("<<ListboxSelect>>") self.lbl_coords = Label(self, text="Re, Im", fg="grey") self.btn_plot = Button( self, text=BTNPLOT, width=8, fg="green", command=lambda: self.__app.frm_fractal.plot(), ) self.btn_cancel = Button( self, text=BTNCAN, width=8, command=lambda: self.__app.frm_fractal.cancel_press(), ) self.btn_reset = Button(self, text=BTNRST, width=8, command=self.reset) self.ent_save = Entry( self, textvariable=self._filename, width=6, border=2, relief="sunken", bg=GOOD, justify=LEFT, ) self._filename.set(self._image_name + str(self._image_num)) self.btn_save = Button(self, text=BTNSAVE, width=8, command=self.save_image) self.lbl_auto = Label(self, text=LBLAUTO, justify=LEFT) self.btn_autozoom = Button( self, text=BTNZOOM, width=8, command=lambda: self.__app.frm_fractal.animate_zoom(), ) self.btn_autospin = Button( self, text=BTNSPIN, width=8, command=lambda: self.__app.frm_fractal.animate_spin(), state=DISABLED, ) self.chk_autosave = Checkbutton(self, text=BTNSAVE, variable=self._autosave, onvalue=1, offvalue=0) self.lbl_frames = Label(self, text=FRMSTXT) self.ent_frames = Entry(self, width=5, border=2, bg=GOOD, justify=RIGHT, textvariable=self._frames) # Get list of available themes for idx, theme in enumerate(THEMES): self.lbx_theme.insert(idx, theme) self.body_arrange() # Position all widgets in frame self.reset() # Reset all settings to their defaults self.set_traces( ) # Trace entry variables for validation and event handling def body_arrange(self): """ Position widgets in frame """ # Position all widgets in their parent frames self.btn_plot.grid(column=0, row=1, ipadx=3, ipady=3, sticky=(W), padx=3, pady=3) self.btn_cancel.grid(column=1, row=1, ipadx=3, ipady=3, sticky=(W), padx=3, pady=3) self.btn_reset.grid(column=2, row=1, ipadx=3, ipady=3, sticky=(W), padx=3, pady=3) self.ent_save.grid(column=0, row=2, columnspan=2, sticky=(W, E), padx=3, pady=3) self.btn_save.grid(column=2, row=2, ipadx=3, ipady=3, sticky=(W), padx=3, pady=3) self.lbl_auto.grid(column=0, row=3, sticky=(W)) self.btn_autozoom.grid(column=1, row=3, ipadx=3, ipady=3, sticky=(W), padx=3, pady=3) self.btn_autospin.grid(column=2, row=3, ipadx=3, ipady=3, sticky=(W), padx=3, pady=3) self.lbl_frames.grid(column=0, row=4, sticky=(W)) self.ent_frames.grid(column=1, row=4, sticky=(W), padx=3, pady=3) self.chk_autosave.grid(column=2, row=4, sticky=(W), padx=3, pady=3) self.sep_1.grid(column=0, row=5, columnspan=3, pady=5, sticky=(W, E)) self.lbl_settype.grid(column=0, row=6, sticky=(W)) self.spn_settype.grid(column=1, row=6, columnspan=2, sticky=(W, E), padx=3, pady=3) self.lbl_zoom.grid(column=0, row=7, sticky=(W)) self.ent_zoom.grid(column=1, row=7, columnspan=2, sticky=(W, E), padx=3, pady=3) self.lbl_zoominc.grid(column=0, row=8, sticky=(W)) self.ent_zoominc.grid(column=1, row=8, sticky=(W), padx=3, pady=3) self.lbl_zx_off.grid(column=0, row=9, sticky=(W)) self.ent_zx_off.grid(column=1, row=9, columnspan=2, sticky=(W, E), padx=3, pady=3) self.lbl_zy_off.grid(column=0, row=10, sticky=(W)) self.ent_zy_off.grid(column=1, row=10, columnspan=2, sticky=(W, E), padx=3, pady=3) self.lbl_cx_off.grid(column=0, row=11, sticky=(W)) self.ent_cx_off.grid(column=1, row=11, columnspan=2, sticky=(W, E), padx=3, pady=3) self.lbl_cy_off.grid(column=0, row=12, sticky=(W)) self.ent_cy_off.grid(column=1, row=12, columnspan=2, sticky=(W, E), padx=3, pady=3) self.lbl_niter.grid(column=0, row=13, sticky=(W)) self.ent_maxiter.grid(column=1, row=13, sticky=(W), padx=3, pady=3) self.chk_autoiter.grid(column=2, row=13, sticky=(W), padx=3, pady=3) self.lbl_radius.grid(column=0, row=14, sticky=(W)) self.ent_radius.grid(column=1, row=14, sticky=(W), padx=3, pady=3) self.lbl_exp.grid(column=0, row=15, sticky=(W)) self.spn_exp.grid(column=1, row=15, sticky=(W), padx=3, pady=3) self.lbl_theme.grid(column=0, row=16, sticky=(W)) self.lbx_theme.grid(column=1, row=16, padx=3, pady=3, columnspan=2, sticky=(N, S, W, E)) self.scrollbar.grid(column=2, row=16, sticky=(N, S, E)) self.lbl_shift.grid(column=0, row=17, sticky=(W)) self.scl_shift.grid(column=1, row=17, columnspan=2, padx=3, pady=3, sticky=(W, E)) self.lbx_theme.bind("<<ListboxSelect>>", self.get_sel_theme) def set_traces(self): """ Set up entry variable traces for validation and event handling """ self._validsettings = True self._settype.trace("w", self.val_settings) self._zoom.trace("w", self.val_settings) self._zx_off.trace("w", self.val_settings) self._zy_off.trace("w", self.val_settings) self._cx_off.trace("w", self.val_settings) self._cy_off.trace("w", self.val_settings) self._maxiter.trace("w", self.val_settings) self._radius.trace("w", self.val_settings) self._exponent.trace("w", self.val_settings) self._filename.trace("w", self.val_settings) self._frames.trace("w", self.val_settings) self._zoominc.trace("w", self.val_settings) def val_settings(self, *args, **kwargs): """ Validate all user-entered settings. (A personal choice but I find this user experience more intuitive than the standard validatecommand method for Entry widgets) """ self._validsettings = True self.__app.set_status("") if self.is_float(self.ent_zoom.get()) and self._zoom.get() > 0: flg = GOOD else: flg = BAD self.flag_entry(self.ent_zoom, flg) if self.is_float(self.ent_zx_off.get()): flg = GOOD else: flg = BAD self.flag_entry(self.ent_zx_off, flg) if self.is_float(self.ent_zy_off.get()): flg = GOOD else: flg = BAD self.flag_entry(self.ent_zy_off, flg) if self.is_float(self.ent_cx_off.get()): flg = GOOD else: flg = BAD self.flag_entry(self.ent_cx_off, flg) if self.is_float(self.ent_cy_off.get()): flg = GOOD else: flg = BAD self.flag_entry(self.ent_cy_off, flg) if self.is_integer(self.ent_maxiter.get()) and self._maxiter.get() > 0: flg = GOOD else: flg = BAD self.flag_entry(self.ent_maxiter, flg) if self.is_float(self.ent_radius.get()) and self._radius.get() > 0: flg = GOOD else: flg = BAD self.flag_entry(self.ent_radius, flg) if self.is_integer(self.spn_exp.get()) and self._exponent.get() > 1: flg = GOOD else: flg = BAD self.flag_entry(self.spn_exp, flg) if self.is_integer(self.ent_frames.get()) and self._frames.get() > 0: flg = GOOD else: flg = BAD self.flag_entry(self.ent_frames, flg) if self.is_float(self.ent_zoominc.get()) and self._zoominc.get() > 0: flg = GOOD else: flg = BAD self.flag_entry(self.ent_zoominc, flg) if self.is_filename(self.ent_save.get()): flg = GOOD else: flg = BAD self.flag_entry(self.ent_save, flg) if self.spn_settype.get() in {"Mandelbrot", "Tricorn", "BurningShip"}: self.btn_autospin.config(state=DISABLED) self.ent_cx_off.config(state=DISABLED) self.ent_cy_off.config(state=DISABLED) self._cx_off.set(0) self._cy_off.set(0) flg = GOOD elif self.spn_settype.get() == "Julia": self.btn_autospin.config(state=NORMAL) self.ent_cx_off.config(state=NORMAL) self.ent_cy_off.config(state=NORMAL) flg = GOOD else: flg = BAD self.flag_entry(self.spn_settype, flg) def flag_entry(self, ent, flag): """ Flag entry field as valid or invalid and set global validity status flag. This flag is used throughout to determine whether functions can proceed or not. """ ent.config(bg=flag) if flag == BAD: self._validsettings = False self.__app.set_status(VALERROR, "red") def is_float(self, flag): """ Validate if entry is a float. """ try: float(flag) return True except ValueError: return False def is_integer(self, flag): """ Validate if entry is a positive integer. """ try: int(flag) if int(flag) > 0: return True return False except ValueError: return False def is_filename(self, flag): """ Validate if entry represents a valid filename using a regexp. """ return match("^[\w\-. ]+$", flag) and flag != "" def reset(self): """ Reset settings to defaults. """ self._settype.set("Mandelbrot") self._zoom.set(0.75) self._zx_off.set(-0.5) self._zy_off.set(0.0) self._cx_off.set(0.0) self._cy_off.set(0.0) self._maxiter.set(128) self._radius.set(2.0) self._exponent.set(2) self._frames.set(10) self._zoominc.set(2.0) self._autoiter.set(1) self._autosave.set(0) self._theme.set("Default") self._filename.set("image0") self._shift.set(0) self.set_sel_theme() self.__app.set_status(SETINITTXT) def get_sel_theme(self, *args, **kwargs): """ Get selected theme from listbox and set global variable. """ idx = self.lbx_theme.curselection() if idx == "": idx = 0 self._theme.set(self.lbx_theme.get(idx)) def set_sel_theme(self): """ Lookup index of selected theme and highlight that listbox position. NB: this requires 'exportselection=False' option to be set on listbox to work properly. """ for idx, theme in enumerate(THEMES): if theme == self._theme.get(): self.lbx_theme.activate(idx) self.lbx_theme.see(idx) break def get_settings(self): """ Return all current settings as a dict. """ if not self._validsettings: settings = {"valid": self._validsettings} return settings settings = { "settype": self._settype.get(), "zoom": self._zoom.get(), "zxoffset": self._zx_off.get(), "zyoffset": self._zy_off.get(), "cxoffset": self._cx_off.get(), "cyoffset": self._cy_off.get(), "maxiter": self._maxiter.get(), "autoiter": self._autoiter.get(), "autosave": self._autosave.get(), "radius": self._radius.get(), "exponent": self._exponent.get(), "theme": self._theme.get(), "shift": self._shift.get(), "filepath": self._filepath, "filename": self._filename.get(), "frames": self._frames.get(), "zoominc": self._zoominc.get(), "valid": self._validsettings, } return settings def update_settings(self, **kwargs): """ Update settings from keyword parms. """ if "settype" in kwargs: self._settype.set(kwargs["settype"]) if "zoom" in kwargs: self._zoom.set(kwargs["zoom"]) if "zxoffset" in kwargs: self._zx_off.set(kwargs["zxoffset"]) if "zyoffset" in kwargs: self._zy_off.set(kwargs["zyoffset"]) if "cxoffset" in kwargs: self._cx_off.set(kwargs["cxoffset"]) if "cyoffset" in kwargs: self._cy_off.set(kwargs["cyoffset"]) if "maxiter" in kwargs: self._maxiter.set(kwargs["maxiter"]) if "autoiter" in kwargs: self._autoiter.set(kwargs["autoiter"]) if "autosave" in kwargs: self._autosave.set(kwargs["autosave"]) if "radius" in kwargs: self._radius.set(kwargs["radius"]) if "exponent" in kwargs: self._exponent.set(kwargs["exponent"]) if "filepath" in kwargs: self._filepath.set(kwargs["filepath"]) if "filename" in kwargs: self._filename.set(kwargs["filename"]) if "frames" in kwargs: self._frames.set(kwargs["frames"]) if "zoominc" in kwargs: self._zoominc.set(kwargs["zoominc"]) if "theme" in kwargs: self._theme.set(kwargs["theme"]) self.set_sel_theme() if "shift" in kwargs: self._shift.set(kwargs["shift"]) def set_filepath(self): """ Sets filepath for saved files for the duration of this session. """ default = os.getcwd() # Default _filepath is current working directory if self._filepath is None: self._filepath = filedialog.askdirectory(title=SAVETITLE, initialdir=default, mustexist=True) if self._filepath == "": self._filepath = None # User cancelled return self._filepath def save_image(self): """ Save image as PNG file to selected filepath and automatically increment default image name. NB: currently this will overwrite any existing file of the same name without warning. """ # Bug out if the settings are invalid settings = self.__app.frm_settings.get_settings() if not settings["valid"]: return # Check if image has been created image = self.__app.frm_fractal.mandelbrot.get_image() if image is None: self.__app.set_status(NOIMGERROR, "red") return # Set _filename and path if self.set_filepath() is None: # User cancelled return fname = self._filename.get() fqname = self._filepath + "/" + fname # Save the image along with its metadata try: # image.write(fqname + ".png", format="png") image.save(fqname + ".png", format="png") self.save_metadata() except OSError: self.__app.set_status(SAVEERROR, "red") self._filepath = None return self._image_num += 1 self._filename.set(self._image_name + str(self._image_num)) self.__app.set_status(IMGSAVETXT + fqname + ".png", "green") # Return focus to image frame self.__app.frm_fractal.focus_set() def save_metadata(self): """ Save json file containing meta data associated with image, allowing it to be imported and reproduced. """ if self._filepath is None: if self.set_filepath() is None: # User cancelled return fname = self._filename.get() fqname = self._filepath + "/" + fname filename = fqname + ".json" createtime = strftime("%b %d %Y %H:%M:%S %Z", gmtime()) jsondata = { MODULENAME: { "filename": fqname + ".png", "created": createtime, "settype": self._settype.get(), "zoom": self._zoom.get(), "zoominc": self._zoominc.get(), "frames": self._frames.get(), "escradius": self._radius.get(), "exponent": self._exponent.get(), "maxiter": self._maxiter.get(), "zxoffset": self._zx_off.get(), "zyoffset": self._zy_off.get(), "cxoffset": self._cx_off.get(), "cyoffset": self._cy_off.get(), "theme": self._theme.get(), "shift": self._shift.get(), } } try: with open(filename, "w") as outfile: dump(jsondata, outfile) except OSError: self.__app.set_status(METASAVEERROR, "red") self._filepath = None # Return focus to image frame self.__app.frm_fractal.focus_set() def import_metadata(self): """ Update settings from imported json metadata file. """ # Select and read file try: default = os.getcwd() filepath = filedialog.askopenfilename( initialdir=default, title=SELTITLE, filetypes=(("json files", "*.json"), ("all files", "*.*")), ) if filepath == "": # User cancelled return with open(filepath, "r") as infile: jsondata = infile.read() except OSError: self.__app.set_status(OPENFILEERROR, "red") return # Parse file try: settings = loads(jsondata).get(MODULENAME) # Set plot parameters self._settype.set(settings.get("settype", "Mandelbrot")) self._zoom.set(settings.get("zoom", 1)) self._zoominc.set(settings.get("zoominc", 2.0)) self._frames.set(settings.get("frames", 10)) self._radius.set(settings.get("escradius", 2.0)) self._exponent.set(settings.get("exponent", 2)) self._maxiter.set(settings.get("maxiter", 256)) self._zx_off.set(settings.get("zxoffset", 0)) self._zy_off.set(settings.get("zyoffset", 0)) self._cx_off.set(settings.get("cxoffset", 0)) self._cy_off.set(settings.get("cyoffset", 0)) self._theme.set(settings.get("theme", "Default")) self._shift.set(settings.get("shift", 0)) except OSError: self.__app.set_status(BADJSONERROR, "red") return self.set_sel_theme() fbase = os.path.basename(filepath) filename, fileext = os.path.splitext(fbase) self.__app.set_status( "Metadata file " + filename + fileext + METAPROMPTTXT, "green") # Return focus to image frame self.__app.frm_fractal.focus_set()
def openCalculator(handler): global conversionresulttext, fromCurrencyInput, toCurrencyInput, amountInput, calculatorWindow currencyapi = get("https://api.exchangeratesapi.io/latest", data=None) if currencyapi.status_code == 200: #Check for reponse exchangerates = loads(currencyapi.content.decode()) exchangerates["rates"]["DUCO"] = float(ducofiat) calculatorWindow = Toplevel() calculatorWindow.resizable(False, False) calculatorWindow.title("Duino-Coin Wallet - Calculator") calculatorWindow.configure(background = backgroundColor) calculatorWindow.transient([root]) textFont2 = Font(calculatorWindow, size=12,weight="bold") textFont3 = Font(calculatorWindow, size=14,weight="bold") textFont = Font(calculatorWindow, size=12,weight="normal") Label(calculatorWindow, text="CURRENCY CONVERTER", background = backgroundColor, foreground = foregroundColor, font = textFont3).grid(row=0, column=0) Label(calculatorWindow, text="FROM", background = backgroundColor, foreground = foregroundColor, font = textFont2).grid(row=1, column=0) fromCurrencyInput = Listbox(calculatorWindow, exportselection=False, background = backgroundColor, foreground = foregroundColor, selectbackground = "#7bed9f", border="0", font=textFont, width="20", height="13") fromCurrencyInput.grid(row=2, column=0) i=0 for currency in exchangerates["rates"]: fromCurrencyInput.insert(i, currency) i = i+1 Label(calculatorWindow, text="TO", background = backgroundColor, foreground = foregroundColor, font = textFont2).grid(row=1, column=1) toCurrencyInput = Listbox(calculatorWindow, exportselection=False, foreground = foregroundColor, background = backgroundColor, selectbackground = "#7bed9f", border="0", font=textFont, width="20", height="13") toCurrencyInput.grid(row=2, column=1) i=0 for currency in exchangerates["rates"]: toCurrencyInput.insert(i, currency) i = i+1 toCurrencyInput.select_set(0) toCurrencyInput.event_generate("<<ListboxSelect>>") fromCurrencyInput.select_set(32) fromCurrencyInput.event_generate("<<ListboxSelect>>") Label(calculatorWindow, text="AMOUNT", background = backgroundColor, foreground = foregroundColor, font = textFont2).grid(row=3, column=0) def clear_ccamount_placeholder(self): amountInput.delete("0", "100") amountInput = Entry(calculatorWindow, background = "#7bed9f", foreground=foregroundColor, border="0", font=textFont, width="20") amountInput.grid(row=4, column=0) amountInput.insert("0", str(getBalance())) amountInput.bind("<FocusIn>", clear_ccamount_placeholder) Button(calculatorWindow, text="Convert", background = "#FEEEDA", foreground=foregroundColor, command=currencyConvert, width="22").grid(row=3, column=1, pady=(5, 0)) conversionresulttext = StringVar(calculatorWindow) conversionresulttext.set("RESULT: 0.0") conversionresultLabel = Label(calculatorWindow, textvariable=conversionresulttext, background = backgroundColor, foreground = foregroundColor, font = textFont2) conversionresultLabel.grid(row=4, column=1) Label(calculatorWindow, text=" ", background = backgroundColor, foreground = foregroundColor, font = textFont2).grid(row=5, column=0) calculatorWindow.mainloop()
class BattleshipsDemoClient(Frame): def __init__(self, tk, args): Frame.__init__(self, tk) # empty string for platform's default settings locale.setlocale(locale.LC_ALL, '') self.master = tk tk.title(APP_TITLE) tk.resizable(False, False) try: if WINDOWS: tk.iconbitmap("200x200/icon.ico") else: tk.iconbitmap("@200x200/icon.xbm") except Exception as e: print(e) atexit.register(self.cancel_game) # Init class data fields that we use for storing info that we need for using the API self.bot_id = None self.bot_password = None self.logged_in = False self.game_style_ids = [] self.gameChips = 0 self.gameDeals = 0 self.gameStake = 0 self.gamePrize = 0 self.player_key = None self.play_again = BooleanVar() self.do_not_play_same_user = BooleanVar() self.close_after_game = False self.game_cancelled = False self.in_game = False self.topFrame = Frame(tk, padx=12, pady=12) self.middleFrame = Frame(tk, padx=12) self.middleFrameLeft = Frame(self.middleFrame) self.middleFrameRight = Frame(self.middleFrame) self.middleFrameRighter = Frame(self.middleFrame) self.topFrame.grid(row=0, sticky=W + E) self.middleFrame.grid(row=1, sticky=W) self.middleFrameLeft.grid(row=1, column=0) self.middleFrameRight.grid(row=1, column=1) self.middleFrameRighter.grid(row=1, column=2) # =================================== # Create form elements # Top Frame Elements self.botNameLabel = Label(self.topFrame, text="Bot Name:") self.bot_id_entry = Entry(self.topFrame) self.bot_id_entry.bind('<Return>', self.log_in_if_not) self.bot_id_entry.focus() self.passwordLabel = Label(self.topFrame, text="Password:"******"Login", command=self.log_in_out_clicked) self.balanceLabel = Label(self.topFrame, text="Bot Balance:") self.balance = Label(self.topFrame, text="0") self.close_button = Button(self.topFrame, text="Close", padx=2, command=tk.destroy) # Middle Frame Elements # Middle Frame LEFT Elements self.gameStyleLabel = Label(self.middleFrameLeft, font=(None, 18), pady=0, text="Game Style Selection") self.opponentLabel = Label(self.middleFrameLeft, text="Specify Opponent (optional):") self.specify_opponent_entry = Entry(self.middleFrameLeft) self.do_not_play_same_user_check = Checkbutton( self.middleFrameLeft, text='Don\'t play another bot in same user account as me', var=self.do_not_play_same_user) self.game_styles_listbox = Listbox(self.middleFrameLeft, background='#FFFFFF', height=8) self.game_styles_listbox.bind('<Double-1>', self.find_game_double_clicked) self.game_styles_listbox.bind( '<Return>', self.find_game_double_clicked ) # Not a double click but we want it to do the same thing self.refresh_game_styles_button = Button( self.middleFrameLeft, text="Refresh Game Styles", command=self.refresh_game_styles_clicked) self.thinkingTimeLabel = Label(self.middleFrameLeft, text="Add \"Thinking Time\" (ms):") self.thinking_time_entry = Entry(self.middleFrameLeft) self.auto_play_next_game_check = Checkbutton( self.middleFrameLeft, text='Play another game when complete', var=self.play_again) self.cancel_stop_game_button = Button( self.middleFrameLeft, text=CANCEL_GAME_TEXT, command=self.cancel_stop_game_clicked) self.find_game_button = Button(self.middleFrameLeft, text="Find Game", command=self.find_game_clicked) self.resultText = Message( self.middleFrameLeft, width=300, text="This is where the informational messages will appear") self.spacerLabel = Label(self.middleFrameLeft, text=" ") # Middle Frame RIGHT Elements self.gameTitleLabel = Label(self.middleFrameRight, text="Game Title") self.gameTitleText = Text(self.middleFrameRight, height=3, background='white', spacing1=3, pady=0) self.player = battleships_visuals.BattleshipsVisuals( self.middleFrameRight) # Game Display Table self.opponent = battleships_visuals.BattleshipsVisuals( self.middleFrameRight) # Game Display Table self.gameActionLabel = Label(self.middleFrameRight, text="") # =================================== # Set initial element states self.set_gamestyle_controls_states(DISABLED) self.cancel_stop_game_button.config(state=DISABLED) self.game_styles_listbox.config(background='white') self.thinking_time_entry.insert(0, 100) self.gameTitleText.config(state=DISABLED) self.set_balance(0) self.gameTitleText.tag_configure("center", justify='center') self.gameTitleText.tag_configure("bold", font='-weight bold') # =================================== # Form Layout # Top Frame Form Layout self.topFrame.grid_rowconfigure(0, weight=1) self.botNameLabel.grid(row=0, column=0, sticky=E) self.bot_id_entry.grid(row=0, column=1, sticky=W) self.passwordLabel.grid(row=0, column=2, sticky=E) self.bot_password_entry.grid(row=0, column=3, sticky=W) self.log_in_out_button.grid(row=0, column=4, sticky=E) self.topFrame.grid_columnconfigure(5, weight=1) self.balanceLabel.grid(row=0, column=5, sticky=E) self.balance.grid(row=0, column=6, sticky=W) self.close_button.grid(row=0, column=7, sticky=E, padx=(50, 0)) # Middle Frame Form Layout self.middleFrame.grid_rowconfigure(0, weight=1) self.gameStyleLabel.grid(row=0, column=0, columnspan=1, sticky=W + E) self.spacerLabel.grid(row=0, column=2, sticky=E) self.opponentLabel.grid(row=2, column=0, sticky=W, pady=4) self.specify_opponent_entry.grid(row=2, column=0, sticky=E, pady=4) self.do_not_play_same_user_check.grid(row=3, column=0, columnspan=1, sticky='we', pady=4) self.game_styles_listbox.grid(row=4, column=0, columnspan=1, sticky='we', pady=4) self.find_game_button.grid(row=5, column=0, pady=4, sticky=W) self.refresh_game_styles_button.grid(row=5, column=0, columnspan=1, sticky='', pady=4) self.cancel_stop_game_button.grid(row=5, column=0, sticky=E) self.thinkingTimeLabel.grid(row=6, column=0, sticky=W, pady=4) self.thinking_time_entry.grid(row=6, column=0, sticky=E, pady=4) self.auto_play_next_game_check.grid(row=7, column=0, columnspan=1, sticky=W, pady=4) self.resultText.grid(row=9, column=0, columnspan=2, sticky=W, pady=4) self.middleFrame.grid_columnconfigure(9, weight=1) self.gameTitleLabel.grid(row=0, column=3) self.gameTitleText.grid(row=0, column=3, columnspan=2) self.player.grid(row=1, column=3) self.opponent.grid(row=1, column=4) self.gameActionLabel.grid(row=11, column=3, sticky='w') if args.botid is not None: self.auto_play(args) def auto_play(self, args): self.bot_id_entry.insert(0, args.botid) self.bot_password_entry.insert(0, args.password) self.log_in_out_clicked() self.thinking_time_entry.insert(0, args.timeout) if args.playanothergame: self.auto_play_next_game_check.select() if args.dontplaysameuserbot: self.do_not_play_same_user_check.select() if args.closeaftergame: self.close_after_game = True i = 0 for i in range(self.game_styles_listbox.size()): if args.gamestyle in str(self.game_styles_listbox.get(i)): break self.game_styles_listbox.select_set(i, i) self.find_game_clicked() def log_in_out_clicked(self): """Click handler for the 'Login'/'Logout' button.""" # This means we're logging out if self.logged_in: self.resultText.config(text='Logged Out') self.master.title(APP_TITLE + " (Not Logged In)") self.cancel_game() self.bot_id = 'housebot-competition' self.bot_password = None self.clear_game_title_text() self.gameActionLabel.config(text="") self.reset_game_styles_listbox() self.clear_all_boards() self.opponent.delete("all") self.log_in_out_button.config(text='Login') self.set_login_controls_states(ENABLED) self.set_gamestyle_controls_states(DISABLED) self.logged_in = False self.bot_password_entry.delete(0, 'end') self.set_balance(0) # This means we're logging in else: self.bot_id = self.bot_id_entry.get() self.bot_password = '******' res = self.get_list_of_game_styles() if res['Result'] == 'SUCCESS': self.resultText.config(text='Logged In') game_styles = res['GameStyles'] self.master.title(self.bot_id + " - " + APP_TITLE) self.set_login_controls_states(DISABLED) self.set_gamestyle_controls_states(ENABLED) self.set_game_styles_listbox(game_styles) self.set_balance(res['Balance']) self.log_in_out_button.config(text='Logout') self.logged_in = True else: messagebox.showerror( 'Error', 'Invalid login attempt. Please check the username and password entered.' ) def log_in_if_not(self, _): if not self.logged_in: self.log_in_out_clicked() def clear_all_boards(self): self.player.delete("all") self.opponent.delete("all") self.player.myBoard = None self.opponent.oppBoard = None def set_in_game(self, value): self.in_game = value def set_game_title_text(self, text, tag): self.gameTitleText.config(state=ENABLED) self.gameTitleText.insert("end", text, ("center", tag)) self.gameTitleText.config(state=DISABLED) def clear_game_title_text(self): self.gameTitleText.config(state=ENABLED) self.gameTitleText.delete("1.0", "end") self.gameTitleText.config(state=DISABLED) def set_login_controls_states(self, state): self.bot_id_entry.config(state=state) self.bot_password_entry.config(state=state) def set_gamestyle_controls_states(self, state): self.specify_opponent_entry.config(state=state) self.do_not_play_same_user_check.config(state=state) self.game_styles_listbox.config(state=state) self.find_game_button.config(state=state) self.refresh_game_styles_button.config(state=state) self.auto_play_next_game_check.config(state=state) self.thinking_time_entry.config(state=state) self.opponentLabel.config(state=state) self.thinkingTimeLabel.config(state=state) self.balanceLabel.config(state=state) self.balance.config(state=state) self.gameStyleLabel.config(state=state) self.game_styles_listbox.config(state=state) self.player.config(state=state) self.opponent.config(state=state) def set_balance(self, balance): """Set the balance field""" self.balance['text'] = int_with_commas(balance) self.balance['text'] += ' sat' def get_list_of_game_styles(self): """Get list of game styles from the server.""" req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'GameTypeId': BATTLESHIPS_GAME_TYPE_ID } url = BASE_URL + GET_LIST_OF_GAME_STYLES_EXTENSION return BattleshipsDemoClient.make_api_call(url, req) def set_game_styles_listbox(self, game_styles): """Set the content of the game styles listbox with a list of GameStyle dictionaries. Keyword Arguments: game_styles -- The list of GameStyle dictionaries, this should be obtained through get_list_of_game_styles(). """ self.reset_game_styles_listbox() for index, game_style in enumerate(game_styles): self.game_styles_listbox.insert( index, GAME_STYLE_LISTBOX_TEXT.format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['Ships'], game_style['GameTypeSpecificInfo']['Board Size'], game_style['GameTypeSpecificInfo']['Timeout ms'], game_style['GameTypeSpecificInfo']['DealsTotal'], game_style['GameTypeSpecificInfo']['PercentageLand'], game_style['GameTypeSpecificInfo']['RandomLand'])) self.game_style_ids.append(game_style['GameStyleId']) # self.game_styles_listbox.select_set(GAME_STYLE_LISTBOX_DEFAULT_SELECTION) def reset_game_styles_listbox(self): """Clear the content of the game styles listbox.""" if self.game_styles_listbox.size() != 0: self.game_styles_listbox.delete(0, 'end') self.game_style_ids = [] def refresh_game_styles_clicked(self): """Click handler for the 'Refresh Game Styles' button.""" res = self.get_list_of_game_styles() game_styles = res['GameStyles'] self.set_game_styles_listbox(game_styles) def find_game_clicked(self): """Click handler for the 'Find Game' button""" self.find_game_button.config(state=DISABLED) self.cancel_stop_game_button.config(state=ENABLED) self.clear_all_boards() # Here we dispatch the work to a separate thread, to keep the GUI responsive. if not MAC: threading.Thread(target=self.game_loop, daemon=True).start() else: self.game_loop() # Doesn't work on MACs def find_game_double_clicked(self, _): self.find_game_clicked() def game_loop(self): """Loop through finding and playing games.""" while True: self.clear_all_boards() self.find_game() if self.game_cancelled: break self.play_game() if self.close_after_game: self.close_button.invoke() if self.game_cancelled: break if not self.play_again.get(): break self.find_game_button.config(state=ENABLED) self.cancel_stop_game_button.config(state=DISABLED, text=CANCEL_GAME_TEXT) self.game_cancelled = False def find_game(self): """Find a game.""" offer_game_res = self.offer_game() if offer_game_res['Result'] == 'INVALID_LOGIN_OR_PASSWORD': self.cancel_stop_game_clicked() if 'ErrorMessage' in offer_game_res and offer_game_res[ 'ErrorMessage'] == 'Check of OpponentId failed': self.resultText.config(text='Invalid Opponent ID') else: self.resultText.config(text='Invalid login or password') elif offer_game_res['Result'] == 'INSUFFICIENT_BALANCE': self.cancel_stop_game_clicked() self.resultText.config(text='Insufficient balance') elif offer_game_res['Result'] == 'BOT_IS_INACTIVE': self.cancel_stop_game_clicked() self.resultText.config(text='Bot is inactive') else: self.player_key = offer_game_res['PlayerKey'] if offer_game_res['Result'] == 'WAITING_FOR_GAME': self.wait_for_game() def offer_game(self): """Offer a game.""" opponent_id = self.specify_opponent_entry.get() if len(opponent_id) == 0: opponent_id = None try: game_style_id = self.game_style_ids[int( self.game_styles_listbox.curselection()[0])] except IndexError: self.game_styles_listbox.select_set( GAME_STYLE_LISTBOX_DEFAULT_SELECTION) game_style_id = self.game_style_ids[0] req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'MaximumWaitTime': 1000, 'GameStyleId': game_style_id, 'DontPlayAgainstSameUser': self.do_not_play_same_user.get(), 'DontPlayAgainstSameBot': False, 'OpponentId': opponent_id } url = BASE_URL + OFFER_GAME_EXTENSION return BattleshipsDemoClient.make_api_call(url, req) def wait_for_game(self): """Wait for game to start.""" self.resultText.config(text='Waiting for game') while True: if self.game_cancelled: self.cancel_game() self.find_game_button.config(state=ENABLED) self.cancel_stop_game_button.config(state=DISABLED, text=CANCEL_GAME_TEXT) break poll_results = self.poll_for_game_state() if poll_results['Result'] == 'SUCCESS': break if poll_results['Result'] == 'INVALID_PLAYER_KEY' or poll_results[ 'Result'] == 'GAME_HAS_ENDED' or poll_results[ 'Result'] == 'GAME_WAS_STOPPED': self.game_cancelled = True time.sleep(2) def play_game(self): """Play a game.""" self.resultText.config(text='Playing game') self.in_game = True poll_results = self.poll_for_game_state() if poll_results["Result"] != "SUCCESS": return game_state = poll_results['GameState'] title = format('Game ID: ' + str(game_state['GameId'])) game_style_details = self.game_styles_listbox.get('active').split( " | ") title += format(' / Style: ' + str(self.game_style_ids[int( self.game_styles_listbox.curselection()[0])])) title += format(' / Land: ' + game_style_details[6].split(" ")[2] + '%') title += format(' / Deals: ' + game_style_details[5].split(" ")[1]) title += format(' / ' + game_style_details[7]) title += "\n" versus = format(self.bot_id + ' vs ' + game_state['OpponentId']) self.clear_game_title_text() self.set_game_title_text(title, "") self.set_game_title_text(versus, "bold") self.middleFrame.update() while True: if self.game_cancelled: break if game_state['IsMover']: self.resultText.config(text='Playing Game - Your Turn') move = battleships_move.calculateMove(game_state) move_results = self.make_move(move) if move_results['Result'] == 'INVALID_MOVE': self.resultText.config(text="Invalid Move") elif move_results['Result'] != 'SUCCESS': self.resultText.config(text='Game has ended: ' + move_results['Result']) print("Game ended") break else: game_state = move_results['GameState'] else: self.resultText.config(text="Playing Game - Opponent's Turn") # ---- Code here will be called on your opponent's turn ---- # ---------------------------------------------------------- poll_results = self.poll_for_game_state() if poll_results['Result'] != 'SUCCESS': self.resultText.config(text='Game has ended: ' + poll_results['Result']) break game_state = poll_results['GameState'] if game_state['GameStatus'] != 'RUNNING': break self.middleFrameRight.update() try: if int(self.thinking_time_entry.get()) > 0: time.sleep((int(self.thinking_time_entry.get()) / 1000)) else: time.sleep(0.1) except ValueError: time.sleep(0.1) self.set_in_game(False) def make_move(self, move): """Make a move.""" req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'PlayerKey': self.player_key, 'Move': move } url = BASE_URL + MAKE_MOVE_EXTENSION result = BattleshipsDemoClient.make_api_call(url, req) if result['Result'] == 'SUCCESS' or "GAME_HAS_ENDED" in result[ 'Result']: print(result) try: self.player.draw_game_state(result['GameState'], True) self.opponent.draw_game_state(result['GameState'], False) except Exception as e: print("Gamestate error: " + str(e)) return result def poll_for_game_state(self): """Poll the server for the latest GameState.""" req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'MaximumWaitTime': 1000, 'PlayerKey': self.player_key } url = BASE_URL + POLL_FOR_GAME_STATE_EXTENSION result = BattleshipsDemoClient.make_api_call(url, req) if result['Result'] == 'SUCCESS' or "GAME_HAS_ENDED" in result[ 'Result']: self.player.draw_game_state(result['GameState'], True) self.opponent.draw_game_state(result['GameState'], False) return result def cancel_stop_game_clicked(self): self.game_cancelled = True self.cancel_game() self.find_game_button.config(state=ENABLED) self.cancel_stop_game_button.config(state=DISABLED, text=CANCEL_GAME_TEXT) def cancel_game(self): if self.player_key is None: return req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'PlayerKey': self.player_key } url = BASE_URL + CANCEL_GAME_OFFER_EXTENSION BattleshipsDemoClient.make_api_call(url, req) try: self.resultText.config(text='Cancelled game') except Exception as e: print(str(e) + " -- resultText Message object no longer exists") @staticmethod def make_api_call(url, req): """Make an API call.""" while True: try: res = requests.post(url, json=req, headers=API_CALL_HEADERS, timeout=60.0) try: jres = res.json() if 'Result' in jres: return jres time.sleep(0.1) except ValueError: time.sleep(0.1) except requests.ConnectionError: time.sleep(0.1) except requests.Timeout: time.sleep(0.1) except requests.HTTPError: time.sleep(0.1) except BaseException as e: # Bad code but needed for testing purposes print(e) time.sleep(0.1)
lbl_SelAut = Label(menuCrearBasico, text='Seleccione una opción', fg='white', bg="#354154", font=("Helvetica", 16)) lbl_SelAut.pack(fill="x", pady=(0, 10)) lstbox_Crear = Listbox(menuCrearBasico, width=25, height=4, font=("Helvetica", 16)) lstbox_Crear.pack(pady=(0, 10)) for item in ["F1", "F2", "F3", "F4"]: lstbox_Crear.insert(END, item) lstbox_Crear.select_set(1) bttn_CrearBasico = myButton("Seleccionar", menuCrearBasico) bttn_CrearBasico.button.config( command=lambda: basico(lstbox_Crear.get(ACTIVE), inExp.get())) bttn_back_CrearBasico = myButton("Volver al menú", menuCrearBasico) bttn_back_CrearBasico.button.config(command=lambda: raise_frame(menuPrincipal), bg="#39547f") err_lbl_CrearBasico = Label(menuCrearBasico, text=" ", fg="red", bg="#496ba0", font=("Helvetica", 16)) err_lbl_CrearBasico.pack()
class ChapterListWindow(BaseListMenu): # Window title TITLE = 'Chapter Results' def __init__(self, prior_window, manga_scraper_obj: MangaReaderScraper): # call parent object super().__init__(title=self.TITLE) # set scraper attribute self.scraper = manga_scraper_obj # listbox self.list_box = Listbox(self.frame, width=50, selectmode='single', yscrollcommand=self.scrollbar.set) # Update scraper object with current list of chapters for series. self.scraper.get_chapters_for_series() # Add each chapter number to list box [ self.list_box.insert('end', i) for i in self.scraper.get_chapters.keys() ] # default selection to first index self.list_box.select_set(0) # set scrollbar view to listbox self.scrollbar.config(command=self.list_box.yview) # pack scrollbar self.scrollbar.pack(side='right', fill='y') # set default icon self.iconbitmap(ICON_PATH) # pack frame self.frame.pack() # pack list box self.list_box.pack(pady=15) # inner method for retrieving chapter image files def get_chapter(self, chapter_chosen, chapter_text): try: # Update chapter attribute self.scraper.chapter = chapter_chosen self.scraper.chapter_name = utils.FileRenaming.strip_unwanted_characters( chapter_text) # Download image LoadingBar(func=self.scraper.get_pages) except Exception as e: messagebox.showerror(title='ERROR', message=e) finally: return # OK Button self.ok_btn = Button(self, text='OK', command=lambda: get_chapter( self, chapter_chosen=self.scraper.get_chapters[ self.list_box.selection_get()], chapter_text=self.list_box.selection_get())) self.ok_btn.pack(side='left', padx=(80, 10), pady=10) # closes the current window and restores focus to the prior open window (in this instance, the series results) def close_and_restore_focus(self, prior_window): self.destroy() prior_window.focus_force() prior_window.grab_set() # Cancel Button self.cancel_btn = Button( self, text='Cancel', command=lambda: close_and_restore_focus(self, prior_window)) self.cancel_btn.pack(side='right', padx=(10, 80), pady=10)
class AllNumbers(Frame): def __init__(self, parent, controller): Frame.__init__(self, parent) self.controller = controller self.left_value = StringVar() # the input on the left self.right_value = StringVar() # the input on the right self.OPTIONS = {'binary': 2, 'octal': 8, 'decimal': 10, 'hexadecimal': 16, 'base-2': 2, 'base-3': 3, 'base-4': 4, 'base-5': 5, 'base-6': 6, 'base-7': 7, 'base-8': 8, 'base-9': 9, 'base-10': 10, 'base-11': 11, 'base-12': 12, 'base-13': 13, 'base-14': 14, 'base-15': 15, 'base-16': 16, 'base-17': 17, 'base-18': 18, 'base-19': 19, 'base-20': 20, 'base-21': 21, 'base-22': 22, 'base-23': 23, 'base-24': 24, 'base-25': 25, 'base-26': 26, 'base-27': 27, 'base-28': 28, 'base-29': 29, 'base-30': 30, 'base-31': 31, 'base-32': 32, 'base-33': 33, 'base-34': 34, 'base-35': 35, 'base-36': 36} self.columnconfigure(0, weight=1, pad=5) self.columnconfigure(1, weight=1, pad=5) self.rowconfigure(0, pad=5) self.rowconfigure(1, pad=5) self.rowconfigure(2, pad=5) self.rowconfigure(3, weight=1, pad=5) # Title bbutton = Button(self, text="<", command=lambda: controller.show_frame("MainPage")) bbutton.grid(row=0, column=0, padx=10, sticky=W) title = Label(self, text="All Numbers") title.grid(row=0, columnspan=4, padx=10) # Labels flabel = Label(self, text="From:") flabel.grid(row=1, column=0, padx=10, sticky=W) tlabel = Label(self, text="To:") tlabel.grid(row=1, column=1, padx=10, sticky=W) # In/Outputs self.left = Entry(self, textvariable=self.left_value) self.left.grid(row=2, column=0, padx=10, sticky=E+W) self.right = Entry(self, textvariable=self.right_value) self.right.grid(row=2, column=1, padx=10, sticky=E+W) # Options self.loptions = Listbox(self, exportselection=0) self.loptions.grid(row=3, column=0, padx=12, pady=8, sticky=N+E+S+W) self.roptions = Listbox(self, exportselection=0) self.roptions.grid(row=3, column=1, padx=12, pady=8, sticky=N+E+S+W) self.loptions.bind('<<ListboxSelect>>', lambda a: self.update_outputs(1)) lscroll = Scrollbar(self, command=self.loptions.yview) lscroll.grid(row=3, column=0, pady=8, sticky=N+S+E) self.loptions.configure(yscrollcommand=lscroll.set) self.roptions.bind('<<ListboxSelect>>', lambda a: self.update_outputs(0)) rscroll = Scrollbar(self, command=self.roptions.yview) rscroll.grid(row=3, column=1, pady=8, sticky=N+S+E) self.roptions.configure(yscrollcommand=rscroll.set) # Insert all keys in the dictionary in the listboxes l = ['binary', 'octal', 'decimal', 'hexadecimal'] for i in range(0, 4): self.loptions.insert('end', l[i]) self.roptions.insert('end', l[i]) for i in range(2, 37): self.loptions.insert('end', "base-" + str(i)) self.roptions.insert('end', "base-" + str(i)) self.loptions.select_set(0) # select first item on the left self.roptions.select_set(0) # select first item on the right # If the contents of an entry box change, update each box self.update_in_progress = False self.left_value.trace("w", lambda a,b,c: self.update_outputs(0)) self.right_value.trace("w", lambda a,b,c: self.update_outputs(1)) def update_outputs(self, *args): if self.update_in_progress: return try: self.update_in_progress = True temp_left = self.left_value.get() temp_right = self.right_value.get() lselection = self.loptions.curselection() left_type = self.loptions.get(lselection[0]) rselection = self.roptions.curselection() right_type = self.roptions.get(rselection[0]) x = self.OPTIONS[left_type] y = self.OPTIONS[right_type] if args[0] == 0: self.right_value.set(convert_numbers(temp_left, x, y)) else: self.left_value.set(convert_numbers(temp_right, y, x)) except ValueError: if args[0] == 0: self.right_value.set("Invalid input!") else: self.left_value.set("Invalid input!") except: print("Unexpected error:", sys.exc_info()[0]) raise self.update_in_progress = False
class MusicPanel(Frame): def __init__(self, parent, musicController: IMusicController): super().__init__(parent) self.musicController = musicController self.musicList: List[Music] = [] self.selectedMusicPath: str = None self.__initView() def __initView(self): self.grid_columnconfigure(0, weight=1) self.musicListBox = Listbox(self) self.musicListBox.grid(row=0, column=0, sticky='WE', padx=(10, 0), pady=10) self.musicListBox.bind('<Double-1>', self.musicDoubleClicked) self.musicListBox.bind("<<ListboxSelect>>", self.musicSelected) musicScrollbar = Scrollbar(self, command=self.musicListBox.yview) musicScrollbar.grid(row=0, column=1, sticky='NS', padx=(0, 10), pady=10) self.musicListBox.configure(yscrollcommand=musicScrollbar.set) ################################################################################ skipLabel = Label(self, text=SKIP_TEXT) skipLabel.grid(row=1, column=0) self.skipListBox = Listbox(self, exportselection=0) self.skipListBox.grid(row=2, column=0, sticky='WE', padx=(10, 0), pady=10) skipScrollbar = Scrollbar(self, command=self.skipListBox.yview) skipScrollbar.grid(row=2, column=1, sticky='NS', padx=(0, 10), pady=10) self.skipListBox.configure(yscrollcommand=skipScrollbar.set) self.deleteSkipButton = Button(self, text=DELETE_SKIP_TEXT, command=self.onSkipDelete) self.deleteSkipButton.grid(row=3, column=0, sticky='W', padx=10) ################################################################################ self.addSkipFrame = Frame(self) self.addSkipFrame.grid(row=4, column=0, padx=10, sticky='W') self.addSkipLabel = Label(self.addSkipFrame, text=ADD_SKIP_LABEL_TEXT) self.addSkipLabel.grid(row=0, column=0) self.addSkipStartMinutesTE = Entry(self.addSkipFrame, width=5, exportselection=0) self.addSkipStartMinutesTE.insert(END, '0') self.addSkipStartMinutesTE.grid(row=0, column=1) label = Label(self.addSkipFrame, text=':') label.grid(row=0, column=2) self.addSkipStartSecondsTE = Entry(self.addSkipFrame, width=5, exportselection=0) self.addSkipStartSecondsTE.insert(END, '0') self.addSkipStartSecondsTE.grid(row=0, column=3) label = Label(self.addSkipFrame, text=ADD_SKIP_TO_LABEL_TEXT) label.grid(row=0, column=4) self.addSkipEndMinutesTE = Entry(self.addSkipFrame, width=5, exportselection=0) self.addSkipEndMinutesTE.insert(END, '0') self.addSkipEndMinutesTE.grid(row=0, column=5) label = Label(self.addSkipFrame, text=':') label.grid(row=0, column=6) self.addSkipEndSecondsTE = Entry(self.addSkipFrame, width=5, exportselection=0) self.addSkipEndSecondsTE.insert(END, '0') self.addSkipEndSecondsTE.grid(row=0, column=7) self.addSkipButton = Button(self.addSkipFrame, text=ADD_SKIP_BUTTON_TEXT, command=self.__addSkip) self.addSkipButton.grid(row=0, column=8, padx=2) def displayMusic(self, music: List[Music]): self.musicList = music self.musicListBox.delete(0, 'end') for i in range(len(music)): m = music[i] self.musicListBox.insert(i, m) if self.selectedMusicPath is not None: selectedIndex = -1 for i in range(len(self.musicList)): if self.musicList[i].path == self.selectedMusicPath: selectedIndex = i break if selectedIndex >= 0: self.musicListBox.select_set(selectedIndex) self.musicListBox.event_generate("<<ListboxSelect>>") def musicDoubleClicked(self, event): music = self.musicList[self.musicListBox.curselection()[0]] self.musicController.onMusicDoubleClicked(music) def onSkipDelete(self): musicSelection = self.musicListBox.curselection() skipSelection = self.skipListBox.curselection() if len(skipSelection) <= 0 or len(musicSelection) <= 0: messagebox.showwarning('Warning', DELETE_SKIP_SELECT_MUSIC) return music = self.musicList[musicSelection[0]] self.musicController.onSkipDeleteClicked(music.skips[skipSelection[0]]) def musicSelected(self, event): self.skipListBox.delete(0, 'end') selection = self.musicListBox.curselection() if len(selection) <= 0: return selectedMusic = self.musicList[selection[0]] self.selectedMusicPath = selectedMusic.path if selectedMusic.skips is not None: for i in range(len(selectedMusic.skips)): s = selectedMusic.skips[i] startMinute = int(s.start / 60) startSecond = s.start % 60 stopMinute = int(s.end / 60) stopSecond = s.end % 60 text = f'Skip from {startMinute:02d}:{startSecond:02d} to {stopMinute:02d}:{stopSecond:02d}' self.skipListBox.insert(i, text) def __addSkip(self): selection = self.musicListBox.curselection() if len(selection) <= 0: messagebox.showwarning('Warning', ADD_SKIP_SELECT_MUSIC) return music = self.musicList[selection[0]] try: startMinutes = int(self.addSkipStartMinutesTE.get()) startSeconds = int(self.addSkipStartSecondsTE.get()) endMinutes = int(self.addSkipEndMinutesTE.get()) endSeconds = int(self.addSkipEndSecondsTE.get()) except: messagebox.showwarning('Warning', ADD_SKIP_PARSE_ERROR_TEXT) return start = startMinutes * 60 + startSeconds end = endMinutes * 60 + endSeconds if end <= start: messagebox.showwarning('Warning', ADD_SKIP_END_LOWER_THAN_START) return self.musicController.onSkipAddClicked(music.path, start, end)
class Trace(Module): ''' Module to manage all of the different traces (with unique names/colors) and the Crosshairs objects associated to each one. In particular, handles creation/modfication of traces and crosshairs. ''' def __init__(self, app): info(' - initializing module: Trace') self.app = app # some images for the buttons # Source for icons: https://material.io/tools/icons/?style=outline # License: Apache Version 2.0 www.apache.org/licenses/LICENSE-2.0.txt data_copy = '''R0lGODlhGAAYAPAAAAAAAAAAACH5BAEAAAEALAAAAAAYABgAAAJHjI+pCe3/1oHUSdOunmDvHFTWBYrjUnbMuWIqAqEqCMdt+HI25yrVTZMEcT3NMPXJEZckJdKorCWbU2H0JqvKTBErl+XZFAAAOw''' data_paste = '''R0lGODlhGAAYAPAAAAAAAAAAACH5BAEAAAEALAAAAAAYABgAAAJBjI+pq+DAonlPToqza7rv9FlBeJCSOUJpd3EXm7piDKoi+nkqvnttPaMhUAzeiwJMapJDm8U44+kynCkmiM1qZwUAOw''' self.img_copy = PhotoImage(data=data_copy) self.img_paste = PhotoImage(data=data_paste) self.displayedColour = None #self.app.Data.getCurrentTraceColor() # array of trace names for this directory self.available = self.app.Data.getTopLevel('traces') self.available = [] if self.available == None else self.available # dictionary to hold trace -> [crosshairs] data self.crosshairs = {} # set of currently selected crosshairs self.selected = set() # set of copied crosshairs self.copied = [] # declare & init trace string variable self.traceSV = StringVar() self.traceSV.set('') # frame for (most of) our widgets self.frame = Frame(self.app.LEFT) #, pady=7, padx=7) self.frame.grid(row=4) # listbox to contain all of our traces lbframe = Frame(self.frame) self.scrollbar = Scrollbar(lbframe) self.listbox = Listbox(lbframe, yscrollcommand=self.scrollbar.set, width=12, exportselection=False, takefocus=0) self.scrollbar.config(command=self.listbox.yview) for trace in self.available: self.listbox.insert('end', trace) for i, item in enumerate(self.listbox.get(0, 'end')): # select our "default trace" if item == self.app.Data.getTopLevel('defaultTraceName'): self.listbox.selection_clear(0, 'end') self.listbox.select_set(i) # this module is responsible for so many widgets that we need a different # strategy for keeping track of everything that needs constistent grid() / # grid_remove() behavior self.TkWidgets = [ self.getWidget(Header(self.frame, text="Choose a trace"), row=5, column=0, columnspan=4), self.getWidget(lbframe, row=10, column=0, rowspan=50), self.getWidget(Button(self.frame, text='Set as default', command=self.setDefaultTraceName, takefocus=0), row=10, column=2, columnspan=2), self.getWidget(Button(self.frame, text='Select all', command=self.selectAll, takefocus=0), row=11, column=2, columnspan=2), self.getWidget(Button(self.frame, image=self.img_copy, command=self.copy, takefocus=0), row=12, column=2), # FIXME: add tooltip for "Copy" self.getWidget(Button(self.frame, image=self.img_paste, command=self.paste, takefocus=0), row=12, column=3), # FIXME: add tooltip for "Paste" self.getWidget(Entry(self.frame, width=8, textvariable=self.displayedColour), row=13, column=1, columnspan=2, sticky='w'), self.getWidget(Button(self.frame, text='Recolor', command=self.recolor, takefocus=0), row=13, column=3), self.getWidget(Button(self.frame, text='Clear', command=self.clear, takefocus=0), row=15, column=2, columnspan=2), self.getWidget(Entry(self.frame, width=12, textvariable=self.traceSV), row=100, column=0, sticky='w'), self.getWidget(Button(self.frame, text='New', command=self.newTrace, takefocus=0), row=100, column=2), self.getWidget(Button(self.frame, text='Rename', command=self.renameTrace, takefocus=0), row=100, column=3) ] # there's probably a better way to do this than indexing into self.TkWidgets self.TkWidgets[6]['widget'].bind( '<Return>', lambda ev: self.TkWidgets[0]['widget'].focus()) self.TkWidgets[6]['widget'].bind( '<Escape>', lambda ev: self.TkWidgets[0]['widget'].focus()) self.TkWidgets[9]['widget'].bind( '<Return>', lambda ev: self.TkWidgets[0]['widget'].focus()) self.TkWidgets[9]['widget'].bind( '<Escape>', lambda ev: self.TkWidgets[0]['widget'].focus()) if util.get_platform() == 'Linux': self.app.bind('<Control-r>', self.recolor) self.app.bind('<Control-c>', self.copy) self.app.bind('<Control-v>', self.paste) else: self.app.bind('<Command-r>', self.recolor) self.app.bind('<Command-c>', self.copy) self.app.bind('<Command-v>', self.paste) self.grid() def update(self): ''' on change frames ''' # self.grid() #NOTE this is called during zoom and pan #this means the crosshairs are redrawn for every <Motion> call, which is a lot #we could probably just move them instead self.reset() # clear our crosshairs self.read() # read from file #self.frame.update() #debug("TraceModule", self.frame.winfo_width()) def reset(self): ''' on change files ''' # undraw all the crosshairs for trace in self.crosshairs: for ch in self.crosshairs[trace]: ch.undraw() # and empty out our trackers self.crosshairs = {} self.selected = set() def add(self, x, y, _trace=None, transform=True): ''' add a crosshair to the zoom frame canvas ''' trace = self.getCurrentTraceName() if _trace == None else _trace color = self.available[trace]['color'] ch = Crosshairs(self.app.Dicom.zframe, x, y, color, transform) if trace not in self.crosshairs: self.crosshairs[trace] = [] self.crosshairs[trace].append(ch) return ch def remove(self, ch, write=True): ''' remove a crosshair from the zoom frame canvas ... doesn't actually remove it but instead just makes it "invisible" ''' ch.undraw() if write: self.write() return ch def move(self): ''' called when window resizes to move to correct relative locations''' # trace = self.getCurrentTraceName() if self.crosshairs: for trace in self.crosshairs: for ch in self.crosshairs[trace]: truex, truey = ch.getTrueCoords() ch.x, ch.y = ch.transformTrueToCoords(truex, truey) ch.dragTo((ch.x, ch.y)) def read(self): ''' read a list of crosshair coordinates from the metadata file ''' frame = self.app.frame for trace in self.available: try: newCrosshairs = [] for item in self.app.Data.getTraceCurrentFrame(trace): ch = self.add(item['x'], item['y'], _trace=trace, transform=False) if trace not in self.crosshairs: self.crosshairs[trace] = [] self.crosshairs[trace].append(ch) newCrosshairs.append(ch) self.app.Control.push({'type': 'add', 'chs': newCrosshairs}) except KeyError: pass def write(self): ''' write out the coordinates of all of our crosshairs to the metadata file: ''' trace = self.getCurrentTraceName() traces = [] # prepare trace data in format for metadata array if trace in self.crosshairs: for ch in self.crosshairs[trace]: if ch.isVisible: x, y = ch.getTrueCoords() data = {'x': x, 'y': y} if data not in traces: # add trace to temporary array for including in metadata array traces.append(data) # add to metadata array and update file self.app.Data.setCurrentTraceCurrentFrame(traces) # update tier labels for number of annotated frames self.app.TextGrid.updateTierLabels() def getCurrentTraceName(self): ''' return string of current trace name ''' try: return self.listbox.get(self.listbox.curselection()) except Exception as e: # tkinter.TclError? error('Can\'t select from empty listbox!', e) def setDefaultTraceName(self): ''' wrapper for changing the default trace ''' self.app.Data.setTopLevel('defaultTraceName', self.getCurrentTraceName()) def select(self, ch): ''' select a crosshairs ''' ch.select() self.selected.add(ch) def selectAll(self): ''' select all crosshairs ''' if self.getCurrentTraceName() in self.crosshairs: for ch in self.crosshairs[self.getCurrentTraceName()]: self.select(ch) def unselect(self, ch): ''' unselect a crosshairs ''' ch.unselect() self.selected.remove(ch) def unselectAll(self): ''' unselect all crosshairs ''' for ch in self.selected: ch.unselect() self.selected = set() def getNearClickAllTraces(self, click): ''' takes a click object ( (x,y) tuple ) and returns a list of crosshairs within _CROSSHAIR_SELECT_RADIUS first searches for crosshairs matching the current trace iterates thru the other traces if it doesnt find anything if nothing is found for any trace, returns None ''' # get nearby crosshairs from this trace nearby = self.getNearClickOneTrace(click, self.getCurrentTraceName()) if nearby != None: return nearby # otherwise else: # ... check our other traces to see if they contain any nearby guys for trace in self.available: nearby = self.getNearClickOneTrace(click, trace) # if we got something if nearby != None: # switch to that trace and exit the loop for i, item in enumerate(self.listbox.get(0, 'end')): if item == trace: self.listbox.selection_clear(0, 'end') self.listbox.select_set(i) return nearby return None def getNearClickOneTrace(self, click, trace): ''' takes a click object and a trace and returns a list of crosshairs within util.CROSSHAIR_SELECT_RADIUS of that click ''' # see if we clicked near any existing crosshairs possibleSelections = {} if trace in self.crosshairs: for ch in self.crosshairs[trace]: d = ch.getDistance(click) if d < util.CROSSHAIR_SELECT_RADIUS: if d in possibleSelections: possibleSelections[d].append(ch) else: possibleSelections[d] = [ch] # if we did ... if possibleSelections != {}: # ... get the closest one ... dMin = sorted(possibleSelections.keys())[0] # ... in case of a tie, select a random one ch = random.choice(possibleSelections[dMin]) return ch return None def copy(self, event=None): ''' copies relative positions of selected crosshairs for pasting''' # debug('copy') self.copied = [] if len(self.selected) > 0: for ch in self.selected: self.copied.append(ch.getTrueCoords()) def paste(self, event=None): ''' pastes copied crosshairs and add them to undo/redo buffer ''' if len(self.copied) > 0: newChs = [] for xy in self.copied: ch = self.add(xy[0], xy[1], transform=False) newChs.append(ch) self.write() self.app.Control.push({'type': 'add', 'chs': newChs}) def recolor(self, event=None, trace=None, color=None): ''' change the color of a particular trace ''' trace = self.getCurrentTraceName() if trace == None else trace # grab a new color and save our old color (for generating Control data) newColor = self.getRandomHexColor() if color == None else color oldColor = self.app.Data.getCurrentTraceColor() self.available[trace]['color'] = newColor self.app.Data.setTraceColor(trace, newColor) if trace in self.crosshairs: for ch in self.crosshairs[trace]: ch.recolor(newColor) if trace == None or color == None: self.app.Control.push({ 'type': 'recolor', 'trace': self.getCurrentTraceName(), 'color': oldColor }) self.redoQueue = [] # FIXME: get this to update the widget self.app.Trace.displayedColour = newColor # FIXME: also get the widget to update the colour! return oldColor def clear(self): ''' remove all crosshairs for the current trace ''' # now we remove all the traces and save deleted = [] trace = self.getCurrentTraceName() if trace in self.crosshairs: for ch in self.crosshairs[trace]: if ch.isVisible: deleted.append(ch) self.remove(ch, write=False) self.write() self.app.Control.push({'type': 'delete', 'chs': deleted}) def newTrace(self): ''' add a new trace to our listbox ''' # max length 12 chars (so it displays nicely) name = self.traceSV.get()[:12] # don't want to add traces we already have or empty strings if name not in self.available and len(name) > 0: # choose a random color color = self.getRandomHexColor() # save the new trace name and color to metadata & update vars self.available[name] = {'color': color, 'files': {}} self.app.Data.setTopLevel('traces', self.available) self.traceSV.set('') # update our listbox self.listbox.insert('end', name) self.listbox.selection_clear(0, 'end') self.listbox.select_set(len(self.available) - 1) def renameTrace(self, oldName=None, newName=None): ''' change a trace name from oldName -> newName ''' fromUndo = (oldName != None or newName != None) oldName = self.getCurrentTraceName() if oldName == None else oldName newName = self.traceSV.get()[:12] if newName == None else newName # don't overwrite anything if newName not in self.available and len(newName) > 0: # get data from the old name and change the dictionary key in the metadata data = self.available.pop(oldName) self.available[newName] = data self.app.Data.setTopLevel('traces', self.available) if oldName == self.app.Data.getTopLevel('defaultTraceName'): self.app.Data.setTopLevel('defaultTraceName', newName) self.traceSV.set('') # update our listbox index = self.listbox.curselection() self.listbox.delete(index) self.listbox.insert(index, newName) self.listbox.selection_clear(0, 'end') self.listbox.select_set(index) if not (fromUndo): self.app.Control.push({ 'type': 'rename', 'old': oldName, 'new': newName }) def getRandomHexColor(self): ''' helper for getting a random color ''' return '#%06x' % random.randint(0, 0xFFFFFF) def getWidget(self, widget, row=0, column=0, rowspan=1, columnspan=1, sticky=()): ''' helper for managing all of our widgets ''' return { 'widget': widget, 'row': row, 'rowspan': rowspan, 'column': column, 'columnspan': columnspan, 'sticky': sticky } def grid(self): ''' grid all of our widgets ''' for item in self.TkWidgets: item['widget'].grid(row=item['row'], column=item['column'], rowspan=item['rowspan'], columnspan=item['columnspan'], sticky=item['sticky']) self.listbox.pack(side='left', fill='y') self.scrollbar.pack(side='right', fill='y') def grid_remove(self): ''' remove all of our widgets from the grid ''' for item in self.TkWidgets: item['widget'].grid_remove() self.listbox.packforget() self.scrollbar.packforget()
class DemoClient(Frame): def __init__(self, tk, args): Frame.__init__(self, tk) locale.setlocale(locale.LC_ALL, '') # empty string for platform's default settings self.master = tk self.config = json.load(open('config.json', 'r')) self.config['COMBOBOX_INDEX'] = sorted(self.config['COMBOBOX_INDEX'], key=lambda x: x[0]) self.game_type = int( args.gametype ) if args.gametype else self.config["DEFAULT_GAME_TYPE_ID"] tk.title(self.config["APP_TITLE"]) tk.resizable(False, False) self.get_icon() atexit.register(self.cancel_game) # Init class data fields that we use for storing info that we need for using the API self.bot_id = None self.bot_password = None self.logged_in = False self.game_style_ids = [] self.gameChips = 0 self.gameDeals = 0 self.gameStake = 0 self.gamePrize = 0 self.player_key = None self.play_again = BooleanVar() self.do_not_play_same_user = BooleanVar() self.close_after_game = False self.game_cancelled = False self.in_game = False self.topFrame = Frame(tk, padx=12, pady=12) self.middleFrame = Frame(tk, padx=12) self.middleFrameLeft = Frame(self.middleFrame) self.middleFrameRight = Frame(self.middleFrame) self.middleFrameRighter = Frame(self.middleFrame) self.topFrame.grid(row=0, sticky=W + E) self.middleFrame.grid(row=1, sticky=W) self.middleFrameLeft.grid(row=1, column=0) self.middleFrameRight.grid(row=1, column=1) self.middleFrameRighter.grid(row=1, column=2) # =================================== # Create form elements # Top Frame Elements self.botNameLabel = Label(self.topFrame, text="Bot Name:") self.bot_id_entry = Entry(self.topFrame) self.bot_id_entry.bind('<Return>', self.log_in_if_not) self.bot_id_entry.focus() self.passwordLabel = Label(self.topFrame, text="Password:"******"Login", command=self.log_in_out_clicked) self.balanceLabel = Label(self.topFrame, text="Bot Balance:") self.balance = Label(self.topFrame, text="0") self.close_button = Button(self.topFrame, text="Close", padx=2, command=tk.destroy) # Middle Frame Elements # Middle Frame LEFT Elements self.gameTypeCmb = ttk.Combobox( self.middleFrameLeft, state="disabled", values=tuple((game[0]) for game in self.config['COMBOBOX_INDEX'])) if self.game_type != self.config['NULL_GAME_TYPE_ID']: index = [ i for i in range(len(self.config['COMBOBOX_INDEX'])) if self.config['COMBOBOX_INDEX'][i][1] == self.game_type ][0] self.gameTypeCmb.current( index) # Default selection matches default game type id self.gameTypeCmb.bind("<<ComboboxSelected>>", self.game_type_selected) self.gameStyleLabel = Label(self.middleFrameLeft, font=(None, 18), pady=0, text="Game Style Selection") self.opponentLabel = Label(self.middleFrameLeft, text="Specify Opponent (optional):") self.specify_opponent_cmb = ttk.Combobox( self.middleFrameLeft, values=self.config['AVAILABLE_OPPONENTS']) self.do_not_play_same_user_check = Checkbutton( self.middleFrameLeft, text='Don\'t play another bot in same user account as me', var=self.do_not_play_same_user) self.game_styles_listbox = Listbox(self.middleFrameLeft, background='#FFFFFF', height=8) self.game_styles_listbox.bind('<Double-1>', self.find_game_double_clicked) self.game_styles_listbox.bind( '<Return>', self.find_game_double_clicked ) # Not a double click but we want it to do the same thing self.refresh_game_styles_button = Button( self.middleFrameLeft, text="Refresh Game Styles", command=self.refresh_game_styles_clicked) self.thinkingTimeLabel = Label(self.middleFrameLeft, text="Add \"Thinking Time\" (ms):") self.thinking_time_entry = Entry(self.middleFrameLeft) self.auto_play_next_game_check = Checkbutton( self.middleFrameLeft, text='Play another game when complete', var=self.play_again) self.cancel_stop_game_button = Button( self.middleFrameLeft, text=CANCEL_GAME_TEXT, command=self.cancel_stop_game_clicked) self.find_game_button = Button(self.middleFrameLeft, text="Find Game", command=self.find_game_clicked) self.resultText = Message( self.middleFrameLeft, width=300, text="This is where the informational messages will appear") self.spacerLabel = Label(self.middleFrameLeft, text=" ") # Middle Frame RIGHT Elements self.gameTitleLabel = Label(self.middleFrameRight, text="Game Title") self.gameTitleText = Text(self.middleFrameRight, height=3, background='white', spacing1=3, pady=0) self.player = None # Initialise as none before updating in create_visuals() self.opponent = None # Initialise as none before updating in create_visuals() self.create_visuals() self.gameActionLabel = Label(self.middleFrameRight, text="") # =================================== # Set initial element states self.set_gamestyle_controls_states(DISABLED) self.cancel_stop_game_button.config(state=DISABLED) self.game_styles_listbox.config(background='white') self.thinking_time_entry.insert(0, 100) self.gameTitleText.config(state=DISABLED) self.set_balance(0) self.gameTitleText.tag_configure("center", justify='center') self.gameTitleText.tag_configure("bold", font='-weight bold') # =================================== # Form Layout # Top Frame Form Layout self.topFrame.grid_rowconfigure(0, weight=1) self.botNameLabel.grid(row=0, column=0, sticky=E) self.bot_id_entry.grid(row=0, column=1, sticky=W) self.passwordLabel.grid(row=0, column=2, sticky=E) self.bot_password_entry.grid(row=0, column=3, sticky=W) self.log_in_out_button.grid(row=0, column=4, sticky=E) self.topFrame.grid_columnconfigure(5, weight=1) self.balanceLabel.grid(row=0, column=5, sticky=E) self.balance.grid(row=0, column=6, sticky=W) self.close_button.grid(row=0, column=7, sticky=E, padx=(50, 0)) # Middle Frame Form Layout self.middleFrame.grid_rowconfigure(0, weight=1) self.gameTypeCmb.grid(row=0, column=0, columnspan=1, sticky=W + E) self.gameStyleLabel.grid(row=1, column=0, columnspan=1, sticky=W + E) self.spacerLabel.grid(row=1, column=2, sticky=E) self.opponentLabel.grid(row=2, column=0, sticky=W, pady=4) self.specify_opponent_cmb.grid(row=2, column=0, sticky=E, pady=4) self.do_not_play_same_user_check.grid(row=3, column=0, columnspan=1, sticky='we', pady=4) self.game_styles_listbox.grid(row=4, column=0, columnspan=1, sticky='we', pady=4) self.find_game_button.grid(row=5, column=0, pady=4, sticky=W) self.refresh_game_styles_button.grid(row=5, column=0, columnspan=1, sticky='', pady=4) self.cancel_stop_game_button.grid(row=5, column=0, sticky=E) self.thinkingTimeLabel.grid(row=6, column=0, sticky=W, pady=4) self.thinking_time_entry.grid(row=6, column=0, sticky=E, pady=4) self.auto_play_next_game_check.grid(row=7, column=0, columnspan=1, sticky=W, pady=4) self.resultText.grid(row=9, column=0, columnspan=2, sticky=W, pady=4) self.middleFrame.grid_columnconfigure(9, weight=1) self.gameTitleLabel.grid(row=0, column=3) self.gameTitleText.grid(row=0, column=3, columnspan=2) self.gameActionLabel.grid(row=11, column=3, sticky='w') if args.botid is not None and args.password is not None: self.auto_play(args) def auto_play(self, args): self.bot_id_entry.insert(0, args.botid) self.bot_password_entry.insert(0, args.password) self.log_in_out_clicked() self.thinking_time_entry.insert(0, args.timeout) if args.playanothergame: self.auto_play_next_game_check.select() if args.dontplaysameuserbot: self.do_not_play_same_user_check.select() if args.closeaftergame: self.close_after_game = True if args.gamestyle is not None: i = 0 for i in range(self.game_styles_listbox.size()): if args.gamestyle in str(self.game_styles_listbox.get(i)): break self.game_styles_listbox.select_set(i, i) self.find_game_clicked() def log_in_out_clicked(self): """Click handler for the 'Login'/'Logout' button.""" # This means we're logging out if self.logged_in: self.resultText.config(text='Logged Out') self.master.title(self.config["APP_TITLE"] + " (Not Logged In)") self.cancel_game() self.bot_id = None self.bot_password = None self.clear_game_title_text() self.gameActionLabel.config(text="") self.reset_game_styles_listbox() self.clear_all_boards() self.opponent.delete("all") self.log_in_out_button.config(text='Login') self.set_login_controls_states(ENABLED) self.set_gamestyle_controls_states(DISABLED) self.gameTypeCmb.config(state="disabled") self.logged_in = False self.bot_password_entry.delete(0, 'end') self.set_balance(0) # This means we're logging in else: self.bot_id = self.bot_id_entry.get() self.bot_password = self.bot_password_entry.get() res = self.get_list_of_game_styles() if res['Result'] == 'SUCCESS': self.resultText.config(text='Logged In') game_styles = res['GameStyles'] self.master.title(self.bot_id + " - " + self.config["APP_TITLE"]) self.set_login_controls_states(DISABLED) self.set_gamestyle_controls_states(ENABLED) self.gameTypeCmb.config(state="readonly") self.set_game_styles_listbox(game_styles) self.set_balance(res['Balance']) self.log_in_out_button.config(text='Logout') self.logged_in = True else: messagebox.showerror( 'Error', 'Invalid login attempt. Please check the username and password entered.' ) def log_in_if_not(self, _): if not self.logged_in: self.log_in_out_clicked() def clear_all_boards(self): self.player.clear_board() self.opponent.clear_board() self.player.delete("all") self.opponent.delete("all") self.player.myBoard = None self.opponent.oppBoard = None def set_in_game(self, value): self.in_game = value def set_game_title_text(self, text, tag): self.gameTitleText.config(state=ENABLED) self.gameTitleText.insert("end", text, ("center", tag)) self.gameTitleText.config(state=DISABLED) def clear_game_title_text(self): self.gameTitleText.config(state=ENABLED) self.gameTitleText.delete("1.0", "end") self.gameTitleText.config(state=DISABLED) def set_login_controls_states(self, state): self.bot_id_entry.config(state=state) self.bot_password_entry.config(state=state) def set_gamestyle_controls_states(self, state): self.specify_opponent_cmb.config(state=state) self.do_not_play_same_user_check.config(state=state) self.game_styles_listbox.config(state=state) self.find_game_button.config(state=state) self.refresh_game_styles_button.config(state=state) self.auto_play_next_game_check.config(state=state) self.thinking_time_entry.config(state=state) self.opponentLabel.config(state=state) self.thinkingTimeLabel.config(state=state) self.balanceLabel.config(state=state) self.balance.config(state=state) self.gameStyleLabel.config(state=state) self.game_styles_listbox.config(state=state) self.player.config(state=state) self.opponent.config(state=state) def set_balance(self, balance): """Set the balance field""" self.balance['text'] = int_with_commas(balance) def get_list_of_game_styles(self): """Get list of game styles from the server.""" req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'GameTypeId': self.game_type } url = self.config["BASE_URL"] + self.config[ "GET_LIST_OF_GAME_STYLES_EXTENSION"] return DemoClient.make_api_call(url, req) def set_game_styles_listbox(self, game_styles): """Set the content of the game styles listbox with a list of GameStyle dictionaries. Keyword Arguments: game_styles -- The list of GameStyle dictionaries, this should be obtained through get_list_of_game_styles(). """ self.reset_game_styles_listbox() for index, game_style in enumerate(game_styles): if self.game_type == self.config["BATTLESHIPS_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["BATTLESHIPS_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['Ships'], game_style['GameTypeSpecificInfo']['Board Size'], game_style['GameTypeSpecificInfo']['Timeout ms'], game_style['GameTypeSpecificInfo']['DealsTotal'], game_style['GameTypeSpecificInfo']['PercentageLand'], game_style['GameTypeSpecificInfo']['RandomLand'])) elif self.game_type == self.config[ "NOUGHTS_AND_CROSSES_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["NOUGHTS_AND_CROSSES_GAME_STYLE_LISTBOX_TEXT"]. format(game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['DealsTotal'], game_style['GameTypeSpecificInfo']['Timeout ms'])) elif self.game_type == self.config[ "TRAVELLING_SALESDRONE_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self. config["TRAVELLING_SALESDRONE_GAME_STYLE_LISTBOX_TEXT"]. format(game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['TotalCities'], game_style['GameTypeSpecificInfo']['DealLength'])) elif self.game_type == self.config["PREDICTIVE_TEXT_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self. config["PREDICTIVE_TEXT_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo'] ['Number of Sentences'], game_style['GameTypeSpecificInfo'] ['Switched Words Game'], game_style['GameTypeSpecificInfo']['Timeout ms'])) elif self.game_type == self.config["TWIST_CUBE_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["TWIST_CUBE_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['cubeSize'], game_style['GameTypeSpecificInfo']['GameLength'])) elif self.game_type == self.config["SLIDING_PUZZLE_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["SLIDING_PUZZLE_GAME_STYLE_LISTBOX_TEXT"]. format(game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['RowSize'], game_style['GameTypeSpecificInfo']['ColumnSize'], game_style['GameTypeSpecificInfo']['TimeLimit'])) elif self.game_type == self.config["BLURRY_WORD_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["BLURRY_WORD_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['NumImages'], game_style['GameTypeSpecificInfo']['GameLength'])) elif self.game_type == self.config["MASTERMIND_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["MASTERMIND_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['NumPegs'], game_style['GameTypeSpecificInfo']['NumColours'], game_style['GameTypeSpecificInfo'] ['DuplicatesAllowed'])) elif self.game_type == self.config[ "WAREHOUSE_LOGISTICS_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["WAREHOUSE_LOGISTICS_GAME_STYLE_LISTBOX_TEXT"]. format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo'] ['WarehouseDimensions'][0], game_style['GameTypeSpecificInfo'] ['WarehouseDimensions'][1])) elif self.game_type == self.config["FOUR_IN_A_ROW_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["FOUR_IN_A_ROW_GAME_STYLE_LISTBOX_TEXT"]. format(game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['Dimensions'][0], game_style['GameTypeSpecificInfo']['Dimensions'][1], game_style['GameTypeSpecificInfo']['Connections'])) elif self.game_type == self.config["WHO_IS_WHO_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["WHO_IS_WHO_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['NumCharacters'], game_style['GameTypeSpecificInfo']['ComparisonRound'])) elif self.game_type == self.config[ "REVERSING_STONES_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["REVERSING_STONES_GAME_STYLE_LISTBOX_TEXT"]. format(game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['Dimensions'][0], game_style['GameTypeSpecificInfo']['Dimensions'][1], game_style['GameTypeSpecificInfo']['Holes'], game_style['GameTypeSpecificInfo']['Timeout ms'])) elif self.game_type == self.config["CHECKERS_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["CHECKERS_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['Dimensions'][0], game_style['GameTypeSpecificInfo']['Dimensions'][1], game_style['GameTypeSpecificInfo']['Timeout ms'])) elif self.game_type == self.config["GO_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["GO_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['Dimensions'][0], game_style['GameTypeSpecificInfo']['Dimensions'][1], "CAPTURE" if game_style['GameTypeSpecificInfo']['IsCaptureGo'] else game_style['GameTypeSpecificInfo']['ScoringMethod'], game_style['GameTypeSpecificInfo']['Timeout ms'])) elif self.game_type == self.config["LEXICO_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["LEXICO_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['Dimensions'][0], game_style['GameTypeSpecificInfo']['Dimensions'][1], game_style['GameTypeSpecificInfo']['TileMultipliers'], game_style['GameTypeSpecificInfo']['Timeout ms'])) elif self.game_type == self.config["DOMINOES_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["DOMINOES_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['SpotNo'], game_style['GameTypeSpecificInfo']['Timeout ms'])) else: raise ValueError('INVALID GAME TYPE PARAMETER') self.game_style_ids.append(game_style['GameStyleId']) # self.game_styles_listbox.select_set(GAME_STYLE_LISTBOX_DEFAULT_SELECTION) def reset_game_styles_listbox(self): """Clear the content of the game styles listbox.""" if self.game_styles_listbox.size() != 0: self.game_styles_listbox.delete(0, 'end') self.game_style_ids = [] def refresh_game_styles_clicked(self): """Click handler for the 'Refresh Game Styles' button.""" res = self.get_list_of_game_styles() game_styles = res['GameStyles'] self.set_game_styles_listbox(game_styles) def find_game_clicked(self): """Click handler for the 'Find Game' button""" self.find_game_button.config(state=DISABLED) self.cancel_stop_game_button.config(state=ENABLED) self.game_styles_listbox.unbind('<Double-1>') self.game_styles_listbox.unbind('<Return>') self.game_styles_listbox.config(state=DISABLED) self.clear_all_boards() # Here we dispatch the work to a separate thread, to keep the GUI responsive. if not MAC: threading.Thread(target=self.game_loop, daemon=True).start() else: self.game_loop() # Doesn't work on MACs def find_game_double_clicked(self, _): self.find_game_clicked() def game_type_selected(self, _): self.game_type = self.config["COMBOBOX_INDEX"][ self.gameTypeCmb.current()][1] res = self.get_list_of_game_styles() if res['Result'] == 'SUCCESS': game_styles = res['GameStyles'] self.set_game_styles_listbox(game_styles) self.get_icon() self.player.destroy() self.opponent.destroy() self.create_visuals() def get_icon(self): try: if WINDOWS: self.master.iconbitmap("assets/{0}/icon.ico".format( self.game_type)) else: self.master.iconbitmap("./assets/{0}/icon.xbm".format( self.game_type)) except Exception as e: print(e) def create_visuals(self): if self.game_type == self.config["NULL_GAME_TYPE_ID"]: self.player = null_visuals.NullVisuals( self.middleFrameRight) # Game Display Table self.opponent = null_visuals.NullVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["BATTLESHIPS_GAME_TYPE_ID"]: self.player = battleships_visuals.BattleshipsVisuals( self.middleFrameRight) # Game Display Table self.opponent = battleships_visuals.BattleshipsVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["NOUGHTS_AND_CROSSES_GAME_TYPE_ID"]: self.player = noughts_and_crosses_visuals.NoughtsAndCrossesVisuals( self.middleFrameRight) # Game Display Table self.opponent = noughts_and_crosses_visuals.NoughtsAndCrossesVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config[ "TRAVELLING_SALESDRONE_GAME_TYPE_ID"]: self.player = travelling_salesdrone_visuals.TravellingSalesdroneVisuals( self.middleFrameRight) # Game Display Table self.opponent = travelling_salesdrone_visuals.TravellingSalesdroneVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["PREDICTIVE_TEXT_GAME_TYPE_ID"]: self.player = predictive_text_visuals.PredictiveTextVisuals( self.middleFrameRight) # Game Display Table self.opponent = predictive_text_visuals.PredictiveTextVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["TWIST_CUBE_GAME_TYPE_ID"]: self.player = twist_cube_visuals.TwistCubeVisuals( self.middleFrameRight) # Game Display Table self.opponent = twist_cube_visuals.TwistCubeVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["SLIDING_PUZZLE_GAME_TYPE_ID"]: self.player = sliding_puzzle_visuals.SlidingPuzzleVisuals( self.middleFrameRight) # Game Display Table self.opponent = sliding_puzzle_visuals.SlidingPuzzleVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["BLURRY_WORD_GAME_TYPE_ID"]: self.player = blurry_word_visuals.MicrosoftCognitiveChallengeVisuals( self.middleFrameRight) # Game Display Table self.opponent = blurry_word_visuals.MicrosoftCognitiveChallengeVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["MASTERMIND_GAME_TYPE_ID"]: self.player = mastermind_visuals.MastermindVisuals( self.middleFrameRight) # Game Display Table self.opponent = mastermind_visuals.MastermindVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["WAREHOUSE_LOGISTICS_GAME_TYPE_ID"]: self.player = warehouse_logistics_visuals.WarehouseLogisticsVisuals( self.middleFrameRight) # Game Display Table self.opponent = warehouse_logistics_visuals.WarehouseLogisticsVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["FOUR_IN_A_ROW_GAME_TYPE_ID"]: self.player = four_in_a_row_visuals.FourInARowVisuals( self.middleFrameRight) # Game Display Table self.opponent = four_in_a_row_visuals.FourInARowVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["WHO_IS_WHO_GAME_TYPE_ID"]: self.player = who_is_who_visuals.WhoIsWhoVisuals( self.middleFrameRight) # Game Display Table self.opponent = who_is_who_visuals.WhoIsWhoVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["REVERSING_STONES_GAME_TYPE_ID"]: self.player = reversing_stones_visuals.ReversingStonesVisuals( self.middleFrameRight) # Game Display Table self.opponent = reversing_stones_visuals.ReversingStonesVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["CHECKERS_GAME_TYPE_ID"]: self.player = checkers_visuals.CheckersVisuals( self.middleFrameRight) # Game Display Table self.opponent = checkers_visuals.CheckersVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["GO_GAME_TYPE_ID"]: self.player = go_visuals.GoVisuals( self.middleFrameRight) # Game Display Table self.opponent = go_visuals.GoVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["LEXICO_GAME_TYPE_ID"]: self.player = lexico_visuals.LexicoVisuals( self.middleFrameRight) # Game Display Table self.opponent = lexico_visuals.LexicoVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["DOMINOES_GAME_TYPE_ID"]: self.player = dominoes_visuals.DominoesVisuals( self.middleFrameRight) # Game Display Table self.opponent = dominoes_visuals.DominoesVisuals( self.middleFrameRight) # Game Display Table else: raise ValueError('INVALID GAME TYPE PARAMETER') self.player.grid(row=1, column=3) self.opponent.grid(row=1, column=4) def game_loop(self): """Loop through finding and playing games.""" while True: self.clear_all_boards() mover.persistentData = {} self.find_game() self.update_balance() if self.game_cancelled: break self.play_game() self.update_balance() if self.close_after_game: self.close_button.invoke() if self.game_cancelled: break if not self.play_again.get(): break self.find_game_button.config(state=ENABLED) self.cancel_stop_game_button.config(state=DISABLED, text=CANCEL_GAME_TEXT) self.game_styles_listbox.bind('<Double-1>', self.find_game_double_clicked) self.game_styles_listbox.bind('<Return>', self.find_game_double_clicked) self.game_styles_listbox.config(state=ENABLED) self.game_cancelled = False def find_game(self): """Find a game.""" offer_game_res = self.offer_game() if offer_game_res['Result'] == 'INVALID_LOGIN_OR_PASSWORD': self.cancel_stop_game_clicked() if 'ErrorMessage' in offer_game_res and offer_game_res[ 'ErrorMessage'] == 'Check of OpponentId failed': self.resultText.config(text='Invalid Opponent ID') else: self.resultText.config(text='Invalid login or password') elif offer_game_res['Result'] == 'INSUFFICIENT_BALANCE': self.cancel_stop_game_clicked() self.resultText.config(text='Insufficient balance') elif offer_game_res['Result'] == 'BOT_IS_INACTIVE': self.cancel_stop_game_clicked() self.resultText.config(text='Bot is inactive') else: self.player_key = offer_game_res['PlayerKey'] if offer_game_res['Result'] == 'WAITING_FOR_GAME': self.wait_for_game() def offer_game(self): """Offer a game.""" self.cancel_game( ) # Cancel the last outstanding game offer that was made opponent_id = self.specify_opponent_cmb.get() if len(opponent_id) == 0: opponent_id = None try: game_style_id = self.game_style_ids[int( self.game_styles_listbox.curselection()[0])] except IndexError: self.game_styles_listbox.select_set( GAME_STYLE_LISTBOX_DEFAULT_SELECTION) game_style_id = self.game_style_ids[0] req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'MaximumWaitTime': 1000, 'GameStyleId': game_style_id, 'DontPlayAgainstSameUser': self.do_not_play_same_user.get(), 'DontPlayAgainstSameBot': False, 'OpponentId': opponent_id } url = self.config["BASE_URL"] + self.config["OFFER_GAME_EXTENSION"] return DemoClient.make_api_call(url, req) def wait_for_game(self): """Wait for game to start.""" self.resultText.config(text='Waiting for game') while True: if self.game_cancelled: self.cancel_game() self.find_game_button.config(state=ENABLED) self.cancel_stop_game_button.config(state=DISABLED, text=CANCEL_GAME_TEXT) self.game_styles_listbox.bind('<Double-1>', self.find_game_double_clicked) self.game_styles_listbox.bind('<Return>', self.find_game_double_clicked) self.game_styles_listbox.config(state=ENABLED) break poll_results = self.poll_for_game_state() if poll_results['Result'] == 'SUCCESS': break if poll_results['Result'] == 'INVALID_PLAYER_KEY' or poll_results[ 'Result'] == 'GAME_HAS_ENDED' or poll_results[ 'Result'] == 'GAME_WAS_STOPPED': self.game_cancelled = True time.sleep(2) def play_game(self): """Play a game.""" self.resultText.config(text='Playing game') self.in_game = True poll_results = self.poll_for_game_state() if poll_results["Result"] != "SUCCESS": return game_state = poll_results['GameState'] title = format('Game ID: ' + str(game_state['GameId'])) title += format(' / Style: ' + str(self.game_style_ids[int( self.game_styles_listbox.curselection()[0])])) title += "\n" versus = format(self.bot_id + ' vs ' + game_state['OpponentId']) self.clear_game_title_text() self.set_game_title_text(title, "") self.set_game_title_text(versus, "bold") self.middleFrame.update() while True: if self.game_cancelled: break if game_state['IsMover']: self.resultText.config(text='Playing Game - Your Turn') move = mover.calculate_move(self.game_type, game_state) move_results = self.make_move(move) if move_results['Result'] == 'INVALID_MOVE': self.resultText.config(text="Invalid Move") elif move_results['Result'] != 'SUCCESS': self.resultText.config(text='Game has ended: ' + move_results['Result']) print(str(move_results)) print("Game ended") break else: game_state = move_results['GameState'] else: self.resultText.config(text="Playing Game - Opponent's Turn") # ---- Code here will be called on your opponent's turn ---- # ---------------------------------------------------------- poll_results = self.poll_for_game_state() if poll_results['Result'] != 'SUCCESS': self.resultText.config(text='Game has ended: ' + poll_results['Result']) break game_state = poll_results['GameState'] if game_state['GameStatus'] != 'RUNNING': break self.middleFrameRight.update() try: if int(self.thinking_time_entry.get()) > 0: time.sleep((int(self.thinking_time_entry.get()) / 1000)) else: time.sleep(0.1) except ValueError: time.sleep(0.1) self.set_in_game(False) def make_move(self, move): """Make a move.""" req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'PlayerKey': self.player_key, 'Move': move } url = self.config["BASE_URL"] + self.config["MAKE_MOVE_EXTENSION"] result = DemoClient.make_api_call(url, req) if result['Result'] == 'SUCCESS' or "GAME_HAS_ENDED" in result[ 'Result']: print(result) try: self.player.draw_game_state(result['GameState'], True) self.opponent.draw_game_state(result['GameState'], False) except Exception as e: print("Gamestate error: " + str(e)) return result def poll_for_game_state(self): """Poll the server for the latest GameState.""" req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'MaximumWaitTime': 1000, 'PlayerKey': self.player_key } url = self.config["BASE_URL"] + self.config[ "POLL_FOR_GAME_STATE_EXTENSION"] result = DemoClient.make_api_call(url, req) if result['Result'] == 'SUCCESS' or "GAME_HAS_ENDED" in result[ 'Result']: self.player.draw_game_state(result['GameState'], True) self.opponent.draw_game_state(result['GameState'], False) return result def cancel_stop_game_clicked(self): self.game_cancelled = True self.cancel_game() self.find_game_button.config(state=ENABLED) self.cancel_stop_game_button.config(state=DISABLED, text=CANCEL_GAME_TEXT) self.game_styles_listbox.bind('<Double-1>', self.find_game_double_clicked) self.game_styles_listbox.bind('<Return>', self.find_game_double_clicked) self.game_styles_listbox.config(state=ENABLED) def cancel_game(self): print("Cancelling last game offer") if self.player_key is None: return req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'PlayerKey': self.player_key } url = self.config["BASE_URL"] + self.config[ "CANCEL_GAME_OFFER_EXTENSION"] DemoClient.make_api_call(url, req) try: self.resultText.config(text='Cancelled game') except Exception as e: print(str(e) + " -- Demo client has been closed") def update_balance(self): res = self.get_list_of_game_styles() self.set_balance(res['Balance']) @staticmethod def make_api_call(url, req): """Make an API call.""" while True: try: res = requests.post(url, json=req, headers=API_CALL_HEADERS, timeout=60.0) try: jres = res.json() if 'Result' in jres: return jres time.sleep(0.1) except ValueError: time.sleep(0.1) except requests.ConnectionError: time.sleep(0.1) except requests.Timeout: time.sleep(0.1) except requests.HTTPError: time.sleep(0.1) except BaseException as e: # Bad code but needed for testing purposes print(e) time.sleep(0.1)
if bb_[nn][1] == 1: list2[bb_[nn][0]].coords(can, x, y, N2.x, N2.y) else: list2[bb_[nn][0]].coords(can, N1.x, N1.y, x, y) itr += 1 root = Tk() root.geometry("900x700") root.title("Distribution") can = Canvas(root, width=w, height=h, bg='grey') can.pack(side=RIGHT) list1 = Listbox(root) list1.select_set(0) list1.pack() list2 = [] #line list list3 = [] #source list list4 = [] #recepteur list list5 = [] #point de rencontre list6 = [] #resultat b3 = Button(root, text="new source") b3.pack() b4 = Button(root, text="new recever") b4.pack() b5 = Button(root, text="new line") #b5.pack() b52 = Button(root, text="new line 2")
class FilePane: def __init__(self, root, items=list(), on_selection=list(), on_close=list()): self.items = items self.item_count = len(items) self.on_selection = on_selection self.on_close = on_close self.window = Toplevel() self.window.title('Files') self.window.transient(root) self.window.protocol("WM_DELETE_WINDOW", self.on_window_close) self.menubar = Menu(self.window) self.menubar.add_command(label='Previous', command=self.previous) self.menubar.add_command(label='Next', command=self.next) # Display the menu self.window.config(menu=self.menubar) self.scrollbar = Scrollbar(self.window, orient='vertical') self.listbox = Listbox(self.window, yscrollcommand=self.scrollbar.set, exportselection=False) self.set_items(items) self.scrollbar.config(command=self.listbox.yview) self.scrollbar.pack(side='right', fill='y') self.listbox.pack(side='left', fill='both', expand=1) self.listbox.bind('<<ListboxSelect>>', self.on_select) def on_window_close(self): for callback in self.on_close: callback() self.window.withdraw() def hide(self): self.window.withdraw() def show(self): self.window.deiconify() def selected_item(self): return self.items[self.listbox.curselection()[0]] def select_index(self, index): self.listbox.selection_clear(0, END) # From https://stackoverflow.com/a/25451279/11628429 self.listbox.select_set( index) #This only sets focus on the first item. self.listbox.event_generate("<<ListboxSelect>>") def set_items(self, items): self.items = items self.item_count = len(items) self.listbox.delete(0, END) for item in items: item = path.split(item)[1] self.listbox.insert(END, item) self.select_index(0) def previous(self): index = self.listbox.curselection()[0] - 1 if index < 0: index = self.item_count - 1 self.select_index(index) def next(self): index = self.listbox.curselection()[0] + 1 if index >= self.item_count: index = 0 self.select_index(index) def on_select(self, event): if self.on_selection: for callback in self.on_selection: callback(self.selected_item())
class GUIChecker(Frame): def __init__(self, master=None): Frame.__init__(self, master) self.master = master self.grid(columnspan=2000) self.__set_default_value() self.__create_widgets() self.__locate_widges() self.setting_on = False def __set_default_value(self): self.ALL_FIELDS = ["系號", "序號", "餘額", "課程名稱(連結課程地圖)", "學分", "時間", "教師姓名*:主負責老師" "已選課人數", "教室", "選必修", "限選條件", "系所名稱", "年級", "組別", "類別", "班別", "業界專家參與", "英語授課", "Moocs", "跨領域學分學程", "備註", "課程碼", "分班碼", "屬性碼"] self.default_choosen_field = ["系號", "序號", "餘額", "課程名稱(連結課程地圖)", "學分", "時間", "教師姓名*:主負責老師"] self.choosen_field = deepcopy(self.default_choosen_field) def __create_widgets(self): self.input_label = Label(self, text="系所代碼 : ") self.input_field = Entry(self, width=30) self.search_btn = Button(self, text="搜尋", command=self.__search_method) self.clear_btn = Button(self, text="清除", command=self.__clear_method) self.setting_btn = Button(self, text="設定", command=self.__setting_method) self.msg_text = Label(self) def __locate_widges(self): self.input_label.grid(row=0, column=0) self.input_field.grid(row=0, column=1, columnspan=6) self.search_btn.grid(row=1, column=0) self.clear_btn.grid(row=1, column=2) self.setting_btn.grid(row=1, column=4) self.msg_text.grid(row=2, column=0) def __search_method(self): department_no = self.input_field.get() self.msg_text['text'] = '查詢中' try: self.__attach_course_table(department_no) except NoCourseAvailableError as e: logging.debug(e) self.msg_text['text'] = '沒有這個系所' except Exception as e: logging.exception('Seach Method: ') self.msg_text['text'] = '未知的錯誤' else: self.msg_text['text'] = '' def __attach_course_table(self, dept_no): courses = self.__search_courses(dept_no) title = list(courses.columns.values) self.__clear_method() self.__set_up_tree_widget(title, len(courses)) for field in title: self.tree.heading(field, text=field) self.tree.column(field, width=font.Font().measure(field)) for index, course in courses.iterrows(): self.tree.insert('', 'end', values=tuple(course.values)) for ix, val in enumerate(course.values): col_w = font.Font().measure(val) + 10 if self.tree.column(title[ix], width=None) < col_w: self.tree.column(title[ix], width=col_w) def __search_courses(self, dept_no): crawler = NckuCourseCrawler(dept_no=dept_no) html = crawler.get_raw_HTML() parser = NckuCourseParser(html) parser.include_fields = self.choosen_field logging.info("Choosen Field: {}".format(self.choosen_field)) courses = parser.parse(sort=True) print(courses) courses['餘額'] = courses['餘額'].apply(int) return courses def __clear_method(self): try: self.__remove_tree_widget() except Exception as e: logging.debug( 'Widget not yet created. Not and Error. {}'.format(e) ) def __remove_tree_widget(self): self.tree_vsb.grid_remove() self.tree_hsb.grid_remove() self.tree.grid_remove() def __set_up_tree_widget(self, title, courses_num): tree_height = min(30, courses_num) self.tree = ttk.Treeview(columns=title, show="headings", height=tree_height) self.tree_vsb = ttk.Scrollbar(orient="vertical", command=self.tree.yview) self.tree_hsb = ttk.Scrollbar(orient="horizontal", command=self.tree.xview) self.tree.configure(yscrollcommand=self.tree_vsb.set, xscrollcommand=self.tree_hsb.set) self.tree.grid(row=3, column=0) self.tree_vsb.grid(row=3, column=1, sticky="ns") self.tree_hsb.grid(row=4, column=0, sticky="we") def __setting_method(self): if not self.setting_on: self.setting_on = True self.setting_win = Toplevel(self) self.setting_win.wm_title("Settings") self.__create_setting_win_widget() def __create_setting_win_widget(self): choose_field_label = Label(self.setting_win, text="選擇欄位") self.__create_choose_field_listbox() confirm_btn = Button(self.setting_win, text="確定", command=self.__confirm_setting) default_btn = Button(self.setting_win, text="回復預設值", command=self.__restore_setting) confirm_btn.grid(row=0, column=0) default_btn.grid(row=0, column=1) choose_field_label.grid(row=1, column=0) def __create_choose_field_listbox(self): self.choose_field_listbox = Listbox(self.setting_win, selectmode=MULTIPLE, height=len(self.ALL_FIELDS)) for i in self.ALL_FIELDS: self.choose_field_listbox.insert(END, i) for index, choosen in enumerate(self.choosen_field): if choosen: self.choose_field_listbox.select_set(index) self.choose_field_listbox.grid(row=1, column=1, sticky="nsew") def __confirm_setting(self): print(self.choose_field_listbox) print(self.choose_field_listbox.curselection()) selections = self.choose_field_listbox.curselection() self.choosen_field = [ self.ALL_FIELDS[col_index] for col_index in selections ] self.setting_win.withdraw() self.setting_on = False def __restore_setting(self): self.choose_field_listbox.grid_remove() self.choosen_field = self.default_choosen_field self.__create_choose_field_listbox()