Как мне построить выпадающее меню на определенном экране в Kivy? - PullRequest
0 голосов
/ 02 ноября 2019

Я пытаюсь заставить мою программу отображать выпадающее меню на определенном экране (экран два). Я попытался сделать это, определив функцию, которая создает выпадающее меню в Class ScreenTwo. Однако, когда я запускаю программу, раскрывающееся меню вообще не отображается (черный ящик - это кнопка, а не глюк).

Раскрывающееся меню не отображается

Я попытался обойти эту проблему, построив раскрывающееся меню, используя выражение ScreenTwo.drop_down(self) в

def build(self):
    Clock.schedule_once(self.blink_animation)
    return ScreenTwo.drop_down(self)
    return screen_manager

Однако теперь отображается только раскрывающееся меню, и ни один из других экранов или виджетовотображаются. ScreenOne тоже не отображается, только выпадающее меню. Я понимаю, это потому, что функция drop_down возвращается первой до screen_manager.

Отображается только раскрывающееся меню

Я также пытался создать раскрывающееся меню только на языке .kv, однако class ScreenOne(Screen) не разрешало это (или так я предполагаю, я очень новичок в Киви). Я сохранил весь код ниже и выделил соответствующие биты.

    import kivy
kivy.require('1.11.1')

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.config import Config
from kivy.animation import Animation
from kivy.clock import Clock
from datetime import datetime
from datetime import timedelta
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.base import runTouchApp
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.scrollview import ScrollView
from kivy.uix.gridlayout import GridLayout




# You can create your kv code in the Python file
Builder.load_string("""
<ScreenOne>:
    FloatLayout:
        orientation: 'horizontal'
        canvas:
            Rectangle:
                source: 'back1.jpg'
                size: self.size
                pos: self.pos
    BoxLayout:
        Button:
            background_color: 0, 0, 0, 0
            on_press:
                # You can define the duration of the change
                # and the direction of the slide
                root.manager.transition.direction = 'up'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_two'

    BoxLayout: 
        Label:
            id: blinky
            text: "Click Anywhere To Continue"
            font_size: '20sp'
            font_name: "Raleway-Regular"
            size_hint: (1.0, 0)
            alpha: 1
            color: (1, 1, 1, self.alpha)


<ScreenTwo>:
    FloatLayout:
        orientation: 'horizontal'
        canvas:
            Rectangle:
                source: 'back2.jpg'
                size: self.size
                pos: self.pos
        Label:
            id: white_box
            size: (500,500)
            alpha: 1
            bcolor: (1, 1, 1, self.alpha)
        Button:
            background_color: 0, 0, 0, 1
            size: (400, 130)
            size_hint: (None, None)
            pos_hint: {'right': 0.6, 'center_y': 0.30}
            on_press:
                root.time_now()
                root.manager.current = 'screen_three'

<ScreenThree>:
    BoxLayout:
        Button:
            background_color: 1, 0, 0, 1
            on_press:
                # You can define the duration of the change
                # and the direction of the slide
                root.manager.current = 'screen_two'
""")

# Create a class for all screens in which you can include
# helpful methods specific to that screen

Config.set('graphics', 'resizable', '0') #0 being off 1 being on as in true/false
Config.set('graphics', 'width', '960')
Config.set('graphics', 'height', '720')

class ScreenOne(Screen):
    pass

class ScreenTwo(Screen):
    def time_now(self):
        global now, month_now, date_now, day_now, hour_now, minute_now, time_now
        now = datetime.now()
        print(now)

        month_now = int(now.strftime("%m"))  # month in int
        print("month:", month_now)

        date_now = int(now.strftime("%d"))  # date in int
        print("date:", date_now)

        day_now = now.strftime("%A")  # day in str
        print("day of the week:", day_now)

        hour_now = int(now.strftime("%H")) * 100
        minute_now = int(now.strftime("%M"))
        time_now = hour_now + minute_now  # day in str in 24 hour format
        print("time:", time_now)
    def check_open(day_now, opening_days, time_now, opening_time):
        global isopen
        opening_days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Saturday"]
        opening_time = [800, 2200]
        isopen = False
        if day_now in opening_days and time_now >= opening_time[0] and time_now <= opening_time[1]:
            isopen = True
            print("Is the store open? ", isopen)
            return isopen
        else:
            print("Is the store open? ", isopen)
            return

