From cc092fa01d357e6bb9076e02c52b29fe04a28779 Mon Sep 17 00:00:00 2001 From: NSasquatch Date: Thu, 10 Nov 2016 18:51:57 +0100 Subject: [PATCH] Initial Commit --- __pycache__/eztext.cpython-35.pyc | Bin 0 -> 8571 bytes __pycache__/textinput.cpython-35.pyc | Bin 0 -> 4314 bytes eztext.py | 151 +++++++++++++++++++++++++++ eztext.pyc | Bin 0 -> 9834 bytes main.py | 29 +++++ pygametextinput/InputHandler.py | 35 +++++++ pygametextinput/__init__.py | 6 ++ textinput.py | 146 ++++++++++++++++++++++++++ 8 files changed, 367 insertions(+) create mode 100644 __pycache__/eztext.cpython-35.pyc create mode 100644 __pycache__/textinput.cpython-35.pyc create mode 100644 eztext.py create mode 100644 eztext.pyc create mode 100644 main.py create mode 100644 pygametextinput/InputHandler.py create mode 100644 pygametextinput/__init__.py create mode 100644 textinput.py diff --git a/__pycache__/eztext.cpython-35.pyc b/__pycache__/eztext.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6cee61b33077a1d98c070ad85e10f19efc911e7c GIT binary patch literal 8571 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 literal 0 HcmV?d00001 diff --git a/eztext.py b/eztext.py new file mode 100644 index 0000000..400fa73 --- /dev/null +++ b/eztext.py @@ -0,0 +1,151 @@ +# input lib +from pygame.locals import * +import pygame, string +from pygame.locals import * + +class ConfigError(KeyError): pass + +class Config: + """ A utility for configuration """ + def __init__(self, options, *look_for): + assertions = [] + for key in look_for: + if key[0] in options.keys(): exec('self.'+key[0]+' = options[\''+key[0]+'\']') + else: exec('self.'+key[0]+' = '+key[1]) + assertions.append(key[0]) + for key in options.keys(): + if key not in assertions: raise ConfigError(key+' not expected as option') + +class Input: + """ A text input for pygame apps """ + def __init__(self, **options): + """ Options: x, y, font, color, restricted, maxlength, prompt """ + self.options = Config(options, ['x', '0'], ['y', '0'], ['font', 'pygame.font.Font(None, 32)'], + ['color', '(0,0,0)'], ['restricted', '\'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!"#$%&\\\'()*+,-./:;<=>?@[\]^_`{|}~\''], + ['maxlength', '-1'], ['prompt', '\'\'']) + self.x = self.options.x; self.y = self.options.y + self.font = self.options.font + self.color = self.options.color + self.restricted = self.options.restricted + self.maxlength = self.options.maxlength + self.prompt = self.options.prompt; self.value = '' + self.shifted = False + + def set_pos(self, x, y): + """ Set the position to x, y """ + self.x = x + self.y = y + + def set_font(self, font): + """ Set the font for the input """ + self.font = font + + def draw(self, surface): + """ Draw the text input to a surface """ + text = self.font.render(self.prompt+self.value, 1, self.color) + surface.blit(text, (self.x, self.y)) + + def update(self, events): + """ Update the input based on passed events """ + for event in events: + if event.type == KEYUP: + if event.key == K_LSHIFT or event.key == K_RSHIFT: self.shifted = False + if event.type == KEYDOWN: + if event.key == K_BACKSPACE: self.value = self.value[:-1] + elif event.key == K_LSHIFT or event.key == K_RSHIFT: self.shifted = True + elif event.key == K_SPACE: self.value += ' ' + if not self.shifted: + if event.key == K_a and 'a' in self.restricted: self.value += 'a' + elif event.key == K_b and 'b' in self.restricted: self.value += 'b' + elif event.key == K_c and 'c' in self.restricted: self.value += 'c' + elif event.key == K_d and 'd' in self.restricted: self.value += 'd' + elif event.key == K_e and 'e' in self.restricted: self.value += 'e' + elif event.key == K_f and 'f' in self.restricted: self.value += 'f' + elif event.key == K_g and 'g' in self.restricted: self.value += 'g' + elif event.key == K_h and 'h' in self.restricted: self.value += 'h' + elif event.key == K_i and 'i' in self.restricted: self.value += 'i' + elif event.key == K_j and 'j' in self.restricted: self.value += 'j' + elif event.key == K_k and 'k' in self.restricted: self.value += 'k' + elif event.key == K_l and 'l' in self.restricted: self.value += 'l' + elif event.key == K_m and 'm' in self.restricted: self.value += 'm' + elif event.key == K_n and 'n' in self.restricted: self.value += 'n' + elif event.key == K_o and 'o' in self.restricted: self.value += 'o' + elif event.key == K_p and 'p' in self.restricted: self.value += 'p' + elif event.key == K_q and 'q' in self.restricted: self.value += 'q' + elif event.key == K_r and 'r' in self.restricted: self.value += 'r' + elif event.key == K_s and 's' in self.restricted: self.value += 's' + elif event.key == K_t and 't' in self.restricted: self.value += 't' + elif event.key == K_u and 'u' in self.restricted: self.value += 'u' + elif event.key == K_v and 'v' in self.restricted: self.value += 'v' + elif event.key == K_w and 'w' in self.restricted: self.value += 'w' + elif event.key == K_x and 'x' in self.restricted: self.value += 'x' + elif event.key == K_y and 'y' in self.restricted: self.value += 'y' + elif event.key == K_z and 'z' in self.restricted: self.value += 'z' + elif event.key == K_0 and '0' in self.restricted: self.value += '0' + elif event.key == K_1 and '1' in self.restricted: self.value += '1' + elif event.key == K_2 and '2' in self.restricted: self.value += '2' + elif event.key == K_3 and '3' in self.restricted: self.value += '3' + elif event.key == K_4 and '4' in self.restricted: self.value += '4' + elif event.key == K_5 and '5' in self.restricted: self.value += '5' + elif event.key == K_6 and '6' in self.restricted: self.value += '6' + elif event.key == K_7 and '7' in self.restricted: self.value += '7' + elif event.key == K_8 and '8' in self.restricted: self.value += '8' + elif event.key == K_9 and '9' in self.restricted: self.value += '9' + elif event.key == K_BACKQUOTE and '`' in self.restricted: self.value += '`' + elif event.key == K_MINUS and '-' in self.restricted: self.value += '-' + elif event.key == K_EQUALS and '=' in self.restricted: self.value += '=' + elif event.key == K_LEFTBRACKET and '[' in self.restricted: self.value += '[' + elif event.key == K_RIGHTBRACKET and ']' in self.restricted: self.value += ']' + elif event.key == K_BACKSLASH and '\\' in self.restricted: self.value += '\\' + elif event.key == K_SEMICOLON and ';' in self.restricted: self.value += ';' + elif event.key == K_QUOTE and '\'' in self.restricted: self.value += '\'' + elif event.key == K_COMMA and ',' in self.restricted: self.value += ',' + elif event.key == K_PERIOD and '.' in self.restricted: self.value += '.' + elif event.key == K_SLASH and '/' in self.restricted: self.value += '/' + elif self.shifted: + if event.key == K_a and 'A' in self.restricted: self.value += 'A' + elif event.key == K_b and 'B' in self.restricted: self.value += 'B' + elif event.key == K_c and 'C' in self.restricted: self.value += 'C' + elif event.key == K_d and 'D' in self.restricted: self.value += 'D' + elif event.key == K_e and 'E' in self.restricted: self.value += 'E' + elif event.key == K_f and 'F' in self.restricted: self.value += 'F' + elif event.key == K_g and 'G' in self.restricted: self.value += 'G' + elif event.key == K_h and 'H' in self.restricted: self.value += 'H' + elif event.key == K_i and 'I' in self.restricted: self.value += 'I' + elif event.key == K_j and 'J' in self.restricted: self.value += 'J' + elif event.key == K_k and 'K' in self.restricted: self.value += 'K' + elif event.key == K_l and 'L' in self.restricted: self.value += 'L' + elif event.key == K_m and 'M' in self.restricted: self.value += 'M' + elif event.key == K_n and 'N' in self.restricted: self.value += 'N' + elif event.key == K_o and 'O' in self.restricted: self.value += 'O' + elif event.key == K_p and 'P' in self.restricted: self.value += 'P' + elif event.key == K_q and 'Q' in self.restricted: self.value += 'Q' + elif event.key == K_r and 'R' in self.restricted: self.value += 'R' + elif event.key == K_s and 'S' in self.restricted: self.value += 'S' + elif event.key == K_t and 'T' in self.restricted: self.value += 'T' + elif event.key == K_u and 'U' in self.restricted: self.value += 'U' + elif event.key == K_v and 'V' in self.restricted: self.value += 'V' + elif event.key == K_w and 'W' in self.restricted: self.value += 'W' + elif event.key == K_x and 'X' in self.restricted: self.value += 'X' + elif event.key == K_y and 'Y' in self.restricted: self.value += 'Y' + elif event.key == K_z and 'Z' in self.restricted: self.value += 'Z' + elif event.key == K_0 and ')' in self.restricted: self.value += ')' + elif event.key == K_1 and '!' in self.restricted: self.value += '!' + elif event.key == K_2 and '@' in self.restricted: self.value += '@' + elif event.key == K_3 and '#' in self.restricted: self.value += '#' + elif event.key == K_4 and '$' in self.restricted: self.value += '$' + elif event.key == K_5 and '%' in self.restricted: self.value += '%' + elif event.key == K_6 and '^' in self.restricted: self.value += '^' + elif event.key == K_7 and '&' in self.restricted: self.value += '&' + elif event.key == K_8 and '*' in self.restricted: self.value += '*' + elif event.key == K_9 and '(' in self.restricted: self.value += '(' + elif event.key == K_BACKQUOTE and '~' in self.restricted: self.value += '~' + elif evelif event.key == K_RIGHTBRACKET and '}' in self.restricted: self.value += '}' + elif event.key == K_BACKSLASH and '|' in self.restricted: self.value += '|' + elif event.key == K_SEMICOLON and ':' in self.restricted: self.value += ':' + elif event.key == K_QUOTE and '"' in self.restricted: self.value += '"' + elif event.key == K_COMMA and '<' in self.restricted: self.value += '<' + elif event.key == K_PERIOD and '>' in self.restricted: self.value += '>' + elif event.key == K_SLASH and '?' in self.restricted: self.value += '?' + + if len(self.value) > self.maxlength and self.maxlength >= 0: self.value = self.value[:-1] diff --git a/eztext.pyc b/eztext.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5229cebda5bd99c96a886008ed0702b33376e263 GIT binary patch literal 9834 zcmdU#%Tp6y7RPTVAt8Z;hYu7H+b01r;9F5qDi@2ve*{eb@7M}PX>zUMyr z(6_z+35Ra^4&KW!_s0w24LIx^2!}s|L2Mdh9+op$(x6<3dsxz=5?*F`*#eyQv0oW` z!PxzzkMSzTgN*xS7Ni4=hZwJxS$-^fDp~^-X8#L6Q3GNQN=Mwm-2Os-A-gzODiuod zKJoNTIP7W=i{X7GrlJsMQ4ffN*{M`My=tXWPKXk#1-_nxq@W;+QOur(Sl3cv)#|dd zxwPG7FQrQs?;1*HoI+`{YruM9)yg|vW9j_jdV0~ayCyfCr9!@|xVZ>*n2xpK znAv=B-RZKnFcB+mCh#8paM*Z9e&%3YwB`Ss(FEs2Gr-hnSOe{o^kS>ST?w$#4zom+0oDW;{K;TzJNP#X)lEgQ|KeE?W@DRdE4L7{YawP{GYds* zu>GKo4BIwmd{j9M1O7A9~wB&fmIl2nQpGO1JoO<1|rpF9EZKCmNgjQHU`9W?PUPLm8o z=toZEE0DBkBJ&?-0F2CEAqPgSmm;u)&=Qk`g`!~oojRH7uyN!?yF1~xou*BtN;?gw z+R~3R+*(*%$}X?uR`Z48TFG|SpFG{z-0Hj8KQK6S>-O--=-7CCV)9O6YI^4G?7jQR z?$c+^o;!cx;-$-nj~qRA{KUhyXnV)W&Qr0jo-0?c^d`OHo^Q7~L8wKx zjh2g3r)l1cR*D6r4SF9|n<&nW1P;{%4%$Q=N&^Z`v&1fx-6(rd_JUALpQLl^7R83r zIoqOj!(PfRfL&?jPM{H}#LB$;X-fpnZ@fQy9|-dtHX4lsMjfj&v8C(|dzytV2^V?PD*z>^bC$ zg-4tgi%oznz)I#}203L|EZNc=D5alL?<;F7^ncp4*GmiO3|I(F6Q>6^8HlD?2_CLi zi6%<|M*@!muprK)jT=B5dFeN<{g&Jqzmu*gxfGYr`y0GYzi|&{#T)6hU(d8q=#|(HFSNNDwuE?kJb;Qpb@XW68^OCR9 z`Fi4C8t~+;@Gm9r*ZBtG-y86luJG?AAJF+m;=da3pGbxOD*0-i-$i_@2cG^FzSRS9 zGHg)icM~7?fS*v|XPS_-)D8==@&d-+Fkh!oQV#tu8!H=^_ViSPA-2U01&SMqf_-%Nbo%j*?BFZp_%KS2CzFKP5f0TTq&L1THyO-}$`0tY6rSq-C$9#OZ!pD4N`|Q^FL&VSf_#TCy zm;4@`H;I4g<9ikUrR4YO{9)qX`*@SWzn6TI&L1KEtB>zf_^*=Rr}IaNZ>{3{6~48q z+}`~nDfxa6C4{y6d5Rs4X$Z%h7w&YvLuZ53}(__va8(fKywKUeXC3jbO1 z2X#J5e8kUN6+YrGx3^X2+llY>^Fs>XEBQk@-$8ud&rOBTOWxG^lf=LFb6DHu`utk* zhjqS__>X>mMBzV5{)o<>BL2IdA65A8l0T~RG2&wZeoWzGfwFy$>3kRQ^8tQb;pZiP zT<5!qe;ME>6#k{;Pw4z<;@<~&o5H`Be4EanA^vNCM-~37-;(53k3I`5^CB_`Kx1b^Z$R&l~w^g$HlMeg2-7 z{MsKd6aIrPK}2{|!ngSpb zlE13+!ngTS!>=j)7s+4KdEwhM*YaM4Z>}x3w^!$dZ!=QMuPgkB_%=OZKA`YD zk{{4{;oB^S`JlotOMX!2g>UmJ%!d^ImE?zXUida2!u*!Pe~|nwofp2%w=lo0@ZThV zTjzyu(-GnD|DGJr9g(tqhIL-}HpvJdQTU|fM|58JHaigx|MAK4cO*Zm^TM}z7vWiFA+Yj@Lwc9uJgjTX|CgOg>SAaw>Pfy!nYZz;}Z%$BKZlO7rxC_9iLSA zEy+*nyzp(_)bTqC|3>n6bYA#2pXzu*;Xg?}q4UDG3Dxr{g%8!2+dHN6!nf(E=hF(` zBl&5a7rxDMJ)cqdWy#Ozyzp&a)$_Xw|4Qiod*6u;ddneK<9;T^R9tERQPw2 zf2i}qxB1e*=M?^n&^_mC*-i<_|j3Ge((+MA`F0I@farubvh3@InINEb*KNtZ~oq|2l$ zq&d=6(mZK_v`D%}S|YVc9ny8uC!|j+ZxAWHmB6hJik>DtLwc6<9O-$|3#1oGFOgm* zeMEYS^cv{{(m5O7Za$>=6^ge}ypuFW+C|z&dXu!Dbbxe_bcpm8>210Q!U(tD)$Nt2}Qq=!jwkRByHMtYodp7cZlnkx($rHpOT z6zNIQUr3*mJ|pcRJwkeww3qZc?c>Iyy;vl^S#>sxV#j23@cztX0{8go<@RW5Z0h## z(6pOKP$ID(PA6~!f?f^7B?A+);=_Q^)Xl#B(W%M4{y}=XOodOEU^@o)Tt-uLhBjzN zQ)$|}aTAZ-Fyn^Y4J|iZaKlA6Tyn##8!o%yiW}zKaMca-Zdh=`q8qNcVaW|`H+0-^ z-3_0(;ZrxD`f{K07_LOF@yTeoEv_Nd!AV|`P%-O{H9$A|kT z#wOx!>1s{=6XWB3ZcUSeiQ$QXavxFw_zE62C~50W*(<<3U$H#V1{_6yi@gG@cb(SF zZiv}`#>K%ChCQ}cvD3zOL97<`-5QM`#2SC6$DZHy-M4t!nAncOtv~t{B7viq_DB;4 zFxG-{80GIEm61cSpSMYiGX}Sl>4O&hE+QBXRt0^*D&-Dv1*6I4ZnWnL8Q5MHd)M^M z5k+waAGYnQ0UotB=@TjXmPKr1V?9cdkYYcrQFISi#Wz;HXmA@pum~CZjF4xqXIIVt E0B+b{wg3PC literal 0 HcmV?d00001 diff --git a/main.py b/main.py new file mode 100644 index 0000000..fbaa36a --- /dev/null +++ b/main.py @@ -0,0 +1,29 @@ +#!/usr/bin/python3 +import textinput +import pygame +pygame.init() + +textinput_obj = textinput.TextInput(font_family="Ubuntu") + +screen = pygame.display.set_mode((1000, 200)) +clock = pygame.time.Clock() + +color_switch = True + +while True: + screen.fill((225, 225, 225)) + + color_switch = not color_switch + + events = pygame.event.get() + for event in events: + if event.type == pygame.QUIT: + exit() + + # Space to do things + value = textinput_obj.update(events) + if value: print(value) + screen.blit(textinput_obj.get_surface(), (10, 10)) + + pygame.display.update() + clock.tick(30) diff --git a/pygametextinput/InputHandler.py b/pygametextinput/InputHandler.py new file mode 100644 index 0000000..fc870a3 --- /dev/null +++ b/pygametextinput/InputHandler.py @@ -0,0 +1,35 @@ +import pygame + +# Font module of pygame must be initialized before it can be used: +pygame.font.init() + +class InputHandler: + def __init__(self, surface_size, fontname=None, fontsize=12): + """ + (WIP DOCS) + * Removes all KEYDOWN events from the event queue + """ + self.text_array = [] + self.font_object = pygame.font.Font(pygamge.font.match_font(fontname), fontsize) + self.rerender = False # If True the surface gets rerendered + self.text_color = 1, 1, 1 + + self.cursor_pos = 0 # pos in text_array + self.cursor_blinking_speed = 500 #ms + self.cursor_visible = False + self.cursor_time_counter = 0 + self.cursor_surface = pygame.Surface(self.font_object.size("|")) + + + self.surface = pygame.Surface(surface_size) + + def update(self, dt): + + # Update visual representation of cursor: + self.cursor_time_counter += dt + if self.cursor_time_counter >= self.cursor_blinking_speed: + self.cursor_visible = not self.cursor_visible + self.rerender = True + + for key in pygame.event.get(pygame.KEYDOWN): + key diff --git a/pygametextinput/__init__.py b/pygametextinput/__init__.py new file mode 100644 index 0000000..01ad88e --- /dev/null +++ b/pygametextinput/__init__.py @@ -0,0 +1,6 @@ +import pygame +from pygame.locals import * + +from InputHandler import * + +__all__ = [] diff --git a/textinput.py b/textinput.py new file mode 100644 index 0000000..a8c57d0 --- /dev/null +++ b/textinput.py @@ -0,0 +1,146 @@ +import pygame, string +import pygame.locals as pl + +pygame.font.init() + + +class TextInput: + """ + This class lets the user input a piece of text, e.g. a name or a message. + + This class let's the user input a short, one-lines piece of text at a blinking cursor + that can be moved using the arrow-keys. + """ + def __init__(self, font_family = "", + font_size = 35, + antialias=True, + text_color=(0, 0, 0), + cursor_color=(0, 0, 1), + repeat_keys_initial_ms=400, + repeat_keys_interval_ms=35): + """ + Args: + font_family: Name or path of the font that should be used. Default is pygame-font + font_size: Size of the font in pixels + antialias: (bool) Determines if antialias is used on fonts or not + text_color: Color of the text + repeat_keys_initial_ms: ms until the keydowns get repeated when a key is not released + repeat_keys_interval_ms: ms between to keydown-repeats if key is not released + """ + + # Text related vars: + self.antialias = antialias + self.text_color = text_color + self.font_size = font_size + self.input_string = "" # Inputted text + self.font_object = pygame.font.Font(pygame.font.match_font(font_family), font_size) + + # Text-surface will be created during the first update call: + self.surface = pygame.Surface((1, 1)) + self.surface.set_alpha(0) + + # Vars to make keydowns repeat after user pressed a key for some time: + self.keyrepeat_counters = {} # {event.key: (counter_int, event.unicode)} (look for "***") + self.keyrepeat_intial_interval_ms = repeat_keys_initial_ms + self.keyrepeat_interval_ms = repeat_keys_interval_ms + + # Things cursor: + self.cursor_surface = pygame.Surface((int(self.font_size/20+1), self.font_size)) + self.cursor_surface.fill(cursor_color) + self.cursor_position = 0 # Inside text + self.cursor_visible = True # Switches every self.cursor_switch_ms ms + self.cursor_switch_ms = 500 # /|\ + self.cursor_ms_counter = 0 + + self.clock = pygame.time.Clock() + + def update(self, events): + for event in events: + if event.type == pygame.KEYDOWN: + self.cursor_visible = True # To see better where we are: + + # If none exist, create counter for that key: + if not event.key in self.keyrepeat_counters: + self.keyrepeat_counters[event.key] = [0, event.unicode] + + if event.key == pl.K_BACKSPACE: + self.input_string = self.input_string[:self.cursor_position - 1] + \ + self.input_string[self.cursor_position:] + self.cursor_position -= 1 + elif event.key == pl.K_DELETE: + self.input_string = self.input_string[:self.cursor_position] + \ + self.input_string[self.cursor_position + 1:] + + elif event.key == pl.K_RETURN: + return self.input_string + + elif event.key == pl.K_RIGHT: + # Add one to cursor_pos, but do not exceed len(input_string) + self.cursor_position = min(self.cursor_position + 1, len(self.input_string)) + + elif event.key == pl.K_LEFT: + # Subtract one from cursor_pos, but do not go below zero: + self.cursor_position = max(self.cursor_position - 1, 0) + + elif event.key == pl.K_END: + self.cursor_position = len(self.input_string) + + elif event.key == pl.K_HOME: + self.cursor_position = 0 + + else: + self.input_string = self.input_string[:self.cursor_position] + \ + event.unicode + \ + self.input_string[self.cursor_position:] + self.cursor_position += len(event.unicode) # Some are empty, e.g. K_UP + + elif event.type == pl.KEYUP: + # *** Because KEYUP doesn't include event.unicode, this dict is stored in such a weird way + if event.key in self.keyrepeat_counters: + del self.keyrepeat_counters[event.key] + + # Update key counters: + for key in self.keyrepeat_counters : + self.keyrepeat_counters[key][0] += self.clock.get_time() # Update clock + # Generate new key events if enough time has passed: + if self.keyrepeat_counters[key][0] >= self.keyrepeat_intial_interval_ms: + self.keyrepeat_counters[key][0] = self.keyrepeat_intial_interval_ms - \ + self.keyrepeat_interval_ms + + event_key, event_unicode = key, self.keyrepeat_counters[key][1] + pygame.event.post(pygame.event.Event(pl.KEYDOWN, key=event_key, unicode=event_unicode)) + + # Rerender text surface: + self.surface = self.font_object.render(self.input_string, self.antialias, self.text_color) + + # Update self.cursor_visible + self.cursor_ms_counter += self.clock.get_time() + if self.cursor_ms_counter >= self.cursor_switch_ms: + self.cursor_ms_counter %= self.cursor_switch_ms + self.cursor_visible = not self.cursor_visible + + # Render cursor + if self.cursor_visible: + cursor_y_pos = self.font_object.size(self.input_string[:self.cursor_position])[0] + # Without this, the cursor is invisible when self.cursor_position > 0: + if self.cursor_position > 0: + cursor_y_pos -= self.cursor_surface.get_width() + self.surface.blit(self.cursor_surface, (cursor_y_pos, 0)) + + self.clock.tick() + return False + + def get_surface(self): + return self.surface + + def get_text(self): + return self.input_string + + def get_cursor_position(self): + return self.cursor_position + + def set_text_color(self, color): + self.text_color = color + + def set_cursor_color(self, color): + self.cursor_surface.fill(color)