listeningpy.gui.gui

This module contains the GUI classes for the listeningpy package.

  1"""
  2This module contains the GUI classes for the listeningpy package.
  3"""
  4import customtkinter as ctk
  5import time
  6import logging
  7from typing import Callable
  8from numpy import ndarray
  9# logging.basicConfig(level=logging.INFO)
 10import configparser
 11
 12import sys
 13from listeningpy.stimuli import play_sound
 14from listeningpy.processing import straight
 15from listeningpy.config import person_identifiers
 16
 17class PlayButton(ctk.CTkButton):
 18    '''Customized customtkinter.CTkButton
 19    Attributes
 20    ----------
 21    parent
 22        parent customtkinter widget    
 23
 24    Methods
 25    -------
 26    reset_count()
 27        Resets the click counter variable to 0.
 28    '''
 29    def __init__(self, parent, *args, **kwargs):
 30        ctk.CTkButton.__init__(self, parent, *args, **kwargs)
 31        self.click_count = 0
 32    
 33    def reset_count(self):
 34        self.click_count = 0
 35
 36class InitFrame(ctk.CTkFrame):
 37    def __init__(self, master, test_frame, cfg_file=None, *args, **kwargs):
 38        ctk.CTkFrame.__init__(self, master, *args, **kwargs)
 39        self.test_frame = test_frame
 40        self.first_name = str
 41        self.second_name = str
 42        self.date_of_birth = str
 43        self.gender = str
 44        self.hear_impaired = bool
 45        self.first_name_label = ctk.CTkLabel(self, text='First name:')
 46        self.second_name_label = ctk.CTkLabel(self, text='Second name:')
 47        self.date_of_birth_label = ctk.CTkLabel(self, text='Date of birth:')
 48        self.gender_label = ctk.CTkLabel(self, text='Gender:')
 49        self.hear_impaired_label = ctk.CTkLabel(self, text='Hearing impaired:')
 50
 51
 52
 53        self.first_name_entry = ctk.CTkEntry(self)
 54        self.second_name_entry = ctk.CTkEntry(self)
 55        
 56        self.date_of_birth_frame = ctk.CTkFrame(self)
 57        self.date_of_birth_day_entry = ctk.CTkEntry(
 58            self.date_of_birth_frame,
 59            width=35,
 60            placeholder_text='DD'
 61            )
 62        self.label_slash = ctk.CTkLabel(self.date_of_birth_frame, text='/')
 63        self.date_of_birth_month_entry = ctk.CTkEntry(
 64            self.date_of_birth_frame,
 65            width=35,
 66            placeholder_text='MM'
 67            )
 68        self.label_slash2 = ctk.CTkLabel(self.date_of_birth_frame, text='/')
 69        self.date_of_birth_year_entry = ctk.CTkEntry(
 70            self.date_of_birth_frame,
 71            width=50,
 72            placeholder_text='YYYY'
 73            )
 74
 75        self.gender_menu = ctk.CTkComboBox(self, 
 76            values=['Man', 'Woman', 'Other']
 77            )
 78        
 79        self.hear_impaired_toggle = ctk.CTkSwitch(
 80            self,
 81            text='', 
 82            onvalue=True, 
 83            offvalue=False)
 84
 85        if cfg_file is not None:
 86            self.set_identifiers(cfg_file)
 87
 88        self.start_button = ctk.CTkButton(self, text='Start test', command=self.button_clicked)
 89
 90        self.first_name_label.grid(column=0, row=1,
 91            padx=10,
 92            pady=5,
 93            sticky='e')
 94        self.second_name_label.grid(column=0, row=2,
 95            padx=10,
 96            pady=5,
 97            sticky='e')
 98        self.date_of_birth_label.grid(column=0, row=3,
 99            padx=10,
100            pady=5,
101            sticky='e')
102        self.gender_label.grid(column=0, row=4,
103            padx=10,
104            pady=5,
105            sticky='e')
106        self.hear_impaired_label.grid(column=0, row=5,
107            padx=10,
108            pady=5,
109            sticky='e')
110        
111        self.first_name_entry.grid(column=1, row=1,
112            padx=10,
113            pady=5)
114        self.second_name_entry.grid(column=1, row=2,
115            padx=10,
116            pady=5)
117        self.date_of_birth_frame.grid(column=1, row=3)
118        self.date_of_birth_day_entry.grid(column=0, row=0,
119            padx=1,
120            pady=5)
121        self.label_slash.grid(column=1, row=0,
122            padx=1,
123            pady=5)
124        self.date_of_birth_month_entry.grid(column=2, row=0,
125            padx=1,
126            pady=5)
127        self.label_slash2.grid(column=3, row=0,
128            padx=2,
129            pady=5)
130        self.date_of_birth_year_entry.grid(column=4, row=0,
131            padx=1,
132            pady=5)
133
134        self.gender_menu.grid(column=1, row=4,
135            padx=10,
136            pady=5)
137        self.hear_impaired_toggle.grid(column=1, row=5,
138            padx=10,
139            pady=8, sticky='w')
140        self.start_button.grid(column=1, row=6,
141            padx=10,
142            pady=5)
143    
144    def set_identifiers(self, cfg_file):
145        identifiers = person_identifiers(cfg_file)
146        keys = identifiers.keys()
147        if 'first_name' in keys:
148                self.first_name = identifiers['first_name']
149                self.first_name_entry.insert(0, self.first_name)
150        if 'second_name' in keys:
151            self.second_name = identifiers['second_name']
152            self.second_name_entry.insert(0, self.second_name)
153        if 'date_of_birth' in keys:
154            self.date_of_birth = identifiers['date_of_birth']
155            self.date_of_birth_day_entry.insert(0, self.date_of_birth[:2])
156            self.date_of_birth_month_entry.insert(0, self.date_of_birth[3:5])
157            self.date_of_birth_year_entry.insert(0, self.date_of_birth[6:10])
158        if 'gender' in keys:
159            self.gender = identifiers['gender']
160            self.gender_menu.set(self.gender)
161        if 'hear_impaired' in keys:
162            print(identifiers['hear_impaired'])
163            self.hear_impaired = identifiers['hear_impaired'].lower() == "true"
164            print(self.hear_impaired)
165            if self.hear_impaired:
166                self.hear_impaired_toggle.select()
167
168    def button_clicked(self):
169        self.first_name = self.first_name_entry.get()
170        self.second_name = self.second_name_entry.get()
171        self.date_of_birth = f'{self.date_of_birth_day_entry.get()}/{self.date_of_birth_month_entry.get()}/{self.date_of_birth_year_entry.get()}'
172        self.gender = self.gender_menu.get()
173        self.hear_impaired = self.hear_impaired_toggle.get()
174        self.master.switch_frame(self.test_frame)
175
176class InitFrameAdaptive(ctk.CTkFrame):
177    """A class representing the initial frame for an adaptive test.
178
179    This frame allows the user to input the participant identifier and the sentence set for the test.
180
181    Parameters
182    ----------
183    master : cTK.Widget
184        The master widget.
185    test_frame : _type_
186        The frame representing the test.
187
188    Attributes
189    ----------
190    test_frame : _type_
191        The frame representing the test.
192    timestamp : str
193        The current timestamp in the format "yy-mm-dd_HH-MM".
194    participant : str
195        The participant identifier.
196    sentence_set : str
197        The sentence set for the test.
198    participant_label : ctk.CTkLabel
199        The label for the participant identifier.
200    sentence_set_label : ctk.CTkLabel
201        The label for the sentence set.
202    participant_entry : ctk.CTkEntry
203        The entry field for the participant identifier.
204    sentence_set_entry : ctk.CTkEntry
205        The entry field for the sentence set.
206    start_button : ctk.CTkButton
207        The button to start the test.
208
209    Methods
210    -------
211    button_clicked()
212        Event handler for the button click event. Sets the participant identifier and sentence set,
213        loads the sentences for the test, and switches to the test frame.
214    """
215    def __init__(self, master, test_frame, *args, **kwargs):
216        ctk.CTkFrame.__init__(self, master, *args, **kwargs)
217        self.test_frame : ctk.CTkFrame = test_frame
218        self.timestamp = time.strftime("%y-%m-%d_%H-%M")
219        self.participant = str
220        self.sentence_set = str
221        self.participant_label = ctk.CTkLabel(self, text='Participant identifier:')
222        self.sentence_set_label = ctk.CTkLabel(self, text='Sentence set:')
223        self.participant_entry = ctk.CTkEntry(self)
224        self.sentence_set_entry = ctk.CTkEntry(self)
225        self.start_button = ctk.CTkButton(
226            self, 
227            text='Start test', 
228            command=self.button_clicked)
229        
230        self.participant_label.grid(column=0, row=1,
231            padx=10,
232            pady=5,
233            sticky='e')
234        self.sentence_set_label.grid(column=0, row=2,
235            padx=10,
236            pady=5,
237            sticky='e')
238        self.participant_entry.grid(column=1, row=1,
239            padx=10,
240            pady=5)
241        self.sentence_set_entry.grid(column=1, row=2,
242            padx=10,
243            pady=5)
244        self.start_button.grid(column=1, row=3,
245            padx=10,
246            pady=5)
247        
248    def button_clicked(self):
249        """Handles the button click event.
250
251        This method retrieves the participant and sentence set information from the GUI,
252        sets the ID of the sentence set, loads the sentences, and switches to the test frame.
253
254        """
255        self.participant = self.participant_entry.get()
256        self.sentence_set = self.sentence_set_entry.get()
257        self.test_frame.set_id = self.sentence_set
258        self.test_frame.load_sentences()
259        self.master.switch_frame(self.test_frame)
260        
261class IntermediateFrameAdaptive(ctk.CTkFrame):
262    """A custom frame for intermediate adaptive testing.
263
264    This frame is used to display the intermediate adaptive testing interface.
265    It contains widgets for entering the next sentence set, starting the test,
266    and ending the test.
267
268    Parameters
269    ----------
270    master : tk.Tk
271        The master widget.
272    test_frame : TestFrame
273        The test frame to switch to after starting the test.
274    *args : tuple
275        Additional positional arguments.
276    **kwargs : dict
277        Additional keyword arguments.
278    """
279    def __init__(self, master, test_frame, *args, **kwargs):
280        ctk.CTkFrame.__init__(self, master, *args, **kwargs)
281        self.test_frame = test_frame
282        self.sentence_set = str
283        self.sentence_set_label = ctk.CTkLabel(self, text='Next sentence set:')
284        self.sentence_set_entry = ctk.CTkEntry(self)
285        self.start_button = ctk.CTkButton(
286            self, 
287            text='Start test', 
288            command=self.button_clicked)
289        self.end_button = ctk.CTkButton(
290            self, 
291            text='End test', 
292            command=self.master.destroy)
293        
294        self.sentence_set_label.grid(column=0, row=2,
295            padx=10,
296            pady=5,
297            sticky='e')
298        self.sentence_set_entry.grid(column=1, row=2,
299            padx=10,
300            pady=5)
301        self.start_button.grid(column=1, row=3,
302            padx=10,
303            pady=5)
304        self.end_button.grid(column=1, row=4,
305            padx=10,
306            pady=5,
307            )
308        
309    def button_clicked(self):
310        """Callback function for the start button click event.
311
312        This function is called when the start button is clicked. It retrieves
313        the sentence set entered by the user, sets it in the test frame, loads
314        the sentences for the test, and switches to the test frame.
315        """
316        self.sentence_set = self.sentence_set_entry.get()
317        self.test_frame.set_id = self.sentence_set
318        self.test_frame.load_sentences()
319        self.master.switch_frame(self.test_frame)
320
321def count_add(button: PlayButton):
322    '''Adds 1 to click counter attribute of a PlayButton
323
324    Parameters
325    ----------
326    button : PlayButton
327    '''
328    button.click_count += 1
329
330def first_clicked(button: ctk.CTkButton):
331    '''Checks whether the button is clicked for the first time. In case
332    it is, the current time is stored for future duration evaluation.
333
334    Parameters
335    ----------
336    button : ctk.CTkButton
337    '''
338    if not hasattr(button, 'time') or button.time == 0:
339        button.time = time.time()
340        logging.info("clicked!")
341
342def stopwatch(
343        button_start: PlayButton,
344        button_end: ctk.CTkButton
345        ) -> float:
346    '''Calculates the time needed for the completion of current set.
347
348    Parameters
349    ----------
350    button_start : PlayButton
351        first button clicked
352    button_end : ctk.CTkButton
353        last button clicked ('Next')
354    Returns
355    -------
356    t : float
357        time between first and last click
358    '''
359    t = button_end.time-button_start.time
360    button_start.time = 0
361    button_end.time = 0
362    return t
363
364def play_click(
365        stimuli_path: str,
366        button: PlayButton,
367        next_buttons: list[ctk.CTkButton, ctk.CTkRadioButton],
368        processing_func: Callable[[ndarray, int], ndarray]=straight,
369        **kwargs
370        ) -> None:
371    '''Defines actions for playback buttons.
372
373    - adding 1 to button.click_count
374    - playing stimuli
375    - enables next button
376
377    Parameters
378    ----------
379    stimuli_path : str
380        path to stimuli
381    button : PlayButton
382        button just clicked (for counter)
383    next_buttons : list[ctk.CTkButton, ctk.CTkRadioButton]
384        list of buttons to be enabled after click
385    '''
386    count_add(button)
387    first_clicked(button)
388    logging.info(f"Playing {stimuli_path}")
389    play_sound(path=stimuli_path, processing_func=processing_func, **kwargs)
390    for n in next_buttons:
391        n.configure(state=ctk.NORMAL)
392
393def check_choice(
394        last_played: PlayButton,
395        button_end: ctk.CTkButton
396        ):
397    '''Enables the 'Next' button. Checks whether all stimuli were played and
398    one chosen.
399
400    Parameters
401    ----------
402    last_played : PlayButton
403        last enabled PlayButton
404    button_end : ctk.CTkButton
405        'Next' button
406    '''
407    if last_played.cget("state") == ctk.NORMAL:
408        button_end.configure(state=ctk.NORMAL)
class PlayButton(customtkinter.windows.widgets.ctk_button.CTkButton):
18class PlayButton(ctk.CTkButton):
19    '''Customized customtkinter.CTkButton
20    Attributes
21    ----------
22    parent
23        parent customtkinter widget    
24
25    Methods
26    -------
27    reset_count()
28        Resets the click counter variable to 0.
29    '''
30    def __init__(self, parent, *args, **kwargs):
31        ctk.CTkButton.__init__(self, parent, *args, **kwargs)
32        self.click_count = 0
33    
34    def reset_count(self):
35        self.click_count = 0

Customized customtkinter.CTkButton

Attributes
  • parent: parent customtkinter widget
Methods

reset_count() Resets the click counter variable to 0.

PlayButton(parent, *args, **kwargs)
30    def __init__(self, parent, *args, **kwargs):
31        ctk.CTkButton.__init__(self, parent, *args, **kwargs)
32        self.click_count = 0

Construct a frame widget with the parent MASTER.

Valid resource names: background, bd, bg, borderwidth, class, colormap, container, cursor, height, highlightbackground, highlightcolor, highlightthickness, relief, takefocus, visual, width.

Inherited Members
customtkinter.windows.widgets.ctk_button.CTkButton
destroy
configure
cget
invoke
bind
unbind
focus
focus_set
focus_force
customtkinter.windows.widgets.core_widget_classes.ctk_base_class.CTkBaseClass
config
unbind_all
bind_all
place
place_forget
pack
pack_forget
grid
grid_forget
tkinter.Misc
deletecommand
tk_strictMotif
tk_bisque
tk_setPalette
wait_variable
waitvar
wait_window
wait_visibility
setvar
getvar
getboolean
focus_get
focus_displayof
focus_lastfor
tk_focusFollowsMouse
tk_focusNext
tk_focusPrev
after
after_idle
after_cancel
bell
clipboard_get
clipboard_clear
clipboard_append
grab_current
grab_release
grab_set
grab_set_global
grab_status
option_add
option_clear
option_get
option_readfile
selection_clear
selection_get
selection_handle
selection_own
selection_own_get
send
lower
tkraise
lift
winfo_atom
winfo_atomname
winfo_cells
winfo_children
winfo_class
winfo_colormapfull
winfo_containing
winfo_depth
winfo_exists
winfo_fpixels
winfo_geometry
winfo_height
winfo_id
winfo_interps
winfo_ismapped
winfo_manager
winfo_name
winfo_parent
winfo_pathname
winfo_pixels
winfo_pointerx
winfo_pointerxy
winfo_pointery
winfo_reqheight
winfo_reqwidth
winfo_rgb
winfo_rootx
winfo_rooty
winfo_screen
winfo_screencells
winfo_screendepth
winfo_screenheight
winfo_screenmmheight
winfo_screenmmwidth
winfo_screenvisual
winfo_screenwidth
winfo_server
winfo_toplevel
winfo_viewable
winfo_visual
winfo_visualid
winfo_visualsavailable
winfo_vrootheight
winfo_vrootwidth
winfo_vrootx
winfo_vrooty
winfo_width
winfo_x
winfo_y
update
update_idletasks
bindtags
bind_class
unbind_class
mainloop
quit
nametowidget
register
keys
pack_propagate
propagate
pack_slaves
slaves
place_slaves
grid_anchor
anchor
grid_bbox
bbox
grid_columnconfigure
columnconfigure
grid_location
grid_propagate
grid_rowconfigure
rowconfigure
grid_size
size
grid_slaves
event_add
event_delete
event_generate
event_info
image_names
image_types
tkinter.Pack
pack_configure
forget
pack_info
info
tkinter.Place
place_configure
place_info
tkinter.Grid
grid_configure
grid_remove
grid_info
location
class InitFrame(customtkinter.windows.widgets.ctk_frame.CTkFrame):
 37class InitFrame(ctk.CTkFrame):
 38    def __init__(self, master, test_frame, cfg_file=None, *args, **kwargs):
 39        ctk.CTkFrame.__init__(self, master, *args, **kwargs)
 40        self.test_frame = test_frame
 41        self.first_name = str
 42        self.second_name = str
 43        self.date_of_birth = str
 44        self.gender = str
 45        self.hear_impaired = bool
 46        self.first_name_label = ctk.CTkLabel(self, text='First name:')
 47        self.second_name_label = ctk.CTkLabel(self, text='Second name:')
 48        self.date_of_birth_label = ctk.CTkLabel(self, text='Date of birth:')
 49        self.gender_label = ctk.CTkLabel(self, text='Gender:')
 50        self.hear_impaired_label = ctk.CTkLabel(self, text='Hearing impaired:')
 51
 52
 53
 54        self.first_name_entry = ctk.CTkEntry(self)
 55        self.second_name_entry = ctk.CTkEntry(self)
 56        
 57        self.date_of_birth_frame = ctk.CTkFrame(self)
 58        self.date_of_birth_day_entry = ctk.CTkEntry(
 59            self.date_of_birth_frame,
 60            width=35,
 61            placeholder_text='DD'
 62            )
 63        self.label_slash = ctk.CTkLabel(self.date_of_birth_frame, text='/')
 64        self.date_of_birth_month_entry = ctk.CTkEntry(
 65            self.date_of_birth_frame,
 66            width=35,
 67            placeholder_text='MM'
 68            )
 69        self.label_slash2 = ctk.CTkLabel(self.date_of_birth_frame, text='/')
 70        self.date_of_birth_year_entry = ctk.CTkEntry(
 71            self.date_of_birth_frame,
 72            width=50,
 73            placeholder_text='YYYY'
 74            )
 75
 76        self.gender_menu = ctk.CTkComboBox(self, 
 77            values=['Man', 'Woman', 'Other']
 78            )
 79        
 80        self.hear_impaired_toggle = ctk.CTkSwitch(
 81            self,
 82            text='', 
 83            onvalue=True, 
 84            offvalue=False)
 85
 86        if cfg_file is not None:
 87            self.set_identifiers(cfg_file)
 88
 89        self.start_button = ctk.CTkButton(self, text='Start test', command=self.button_clicked)
 90
 91        self.first_name_label.grid(column=0, row=1,
 92            padx=10,
 93            pady=5,
 94            sticky='e')
 95        self.second_name_label.grid(column=0, row=2,
 96            padx=10,
 97            pady=5,
 98            sticky='e')
 99        self.date_of_birth_label.grid(column=0, row=3,
100            padx=10,
101            pady=5,
102            sticky='e')
103        self.gender_label.grid(column=0, row=4,
104            padx=10,
105            pady=5,
106            sticky='e')
107        self.hear_impaired_label.grid(column=0, row=5,
108            padx=10,
109            pady=5,
110            sticky='e')
111        
112        self.first_name_entry.grid(column=1, row=1,
113            padx=10,
114            pady=5)
115        self.second_name_entry.grid(column=1, row=2,
116            padx=10,
117            pady=5)
118        self.date_of_birth_frame.grid(column=1, row=3)
119        self.date_of_birth_day_entry.grid(column=0, row=0,
120            padx=1,
121            pady=5)
122        self.label_slash.grid(column=1, row=0,
123            padx=1,
124            pady=5)
125        self.date_of_birth_month_entry.grid(column=2, row=0,
126            padx=1,
127            pady=5)
128        self.label_slash2.grid(column=3, row=0,
129            padx=2,
130            pady=5)
131        self.date_of_birth_year_entry.grid(column=4, row=0,
132            padx=1,
133            pady=5)
134
135        self.gender_menu.grid(column=1, row=4,
136            padx=10,
137            pady=5)
138        self.hear_impaired_toggle.grid(column=1, row=5,
139            padx=10,
140            pady=8, sticky='w')
141        self.start_button.grid(column=1, row=6,
142            padx=10,
143            pady=5)
144    
145    def set_identifiers(self, cfg_file):
146        identifiers = person_identifiers(cfg_file)
147        keys = identifiers.keys()
148        if 'first_name' in keys:
149                self.first_name = identifiers['first_name']
150                self.first_name_entry.insert(0, self.first_name)
151        if 'second_name' in keys:
152            self.second_name = identifiers['second_name']
153            self.second_name_entry.insert(0, self.second_name)
154        if 'date_of_birth' in keys:
155            self.date_of_birth = identifiers['date_of_birth']
156            self.date_of_birth_day_entry.insert(0, self.date_of_birth[:2])
157            self.date_of_birth_month_entry.insert(0, self.date_of_birth[3:5])
158            self.date_of_birth_year_entry.insert(0, self.date_of_birth[6:10])
159        if 'gender' in keys:
160            self.gender = identifiers['gender']
161            self.gender_menu.set(self.gender)
162        if 'hear_impaired' in keys:
163            print(identifiers['hear_impaired'])
164            self.hear_impaired = identifiers['hear_impaired'].lower() == "true"
165            print(self.hear_impaired)
166            if self.hear_impaired:
167                self.hear_impaired_toggle.select()
168
169    def button_clicked(self):
170        self.first_name = self.first_name_entry.get()
171        self.second_name = self.second_name_entry.get()
172        self.date_of_birth = f'{self.date_of_birth_day_entry.get()}/{self.date_of_birth_month_entry.get()}/{self.date_of_birth_year_entry.get()}'
173        self.gender = self.gender_menu.get()
174        self.hear_impaired = self.hear_impaired_toggle.get()
175        self.master.switch_frame(self.test_frame)