Это собственно выпадающее меню

def drop_down(self):
        global days
        days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
        global layout
        layout = GridLayout(cols=4, spacing=10, size_hint_y=None)
        dropdown1 = DropDown()
        for index in range(7):
            btn1 = Button(text=days[index], size_hint_y=None, height=44)
            btn1.bind(on_release=lambda btn1: dropdown1.select(btn1.text))
            dropdown1.add_widget(btn1)
        daybutton = Button(text='Day', size_hint=(None, None))
        daybutton.bind(on_release=dropdown1.open)
        dropdown1.bind(on_select=lambda instance, x: setattr(daybutton, 'text', x))
        layout.add_widget(daybutton)
        dropdown = DropDown()
        for index in range(24):
            # When adding widgets, we need to specify the height manually
            # (disabling the size_hint_y) so the dropdown can calculate
            # the area it needs.
            btn = Button(text='%d' % index, size_hint_y=None, height=44)
            # for each button, attach a callback that will call the select() method
            # on the dropdown. We'll pass the text of the button as the data of the
            # selection.
            btn.bind(on_release=lambda btn: dropdown.select(btn.text))
            # then add the button inside the dropdown
            dropdown.add_widget(btn)
        # create a big main button
        mainbutton = Button(text='Hour', size_hint=(None, None))

    # show the dropdown menu when the main button is released
    # note: all the bind() calls pass the instance of the caller (here, the
    # mainbutton instance) as the first argument of the callback (here,
    # dropdown.open.).
    mainbutton.bind(on_release=dropdown.open)
    # one last thing, listen for the selection in the dropdown list and
    # assign the data to the button text.
    dropdown.bind(on_select=lambda instance, x: setattr(mainbutton, 'text', x))
    layout.add_widget(mainbutton)
    dropdown2 = DropDown()
    for index in range(60):
        btn2 = Button(text='%d' % index, size_hint_y=None, height=44)
        btn2.bind(on_release=lambda btn2: dropdown2.select(btn2.text))
        dropdown2.add_widget(btn2)
    minutebutton = Button(text='Minute', size_hint=(None, None))
    minutebutton.bind(on_release=dropdown2.open)
    dropdown2.bind(on_select=lambda instance, x: setattr(minutebutton, 'text', x))
    layout.add_widget(minutebutton)

    def submitted(self):
        global day_now
        global hour_now
        global minute_now
        global time_now
        day_now = daybutton.text
        hour_now = int(mainbutton.text)
        minute_now = int(minutebutton.text)
        time_now = hour_now + minute_now
        check_open(day_now, opening_days, time_now, opening_time)
        return day_now, hour_now, minute_now, time_now

    #        submitbutton = Button(text='Submit', size_hint=(None, None))
    #        submitbutton.bind(on_release=submitbutton.submitted)

    #        layout.add_widget(submitbutton)

    return layout

pass

class ScreenThree(Screen):
    pass



# The ScreenManager controls moving between screens
screen_manager = ScreenManager()

# Add the screens to the manager and then supply a name
# that is used to switch screens
screen_manager.add_widget(ScreenOne(name="screen_one"))
screen_manager.add_widget(ScreenTwo(name="screen_two"))
screen_manager.add_widget(ScreenThree(name="screen_three"))

class KivyTut2App(App):
    def blink_animation(self, dt):
        anim = Animation(alpha=0, duration=1) + Animation(alpha=1, duration=1)
        anim.repeat = True
        anim.start(screen_manager.get_screen('screen_one').ids.blinky)
    def build(self):
        Clock.schedule_once(self.blink_animation)

Я пытаюсь создать здесь выпадающее меню

    return ScreenTwo.drop_down(self)
return screen_manager

sample_app = KivyTut2App()
sample_app.run()

1 Ответ

1 голос
/ 02 ноября 2019

Несколько изменений, чтобы ваш DropDown заработал.

  • Измените return в методе build() на return screen_manager и удалите остальные return из этого метода. Метод может возвращаться только один раз.
  • Переименуйте ваш метод drop_down в def on_enter(self, *args):. Метод будет вызываться автоматически при отображении ScreenTwo.
  • Заменить оператор return layout в конце вышеуказанного метода на self.add_widget(layout). Это добавит DropDown к ScreenTwo.
...