【问题标题】:widget won't display until screen size changed在屏幕尺寸更改之前,小部件不会显示
【发布时间】:2014-02-06 12:00:51
【问题描述】:

我想制作一个游戏,我选择了 Kivy 作为我的 GUI,因为我用 Python 编写了我的后端。我目前正在使用runTouchApp(appwindow) 运行应用程序,其中appwindowFloatLayout() 对象。我更新屏幕的方式是运行appwindow.clear_widgets()then appwindow.add_widget(new_screen),其中new_screen 是包含所有其他小部件的布局对象。

到目前为止它工作得很好,但由于某种原因,我无法理解我添加的小部件被正确加载(根据在后台运行的 cmd),但在我更改屏幕尺寸之前不会显示。

这是一个示例代码:

import kivy
kivy.require('1.1.1')
from kivy.base import runTouchApp
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image


appwindow = FloatLayout()
class MenuScreen():
    def build(self):
        bg = Image(source = 'Images/bg/bg.jpg',allow_stretch= True,keep_ratio= False)
        box = BoxLayout(orientation = 'vertical')
        menu_items = []
        for i in range (0,4):
            button = Button(text = 'Menu item no:'+str(i))
            button.bind(state = checkMenuPress)
            menu_items.append(button)
        for button in menu_items:
            box.add_widget(button)
        floater = FloatLayout(size = bg.size)
        floater.add_widget(bg)
        floater.add_widget(box)
        floater.size_hint = 1,1
        return floater
class SecondScreen():
    def build(self):
        bg = Image(source = 'Images/bg/bg.jpg',allow_stretch= True,keep_ratio= False)
        box = BoxLayout(orientation = 'vertical')
        box.add_widget(bg)
        return box
def checkMenuPress(button,*args):
    if button.state == 'normal':
        sc = SecondScreen().build()
        appwindow.clear_widgets()
        appwindow.add_widget(sc)
if __name__ == '__main__':
    menuscreen = MenuScreen().build()
    appwindow.add_widget(menuscreen)
    runTouchApp(appwindow)

【问题讨论】:

  • 请提供一个简短的工作示例来说明您的问题。用这么少的信息是不可能调试的。
  • 上面的代码工作正常,但是在几次屏幕更新后,最终屏幕只显示背景图像和标签。按钮和其他图像已加载但在窗口大小更改之前不显示

标签: python widget kivy


【解决方案1】:

好的,这里有一些问题。要创建应用程序,您应该继承 kivy.app.App 并让它的构建方法返回“根”小部件。只有这个类需要构建方法:其他的都是多余的。

一旦您有了根小部件,只需插入和移除小部件即可。这就是我的处理方式。

import kivy
kivy.require('1.1.1')
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
from kivy.app import App


class MenuScreen(App):
    floater = None

    def build(self):
        bg = Image(source='Images/bg/bg.jpg',
                   allow_stretch= True,
                   keep_ratio= False)
        box = BoxLayout(orientation='vertical')
        menu_items = []
        for i in range(0, 4):
            button = Button(text='Menu item no:'+str(i))
            button.bind(state=self.checkMenuPress)
            menu_items.append(button)
        for button in menu_items:
            box.add_widget(button)
        self.floater = FloatLayout(size=bg.size)
        self.floater.add_widget(bg)
        self.floater.add_widget(box)
        self.floater.size_hint = 1, 1
        return self.floater

    def checkMenuPress(self, button,*args):
        if button.state == 'normal':
            self.floater.clear_widgets()
            self.floater.add_widget(SecondScreen())


class SecondScreen(FloatLayout):
    def __init__(self, **kwargs):
        super(SecondScreen, self).__init__(**kwargs)
        self.add_widget(Image(source='Images/bg/bg.jpg',
                              allow_stretch=True,
                              keep_ratio=False))

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

【讨论】:

  • 我已经相应地更新了我的代码,但徒劳无功。我的代码肯定变得更清晰了,但仍然没有解决问题。最后一个窗口仍然没有更新。是否有更新小部件或应用程序的 kivy 功能​​?在这样的结构中,stopTouchApp() 的等价物是什么?
  • 当你说最后一个窗口没有更新时,我不确定你的意思。单击按钮切换到显示图片的第二个屏幕?但我不确定你想做什么。
  • 抱歉,过早的帖子...;-) 不确定您要做什么,但这是类似的吗?只需将一些图像放入“图像”子文件夹中即可....gist.github.com/Zen-CODE/9115401
  • 这只是一个示例代码。我刚刚在第二个屏幕中显示了背景图像我有一个复杂的网格布局屏幕,每个位置都有一个带有 -ve 间距的框布局,并且框布局中的每个小部件都是一个自定义按钮小部件,每个按钮上都有一个图像或简单的图像。当我将我的实际屏幕作为单独的应用程序运行时,它会完美加载,但是当以上述方式将同一屏幕作为子小部件加载时,背景图像、标签和按钮会在没有任何其他图像的情况下加载(包括在按钮)。
  • 您是否尝试过使用屏幕管理器在屏幕之间切换,而不是清除小部件? kivy.org/docs/api-kivy.uix.screenmanager.html 这可能是比清除小部件并每次都添加它们更清洁的方法?毕竟,不同屏幕之间的转换是 ScreenManager 的目的......
【解决方案2】:

好的,下面是使用 Screens 对示例的快速修改。不知道自己要做什么是很困难的,所以如果这没有帮助,试着写下你正在寻找的行为的摘要。

from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen


class MenuScreen(Screen):
    """
    The Screen containing the menu
    """
    def __init__(self, sm, **kwargs):
        super(MenuScreen, self).__init__(**kwargs)
        self.sm = sm  # Store a reference to the screen manager

        bg = Image(source='Images/bg/bg.jpg',
                   allow_stretch= True,
                   keep_ratio= False)
        box = BoxLayout(orientation='vertical')
        menu_items = []
        for i in range(0, 4):
            button = Button(text='Menu item no:'+str(i))
            button.bind(state=self.check_menu_press)
            menu_items.append(button)
        for button in menu_items:
            box.add_widget(button)
        floater = FloatLayout(size=bg.size)
        floater.add_widget(bg)
        floater.add_widget(box)
        floater.size_hint = 1, 1
        self.add_widget(floater)

    def check_menu_press(self, button, *args):
        if button.state == 'normal':
            self.sm.current = "second"


class SecondScreen(Screen):
    def __init__(self, sm, **kwargs):
        super(SecondScreen, self).__init__(**kwargs)
        self.add_widget(Image(source='Images/bg/bg.jpg',
                              allow_stretch=True,
                              keep_ratio=False))
        self.sm = sm  # Store a reference to the screen manager

    def on_touch_down(self, touch):
        self.sm.current = "menu"


class MainApp(App):
    def build(self):
        sm = ScreenManager()
        sm.add_widget(MenuScreen(sm, name="menu"))
        sm.add_widget(SecondScreen(sm, name="second"))
        return sm

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

【讨论】:

  • 抱歉,我没有看到任何模块?如果您可以发布可运行的代码,我可以尝试让它工作....
【解决方案3】:

看起来我找到了崩溃问题的根源。我曾将多线程用于服务器客户端交互。我一直在使用两个额外的线程,一个用于服务器,另一个用于客户端。如果我尝试将客户端线程与 GUI 集成,则会引发另一个问题。即使 socket.recv() 在 ScreenManager.current = "newscreen" 行之后,应用程序的屏幕也不会改变。它以我离开它的方式冻结。它只有在收到来自服务器的消息后才会恢复。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-10
    • 1970-01-01
    • 2021-05-21
    • 2011-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多