KivyのFileChooserのListViewで複数選択したときも色を変えてどれを選択したか分かるようにするの巻
はじめに
KivyのFileChooserで、ListViewを使って複数のファイルをLoadしようとしたときに、どのファイルを選択したかが分かりにくいのです。
どういうことかというと、普通にFileChooserを作ると下の動画のような状態です。
と、こんな感じでListViewでは複数のファイルを選択したときに、最後にクリックしたファイルしか背景色が変わりません。ついでに、背景色が変わったファイルのところをクリックしても背景色が元に戻りません。ですので、どのファイルを選択したかが分からなくなります、ワタシは。。。
IconViewであれば、選択したファイルの背景色がちゃんと変わっているのですけどね(動画の最後の部分です)。。。という状態です。
ファイル名が長い時はListViewのほうが見やすいので使いたいのですが、いちいちIconViewに戻ってどれが選択されているか確認するのもなんだかなぁなので、ListViewの時でもどのファイルを選択したかが分かるようにしたいぞう。
ということで、
という感じにしたときの方法の備忘録です。
もっと良い方法があるかもしれませんけど。
方法
方法としては(あ、Pythonです)
.pyファイルで、
- 背景を変えるためにColorとRectangleをimportしておく
- 以下の処理を行う関数を設定する(関数名はreset_colorとしています)
- treeviewの要素オブジェクトをforで取り出す
- ListViewの行の背景色を設定し、(奇数行oddと偶数行evenでストライプになるように)一旦、設定した元の背景色に戻す
- 要素オブジェクトがselectedの状態であれば、selected用の背景色に変える
.kvファイルで、
- FileChooser全体の背景色を設定する
- 作成した関数が、ListViewを選択するボタンを押して離したとき(on_release)と、
ListViewでファイルを選択したとき(on_selection)に発動するようにする
としています。
*背景色はデフォルトの設定から変更した方がわかりやすいので変更しています(ここではLoadDialogだけ)
コード
コードはKivyのオフィシャルサイトのFileChooserの項目のコードを都合のいいようにモディファイしたものをベースにしています。https://kivy.org/doc/stable/api-kivy.uix.filechooser.html
コメントを付けているところが今回の件のために追記したところで、
上述の方法の項における数字に対応しています(つもり)。
なお、FileChooserのidをfcとしています。
main.py
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.factory import Factory
from kivy.properties import ObjectProperty
from kivy.uix.popup import Popup
# .py 1. for changing background color
from kivy.graphics import Color, Rectangle
import os
class LoadDialog(FloatLayout):
load = ObjectProperty(None)
cancel = ObjectProperty(None)
class SaveDialog(FloatLayout):
save = ObjectProperty(None)
text_input = ObjectProperty(None)
cancel = ObjectProperty(None)
class Root(FloatLayout):
loadfile = ObjectProperty(None)
savefile = ObjectProperty(None)
text_input = ObjectProperty(None)
def dismiss_popup(self):
self._popup.dismiss()
def show_load(self):
content = LoadDialog(load=self.load, cancel=self.dismiss_popup)
self._popup = Popup(title="Load file", content=content,
size_hint=(0.9, 0.9))
self._popup.open()
def show_save(self):
content = SaveDialog(save=self.save, cancel=self.dismiss_popup)
self._popup = Popup(title="Save file", content=content,
size_hint=(0.9, 0.9))
self._popup.open()
def load(self, path, filename):
with open(os.path.join(path, filename[0])) as stream:
self.text_input = stream.read()
self.dismiss_popup()
def save(self, path, filename):
with open(os.path.join(path, filename), 'w') as stream:
stream.write(self.text_input)
self.dismiss_popup()
# .py 2. define function
# pass fc.selection in the .kv file to the function as selectedfiles
def reset_color(self, selectedfiles):
#process when viewmode is listView
if self._popup.content.ids.fc.view_mode == 'list':
for i in self._popup.content.ids.fc.children[0].children[0].children[0].ids.treeview.children:
#Return the background color to the original color
with i.canvas.before:
Color(rgba=(29/255,49/255,86/255,1) if i.odd else (39/255,57/255,90/255,1))
#change the color with parent width
Rectangle(size=(i.parent.size[0], i.size[1]) if i.parent else (0,0), pos=(i.parent.x, i.y) if i.parent else (1,1))
#if selected rows are exist, change background color
#(attribute 'selected' is only added after selected a file)
if hasattr(i, 'selected') and i.selected:
with i.canvas.before:
Color(55/255, 65/255, 85/255, 1.0)
#change the color with parent width
Rectangle(size=(i.parent.size[0], i.size[1]) if i.parent else (0,0), pos=(i.parent.x, i.y) if i.parent else (1,1))
else:
pass
else:
pass
class Editor(App):
pass
Factory.register('Root', cls=Root)
Factory.register('LoadDialog', cls=LoadDialog)
Factory.register('SaveDialog', cls=SaveDialog)
if __name__ == '__main__':
Editor().run()
editor.kv
#:kivy 2.0.0
Root:
BoxLayout:
orientation: 'vertical'
BoxLayout:
size_hint_y: 1
Button:
text: 'Load'
on_release:
root.show_load()
Button:
text: 'Save'
on_release: root.show_save()
<LoadDialog>:
BoxLayout:
size: root.size
pos: root.pos
orientation: "vertical"
BoxLayout:
size_hint_y: None
height: sp(52)
Button:
text: 'Icon View'
on_press: fc.view_mode = 'icon'
Button:
text: 'List View'
on_press: fc.view_mode = 'list'
# .kv 2. fire function on_release
on_release: app.root.reset_color(fc.selection)
FileChooser:
id: fc
filters:['*.text']
# enable multiselection
multiselect: True
path: '.'
# .kv 2. fire function on_selection
on_selection: app.root.reset_color(fc.selection)
FileChooserIconLayout
FileChooserListLayout
BoxLayout:
size_hint_y: None
height: 100
Button:
text: "Cancel"
on_release: root.cancel()
Button:
text: "Load"
on_release: root.load(filechooser.path, filechooser.selection)
<SaveDialog>:
text_input: text_input
BoxLayout:
size: root.size
pos: root.pos
orientation: "vertical"
FileChooserListView:
id: filechooser
on_selection: text_input.text = self.selection and self.selection[0] or ''
TextInput:
id: text_input
size_hint_y: None
height:100
multiline: False
BoxLayout:
size_hint_y: None
height:100
Button:
text: "Cancel"
on_release: root.cancel()
Button:
text: "Save"
on_release: root.save(filechooser.path, text_input.text)
# .kv 1. set background color of FileChooser
<FileChooser>:
canvas.before:
Color:
rgba: 29/255,49/255,86/255,1 #Navy blue
Rectangle:
size: self.size
で、こうなる、と。
めでたしめでたし。
おわりに
KivyのFileChooserのListviewが少し分かりやすくなりました。
どこをどういじればいいか試行錯誤に難儀しましたので備忘録として残しておきます。
ついでにうっかりどなたかのお役に立てばうれしいです。
実施環境
Python 3.9.4
Kivy 2.0.0
macOS Catalina ver.10.15.7
参考にしたサイトなど
Kivyのオフィシャルサイト Filechooser; https://kivy.org/doc/stable/api-kivy.uix.filechooser.html
広告
https://business.xserver.ne.jp/
https://www.xdomain.ne.jp/
★LOLIPOP★
.tokyo
MuuMuu Domain!