Frame with rounded corners and border. Default foreground colors are set according to theme. To make the frame transparent set fg_color=None. For detailed information check out the documentation.

InitFrame(master, test_frame, cfg_file=None, *args, **kwargs)
 38    def __init__(self, master, test_frame, cfg_file=None, *args, **kwargs):
 39        ctk.CTkFrame.__init__(self, master, *args, **kwargs)
 40        self.test_frame = test_frame
 41        self.first_name = str
 42        self.second_name = str
 43        self.date_of_birth = str
 44        self.gender = str
 45        self.hear_impaired = bool
 46        self.first_name_label = ctk.CTkLabel(self, text='First name:')
 47        self.second_name_label = ctk.CTkLabel(self, text='Second name:')
 48        self.date_of_birth_label = ctk.CTkLabel(self, text='Date of birth:')
 49        self.gender_label = ctk.CTkLabel(self, text='Gender:')
 50        self.hear_impaired_label = ctk.CTkLabel(self, text='Hearing impaired:')
 51
 52
 53
 54        self.first_name_entry = ctk.CTkEntry(self)
 55        self.second_name_entry = ctk.CTkEntry(self)
 56        
 57        self.date_of_birth_frame = ctk.CTkFrame(self)
 58        self.date_of_birth_day_entry = ctk.CTkEntry(
 59            self.date_of_birth_frame,
 60            width=35,
 61            placeholder_text='DD'
 62            )
 63        self.label_slash = ctk.CTkLabel(self.date_of_birth_frame, text='/')
 64        self.date_of_birth_month_entry = ctk.CTkEntry(
 65            self.date_of_birth_frame,
 66            width=35,
 67            placeholder_text='MM'
 68            )
 69        self.label_slash2 = ctk.CTkLabel(self.date_of_birth_frame, text='/')
 70        self.date_of_birth_year_entry = ctk.CTkEntry(
 71            self.date_of_birth_frame,
 72            width=50,
 73            placeholder_text='YYYY'
 74            )
 75
 76        self.gender_menu = ctk.CTkComboBox(self, 
 77            values=['Man', 'Woman', 'Other']
 78            )
 79        
 80        self.hear_impaired_toggle = ctk.CTkSwitch(
 81            self,
 82            text='', 
 83            onvalue=True, 
 84            offvalue=False)
 85
 86        if cfg_file is not None:
 87            self.set_identifiers(cfg_file)
 88
 89        self.start_button = ctk.CTkButton(self, text='Start test', command=self.button_clicked)
 90
 91        self.first_name_label.grid(column=0, row=1,
 92            padx=10,
 93            pady=5,
 94            sticky='e')
 95        self.second_name_label.grid(column=0, row=2,
 96            padx=10,
 97            pady=5,
 98            sticky='e')
 99        self.date_of_birth_label.grid(column=0, row=3,
100            padx=10,
101            pady=5,
102            sticky='e')
103        self.gender_label.grid(column=0, row=4,
104            padx=10,
105            pady=5,
106            sticky='e')
107        self.hear_impaired_label.grid(column=0, row=5,
108            padx=10,
109            pady=5,
110            sticky='e')
111        
112        self.first_name_entry.grid(column=1, row=1,
113            padx=10,
114            pady=5)
115        self.second_name_entry.grid(column=1, row=2,
116            padx=10,
117            pady=5)
118        self.date_of_birth_frame.grid(column=1, row=3)
119        self.date_of_birth_day_entry.grid(column=0, row=0,
120            padx=1,
121            pady=5)
122        self.label_slash.grid(column=1, row=0,
123            padx=1,
124            pady=5)
125        self.date_of_birth_month_entry.grid(column=2, row=0,
126            padx=1,
127            pady=5)
128        self.label_slash2.grid(column=3, row=0,
129            padx=2,
130            pady=5)
131        self.date_of_birth_year_entry.grid(column=4, row=0,
132            padx=1,
133            pady=5)
134
135        self.gender_menu.grid(column=1, row=4,
136            padx=10,
137            pady=5)
138        self.hear_impaired_toggle.grid(column=1, row=5,
139            padx=10,
140            pady=8, sticky='w')
141        self.start_button.grid(column=1, row=6,
142            padx=10,
143            pady=5)

