Kivy 从 FloatLayout 继承 ScreenManager

Kivy Inherit ScreenManager from FloatLayout

我无法理解如何使用 Kivy 将一个 class 的功能继承到另一个。我理解错误消息 ('LoadDialog_Directory' object has no attribute 'manager'),但我只是不明白如何修复它。我相信我需要用下面的功能做点什么,但最终,我不知道。

def __init__(self, **kwargs):
        super().__init__(**kwargs)

此脚本的目标是能够select 将特定驱动程序作为 path 用于 filechooser。我选择 而不是其他人,因为大多数人都在使用 Kivy 1.11.1,这个版本有很多不适用于 2.0 的已弃用功能。

.py

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang.builder import Builder
from kivy.uix.spinner import SpinnerOption
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ObjectProperty
from kivy.utils import platform
from kivy.properties import StringProperty

import os
import string


class WindowManager(ScreenManager):
    pass   
class MyOption(SpinnerOption):
    pass


class LoadDialog_Directory(FloatLayout):
    load = ObjectProperty(None)
    cancel = ObjectProperty(None)

    def dir_driver(self):
        x = self.manager.get_screen("first")
        return str(x.ids.drive_dir.text)

        
        
class FirstWindow(Screen):

    def get_drives(self):
        drives = ['%s:' % d for d in string.ascii_uppercase if os.path.exists('%s:' % d)]
        return drives
        
      
    def dismiss_popup(self):
        self._popup.dismiss()
  
        
    def show_load_directory(self):
        content = LoadDialog_Directory(load=self.directroy_path, cancel=self.dismiss_popup)
        self._popup = Popup(title="Load file", content=content, size_hint=(0.9, 0.9))
        self._popup.open()
        
                
    def directroy_path(self, path, filename):        
        self.ids.text_input_directory.text = str(filename[0])
        self.dismiss_popup()
        
             
kv_main = Builder.load_file('main.kv')

#
class MyApp(App):
    def build(self):
        return kv_main
        

if __name__ == '__main__':
    
    MyApp().run()

main.kv

#:include first.kv

WindowManager:
    FirstWindow:
    
<LoadDialog_Directory>:
    BoxLayout:
        size: root.size
        pos: root.pos
        orientation: "vertical"
        FileChooserListView:
            id: filechooser
            dirselect: True
            path: root.dir_driver()

        BoxLayout:
            size_hint_y: None
            height: 30
            Button:
                text: "Cancel"
                on_release: root.cancel()
            Button:
                text: "Load"
                on_release: root.load(filechooser.path, filechooser.selection)

first.kv

<FirstWindow>
    name: 'first'
    GridLayout:
        cols: 1
        
        BoxLayout:
            orientation: "horizontal"               
            TextInput:
        
        BoxLayout:
            orientation: "horizontal"
            Spinner:    
                id: drive_dir
                text: "Root Drive"
                halign: 'center'
                option_cls: "MyOption"
                values: root.get_drives()               
            Button:
                text: "Set Result Directory"
                on_release: root.show_load_directory()
            TextInput:
                id: text_input_directory
                disabled: True
                text: text_input_directory.text
        
        BoxLayout:
            size_hint: (0.01, 1)
            orientation: "horizontal"       
            TextInput:

旁注:额外空白 TextInput 的原因是因为 Spinner 如果占用过多应用程序,将无法运行(显示驱动程序)。

经过几个小时的试验和错误,我终于让它工作了,但我不知道它为什么工作。以下是更改内容:

  1. class LoadDialog_Directory(FloatLayout) 中的新变量 - input_pth
  2. class FirstWindow(Screen) 函数 show_load_directory(self)
  3. 中将 input_pth 调用到我的 content 变量中
  4. 在 main.kv 文件中将我的 filechooser.path 设置为 root.input_pth

我不明白 content 中的 input_pth 变量如何能够引用 class LoadDialog_Directory(FloatLayout) 而不必传递类似的内容:

def __init__(self, input_pth, **kwargs):
        super(LoadDialog_Directory, self).__init__()
        self.input_pth = input_pth

.py

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang.builder import Builder
from kivy.uix.spinner import SpinnerOption
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ObjectProperty
from kivy.utils import platform
from kivy.properties import StringProperty

import os
import string


class WindowManager(ScreenManager):
    pass  
    
class MyOption(SpinnerOption):
    pass


class LoadDialog_Directory(FloatLayout):   
    input_pth = StringProperty()
    load = ObjectProperty()
    cancel = ObjectProperty()
    
        
        
class FirstWindow(Screen):

    def drive_list(self):
        drives = ['%s:' % d for d in string.ascii_uppercase if os.path.exists('%s:' % d)]
        return drives
        
      
    def dismiss_popup(self):
        self._popup.dismiss()
  
        
    def show_load_directory(self):
        content = LoadDialog_Directory(load=self.directroy_path, cancel=self.dismiss_popup, input_pth=self.ids.drive_dir.text)
        
        self._popup = Popup(title="Load file", content=content, size_hint=(0.9, 0.9))
        self._popup.open()
        
                
    def directroy_path(self, path, filename):        
        self.ids.text_input_directory.text = str(filename[0])
        self.dismiss_popup()

        
             
kv_main = Builder.load_file('main.kv')

#
class MyApp(App):
    def build(self):
        return kv_main
        

if __name__ == '__main__':
    
    MyApp().run()

main.kv

#:include first.kv

WindowManager:
    FirstWindow:
    
<LoadDialog_Directory>:
    BoxLayout:
        size: root.size
        pos: root.pos
        orientation: "vertical"
        FileChooserListView:
            id: filechooser
            dirselect: True
            path: root.input_pth

        BoxLayout:
            size_hint_y: None
            height: 30
            Button:
                text: "Cancel"
                on_release: root.cancel()
            Button:
                text: "Load"
                on_release: root.load(filechooser.path, filechooser.selection)

first.kv

<FirstWindow>
    name: 'first'
    GridLayout:
        cols: 1
        
        BoxLayout:
            orientation: "horizontal"               
            TextInput:
        
        BoxLayout:
            orientation: "horizontal"
            Spinner:    
                id: drive_dir
                halign: 'center'
                option_cls: "MyOption"
                values: root.drive_list()

            Button:
                text: "Set Result Directory"
                on_release: root.show_load_directory()
            TextInput:
                id: text_input_directory
                disabled: True
                text: text_input_directory.text
        
        BoxLayout:
            size_hint: (0.01, 1)
            orientation: "horizontal"       
            TextInput: