python - 单击时中断 Kivy 切换按钮状态更改
问题描述
我有一个用于启动和停止进程的切换按钮。当进程停止时,我会出现一个弹出框,要求用户输入密码以确认他们想要结束进程。
只有提供正确的密码后,我才希望切换按钮的状态从“关闭”变为“正常”,因为正在结束的进程使用切换按钮状态来确定进程是否应该继续运行。
我目前遇到的问题是,按下切换按钮的那一刻,状态从“向下”变为“正常”,因此在显示用于验证用户的密码框之前结束该过程。
关于如何在单击切换按钮时中断状态更改的任何建议?
已编辑!
主要.py:
# import kivy modules
from kivy.app import App
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.properties import ObjectProperty
from kivy.config import Config
Config.set('kivy', 'exit_on_escape', '0')
# import self defined backend class
from ProcessPanel import ProcessPanel
class Automation(App):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def build(self):
return AppPanels()
class AppPanels(TabbedPanel):
process_tab = ObjectProperty(None)
process_tab_panel = ObjectProperty(None)
def __init__(self, **kwargs):
super().__init__(**kwargs)
if __name__ == '__main__':
Automation().run()
进程面板.py:
# import kivy modules
from kivy.properties import Clock
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.togglebutton import ToggleButton
from kivy.properties import ObjectProperty
# import self defined backend classes
from ToolStopWindow import ToolStopWindow
class ProcessPanel(BoxLayout):
process_toggle = ObjectProperty()
def __init__(self, **kwargs):
# inherit BoxLayout Attributes and Methods
super().__init__(**kwargs)
self.num = 0
# create the custom query pop up window
self.TSW = ToolStopWindow(passwd="testPassword",
title_text="Are you sure you want to stop the process?",
sub_title_text="Enter Password to Stop Process...",
external_button=self.process_toggle)
self.TSW.confirm_btn.bind(on_release=self.end_process)
self.process_toggle.bind(_do_press=self.toggle_switch_state())
self.process_schedule = []
# Determine if process has been activated
def toggle_switch_state(self):
if self.process_toggle.state == "normal":
self.process_schedule = Clock.schedule_interval(self.my_process, 5)
self.process_toggle._do_unpress()
else:
self.TSW.open()
def my_process(self, dt):
self.num = self.num + 1
print(self.num)
def end_process(self):
self.process_schedule.cancel()
class StartStopToggle(ToggleButton):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def _do_unpress(self):
if (not self.allow_no_selection and
self.group and self.state == 'down'):
return
self._release_group(self)
self.state = 'normal' if self.state == 'down' else 'down'
ToolStopWindow.py:
import time
from kivy.properties import ObjectProperty
from kivy.uix.popup import Popup
class ToolStopWindow(Popup):
passwd_box = ObjectProperty()
passwd = ObjectProperty()
confirm_btn = ObjectProperty()
confirm_btn_callback = ObjectProperty()
cancel_btn = ObjectProperty()
title_text = ObjectProperty()
sub_title = ObjectProperty()
sub_title_text = ObjectProperty()
external_button = ObjectProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.is_true = False
def check_pass(self):
if self.passwd_box.text == self.passwd:
self.sub_title.text = "Password Correct!"
time.sleep(1)
self.external_button._do_unpress()
self.dismiss()
else:
self.is_true = False
self.passwd_box.text = ""
self.sub_title.text = "Invalid Password!"
return
def reset_label_text(self):
if self.sub_title.text != self.sub_title_text:
self.sub_title.text = self.sub_title_text
自动化.kv:
<AppPanels>:
process_tab: process_tab
process_tab_panel: process_tab_panel
id: Tab_Level
size_hint: 1, 1
pos_hint: {'center_x': .5, 'center_y': .5}
do_default_tab: False
tab_pos: 'top_mid'
tab_width: root.width/5
font_size: 24
TabbedPanelItem:
id: process_tab
text: "Process Tab"
ProcessPanel:
id: process_tab_panel
<ProcessPanel>:
orientation: "vertical"
process_toggle: process_toggle
Button:
text: "normal button"
on_release: root.my_process(self)
StartStopToggle:
id: process_toggle
on_state: root.toggle_switch_state()
<StartStopToggle>:
text: "Start Process Schedule"
font_size: 36
<ToolStopWindow>:
id: close_window
auto_dismiss: False
title: root.title_text
size_hint: 0.8, 0.8
passwd_box: passwd_box
confirm_btn: confirm_btn
cancel_btn: cancel_btn
sub_title: sub_title
BoxLayout:
id: main_panel
orientation: "vertical"
Label:
id: sub_title
text: root.sub_title_text
font_size: 36
TextInput:
id: passwd_box
multiline: False
password: True
on_text: root.reset_label_text()
on_text_validate: root.check_pass()
BoxLayout:
id: Buttons
orientation: "horizontal"
Button:
id: confirm_btn
text: "Confirm!"
on_release: root.check_pass()
Button:
id: cancel_btn
text: "Cancel"
on_release: root.dismiss()
我想做的是将 _do_press 函数绑定到 ProcessPanel 类中的一个函数,但我不断收到一个属性错误,说“'None type' object has no attribute'bind'”,我认为这是因为 id 是 i' m 分配给 UI 对象是在init之后分配的吗?
此外,当给出正确的密码时,我对如何取消我创建的时钟来定期调用 my_process 函数有点困惑。
我希望这个例子的添加是有帮助的!
解决方案
我可能会将 ToggleButton 子类化以覆盖这些_do_press
方法做的工作是打开你的弹出窗口,然后
https://github.com/kivy/kivy/blob/master/kivy/uix/behaviors/togglebutton.py#L112-L115
class ConfirmPopup(Popup):
button = ObjectProperty()
password = StringProperty()
def check_password(self, pass):
if self.ids.password.text == self.password:
self.button._do_unpress()
self.dismiss()
class PasswordCheckedToggleButton(ToggleButton):
def _do_press(self):
ConfirmPopup(button=self, password="secret").open()
def _do_unpress(self):
if (not self.allow_no_selection and
self.group and self.state == 'down'):
return
self._release_group(self)
self.state = 'normal' if self.state == 'down' else 'down'
有类似的东西
<ConfirmPopup>:
title: "password!"
BoxLayout:
orientation: "vertical"
TextInput:
id: password
Button:
text: "it’ a me!"
on_release: root.check_password()
推荐阅读
- react-native - React Native 监听所有输入
- postgresql - 是否可以使用 typeorm 在 postgresql 中使用数字数组?
- javascript - 我可以使用 Javascript 将多个音频文件混合成一个音频吗?
- c++ - Qt:使用visual studio开发时在哪里可以找到.pro文件
- python - 如何从项目目录中的文件导入?
- python-3.x - WinError 5:为 Python 安装 pip numba 和 librosa 时拒绝访问
- python - 为什么方法解析顺序会影响我的代码的行为?
- python - 使用 Panda,根据 ID 列表和新值更新列值
- c# - 使用 Process.Start 在 C# 中传递 powershell 多个参数
- java - 将代码python转换为Java,找到达到1的最小步骤数