Construct a frame widget with the parent MASTER.

Valid resource names: background, bd, bg, borderwidth, class, colormap, container, cursor, height, highlightbackground, highlightcolor, highlightthickness, relief, takefocus, visual, width.

Inherited Members
customtkinter.windows.widgets.ctk_frame.CTkFrame
winfo_children
configure
cget
bind
unbind
customtkinter.windows.widgets.core_widget_classes.ctk_base_class.CTkBaseClass
destroy
config
unbind_all
bind_all
place
place_forget
pack
pack_forget
grid
grid_forget
tkinter.Misc
deletecommand
tk_strictMotif
tk_bisque
tk_setPalette
wait_variable
waitvar
wait_window
wait_visibility
setvar
getvar
getboolean
focus_set
focus
focus_force
focus_get
focus_displayof
focus_lastfor
tk_focusFollowsMouse
tk_focusNext
tk_focusPrev
after
after_idle
after_cancel
bell
clipboard_get
clipboard_clear
clipboard_append
grab_current
grab_release
grab_set
grab_set_global
grab_status
option_add
option_clear
option_get
option_readfile
selection_clear
selection_get
selection_handle
selection_own
selection_own_get
send
lower
tkraise
lift
winfo_atom
winfo_atomname
winfo_cells
winfo_class
winfo_colormapfull
winfo_containing
winfo_depth
winfo_exists
winfo_fpixels
winfo_geometry
winfo_height
winfo_id
winfo_interps
winfo_ismapped
winfo_manager
winfo_name
winfo_parent
winfo_pathname
winfo_pixels
winfo_pointerx
winfo_pointerxy
winfo_pointery
winfo_reqheight
winfo_reqwidth
winfo_rgb
winfo_rootx
winfo_rooty
winfo_screen
winfo_screencells
winfo_screendepth
winfo_screenheight
winfo_screenmmheight
winfo_screenmmwidth
winfo_screenvisual
winfo_screenwidth
winfo_server
winfo_toplevel
winfo_viewable
winfo_visual
winfo_visualid
winfo_visualsavailable
winfo_vrootheight
winfo_vrootwidth
winfo_vrootx
winfo_vrooty
winfo_width
winfo_x
winfo_y
update
update_idletasks
bindtags
bind_class
unbind_class
mainloop
quit
nametowidget
register
keys
pack_propagate
propagate
pack_slaves
slaves
place_slaves
grid_anchor
anchor
grid_bbox
bbox
grid_columnconfigure
columnconfigure
grid_location
grid_propagate
grid_rowconfigure
rowconfigure
grid_size
size
grid_slaves
event_add
event_delete
event_generate
event_info
image_names
image_types
tkinter.Pack
pack_configure
forget
pack_info
info
tkinter.Place
place_configure
place_info
tkinter.Grid
grid_configure
grid_remove
grid_info
location
class InitFrameAdaptive(customtkinter.windows.widgets.ctk_frame.CTkFrame):
177class InitFrameAdaptive(ctk.CTkFrame):
178    """A class representing the initial frame for an adaptive test.
179
180    This frame allows the user to input the participant identifier and the sentence set for the test.
181
182    Parameters
183    ----------
184    master : cTK.Widget
185        The master widget.
186    test_frame : _type_
187        The frame representing the test.
188
189    Attributes
190    ----------
191    test_frame : _type_
192        The frame representing the test.
193    timestamp : str
194        The current timestamp in the format "yy-mm-dd_HH-MM".
195    participant : str
196        The participant identifier.
197    sentence_set : str
198        The sentence set for the test.
199    participant_label : ctk.CTkLabel
200        The label for the participant identifier.
201    sentence_set_label : ctk.CTkLabel
202        The label for the sentence set.
203    participant_entry : ctk.CTkEntry
204        The entry field for the participant identifier.
205    sentence_set_entry : ctk.CTkEntry
206        The entry field for the sentence set.
207    start_button : ctk.CTkButton
208        The button to start the test.
209
210    Methods
211    -------
212    button_clicked()
213        Event handler for the button click event. Sets the participant identifier and sentence set,
214        loads the sentences for the test, and switches to the test frame.
215    """
216    def __init__(self, master, test_frame, *args, **kwargs):
217        ctk.CTkFrame.__init__(self, master, *args, **kwargs)
218        self.test_frame : ctk.CTkFrame = test_frame
219        self.timestamp = time.strftime("%y-%m-%d_%H-%M")
220        self.participant = str
221        self.sentence_set = str
222        self.participant_label = ctk.CTkLabel(self, text='Participant identifier:')
223        self.sentence_set_label = ctk.CTkLabel(self, text='Sentence set:')
224        self.participant_entry = ctk.CTkEntry(self)
225        self.sentence_set_entry = ctk.CTkEntry(self)
226        self.start_button = ctk.CTkButton(
227            self, 
228            text='Start test', 
229            command=self.button_clicked)
230        
231        self.participant_label.grid(column=0, row=1,
232            padx=10,
233            pady=5,
234            sticky='e')
235        self.sentence_set_label.grid(column=0, row=2,
236            padx=10,
237            pady=5,
238            sticky='e')
239        self.participant_entry.grid(column=1, row=1,
240            padx=10,
241            pady=5)
242        self.sentence_set_entry.grid(column=1, row=2,
243            padx=10,
244            pady=5)
245        self.start_button.grid(column=1, row=3,
246            padx=10,
247            pady=5)
248        
249    def button_clicked(self):
250        """Handles the button click event.
251
252        This method retrieves the participant and sentence set information from the GUI,
253        sets the ID of the sentence set, loads the sentences, and switches to the test frame.
254
255        """
256        self.participant = self.participant_entry.get()
257        self.sentence_set = self.sentence_set_entry.get()
258        self.test_frame.set_id = self.sentence_set
259        self.test_frame.load_sentences()
260        self.master.switch_frame(self.test_frame)

A class representing the initial frame for an adaptive test.

This frame allows the user to input the participant identifier and the sentence set for the test.

Parameters
  • master (cTK.Widget): The master widget.
  • test_frame (_type_): The frame representing the test.
Attributes
  • test_frame (_type_): The frame representing the test.
  • timestamp (str): The current timestamp in the format "yy-mm-dd_HH-MM".
  • participant (str): The participant identifier.
  • sentence_set (str): The sentence set for the test.
  • participant_label (ctk.CTkLabel): The label for the participant identifier.
  • sentence_set_label (ctk.CTkLabel): The label for the sentence set.
  • participant_entry (ctk.CTkEntry): The entry field for the participant identifier.
  • sentence_set_entry (ctk.CTkEntry): The entry field for the sentence set.
  • start_button (ctk.CTkButton): The button to start the test.
Methods

button_clicked() Event handler for the button click event. Sets the participant identifier and sentence set, loads the sentences for the test, and switches to the test frame.

InitFrameAdaptive(master, test_frame, *args, **kwargs)
216    def __init__(self, master, test_frame, *args, **kwargs):
217        ctk.CTkFrame.__init__(self, master, *args, **kwargs)
218        self.test_frame : ctk.CTkFrame = test_frame
219        self.timestamp = time.strftime("%y-%m-%d_%H-%M")
220        self.participant = str
221        self.sentence_set = str
222        self.participant_label = ctk.CTkLabel(self, text='Participant identifier:')
223        self.sentence_set_label = ctk.CTkLabel(self, text='Sentence set:')
224        self.participant_entry = ctk.CTkEntry(self)
225        self.sentence_set_entry = ctk.CTkEntry(self)
226        self.start_button = ctk.CTkButton(
227            self, 
228            text='Start test', 
229            command=self.button_clicked)
230        
231        self.participant_label.grid(column=0, row=1,
232            padx=10,
233            pady=5,
234            sticky='e')
235        self.sentence_set_label.grid(column=0, row=2,
236            padx=10,
237            pady=5,
238            sticky='e')
239        self.participant_entry.grid(column=1, row=1,
240            padx=10,
241            pady=5)
242        self.sentence_set_entry.grid(column=1, row=2,
243            padx=10,
244            pady=5)
245        self.start_button.grid(column=1, row=3,
246            padx=10,
247            pady=5)

Construct a frame widget with the parent MASTER.

Valid resource names: background, bd, bg, borderwidth, class, colormap, container, cursor, height, highlightbackground, highlightcolor, highlightthickness, relief, takefocus, visual, width.

def button_clicked(self):
249    def button_clicked(self):
250        """Handles the button click event.
251
252        This method retrieves the participant and sentence set information from the GUI,
253        sets the ID of the sentence set, loads the sentences, and switches to the test frame.
254
255        """
256        self.participant = self.participant_entry.get()
257        self.sentence_set = self.sentence_set_entry.get()
258        self.test_frame.set_id = self.sentence_set
259        self.test_frame.load_sentences()
260        self.master.switch_frame(self.test_frame)

Handles the button click event.

This method retrieves the participant and sentence set information from the GUI, sets the ID of the sentence set, loads the sentences, and switches to the test frame.

Inherited Members
customtkinter.windows.widgets.ctk_frame.CTkFrame
winfo_children
configure
cget
bind
unbind
customtkinter.windows.widgets.core_widget_classes.ctk_base_class.CTkBaseClass
destroy
config
unbind_all
bind_all
place
place_forget
pack
pack_forget
grid
grid_forget
tkinter.Misc
deletecommand
tk_strictMotif
tk_bisque
tk_setPalette
wait_variable
waitvar
wait_window
wait_visibility
setvar
getvar
getboolean
focus_set
focus
focus_force
focus_get
focus_displayof
focus_lastfor
tk_focusFollowsMouse
tk_focusNext
tk_focusPrev
after
after_idle
after_cancel
bell
clipboard_get
clipboard_clear
clipboard_append
grab_current
grab_release
grab_set
grab_set_global
grab_status
option_add
option_clear
option_get
option_readfile
selection_clear
selection_get
selection_handle
selection_own
selection_own_get
send
lower
tkraise
lift
winfo_atom
winfo_atomname
winfo_cells
winfo_class
winfo_colormapfull
winfo_containing
winfo_depth
winfo_exists
winfo_fpixels
winfo_geometry
winfo_height
winfo_id
winfo_interps
winfo_ismapped
winfo_manager
winfo_name
winfo_parent
winfo_pathname
winfo_pixels
winfo_pointerx
winfo_pointerxy
winfo_pointery
winfo_reqheight
winfo_reqwidth
winfo_rgb
winfo_rootx
winfo_rooty
winfo_screen
winfo_screencells
winfo_screendepth
winfo_screenheight
winfo_screenmmheight
winfo_screenmmwidth
winfo_screenvisual
winfo_screenwidth
winfo_server
winfo_toplevel
winfo_viewable
winfo_visual
winfo_visualid
winfo_visualsavailable
winfo_vrootheight
winfo_vrootwidth
winfo_vrootx
winfo_vrooty
winfo_width
winfo_x
winfo_y
update
update_idletasks
bindtags
bind_class
unbind_class
mainloop
quit
nametowidget
register
keys
pack_propagate
propagate
pack_slaves
slaves
place_slaves
grid_anchor
anchor
grid_bbox
bbox
grid_columnconfigure
columnconfigure
grid_location
grid_propagate
grid_rowconfigure
rowconfigure
grid_size
size
grid_slaves
event_add
event_delete
event_generate
event_info
image_names
image_types
tkinter.Pack
pack_configure
forget
pack_info
info
tkinter.Place
place_configure
place_info
tkinter.Grid
grid_configure
grid_remove
grid_info
location
class IntermediateFrameAdaptive(customtkinter.windows.widgets.ctk_frame.CTkFrame):
262class IntermediateFrameAdaptive(ctk.CTkFrame):
263    """A custom frame for intermediate adaptive testing.
264
265    This frame is used to display the intermediate adaptive testing interface.
266    It contains widgets for entering the next sentence set, starting the test,
267    and ending the test.
268
269    Parameters
270    ----------
271    master : tk.Tk
272        The master widget.
273    test_frame : TestFrame
274        The test frame to switch to after starting the test.
275    *args : tuple
276        Additional positional arguments.
277    **kwargs : dict
278        Additional keyword arguments.
279    """
280    def __init__(self, master, test_frame, *args, **kwargs):
281        ctk.CTkFrame.__init__(self, master, *args, **kwargs)
282        self.test_frame = test_frame
283        self.sentence_set = str
284        self.sentence_set_label = ctk.CTkLabel(self, text='Next sentence set:')
285        self.sentence_set_entry = ctk.CTkEntry(self)
286        self.start_button = ctk.CTkButton(
287            self, 
288            text='Start test', 
289            command=self.button_clicked)
290        self.end_button = ctk.CTkButton(
291            self, 
292            text='End test', 
293            command=self.master.destroy)
294        
295        self.sentence_set_label.grid(column=0, row=2,
296            padx=10,
297            pady=5,
298            sticky='e')
299        self.sentence_set_entry.grid(column=1, row=2,
300            padx=10,
301            pady=5)
302        self.start_button.grid(column=1, row=3,
303            padx=10,
304            pady=5)
305        self.end_button.grid(column=1, row=4,
306            padx=10,
307            pady=5,
308            )
309        
310    def button_clicked(self):
311        """Callback function for the start button click event.
312
313        This function is called when the start button is clicked. It retrieves
314        the sentence set entered by the user, sets it in the test frame, loads
315        the sentences for the test, and switches to the test frame.
316        """
317        self.sentence_set = self.sentence_set_entry.get()
318        self.test_frame.set_id = self.sentence_set
319        self.test_frame.load_sentences()
320        self.master.switch_frame(self.test_frame)

