Python kivymd 退出时弹出
Posted
技术标签:
【中文标题】Python kivymd 退出时弹出【英文标题】:Python kivymd Popup when exiting 【发布时间】:2019-01-13 22:15:06 【问题描述】:我正在尝试创建一个用于退出应用程序的弹出窗口。但我不断收到错误“object.init() 没有参数”。在我的项目文件夹中,我有一个名为“应用程序”的文件夹。在此文件夹中,我已将相关的 kivymd *.py 文件复制到名为 kivymd 的文件夹中。我很感激任何帮助。单击退出应用程序选项后,我想要一个带有按钮的弹出窗口来接受或取消应用程序的退出。
在应用程序文件夹中,我有三个文件:main.py、main.kv 和 labels.py(用于将标签注入 main.py 和 main.kv)。
main.py 包含应用程序的所有逻辑。
# -*- coding: utf-8 -*-
import os
# Set virtual keyboard
from kivy.app import App
from kivy.config import Config
Config.set('kivy', 'keyboard_mode', 'systemandmulti')
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.core.window import Window
Window.fullscreen = "auto"
from kivy.lang import Builder
from functools import partial
from kivymd.list import BaseListItem
from kivymd.material_resources import DEVICE_TYPE
from kivymd.navigationdrawer import MDNavigationDrawer, NavigationDrawerHeaderBase
from kivymd.theming import ThemeManager
from kivymd.button import MDIconButton
class HackedDemoNavDrawer(MDNavigationDrawer):
# DO NOT USE
def add_widget(self, widget, index=0):
if issubclass(widget.__class__, BaseListItem):
self._list.add_widget(widget, index)
if len(self._list.children) == 1:
widget._active = True
self.active_item = widget
# widget.bind(on_release=lambda x: self.panel.toggle_state())
widget.bind(on_release=lambda x: x._set_active(True, list=self))
elif issubclass(widget.__class__, NavigationDrawerHeaderBase):
self._header_container.add_widget(widget)
else:
super(MDNavigationDrawer, self).add_widget(widget, index)
class MainApp(App):
theme_cls = ThemeManager()
title = "Application"
def build(self):
main_widget = Builder.load_file(
os.path.join(os.path.dirname(__file__), "./main.kv")
)
self.theme_cls.theme_style = 'Dark'
main_widget.ids.text_field_error.bind(
on_text_validate=self.set_error_message,
on_focus=self.set_error_message)
self.bottom_navigation_remove_mobile(main_widget)
return main_widget
def stop(self, *largs):
# Open the popup you want to open and declare callback if user pressed `Yes`
popup = ExitPopup(title="Are you sure?",
content=Button(text='Close me!'),
size=(400, 400), size_hint=(None, None)
)
popup.bind(on_confirm=partial(self.close_app, *largs))
popup.open()
def close_app(self, *largs):
super(MainApp, self).stop(*largs)
def bottom_navigation_remove_mobile(self, widget):
# Removes some items from bottom-navigation demo when on mobile
if DEVICE_TYPE == 'mobile':
widget.ids.bottom_navigation_demo.remove_widget(widget.ids.bottom_navigation_desktop_2)
if DEVICE_TYPE == 'mobile' or DEVICE_TYPE == 'tablet':
widget.ids.bottom_navigation_demo.remove_widget(widget.ids.bottom_navigation_desktop_1)
def set_error_message(self, *args):
if len(self.root.ids.text_field_error.text) == 2:
self.root.ids.text_field_error.error = True
else:
self.root.ids.text_field_error.error = False
def on_pause(self):
return True
def on_stop(self):
pass
class ExitPopup(Popup):
def __init__(self, **kwargs):
super(ExitPopup, self).__init__(**kwargs)
self.register_event_type('on_confirm')
def on_confirm(self):
pass
def on_button_yes(self):
self.dispatch('on_confirm')
if __name__ == '__main__':
MainApp().run()
main.kv是使用kv语言来判断用户界面
# main.kv
#:kivy 1.10.1
#:import Toolbar kivymd.toolbar.Toolbar
#:import MDNavigationDrawer application.kivymd.navigationdrawer.MDNavigationDrawer
#:import NavigationLayout application.kivymd.navigationdrawer.NavigationLayout
#:import NavigationDrawerDivider application.kivymd.navigationdrawer.NavigationDrawerDivider
#:import NavigationDrawerToolbar application.kivymd.navigationdrawer.NavigationDrawerToolbar
#:import NavigationDrawerSubheader application.kivymd.navigationdrawer.NavigationDrawerSubheader
#:import MDTextField application.kivymd.textfields.MDTextField
#:import labels application.labels
NavigationLayout:
id: nav_layout
MDNavigationDrawer:
id: nav_drawer
NavigationDrawerToolbar:
title: labels.NAVIGATION
NavigationDrawerIconButton:
icon: 'checkbox-blank-circle'
text: labels.SYSTEM_PARAMETERS
on_release: app.root.ids.scr_mngr.current = 'system_parameters'
NavigationDrawerIconButton:
icon: "checkbox-blank-circle"
text: labels.CLOSE_APPLICATION
on_release: app.stop()
BoxLayout:
orientation: 'vertical'
halign: "center"
Toolbar:
id: toolbar
title: labels.APPLICATION_NAME
md_bg_color: app.theme_cls.primary_color
background_palette: 'Primary'
background_hue: '500'
left_action_items: [['menu', lambda x: app.root.toggle_nav_drawer()]]
#right_action_items: [['dots-vertical', lambda x: app.root.toggle_nav_drawer()]]
ScreenManager:
id: scr_mngr
Screen:
name: 'system_parameters'
BoxLayout:
orientation: "horizontal"
BoxLayout:
orientation: 'vertical'
size_hint_y: None
height: self.minimum_height
padding: dp(48)
spacing: 10
MDTextField:
hint_text: "Helper text on focus"
helper_text: "This will disappear when you click off"
helper_text_mode: "on_focus"
input_filter: "int"
BoxLayout:
orientation: 'vertical'
size_hint_y: None
height: self.minimum_height
padding: dp(48)
spacing: 10
MDTextField:
hint_text: "Helper text on focus"
helper_text: "This will disappear when you click off"
helper_text_mode: "on_focus"
input_filter: "float"
Screen:
name: 'textfields'
ScrollView:
BoxLayout:
orientation: 'vertical'
MDTextField:
id: text_field_error
hint_text: "Helper text on error (Hit Enter with two characters here)"
helper_text: "Two is my least favorite number"
helper_text_mode: "on_error"
Screen:
name: 'nav_drawer'
HackedDemoNavDrawer:
# NavigationDrawerToolbar:
# title: "Navigation Drawer Widgets"
NavigationDrawerIconButton:
icon: 'checkbox-blank-circle'
text: "Badge text ---->"
badge_text: "99+"
NavigationDrawerIconButton:
active_color_type: 'accent'
text: "Accent active color"
NavigationDrawerIconButton:
active_color_type: 'custom'
text: "Custom active color"
active_color: [1, 0, 1, 1]
NavigationDrawerIconButton:
use_active: False
text: "Use active = False"
NavigationDrawerIconButton:
text: "Different icon"
icon: 'alarm'
NavigationDrawerDivider:
NavigationDrawerSubheader:
text: "NavigationDrawerSubheader"
NavigationDrawerIconButton:
text: "NavigationDrawerDivider \/"
NavigationDrawerDivider:
labels.py 很短
# labels.py
APPLICATION_NAME = "Application"
CLOSE_APPLICATION = "Close Application"
NAVIGATION = "Navigation"
SYSTEM_PARAMETERS = "System Parameters"
【问题讨论】:
【参考方案1】:解决方案 - 使用 KivyMD MDDialog
在以下示例中,它使用 KivyMD MDDialog 作为弹出窗口。
片段
from kivymd.dialog import MDDialog
from kivymd.label import MDLabel
from kivy.metrics import dp
class ExitPopup(MDDialog):
def __init__(self, **kwargs):
super(ExitPopup, self).__init__(**kwargs)
content = MDLabel(font_style='Body1',
theme_text_color='Secondary',
text="Are you sure?",
size_hint_y=None,
valign='top')
content.bind(texture_size=content.setter('size'))
self.dialog = MDDialog(title="Close Application",
content=content,
size_hint=(.3, None),
height=dp(200))
self.dialog.add_action_button("Close me!",
action=lambda *x: self.dismiss_callback())
self.dialog.open()
def dismiss_callback(self):
self.dialog.dismiss()
App.get_running_app().close_app()
...
def stop(self, *largs):
# Open the popup you want to open and declare callback if user pressed `Yes`
ExitPopup()
输出 - KivyMD MDDialog
解决方案 - 使用 Kivy 弹出窗口
详情请参考step-by-step、sn-p和example。
-
添加导入语句,
from kivy.uix.button import Button
将MDIconButton
替换为Button
片段
def stop(self, *largs):
# Open the popup you want to open and declare callback if user pressed `Yes`
popup = ExitPopup(title="Are you sure?",
content=Button(text='Close me!'),
size=(400, 400), size_hint=(None, None)
)
示例 - Kivy 弹出窗口
main.py
># -*- coding: utf-8 -*-
import os
# Set virtual keyboard
from kivy.app import App
from kivy.config import Config
from kivy.uix.popup import Popup
from kivy.uix.button import Button
Config.set('kivy', 'keyboard_mode', 'systemandmulti')
from kivy.core.window import Window
# Window.fullscreen = "auto"
from kivy.lang import Builder
from functools import partial
from kivymd.list import BaseListItem
from kivymd.material_resources import DEVICE_TYPE
from kivymd.navigationdrawer import MDNavigationDrawer, NavigationDrawerHeaderBase
from kivymd.theming import ThemeManager
class HackedDemoNavDrawer(MDNavigationDrawer):
# DO NOT USE
def add_widget(self, widget, index=0):
if issubclass(widget.__class__, BaseListItem):
self._list.add_widget(widget, index)
if len(self._list.children) == 1:
widget._active = True
self.active_item = widget
# widget.bind(on_release=lambda x: self.panel.toggle_state())
widget.bind(on_release=lambda x: x._set_active(True, list=self))
elif issubclass(widget.__class__, NavigationDrawerHeaderBase):
self._header_container.add_widget(widget)
else:
super(MDNavigationDrawer, self).add_widget(widget, index)
class MainApp(App):
theme_cls = ThemeManager()
title = "Application"
def build(self):
main_widget = Builder.load_file(
os.path.join(os.path.dirname(__file__), "./main.kv")
)
self.theme_cls.theme_style = 'Dark'
main_widget.ids.text_field_error.bind(
on_text_validate=self.set_error_message,
on_focus=self.set_error_message)
self.bottom_navigation_remove_mobile(main_widget)
return main_widget
def stop(self, *largs):
# Open the popup you want to open and declare callback if user pressed `Yes`
popup = ExitPopup(title="Are you sure?",
content=Button(text='Close me!'),
size=(400, 400), size_hint=(None, None)
)
popup.bind(on_confirm=partial(self.close_app, *largs))
popup.open()
def close_app(self, *largs):
super(MainApp, self).stop(*largs)
def bottom_navigation_remove_mobile(self, widget):
# Removes some items from bottom-navigation demo when on mobile
if DEVICE_TYPE == 'mobile':
widget.ids.bottom_navigation_demo.remove_widget(widget.ids.bottom_navigation_desktop_2)
if DEVICE_TYPE == 'mobile' or DEVICE_TYPE == 'tablet':
widget.ids.bottom_navigation_demo.remove_widget(widget.ids.bottom_navigation_desktop_1)
def set_error_message(self, *args):
if len(self.root.ids.text_field_error.text) == 2:
self.root.ids.text_field_error.error = True
else:
self.root.ids.text_field_error.error = False
def on_pause(self):
return True
def on_stop(self):
pass
class ExitPopup(Popup):
def __init__(self, **kwargs):
super(ExitPopup, self).__init__(**kwargs)
self.register_event_type('on_confirm')
def on_confirm(self):
pass
def on_button_yes(self):
self.dispatch('on_confirm')
if __name__ == '__main__':
MainApp().run()
输出 - Kivy 弹出窗口
【讨论】:
我编辑了我的 main.py,但它仍然不起作用。你能发布你的 main.py 吗? 我更新了我的帖子。有一点我不得不复制 Config.set("kivy", "keyboard_mode", "systemandmulti") 旁边的 from kivy.config import Config 以确保虚拟键盘在拖动时不会自行关闭。弹出窗口与标准按钮一起使用,但单击该按钮不会关闭应用程序。 我想我需要更改 kv 文件以触发相应的功能。 请参阅用 KivyMD MDDialog 小部件替换 Kivy Popup 小部件的更新帖子。 新版本就像一个魅力!非常感谢您的努力和时间!以上是关于Python kivymd 退出时弹出的主要内容,如果未能解决你的问题,请参考以下文章
如何用python做一个在windows关机时弹出一句消息提示的小程序?
pycharm导入工程文件执行程序时弹出Edit configuration