使用KIvy创建命令行

时间:2018-02-17 11:46:45

标签: python command-line command kivy textinput

我一直试图模拟命令行设计,这样我就可以:
- 输入命令
- 执行它
- 在我输入的命令文本的同一窗口 下输出它。
所以我需要的是:

command_one
命令1已处理,这是输出

我已部分完成此操作,但会发生的是输出文本会覆盖输入而不是“添加”。我遇到的另一个问题是,每次我需要输入内容时,我必须单击 TextInput 窗口,而不是只能在不使用鼠标的情况下输入命令。

是否有任何解决方法可以帮助我解决这个问题?

这是我的代码:(mainapp.py)(已更改)

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout

class MainWindow(BoxLayout):
    # We create a dictionary of all our possible methods to call, along with keys
    def __init__(self, **kwargs):
        super(MainWindow, self).__init__(**kwargs) #This makes sure the kivy super classes from which MainWindow descends get initialized correctly.

        self.command_dict =  {
            'one': self.command_one,
            'two': self.command_two,
            'three': self.command_three,
        }
    def process_command(self):
        # We grab the text from the user text input as a key
        command_key = self.ids.fetch_key_and_process_command.text
        old_text = command_key.strip()

        # We then use that key in the command's built in 'get_method' because it is a dict
        # then we store it into a variable for later use
        called_command = self.command_dict().get[old_text, 'default']
        try:
            # The variable is a method, so by adding we can call it by simple adding your typical () to the end of it.
            called_command()

        except TypeError:
            # However we use an exception clause to catch in case people enter a key that doesn't exist
            self.ids.fetch_key_and_process_command.text = 'Sorry, there is no command key: ' + command_key
    # These are the three commands we call from our command dict.
    def command_one(self):
        self.ids.fetch_key_and_process_command.text = "{}\n{}\n".format(old_text, "Command One has Been Processed")

    def command_two(self):
        self.ids.fetch_key_and_process_command.text = 'Command Two has Been Processed'

    def command_three(self):
        self.ids.fetch_key_and_process_command.text = 'Command Three has been Processed'



class MainApp(App):

    def build(self):
        return MainWindow()

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

(mainapp.kv)

<MainWindow>:
    Label:
        text: 'This is a label'
    TextInput:
        id: fetch_key_and_process_command
        multiline: True  
    Button:
        id: process_command_button
        text: "Process Command"
        on_release: root.process_command()

出现的错误说:

  

第21行,在process_command中        called_command = self.command_dict()。get [command_key,&#39;默认&#39;]    TypeError:&#39; dict&#39;对象不可调用

2 个答案:

答案 0 :(得分:0)

  

我已经部分完成了这个,但结果是输出   文本覆盖输入而不是“添加

你需要做这样的事情:

text_input = self.ids.fetch_key_and_process_command
old_text = text_input.text.strip()
new_text = "{}\n{}\n".format(old_text, "Command One has Been Processed")
text_input.text = new_text

请注意,当您需要多个点来检索某个对象时,例如 self.ids.fetch_key_and_process_command不要一遍又一遍地这样做 - 效率低下。相反,检索一次对象并将对象分配给一个变量,然后使用该变量,这样可以更容易地输入!

  

我遇到的另一个问题是我必须点击   TextInput窗口每次我需要输入内容而不是   只是能够在不使用我的情况下继续输入命令   小鼠

试试这个:

  ... 
  ...
  text_input.text = new_text
  text_input.focus = True
  

我意识到我必须删除多行:False属性   kv文件,但那时我将无法使用on_text命令   我真的不知道从哪里开始。

创建一个用户在完成输入时可以单击的按钮 - 就像您在此处输入问题时单击的Post Your Question按钮一样。然后该按钮可以调用process_command()而不是TextInput:

<MainWindow>:
    Label:
        text: 'This is a label'
    TextInput:
        id: fetch_key_and_process_command
        multiline: True  
    Button:
        id: process_command_button
        text: "Process Command"
        on_release: root.process_command()

对评论的回应:

以下是需要考虑的几件事:

1)向TextInput添加文本的问题是,当您检索第二个命令的文本时,您将获得 all TextInput中的文本,其中包含第一个文本命令以及第一个命令的输出,对吧?因此,包含第一个命令以及第一个命令和第二个命令的输出的长字符串不会成为command_dict中的键,对吧?因此,您将不得不以某种方式处理所有文本并提取第二个命令。

你当然可以这样做,比如在换行符上拆分文本,但输入一个TextInput和输出另一个TextInput或Label会更容易,然后你可以在每个命令后清除输入TextInput。

2)每次当你需要访问它时,而不是像你在这里一样重新创建dict:

def command_dict(self):
    return {
        'one': self.command_one,
        'two': self.command_two,
        'three': self.command_three,
    }

只需创建一次dict并将其附加到self:

def __init__(self, **kwargs):
    super(MainWindow, self).__init__(**kwargs) #This makes sure the kivy super classes from which MainWindow descends get initialized correctly.

    self.command_dict =  {
        'one': self.command_one,
        'two': self.command_two,
        'three': self.command_three,
    }

然后在类中的任何方法内部,您可以使用self.command_dict检索dict,并编写如下内容:

 self.command_dict['one']

您也可以利用__init__()中的机会将重点放在TextInput上。

3)您应始终strip()用户输入的文本。例如,如果用户输入“一个”,然后点击返回,然后意识到他们需要点击按钮,然后他们点击按钮。在这种情况下,文本将是“一个\ n”,这在你的词典中找不到。

答案 1 :(得分:0)

见这个例子:

class Dog:
    def __init__(self):
        self.command_dict = {
                'a': 1,
                'b': 2,
        }

    def bark(self):
        val = self.command_dict['a']
        print(val) #=> 1
        val = self.command_dict.get('c', "hello")
        print(val) #=> hello

        self.command_dict['c'] = 3
        val = self.command_dict.get('c', "goodbye")
        print(val)  #=> 3


    def run(self):
        print(self.command_dict['c'])  #=>3
        print(self.I_cant_spell_command_dict_correctly['a'])  #=> error



d = Dog()
d.bark()
d.run()

输出:

1
hello
3
3

Traceback (most recent call last):
  File "1.py", line 27, in <module>
    d.run()
  File "1.py", line 21, in run
    print(self.I_cant_spell_command_dict_correctly['a'])
AttributeError: 'Dog' object has no attribute 'I_cant_spell_command_dict_correctly'

如果我需要在方法中多次编写self.command_dict,那么我会这样做:

cmd_dict = self.command_dict

之后我会使用cmd_dict。

您知道,kivy适用于中级到高级的Python程序员。试图在像gui编程这样复杂的环境中弄清楚python的基础知识将会非常令人沮丧。

对评论的回应:

我以为我们同意了:

  

是的,你不能写some_dict()因为字典不是函数。

将字典附加到__init__()内的自我后,如何以其他方法检索字典?

答案:self.command_dict

因为自我似乎让你感到困惑,当你需要检索字典时,只需在代码中执行此操作:

my_command_dict = self.command_dict

接下来,如何在字典my_command_dict中检索?你写的是:

val = my_command_dict()

val = my_command_dict['some key']

...

如果你想要一个默认值,如果密钥不存在 - 而不是导致错误 - 因此你决定使用get()方法进行词典,你会写:< / p>

my_command_dict.get['some key', 'default']

my_command_dict.get('some key', 'default')

...

仔细查看我的示例代码和代码:

you: called_command = self.command_dict().get[old_text, 'default']
 me:            val = self.command_dict.get('c', "hello")

您能辨别出语法和语法的差异吗?从等号开始,向右移动,按字符比较每一行。