A custom frame for intermediate adaptive testing.

This frame is used to display the intermediate adaptive testing interface. It contains widgets for entering the next sentence set, starting the test, and ending the test.

Parameters
  • master (tk.Tk): The master widget.
  • test_frame (TestFrame): The test frame to switch to after starting the test.
  • *args (tuple): Additional positional arguments.
  • **kwargs (dict): Additional keyword arguments.
IntermediateFrameAdaptive(master, test_frame, *args, **kwargs)
280    def __init__(self, master, test_frame, *args, **kwargs):
281        ctk.CTkFrame.__init__(self, master, *args, **kwargs)
282        self.test_frame = test_frame
283        self.sentence_set = str
284        self.sentence_set_label = ctk.CTkLabel(self, text='Next sentence set:')
285        self.sentence_set_entry = ctk.CTkEntry(self)
286        self.start_button = ctk.CTkButton(
287            self, 
288            text='Start test', 
289            command=self.button_clicked)
290        self.end_button = ctk.CTkButton(
291            self, 
292            text='End test', 
293            command=self.master.destroy)
294        
295        self.sentence_set_label.grid(column=0, row=2,
296            padx=10,
297            pady=5,
298            sticky='e')
299        self.sentence_set_entry.grid(column=1, row=2,
300            padx=10,
301            pady=5)
302        self.start_button.grid(column=1, row=3,
303            padx=10,
304            pady=5)
305        self.end_button.grid(column=1, row=4,
306            padx=10,
307            pady=5,
308            )

Construct a frame widget with the parent MASTER.

Valid resource names: background, bd, bg, borderwidth, class, colormap, container, cursor, height, highlightbackground, highlightcolor, highlightthickness, relief, takefocus, visual, width.

def button_clicked(self):
310    def button_clicked(self):
311        """Callback function for the start button click event.
312
313        This function is called when the start button is clicked. It retrieves
314        the sentence set entered by the user, sets it in the test frame, loads
315        the sentences for the test, and switches to the test frame.
316        """
317        self.sentence_set = self.sentence_set_entry.get()
318        self.test_frame.set_id = self.sentence_set
319        self.test_frame.load_sentences()
320        self.master.switch_frame(self.test_frame)

Callback function for the start button click event.

This function is called when the start button is clicked. It retrieves the sentence set entered by the user, sets it in the test frame, loads the sentences for the test, and switches to the test frame.

