でも、ちょっと違和感が、、、、
さっきの選択画面に戻ろう。
あれ?
ここはどこなんだ?
現在選択中のパスがわからないと言う問題が、ここで発生したのだ。
ここで、上部の「読み込み中」の後ろに、現在選択パスを入れることにした。
filelist.py
import os
import sys
import json
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.popup import Popup
from kivy.uix.treeview import TreeViewLabel
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty, StringProperty
from kivy.clock import Clock
from pprint import pprint
from kivy.core.text import LabelBase, DEFAULT_FONT
from kivy.resources import resource_add_path
# 日本語フォント設定
resource_add_path('./fonts')
LabelBase.register(DEFAULT_FONT, 'ipaexg.ttf')
sm = ScreenManager()
path_inf = 'path_inf.json'
class MsgboxOk(BoxLayout):
message_text = StringProperty()
ok_button = ObjectProperty(None)
class MsgboxOkCancel(BoxLayout):
message_text = StringProperty()
ok_button = ObjectProperty(None)
cancel_button = ObjectProperty(None)
class SetSCN(Screen):
begin_path_dsp = ObjectProperty(None)
def __init__(self, **kwargs):
super(SetSCN, self).__init__(**kwargs)
def setSelect(self):
'''
content = LoadDialog(load = self.setSelectLoad, cancel = self.setSelectCancel)
self._popup = Popup( title="読み込み中", content=content, size_hint=(0.9,0.9))
self._popup.open()
'''
self._popup = LstPOP( load = self.setSelectLoad, \
cancel = self.setSelectCancel, \
title='読み込み中')
self._popup.open()
def setSelectLoad (self, path, filename):
pprint(path)
pprint(filename)
#self.begin_path_dsp.text = filename[0]
self.begin_path_dsp.text = path
self._popup.dismiss()
def setSelectCancel(self):
self._popup.dismiss()
''' 幽霊メソッドなので、消します
def msgTestOk(self):
pprint ('OKが押されました')
self.popup.dismiss()
def msgTestCancel(self):
pprint ('CANCELが押されました')
self.popup.dismiss()
'''
def selfOk(self):
self.bl = {}
self.bl['begin_path'] = self.begin_path_dsp.text
pprint (self.bl)
try:
#raise OverflowError('やっちまったな')
with open(path_inf, 'w') as fd:
json.dump(self.bl, fd)
except PermissionError as err:
self.msg = '保存データを書き込もうとしましたが、書き込み許可がありません。\n'
self.msg += 'パスは、' + self.bl['begin_path'] + 'です。\n'
self.msg += '保存先の書き込み許可を確認するか、パスが適当かを確認してください。\n\n'
self.msg += str(err)
content = MsgboxOk \
(ok_button= self.msgTestOk, \
message_text= self.msg)
self.popup = Popup(title='書き込み許可エラー', content=content)
self.popup.open()
except IOError as err:
self.msg = '保存データを書き込もうとしましたが、書き込めません。\n'
self.msg += '書き込み先機器に問題があるようです。\n'
self.msg += '書き込み先機器の状態を確認してください。\n\n'
self.msg += str(err)
content = MsgboxOk \
(ok_button= self.msgTestOk, \
message_text= self.msg)
self.popup = Popup(title='I/Oエラー', content=content)
self.popup.open()
except BaseException as err:
self.msg = '保存データを書き込もうとしましたが、何らかのエラーが起きました。\n\n'
self.msg += str(err)
content = MsgboxOk \
(ok_button= self.msgTestOk, \
message_text= self.msg)
self.popup = Popup(title='その他のエラー', content=content)
self.popup.open()
finally:
sm.current = 'all'
def selfCancel(self):
sm.current = 'all'
#class LoadDialog(FloatLayout):
class LstPOP(Popup):
current_dir = os.path.dirname(os.path.abspath(__file__))
load = ObjectProperty(None)
cancel = ObjectProperty(None)
def is_dir(self, dirname, filename):
# ディスレクトリならTrueを返す
return os.path.isdir(os.path.join(dirname, filename))
def lstChooser(self, path, selection):
self.title = '読み込み中 ' + path
print('クリックされました' + path)
class AllSCN(Screen):
tv = ObjectProperty(None)
file_name = ObjectProperty(None)
loadfile = ObjectProperty(None)
text_input = ObjectProperty(None)
def msgOsErrorOk(self):
print('OKが押されました')
self.popup.dismiss()
sys.exit()
def begin_display(self, dt):
path = ''
thisos = os.name
if thisos == 'posix':
path = os.environ.get('HOME')
elif thisos == 'nt':
path = os.environ.get('HOMEDRIVE') + os.environ.get('HOMEPATH')
else:
msg = '内部OS判定(os.name)が、"' + thisos + '”でした。\n'
msg += 'サポートしているOSは、UNIX系統と、Windowsです。\n'
msg += 'したがってこのOSはサポート外です。すみません。'
content = MsgboxOk \
(ok_button= self.msgOsErrorOk, \
message_text= msg)
self.popup = Popup(title='OSサポートエラー', content=content)
self.popup.open()
return
self.manager.get_screen('set').begin_path_dsp.text = path
self.tv.add_node(TreeViewLabel(text ='シンカリオン E1 とき'))
self.tv.add_node(TreeViewLabel(text ='シンカリオン 0 ひかり'))
self.tv.add_node(TreeViewLabel(text ='シンカリオン キハ32 鉄道ホビートレイン'))
def setupButtonClicked(self):
sm.current = 'set'
def show_load(self):
# 仮処置 SetSCN側のロジックが確定次第、そのロジックに変更します
'''
content = LoadDialog(load = self.load, cancel = self.dismiss_popup)
self._popup = Popup( title="読み込み中", content=content, size_hint=(0.9,0.9))
self._popup.open()
'''
def load (self, path, filename):
pprint(filename)
#self.file_name.text = filename[0]
self.file_name.text = path
#with open (os.path.join(path, filename[0])) as stream:
# self.text_input.text = stream.read()
self.dismiss_popup()
def dismiss_popup(self):
self._popup.dismiss()
class FilelistApp(App):
def build(self):
allscn = AllSCN()
setscn = SetSCN()
Clock.schedule_once(allscn.begin_display, 0)
sm.add_widget(allscn)
sm.add_widget(setscn)
return sm
if __name__ == '__main__':
FilelistApp().run()
filelist.kv
<SetSCN>:
name: 'set'
begin_path_dsp: begin_path_dsp
BoxLayout:
orientation: 'vertical'
BoxLayout:
size_hint_y: 0.1
orientation: 'horizontal'
BoxLayout:
Label:
size_hint_x: 0.1
text: '開始パス'
TextInput:
id: begin_path_dsp
size_hint_x: 0.8
Button:
size_hint_x: 0.1
text: '…'
on_release: root.setSelect()
BoxLayout:
size_hint_y: 0.8
BoxLayout:
size_hint_y: 0.1
Button:
size_hint_x: 0.5
text: 'OK'
on_release: root.selfOk()
Button:
size_hint_x: 0.5
text: 'キャンセル'
on_release: root.selfCancel()
<AllSCN>:
name: 'all'
tv: tv
file_name: file_name
BoxLayout:
orientation: 'vertical'
BoxLayout: #OpnSCN
size_hint_y: 0.1
orientation: 'horizontal'
BoxLayout:
Button:
size_hint_x: 0.1
text: '設定'
on_release: root.setupButtonClicked()
TextInput:
id: file_name
size_hint_x: 0.7
text: 'ファイルパス'
Button:
size_hint_x: 0.1
text: '…'
on_release: root.show_load()
Button:
size_hint_x: 0.1
text: '実行'
BoxLayout: #ResultSCN
size_hint_y: 0.9
TreeView:
id: tv
<MsgboxOk>
orientation: 'vertical'
Label:
size_hint_y: 0.9
text: root.message_text
BoxLayout:
size_hint_y: 0.1
orientation: 'horizontal'
Button:
size_hint_x: 10
text: 'OK'
on_release: root.ok_button()
<MsgboxOkCancel>
orientation: 'vertical'
Label:
size_hint_y: 0.9
text: root.message_text
BoxLayout:
size_hint_y: 0.1
orientation: 'horizontal'
Button:
size_hint_x: 10
text: 'OK'
on_release: root.ok_button()
Button:
size_hint_x: 10
text: 'キャンセル'
on_release: root.cancel_button()
#<LoadDialog>:
<LstPOP>:
id:lst_pop
size_hint: 0.9, 0.9
BoxLayout:
size: root.size
pos: root.pos
orientation: 'vertical'
FileChooserListView:
id: filechooser
path: root.current_dir
filters: [root.is_dir]
on_touch_down: lst_pop.lstChooser(filechooser.path, filechooser.selection)
BoxLayout:
size_hint_y : None
height : 30
Button:
text: 'キャンセル'
on_release: root.cancel()
Button:
text: '読み込み'
on_release: root.load(filechooser.path, filechooser.selection)
AllSCN:
ここまでで大きな変更になったのは、LoadDialogクラスをLstPOPクラスに変更したこと。
これは今まで、
としていたLoadDialogクラスを使った画面は、概念的には、
で、kvファイル側もこう書いてあったので、これをPopupを含めたLstPOPという新設classにして、titleの制御をしやすくする。
このように、LstPOPを新設し、これをPopupから継承する。
こういう形に変更しようと思う。
filelist.kvでは、旧LoadDialogを利用し、このLstPOPを作成する。
#<LoadDialog>:
<LstPOP>:
id:lst_pop
size_hint: 0.9, 0.9
BoxLayout:
size: root.size
pos: root.pos
orientation: 'vertical'
FileChooserListView:
id: filechooser
path: root.current_dir
filters: [root.is_dir]
on_touch_down: lst_pop.lstChooser(filechooser.path, filechooser.selection)
FileChooserListView:
のon_touch_down
は、リスト選択時のイベントで、ここでtitleを変更させる。(後述)
filelist.pyの
class SetSCN(Screen):
begin_path_dsp = ObjectProperty(None)
def __init__(self, **kwargs):
super(SetSCN, self).__init__(**kwargs)
def setSelect(self):
'''
content = LoadDialog(load = self.setSelectLoad, cancel = self.setSelectCancel)
self._popup = Popup( title="読み込み中", content=content, size_hint=(0.9,0.9))
self._popup.open()
'''
self._popup = LstPOP( load = self.setSelectLoad, \
cancel = self.setSelectCancel, \
title='読み込み中')
self._popup.open()
まず、ここself._popup
は、元はLoadDialog
をインスタンス化してから、Popup
をインスタンス化したが、LstPOP
のインスタンス化1本にまとめる。
そしてこの、LstPOP
だが、
#class LoadDialog(FloatLayout):
class LstPOP(Popup):
current_dir = os.path.dirname(os.path.abspath(__file__))
load = ObjectProperty(None)
cancel = ObjectProperty(None)
def is_dir(self, dirname, filename):
# ディスレクトリならTrueを返す
return os.path.isdir(os.path.join(dirname, filename))
def lstChooser(self, path, selection):
self.title = '読み込み中 ' + path
print('クリックされました' + path)
旧LoadDialog
を利用して、LstPOP
を作る。
def lstChooser
は、kvファイル側の<LstPOP>:
で指定したon_touch_down
から呼び出される。
しかしこのときは、ここに罠があることには気がつかなかった。
これを実行させてみよう。起動後、「設定」→「・・・」。
これで、「../」を押下。
あれ?
では、「01_filelist_testdata」を押下しよう。
あれれ?
LstPOP
classのlstChooser
メソッドで、
class LstPOP(Popup):
(省略ですわよ)
def lstChooser(self, path, selection):
self.title = '読み込み中 ' + path
print('クリックされました' + path)
path
を使っているのだけど、これが使えないのか!
そして、いろいろいじって幾星霜。
pathの代わりにselectionを使用するということで、回避いたしました。
ただし、単にselectionを使うだけだと、中身が入っていないので、FileChooserListViewのdirselectをTrueとして、実現しました。
これ、今回はディレクトリだけの選択画面だから、この手は使えるんだけど、ファイルの選択の時はどうするんだろうと思うと、昼も寝られません。
しかも、ファイル選択は、ダブルクリックでの選択になるので、なんだかこれでも苦し紛れのロジックぽいんですけどね、私の現在の実力ではこれがどうも限界です。
filechooser.pyも読んでみたんですけどね。
filelist.py
import os
import sys
import json
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.popup import Popup
from kivy.uix.treeview import TreeViewLabel
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty, StringProperty
from kivy.clock import Clock
from pprint import pprint
from kivy.core.text import LabelBase, DEFAULT_FONT
from kivy.resources import resource_add_path
# 日本語フォント設定
resource_add_path('./fonts')
LabelBase.register(DEFAULT_FONT, 'ipaexg.ttf')
sm = ScreenManager()
path_inf = 'path_inf.json'
class MsgboxOk(BoxLayout):
message_text = StringProperty()
ok_button = ObjectProperty(None)
class MsgboxOkCancel(BoxLayout):
message_text = StringProperty()
ok_button = ObjectProperty(None)
cancel_button = ObjectProperty(None)
class SetSCN(Screen):
begin_path_dsp = ObjectProperty(None)
def __init__(self, **kwargs):
super(SetSCN, self).__init__(**kwargs)
def setSelect(self):
'''
content = LoadDialog(load = self.setSelectLoad, cancel = self.setSelectCancel)
self._popup = Popup( title="読み込み中", content=content, size_hint=(0.9,0.9))
self._popup.open()
'''
self._popup = LstPOP( load = self.setSelectLoad, \
cancel = self.setSelectCancel)
self._popup.open()
def setSelectLoad (self, path, filename):
#pprint(path)
#pprint(filename)
#self.begin_path_dsp.text = filename[0]
self.begin_path_dsp.text = path
self._popup.dismiss()
def setSelectCancel(self):
self._popup.dismiss()
''' 幽霊メソッドなので、消します
def msgTestOk(self):
pprint ('OKが押されました')
self.popup.dismiss()
def msgTestCancel(self):
pprint ('CANCELが押されました')
self.popup.dismiss()
'''
def selfOk(self):
self.bl = {}
self.bl['begin_path'] = self.begin_path_dsp.text
pprint (self.bl)
try:
#raise OverflowError('やっちまったな')
with open(path_inf, 'w') as fd:
json.dump(self.bl, fd)
except PermissionError as err:
self.msg = '保存データを書き込もうとしましたが、書き込み許可がありません。\n'
self.msg += 'パスは、' + self.bl['begin_path'] + 'です。\n'
self.msg += '保存先の書き込み許可を確認するか、パスが適当かを確認してください。\n\n'
self.msg += str(err)
content = MsgboxOk \
(ok_button= self.msgTestOk, \
message_text= self.msg)
self.popup = Popup(title='書き込み許可エラー', content=content)
self.popup.open()
except IOError as err:
self.msg = '保存データを書き込もうとしましたが、書き込めません。\n'
self.msg += '書き込み先機器に問題があるようです。\n'
self.msg += '書き込み先機器の状態を確認してください。\n\n'
self.msg += str(err)
content = MsgboxOk \
(ok_button= self.msgTestOk, \
message_text= self.msg)
self.popup = Popup(title='I/Oエラー', content=content)
self.popup.open()
except BaseException as err:
self.msg = '保存データを書き込もうとしましたが、何らかのエラーが起きました。\n\n'
self.msg += str(err)
content = MsgboxOk \
(ok_button= self.msgTestOk, \
message_text= self.msg)
self.popup = Popup(title='その他のエラー', content=content)
self.popup.open()
finally:
sm.current = 'all'
def selfCancel(self):
sm.current = 'all'
#class LoadDialog(FloatLayout):
class LstPOP(Popup):
current_dir = os.path.dirname(os.path.abspath(__file__))
load = ObjectProperty(None)
cancel = ObjectProperty(None)
def __init__(self, **kwargs):
super(LstPOP, self).__init__(**kwargs)
self.title ='読み込み中 ' + os.path.dirname(os.path.abspath(__file__))
def is_dir(self, dirname, filename):
# ディスレクトリならTrueを返す
return os.path.isdir(os.path.join(dirname, filename))
def lstChooser(self, path, selection):
if 0 < len(selection):
self.title = '読み込み中 ' + selection[0]
#print('クリックされました path:' + path)
#print('クリックされました selection:' + selection[0])
class AllSCN(Screen):
tv = ObjectProperty(None)
file_name = ObjectProperty(None)
loadfile = ObjectProperty(None)
text_input = ObjectProperty(None)
def msgOsErrorOk(self):
print('OKが押されました')
self.popup.dismiss()
sys.exit()
def begin_display(self, dt):
path = ''
thisos = os.name
if thisos == 'posix':
path = os.environ.get('HOME')
elif thisos == 'nt':
path = os.environ.get('HOMEDRIVE') + os.environ.get('HOMEPATH')
else:
msg = '内部OS判定(os.name)が、"' + thisos + '”でした。\n'
msg += 'サポートしているOSは、UNIX系統と、Windowsです。\n'
msg += 'したがってこのOSはサポート外です。すみません。'
content = MsgboxOk \
(ok_button= self.msgOsErrorOk, \
message_text= msg)
self.popup = Popup(title='OSサポートエラー', content=content)
self.popup.open()
return
self.manager.get_screen('set').begin_path_dsp.text = path
self.tv.add_node(TreeViewLabel(text ='シンカリオン E1 とき'))
self.tv.add_node(TreeViewLabel(text ='シンカリオン 0 ひかり'))
self.tv.add_node(TreeViewLabel(text ='シンカリオン キハ32 鉄道ホビートレイン'))
def setupButtonClicked(self):
sm.current = 'set'
def show_load(self):
'''
content = LoadDialog(load = self.load, cancel = self.dismiss_popup)
self._popup = Popup( title="読み込み中", content=content, size_hint=(0.9,0.9))
self._popup.open()
'''
self._popup = LstPOP( load = self.load, \
cancel = self.dismiss_popup)
self._popup.open()
def load (self, path, filename):
pprint(filename)
#self.file_name.text = filename[0]
self.file_name.text = path
#with open (os.path.join(path, filename[0])) as stream:
# self.text_input.text = stream.read()
self.dismiss_popup()
def dismiss_popup(self):
self._popup.dismiss()
class FilelistApp(App):
def build(self):
allscn = AllSCN()
setscn = SetSCN()
Clock.schedule_once(allscn.begin_display, 0)
sm.add_widget(allscn)
sm.add_widget(setscn)
return sm
if __name__ == '__main__':
FilelistApp().run()
filelist.kv
<SetSCN>:
name: 'set'
begin_path_dsp: begin_path_dsp
BoxLayout:
orientation: 'vertical'
BoxLayout:
size_hint_y: 0.1
orientation: 'horizontal'
BoxLayout:
Label:
size_hint_x: 0.1
text: '開始パス'
TextInput:
id: begin_path_dsp
size_hint_x: 0.8
Button:
size_hint_x: 0.1
text: '…'
on_release: root.setSelect()
BoxLayout:
size_hint_y: 0.8
BoxLayout:
size_hint_y: 0.1
Button:
size_hint_x: 0.5
text: 'OK'
on_release: root.selfOk()
Button:
size_hint_x: 0.5
text: 'キャンセル'
on_release: root.selfCancel()
<AllSCN>:
name: 'all'
tv: tv
file_name: file_name
BoxLayout:
orientation: 'vertical'
BoxLayout: #OpnSCN
size_hint_y: 0.1
orientation: 'horizontal'
BoxLayout:
Button:
size_hint_x: 0.1
text: '設定'
on_release: root.setupButtonClicked()
TextInput:
id: file_name
size_hint_x: 0.7
text: 'ファイルパス'
Button:
size_hint_x: 0.1
text: '…'
on_release: root.show_load()
Button:
size_hint_x: 0.1
text: '実行'
BoxLayout: #ResultSCN
size_hint_y: 0.9
TreeView:
id: tv
<MsgboxOk>
orientation: 'vertical'
Label:
size_hint_y: 0.9
text: root.message_text
BoxLayout:
size_hint_y: 0.1
orientation: 'horizontal'
Button:
size_hint_x: 10
text: 'OK'
on_release: root.ok_button()
<MsgboxOkCancel>
orientation: 'vertical'
Label:
size_hint_y: 0.9
text: root.message_text
BoxLayout:
size_hint_y: 0.1
orientation: 'horizontal'
Button:
size_hint_x: 10
text: 'OK'
on_release: root.ok_button()
Button:
size_hint_x: 10
text: 'キャンセル'
on_release: root.cancel_button()
#<LoadDialog>:
<LstPOP>:
id:lst_pop
size_hint: 0.9, 0.9
BoxLayout:
size: root.size
pos: root.pos
orientation: 'vertical'
FileChooserListView:
id: filechooser
dirselect: True
path: root.current_dir
filters: [root.is_dir]
on_touch_down: lst_pop.lstChooser(filechooser.path, filechooser.selection)
BoxLayout:
size_hint_y : None
height : 30
Button:
text: 'キャンセル'
on_release: root.cancel()
Button:
text: '読み込み'
on_release: root.load(filechooser.path, filechooser.selection)
AllSCN:
これで起動、「設定」→「…」で、
初期のパス表示が出る。そして、「../」押下(ダブルクリック 以下同じ)で、
ここで「01_filelist_testdata」へ。
「旧」へ
「左巻きなると」へ
ここで「読み込み」
これで入力結果が反映。
なお、起動直後の「…」も、同じロジックにしているので、同様に確認する。
ここで「読み込み」押下で、
ロジックの説明ですけど、filelist.py上の
#class LoadDialog(FloatLayout):
class LstPOP(Popup):
(省略ですわよ)
def lstChooser(self, path, selection):
if 0 < len(selection):
self.title = '読み込み中 ' + selection[0]
#print('クリックされました path:' + path)
#print('クリックされました selection:' + selection[0])
ここが、ダブルクリップとしなければならなくロジックで、一回目のクリックではselection
にはなにも入っておらず、二回目のクリックでselection
に値が入ってくるので、これを利用したのだけど、もっといいロジックないかな。
すみません、現状私のレベルでは、解決できませんでした。また機会があったら改善しようと思います。