从内部调用时 Kivy 弹出窗口行为不当 'on_enter'
Kivy Popup misbehaviour when called from inside 'on_enter'
我正在尝试显示一个弹出窗口,以防今天是 DB 上的一个日期。
问题出在弹窗弹窗上,但它似乎建在主屏幕后面。
我假设这是由于在“on_enter”方法上调用,但无法解决这个问题。
请注意,这个“设置”按钮是从主屏幕呈现的,而不是从弹出窗口本身呈现的。
这是我的 main.py:
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.popup import Popup
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen, ScreenManager
from datetime import date, datetime
from calendar import weekday
from kivymd.toast import toast
from kivymd.uix.list import TwoLineIconListItem
from kivymd.uix.picker import MDDatePicker, MDTimePicker
from datahelper import CreateTable, InsertEstudo, DeletStudy, ReadStudy, UpdateStudy
from kivy.factory import Factory
class Gerenciador(ScreenManager):
pass
class Main(Screen):
# def verificar_estudos(self):
def on_enter(self, *args):
ler_dbestudos = ReadStudy()
resultado = ler_dbestudos.ler_estudos()
for s in resultado:
dia = s[2].split("-")[-1]
mes = s[2].split("-")[-2]
ano = s[2].split("-")[0]
print(f"{dia}/{mes}/{ano}")
dia_hoje = date.today().day
mes_hoje = date.today().month
ano_hoje = date.today().year
if int(dia) == dia_hoje:
print('Hoje é dia de revisão de matéria')
tudo = self.children
Factory.DiaDeRevisao().open()
if int(dia) + 14 == dia_hoje:
print('Hoje é dia de revisão de matéria')
Factory.DiaDeRevisao().open()
if int(mes)+1 == mes_hoje:
print('Hoje é dia de revisão de matéria')
Factory.DiaDeRevisao().open()
class Revisao(Screen):
def ver_estudos(self, *args):
read_studies = ReadStudy()
studies = read_studies.ler_estudos()
for s in studies:
self.ids.scrollviewid.add_widget(TwoLineIconListItem(text=s[1], secondary_text=s[2]))
def ver_lista(self, *args):
for r in range(20):
self.ids.scrollviewid.add_widget(TwoLineIconListItem(text='Azul', secondary_text="Texto Secundário"))
class AddStudy(Screen):
def open_calendar(self):
date_dialog = MDDatePicker(callback=self.get_date)
if self.ids.dtinist.focused == True:
date_dialog.open()
def get_date(self, *args):
'''
:type date: <class 'datetime.date'>
'''
print(args[0])
print(type(args[0]))
self.ids.dtinist.focused = False
self.ids.dtinist.text = str(args[0])
self.ids.dtinist.focused = False
return args[0]
def open_clock(self):
time_dialog = MDTimePicker()
time_dialog.bind(time=self.get_time)
if self.ids.tminist.focused == True:
time_dialog.open()
def get_time(self,*args):
self.ids.tminist.focused = False
self.ids.tminist.text = str(args[1])
self.ids.tminist.focused = False
return args[1]
def selected(self, path, selection):
tipo = selection[0].split(".")[-1]
print(tipo)
if tipo == 'mp3':
toast('Arquivo MP3 selecionado')
with open(selection[0], 'rb') as f:
barq = f.read()
insert = InsertEstudo()
insert.criar_novo_estudo()
def confirm_new(self):
materia = self.ids.materia_estudo.text
data_estudo = self.ids.dtinist.text
hora_estudo = self.ids.tminist.text
insert_new_study = InsertEstudo()
if insert_new_study.criar_novo_estudo(materia, data_estudo, hora_estudo):
toast('Estudo adicionado com sucesso')
else:
toast('Algo deu muito errado. O estudo não foi adicionado. Tente novamente mais tarde')
class SettingsScreen(Screen):
def select_path(self, path):
print(path)
'''It will be called when you click on the file name
or the catalog selection button.
:type path: str;
:param path: path to the selected directory or file;
'''
self.exit_manager()
toast(path)
def open_file_manager(self):
self.file_manager.show('/') # output manager to the screen
self.manager_open = True
def exit_manager(self):
self.manager_open = False
self.file_manager.close()
class SelectAlarm(Screen):
def selected(self, path, selection):
tipo = selection[0].split(".")[-1]
print(tipo)
if tipo == 'mp3':
toast('Arquivo MP3 selecionado')
with open(selection[0], 'rb') as f:
barq = f.read()
insert = InsertEstudo()
insert.criar_novo_estudo()
else:
toast('Por favor, seleecione um arquivo mp3')
class BoraEstudarApp(MDApp):
def on_pause(self):
return True
def build(self):
data_hoje = f"{date.today().year}-{date.today().month}-{date.today().day}"
sm = Gerenciador()
sm.add_widget(Main(name='Principal'))
sm.add_widget(SettingsScreen(name='Preferencias'))
sm.add_widget(AddStudy(name='NovaMateria'))
sm.add_widget(Revisao(name='Revisoes'))
sm.add_widget(SelectAlarm(name='SelecionarAlarme'))
return sm
if __name__ == "__main__":
boraestudar = BoraEstudarApp()
boraestudar.run()
这是我的 kv 文件:
#:import Factory kivy.factory.Factory
<ScreenManager>:
<DiaDeRevisao@Popup>:
title: 'Atenção dia de revisão'
auto_dismiss: False
size_hint:0.7,0.7
BoxLayout:
canvas.before:
Color:
rgba:(1,1,1,1)
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
orientation:'vertical'
MDLabel:
text:'Hoje é dia de revisão'
Button:
text: 'OK'
on_press: root.dismiss()
<FileChooserPop@Popup>:
title:'Escolha o arquivo de audio MP3'
BoxLayout:
canvas.before:
Color:
rgba:(0,0,0,0.35)
Rectangle:
size: self.size
pos: self.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'
FileChooser:
id: fc
FileChooserIconLayout
FileChooserListLayout
BoxLayout:
size_hint_y: None
MDTextButton:
size_hint_x:0.4
text: 'Voltar'
on_press: root.dismiss()
MDIconButton:
halign:'center'
icon:'content-save'
on_press:root.selected(fc.path, fc.selection)
on_release: root.manager.current = 'Principal'
<Main>:
BoxLayout:
orientation:"vertical"
spacing:'50dp'
padding:'70dp'
BoxLayout:
MDTextButton:
text: 'Revisões'
on_press: root.manager.current = 'Revisoes'
# on_release:Factory.FileChooserPop().open()
BoxLayout:
Button:
text: 'Settings'
on_press: root.manager.current = 'Preferencias'
BoxLayout:
MDIconButton:
icon: "plus"
on_press: root.manager.current = 'NovaMateria'
<AddStudy>:
BoxLayout:
orientation:'vertical'
spacing:'100sp'
padding: '100dp'
MDTextField:
id:materia_estudo
hint_text: 'Matéria'
MDTextField:
id: dtinist
text: ''
hint_text: 'data do Estudo'
on_focus: root.open_calendar()
MDTextField:
id:tminist
text:''
hint_text: 'Hora do Estudo'
on_focus: root.open_clock()
BoxLayout:
MDTextButton:
text:'Voltar'
on_press: root.manager.current = 'Principal'
MDTextButton:
text: 'Salvar'
on_press: root.confirm_new()
<SettingsScreen>:
BoxLayout:
MDTextButton:
text: 'Selecionar Alarme'
on_press: root.manager.current = 'SelecionarAlarme'
<SelectAlarm>:
BoxLayout:
canvas.before:
Color:
rgba:(0,0,0,0.35)
Rectangle:
size: self.size
pos: self.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'
FileChooser:
id: fc
FileChooserIconLayout
FileChooserListLayout
BoxLayout:
size_hint_y: None
MDTextButton:
size_hint_x:0.4
text: 'Voltar'
on_press: root.manager.current = 'Principal'
MDIconButton:
halign:'center'
icon:'content-save'
on_press:root.selected(fc.path, fc.selection)
on_release: root.manager.current = 'Principal'
<Revisao>:
BoxLayout:
orientation:'vertical'
BoxLayout:
ScrollView:
do_scroll_y: True
size_hint_y: None
height: '500dp'
MDList:
id:scrollviewid
BoxLayout:
size_hint_y: 0.15
MDTextButton:
size_hint_x: None
text:"Voltar"
on_release: root.manager.current = 'Principal'
MDTextButton:
text:"Ver Lista"
on_release: root.ver_estudos()
这很奇怪,我想不通。
感谢您的帮助。干杯!
问题在于 on_enter()
事件触发得太早,因此 Popup
在 Main
Screen
之前绘制。您可以通过在显示 Popup
之前添加一个非常短的延迟来解决这个问题。我改变了:
Factory.DiaDeRevisao().open()
至:
Clock.schedule_once(lambda dt: Factory.DiaDeRevisao().open())
将提供延迟并允许 Popup
显示在 Screen
之上。
我正在尝试显示一个弹出窗口,以防今天是 DB 上的一个日期。
问题出在弹窗弹窗上,但它似乎建在主屏幕后面。 我假设这是由于在“on_enter”方法上调用,但无法解决这个问题。
请注意,这个“设置”按钮是从主屏幕呈现的,而不是从弹出窗口本身呈现的。
这是我的 main.py:
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.popup import Popup
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen, ScreenManager
from datetime import date, datetime
from calendar import weekday
from kivymd.toast import toast
from kivymd.uix.list import TwoLineIconListItem
from kivymd.uix.picker import MDDatePicker, MDTimePicker
from datahelper import CreateTable, InsertEstudo, DeletStudy, ReadStudy, UpdateStudy
from kivy.factory import Factory
class Gerenciador(ScreenManager):
pass
class Main(Screen):
# def verificar_estudos(self):
def on_enter(self, *args):
ler_dbestudos = ReadStudy()
resultado = ler_dbestudos.ler_estudos()
for s in resultado:
dia = s[2].split("-")[-1]
mes = s[2].split("-")[-2]
ano = s[2].split("-")[0]
print(f"{dia}/{mes}/{ano}")
dia_hoje = date.today().day
mes_hoje = date.today().month
ano_hoje = date.today().year
if int(dia) == dia_hoje:
print('Hoje é dia de revisão de matéria')
tudo = self.children
Factory.DiaDeRevisao().open()
if int(dia) + 14 == dia_hoje:
print('Hoje é dia de revisão de matéria')
Factory.DiaDeRevisao().open()
if int(mes)+1 == mes_hoje:
print('Hoje é dia de revisão de matéria')
Factory.DiaDeRevisao().open()
class Revisao(Screen):
def ver_estudos(self, *args):
read_studies = ReadStudy()
studies = read_studies.ler_estudos()
for s in studies:
self.ids.scrollviewid.add_widget(TwoLineIconListItem(text=s[1], secondary_text=s[2]))
def ver_lista(self, *args):
for r in range(20):
self.ids.scrollviewid.add_widget(TwoLineIconListItem(text='Azul', secondary_text="Texto Secundário"))
class AddStudy(Screen):
def open_calendar(self):
date_dialog = MDDatePicker(callback=self.get_date)
if self.ids.dtinist.focused == True:
date_dialog.open()
def get_date(self, *args):
'''
:type date: <class 'datetime.date'>
'''
print(args[0])
print(type(args[0]))
self.ids.dtinist.focused = False
self.ids.dtinist.text = str(args[0])
self.ids.dtinist.focused = False
return args[0]
def open_clock(self):
time_dialog = MDTimePicker()
time_dialog.bind(time=self.get_time)
if self.ids.tminist.focused == True:
time_dialog.open()
def get_time(self,*args):
self.ids.tminist.focused = False
self.ids.tminist.text = str(args[1])
self.ids.tminist.focused = False
return args[1]
def selected(self, path, selection):
tipo = selection[0].split(".")[-1]
print(tipo)
if tipo == 'mp3':
toast('Arquivo MP3 selecionado')
with open(selection[0], 'rb') as f:
barq = f.read()
insert = InsertEstudo()
insert.criar_novo_estudo()
def confirm_new(self):
materia = self.ids.materia_estudo.text
data_estudo = self.ids.dtinist.text
hora_estudo = self.ids.tminist.text
insert_new_study = InsertEstudo()
if insert_new_study.criar_novo_estudo(materia, data_estudo, hora_estudo):
toast('Estudo adicionado com sucesso')
else:
toast('Algo deu muito errado. O estudo não foi adicionado. Tente novamente mais tarde')
class SettingsScreen(Screen):
def select_path(self, path):
print(path)
'''It will be called when you click on the file name
or the catalog selection button.
:type path: str;
:param path: path to the selected directory or file;
'''
self.exit_manager()
toast(path)
def open_file_manager(self):
self.file_manager.show('/') # output manager to the screen
self.manager_open = True
def exit_manager(self):
self.manager_open = False
self.file_manager.close()
class SelectAlarm(Screen):
def selected(self, path, selection):
tipo = selection[0].split(".")[-1]
print(tipo)
if tipo == 'mp3':
toast('Arquivo MP3 selecionado')
with open(selection[0], 'rb') as f:
barq = f.read()
insert = InsertEstudo()
insert.criar_novo_estudo()
else:
toast('Por favor, seleecione um arquivo mp3')
class BoraEstudarApp(MDApp):
def on_pause(self):
return True
def build(self):
data_hoje = f"{date.today().year}-{date.today().month}-{date.today().day}"
sm = Gerenciador()
sm.add_widget(Main(name='Principal'))
sm.add_widget(SettingsScreen(name='Preferencias'))
sm.add_widget(AddStudy(name='NovaMateria'))
sm.add_widget(Revisao(name='Revisoes'))
sm.add_widget(SelectAlarm(name='SelecionarAlarme'))
return sm
if __name__ == "__main__":
boraestudar = BoraEstudarApp()
boraestudar.run()
这是我的 kv 文件:
#:import Factory kivy.factory.Factory
<ScreenManager>:
<DiaDeRevisao@Popup>:
title: 'Atenção dia de revisão'
auto_dismiss: False
size_hint:0.7,0.7
BoxLayout:
canvas.before:
Color:
rgba:(1,1,1,1)
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
orientation:'vertical'
MDLabel:
text:'Hoje é dia de revisão'
Button:
text: 'OK'
on_press: root.dismiss()
<FileChooserPop@Popup>:
title:'Escolha o arquivo de audio MP3'
BoxLayout:
canvas.before:
Color:
rgba:(0,0,0,0.35)
Rectangle:
size: self.size
pos: self.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'
FileChooser:
id: fc
FileChooserIconLayout
FileChooserListLayout
BoxLayout:
size_hint_y: None
MDTextButton:
size_hint_x:0.4
text: 'Voltar'
on_press: root.dismiss()
MDIconButton:
halign:'center'
icon:'content-save'
on_press:root.selected(fc.path, fc.selection)
on_release: root.manager.current = 'Principal'
<Main>:
BoxLayout:
orientation:"vertical"
spacing:'50dp'
padding:'70dp'
BoxLayout:
MDTextButton:
text: 'Revisões'
on_press: root.manager.current = 'Revisoes'
# on_release:Factory.FileChooserPop().open()
BoxLayout:
Button:
text: 'Settings'
on_press: root.manager.current = 'Preferencias'
BoxLayout:
MDIconButton:
icon: "plus"
on_press: root.manager.current = 'NovaMateria'
<AddStudy>:
BoxLayout:
orientation:'vertical'
spacing:'100sp'
padding: '100dp'
MDTextField:
id:materia_estudo
hint_text: 'Matéria'
MDTextField:
id: dtinist
text: ''
hint_text: 'data do Estudo'
on_focus: root.open_calendar()
MDTextField:
id:tminist
text:''
hint_text: 'Hora do Estudo'
on_focus: root.open_clock()
BoxLayout:
MDTextButton:
text:'Voltar'
on_press: root.manager.current = 'Principal'
MDTextButton:
text: 'Salvar'
on_press: root.confirm_new()
<SettingsScreen>:
BoxLayout:
MDTextButton:
text: 'Selecionar Alarme'
on_press: root.manager.current = 'SelecionarAlarme'
<SelectAlarm>:
BoxLayout:
canvas.before:
Color:
rgba:(0,0,0,0.35)
Rectangle:
size: self.size
pos: self.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'
FileChooser:
id: fc
FileChooserIconLayout
FileChooserListLayout
BoxLayout:
size_hint_y: None
MDTextButton:
size_hint_x:0.4
text: 'Voltar'
on_press: root.manager.current = 'Principal'
MDIconButton:
halign:'center'
icon:'content-save'
on_press:root.selected(fc.path, fc.selection)
on_release: root.manager.current = 'Principal'
<Revisao>:
BoxLayout:
orientation:'vertical'
BoxLayout:
ScrollView:
do_scroll_y: True
size_hint_y: None
height: '500dp'
MDList:
id:scrollviewid
BoxLayout:
size_hint_y: 0.15
MDTextButton:
size_hint_x: None
text:"Voltar"
on_release: root.manager.current = 'Principal'
MDTextButton:
text:"Ver Lista"
on_release: root.ver_estudos()
这很奇怪,我想不通。
感谢您的帮助。干杯!
问题在于 on_enter()
事件触发得太早,因此 Popup
在 Main
Screen
之前绘制。您可以通过在显示 Popup
之前添加一个非常短的延迟来解决这个问题。我改变了:
Factory.DiaDeRevisao().open()
至:
Clock.schedule_once(lambda dt: Factory.DiaDeRevisao().open())
将提供延迟并允许 Popup
显示在 Screen
之上。