Inherited Members
customtkinter.windows.widgets.ctk_frame.CTkFrame
winfo_children
configure
cget
bind
unbind
customtkinter.windows.widgets.core_widget_classes.ctk_base_class.CTkBaseClass
destroy
config
unbind_all
bind_all
place
place_forget
pack
pack_forget
grid
grid_forget
tkinter.Misc
deletecommand
tk_strictMotif
tk_bisque
tk_setPalette
wait_variable
waitvar
wait_window
wait_visibility
setvar
getvar
getboolean
focus_set
focus
focus_force
focus_get
focus_displayof
focus_lastfor
tk_focusFollowsMouse
tk_focusNext
tk_focusPrev
after
after_idle
after_cancel
bell
clipboard_get
clipboard_clear
clipboard_append
grab_current
grab_release
grab_set
grab_set_global
grab_status
option_add
option_clear
option_get
option_readfile
selection_clear
selection_get
selection_handle
selection_own
selection_own_get
send
lower
tkraise
lift
winfo_atom
winfo_atomname
winfo_cells
winfo_class
winfo_colormapfull
winfo_containing
winfo_depth
winfo_exists
winfo_fpixels
winfo_geometry
winfo_height
winfo_id
winfo_interps
winfo_ismapped
winfo_manager
winfo_name
winfo_parent
winfo_pathname
winfo_pixels
winfo_pointerx
winfo_pointerxy
winfo_pointery
winfo_reqheight
winfo_reqwidth
winfo_rgb
winfo_rootx
winfo_rooty
winfo_screen
winfo_screencells
winfo_screendepth
winfo_screenheight
winfo_screenmmheight
winfo_screenmmwidth
winfo_screenvisual
winfo_screenwidth
winfo_server
winfo_toplevel
winfo_viewable
winfo_visual
winfo_visualid
winfo_visualsavailable
winfo_vrootheight
winfo_vrootwidth
winfo_vrootx
winfo_vrooty
winfo_width
winfo_x
winfo_y
update
update_idletasks
bindtags
bind_class
unbind_class
mainloop
quit
nametowidget
register
keys
pack_propagate
propagate
pack_slaves
slaves
place_slaves
grid_anchor
anchor
grid_bbox
bbox
grid_columnconfigure
columnconfigure
grid_location
grid_propagate
grid_rowconfigure
rowconfigure
grid_size
size
grid_slaves
event_add
event_delete
event_generate
event_info
image_names
image_types
tkinter.Pack
pack_configure
forget
pack_info
info
tkinter.Place
place_configure
place_info
tkinter.Grid
grid_configure
grid_remove
grid_info
location
def count_add(button: PlayButton):
322def count_add(button: PlayButton):
323    '''Adds 1 to click counter attribute of a PlayButton
324
325    Parameters
326    ----------
327    button : PlayButton
328    '''
329    button.click_count += 1

Adds 1 to click counter attribute of a PlayButton

Parameters
  • button (PlayButton):
def first_clicked(button: customtkinter.windows.widgets.ctk_button.CTkButton):
331def first_clicked(button: ctk.CTkButton):
332    '''Checks whether the button is clicked for the first time. In case
333    it is, the current time is stored for future duration evaluation.
334
335    Parameters
336    ----------
337    button : ctk.CTkButton
338    '''
339    if not hasattr(button, 'time') or button.time == 0:
340        button.time = time.time()
341        logging.info("clicked!")

Checks whether the button is clicked for the first time. In case it is, the current time is stored for future duration evaluation.

Parameters
  • button (ctk.CTkButton):
def stopwatch( button_start: PlayButton, button_end: customtkinter.windows.widgets.ctk_button.CTkButton) -> float:
343def stopwatch(
344        button_start: PlayButton,
345        button_end: ctk.CTkButton
346        ) -> float:
347    '''Calculates the time needed for the completion of current set.
348
349    Parameters
350    ----------
351    button_start : PlayButton
352        first button clicked
353    button_end : ctk.CTkButton
354        last button clicked ('Next')
355    Returns
356    -------
357    t : float
358        time between first and last click
359    '''
360    t = button_end.time-button_start.time
361    button_start.time = 0
362    button_end.time = 0
363    return t

Calculates the time needed for the completion of current set.

Parameters
  • button_start (PlayButton): first button clicked
  • button_end (ctk.CTkButton): last button clicked ('Next')
Returns
  • t (float): time between first and last click
def play_click( stimuli_path: str, button: PlayButton, next_buttons: list[customtkinter.windows.widgets.ctk_button.CTkButton, customtkinter.windows.widgets.ctk_radiobutton.CTkRadioButton], processing_func: Callable[[numpy.ndarray, int], numpy.ndarray] = <function straight>, **kwargs) -> None:
365def play_click(
366        stimuli_path: str,
367        button: PlayButton,
368        next_buttons: list[ctk.CTkButton, ctk.CTkRadioButton],
369        processing_func: Callable[[ndarray, int], ndarray]=straight,
370        **kwargs
371        ) -> None:
372    '''Defines actions for playback buttons.
373
374    - adding 1 to button.click_count
375    - playing stimuli
376    - enables next button
377
378    Parameters
379    ----------
380    stimuli_path : str
381        path to stimuli
382    button : PlayButton
383        button just clicked (for counter)
384    next_buttons : list[ctk.CTkButton, ctk.CTkRadioButton]
385        list of buttons to be enabled after click
386    '''
387    count_add(button)
388    first_clicked(button)
389    logging.info(f"Playing {stimuli_path}")
390    play_sound(path=stimuli_path, processing_func=processing_func, **kwargs)
391    for n in next_buttons:
392        n.configure(state=ctk.NORMAL)

Defines actions for playback buttons.

  • adding 1 to button.click_count
  • playing stimuli
  • enables next button
Parameters
  • stimuli_path (str): path to stimuli
  • button (PlayButton): button just clicked (for counter)
  • next_buttons (list[ctk.CTkButton, ctk.CTkRadioButton]): list of buttons to be enabled after click
def check_choice( last_played: PlayButton, button_end: customtkinter.windows.widgets.ctk_button.CTkButton):
394def check_choice(
395        last_played: PlayButton,
396        button_end: ctk.CTkButton
397        ):
398    '''Enables the 'Next' button. Checks whether all stimuli were played and
399    one chosen.
400
401    Parameters
402    ----------
403    last_played : PlayButton
404        last enabled PlayButton
405    button_end : ctk.CTkButton
406        'Next' button
407    '''
408    if last_played.cget("state") == ctk.NORMAL:
409        button_end.configure(state=ctk.NORMAL)

Enables the 'Next' button. Checks whether all stimuli were played and one chosen.

Parameters
  • last_played (PlayButton): last enabled PlayButton
  • button_end (ctk.CTkButton): 'Next' button