Kivy テキストファイルの読み込みと保存(Python Kivyの取説・使い方 第13回)
はじめに
Kivyのテキストボックスの内容をtxtファイルへ保存する方法を調べるのに苦労しました。それもそのはずで保存はKivyモジュールは使わずPythonのwrite関数を使うみたいです。最近KivyばかりやっていたのでなんでもKivyでしようとしてました。
Pythonでファイルの読み込みと保存する方法
open関数とread関数、write関数を使います。
open関数
変数 = open(引数1, 引数2)
引数1:ファイル名(同じフォルダにないときはパス名にも注意)
引数2:モード。「r」と指定しない場合は読み込み、「w」で書き込みです。
read関数
変数 = 引数1.read()
引数1:読み込みモードで開いたファイル(の変数)
write関数
引数1.write(引数2)
引数1:書き込みモードで開いたファイル(の変数)
引数2:文字列(の変数)
class MainScreen(Widget): text = StringProperty() def __init__(self, **kwargs): super(MainScreen, self).__init__(**kwargs) self.ids.textinput.text = ' ' self.ids.textinput.text = '' try: file = open('テスト.txt', 'r') self.ids.textinput.text = file.read() file.close() self.text = '「テスト.txt」を開きました' except: self.text = 'ファイルが見つかりません' def on_command(self, **kwargs): text = self.ids.textinput.text file = open('テスト.txt', 'w') file.write(text) file.close() self.text = '保存しました' def on_edit(self, **kwargs): self.text = ''
解説
try関数(except)
簡単に説明すると
「try:
やってみる処理
except:
ダメだった場合の処理」
です。今回は開くファイルが見つからなかった場合のエラーを防ぐために使いました。
def on_command(self, **kwargs):
ボタンが押されたときの処理です。kvファイルで指定しています。
def on_edit(self, **kwargs):
テキストボックスが編集されたときの処理です。kvファイルで指定しています。
苦労した点(ごまかした点)
self.ids.textinput.text = ' '
self.ids.textinput.text = ''
この2行を入れないと、ラベルに「ファイルが見つかりません」を表示した後すぐにテキストボックスが編集されてしまい表示が消えてしまいます。 この2行で先にテキストボックスを編集させるとラベル表示の処理が後になってうまくいきました。
プログラムのコード
# フル画面を解除して画面の幅と高さを設定 from kivy.config import Config Config.set('graphics', 'fullscreen', 0) Config.set('graphics', 'width', 320) Config.set('graphics', 'height', 568) Config.set('graphics', 'resizable', 0) import ctypes from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.widget import Widget from kivy.uix.textinput import TextInput from kivy.uix.label import Label from kivy.resources import resource_add_path from kivy.core.text import LabelBase, DEFAULT_FONT from kivy.utils import platform from kivy.base import EventLoop from kivy.properties import StringProperty, ObjectProperty from kivy.utils import escape_markup resource_add_path('c:/Windows/Fonts') LabelBase.register(DEFAULT_FONT, 'msgothic.ttc') dll = ctypes.cdll.LoadLibrary('./ime_operator.dll') dll.getComposition.restype = ctypes.c_char_p dll.getEnterdString.restype = ctypes.c_char_p class TextInputIME(TextInput): composition_string = StringProperty() sdl_composition = StringProperty() composition_window = ObjectProperty() def __init__(self, **kwargs): super(TextInputIME, self).__init__(**kwargs) self.disable_on_textedit = (False, False) self.is_openIME = False self.old_cursor_color = self.cursor_color self.old_composition = '' EventLoop.window.bind(on_textedit=self._on_textedit) def _on_textedit(self, _, value): self.sdl_composition = value self.is_openIME = bool(dll.getIsOpenIME()) try: entered_text = dll.getEnterdString().decode('cp932') composition_string = dll.getComposition().decode('cp932') except UnicodeError: print('failed to decode IME information') if composition_string != '\n\n': self.composition_string = composition_string else: self.composition_string = '' if (entered_text != '\n\n' and self.is_openIME and self.old_composition != value): index = self.cursor_index() self.text = self.text[:index - 1] + entered_text + self.text[index:] self.composition_string = '' self.old_composition = value return None self.old_composition = value def insert_text(self, substring, from_undo=False): if substring == self.sdl_composition: return None else: return super(TextInputIME, self).insert_text(substring, from_undo) def keyboard_on_key_down(self, window, keycode, text, modifiers, dt=0): cursor_operations = {'left', 'up', 'right', 'down', 'backspace', 'tab'} self.composition_cursor_index = len(self.composition_string) if keycode[1] == 'left': self.composition_cursor_index -= 1 if keycode[1] == 'right': self.composition_cursor_index += 1 if keycode[1] in cursor_operations and self.composition_string: return None return super( TextInputIME, self).keyboard_on_key_down( window, keycode, text, modifiers) def on_composition_string(self, _, value): if self.composition_string: self.cursor_color = (0, 0, 0, 0) else: self.cursor_color = self.old_cursor_color if not dll.getIsOpenIME(): return self.composition_window.text = '[u]' + value + '[/u]' class CompositionLabel(Label): textinput = ObjectProperty() def __init__(self, **kwargs): super(CompositionLabel, self).__init__(**kwargs) class MainScreen(Widget): text = StringProperty() def __init__(self, **kwargs): super(MainScreen, self).__init__(**kwargs) self.ids.textinput.text = ' ' self.ids.textinput.text = '' try: file = open('テスト.txt', 'r') self.ids.textinput.text = file.read() file.close() self.text = '「テスト.txt」を開きました' except: self.text = 'ファイルが見つかりません' def on_command(self, **kwargs): text = self.ids.textinput.text file = open('テスト.txt', 'w') file.write(text) file.close() self.text = '保存しました' def on_edit(self, **kwargs): self.text = '' class TestApp(App): def build(self): self.title = 'テスト' return MainScreen() if __name__ == '__main__': TestApp().run()
kvファイル(test.kv)
<MainScreen>: BoxLayout: size: root.size orientation: "vertical" Label: text: root.text RelativeLayout: TextInputIME: id: textinput composition_window: cmp_window pos: root.pos size: root.size on_text: root.on_edit() CompositionLabel: id: cmp_window textinput: textinput x: textinput.cursor_pos[0] y: textinput.cursor_pos[1] - self.height Button: text: "保存" on_press: root.on_command() <CompositionLabel>: size_hint_x: None size_hint_y: None width: self.font_size * (len(self.text)-7) height: self.font_size color: 0,0,0,1 markup: True canvas.before: Color: rgba: 1,1,1,len(self.text)-7 Rectangle: pos: self.pos size: self.size
まとめ
テキストファイルの読み込みと書き込み自体はそんなに難しくなかったです。ただ思い込みでKivyでの保存方法を探してみたり、ラベルへの表示文字の部分などで時間がかかりました。
次回はテキストボックスを読み込むためのファイル選択ダイアログを作っていきます。
保存ファイル
lesson70.py
test.kv
文責:Luke