如何在kivy中使用Scatter组件精确拖动图片

2 投票
2 回答
3424 浏览
提问于 2025-05-01 08:39

我刚接触kivy,想把一组小图片放在一个叫做Scatter的控件里,这些图片的实际大小是160*200像素。 我在FloatLayout上显示这些图片时位置是对的,但当我尝试移动其中一张图片时,Scatter的边框框比图片大得多,导致我无法通过点击每张图片来选择它们。 我使用的基本kv代码如下:

<TTTGame>:      
FloatLayout:
    Scatter:
        pos: 200, 800
        size: 70,100
        do_rotation: False
        do_scale: False
        do_translation: True
        auto_bring_to_front: True

        Image:
            source: 'data/h2red.jpeg'
            size_hint: 1, 1
            allow_strech: True
            keep_ratio: False
            size: 70, 100

    Scatter:
        pos: 200+(300*1), 800
        size: 70,100
        do_rotation: False
        do_scale: False
        do_translation: True
        auto_bring_to_front: True

        Image:
            source: 'data/h3red.jpeg'
            size_hint: None,None
            size: 70, 100

    Scatter:
        pos: 200+(300*2), 800
        size: 70,100
        do_rotation: False
        do_scale: False
        do_translation: True
        auto_bring_to_front: True

        Image:
            source: 'data/h4red.jpeg'
            size_hint: None,None
            size: 70, 100

    Scatter:
        pos: 200, 400
        size: 70,100
        do_rotation: False
        do_scale: False
        do_translation: True
        auto_bring_to_front: True

        Image:
            source: 'data/c2black.jpeg'
            size_hint: None,None
            size: 70, 100

    Scatter:
        pos: 200+(300*1), 400
        size: 70,100
        do_rotation: False
        do_scale: False
        do_translation: True
        auto_bring_to_front: True

        Image:
            source: 'data/c3black.jpeg'
            size_hint: None,None
            size: 70, 100

    Scatter:
        pos: 200+(300*2), 400
        size: 70,100
        do_rotation: False
        do_scale: False
        do_translation: True
        auto_bring_to_front: True

        Image:
            source: 'data/c4black.jpeg'
            size_hint: None,None
            size: 70, 100

Splitter:
    sizable_from: 'left'
    size_hint: 0.3, 1

    BoxLayout:
        orientation: 'vertical'
        size_hint: 1, 1
        spacing: 10
        padding: 20

        BoxLayout:
            orientation: 'vertical'
            size_hint: 0.7, 0.7

            Label:
                text: 'Game card'
                size_hint: 1, 0.1
                font_size: 20

            Image:
                source: 'data/h2red.jpeg'
                size_hint: 0.9, 0.9

        Button:
            text: 'PASS'
            size_hint: 1, .2
            font_size: 18
            on_press: root.pass_on_press_callback()

        Button:
            text: 'Help'
            size_hint: 1, .2
            font_size: 18
            on_press: root.help_on_press_callback()

总的来说,我希望Scatter的大小和图片一样。 有没有专家能帮帮我呢?

暂无标签

2 个回答

1

这是一个简化的例子。

from kivy.app import App
from kivy.properties import StringProperty
from kivy.lang import Builder

KV = """

#:import win kivy.core.window

<Picture@Scatter>:
   source: None
   on_size: self.center = win.Window.center
   size: image.size
   size_hint: None, None

   Image:
       id: image
       source: root.source

FloatLayout:
   Picture:
       source: "test.jpg"
   Picture:
       source: "test.jpg"

"""

class MyApp(App):

    def build(self):
        return Builder.load_string(KV)

MyApp().run()
1

我觉得你需要的所有东西都在这里。这是一个很好的示例,说明了如何在Scatter中使用图片,并且文档写得很清楚。

主程序文件是 main.py:

import kivy
kivy.require('1.0.6')

from glob import glob
from random import randint
from os.path import join, dirname
from kivy.app import App
from kivy.logger import Logger
from kivy.uix.scatter import Scatter
from kivy.properties import StringProperty
# FIXME this shouldn't be necessary
from kivy.core.window import Window


class Picture(Scatter):
    '''Picture is the class that will show the image with a white border and a
    shadow. They are nothing here because almost everything is inside the
    picture.kv. Check the rule named <Picture> inside the file, and you'll see
    how the Picture() is really constructed and used.
    The source property will be the filename to show.
    '''

    source = StringProperty(None)


class PicturesApp(App):

    def build(self):

        # the root is created in pictures.kv
        root = self.root

        # get any files into images directory
        curdir = dirname(__file__)
        for filename in glob(join(curdir, 'images', '*')):
            try:
                # load the image
                picture = Picture(source=filename, rotation=randint(-30,30))
                # add to the main field
                root.add_widget(picture)
            except Exception as e:
                Logger.exception('Pictures: Unable to load <%s>' % filename)

    def on_pause(self):
        return True


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

布局文件是 pictures.kv:

#:kivy 1.0
#:import kivy kivy
#:import win kivy.core.window

FloatLayout:
    canvas:
        Color:
            rgb: 1, 1, 1
        Rectangle:
            source: 'data/images/background.jpg'
            size: self.size

    BoxLayout:
        padding: 10
        spacing: 10
        size_hint: 1, None
        pos_hint: {'top': 1}
        height: 44
        Image:
            size_hint: None, None
            size: 24, 24
            source: 'data/logo/kivy-icon-24.png'
        Label:
            height: 24
            text_size: self.width, None
            color: (1, 1, 1, .8)
            text: 'Kivy %s - Pictures' % kivy.__version__



<Picture>:
    # each time a picture is created, the image can delay the loading
    # as soon as the image is loaded, ensure that the center is changed
    # to the center of the screen.
    on_size: self.center = win.Window.center
    size: image.size
    size_hint: None, None

    Image:
        id: image
        source: root.source

        # create initial image to be 400 pixels width
        size: 400, 400 / self.image_ratio

        # add shadow background
        canvas.before:
            Color:
                rgba: 1,1,1,1
            BorderImage:
                source: 'shadow32.png'
                border: (36,36,36,36)
                size:(self.width+72, self.height+72)
                pos: (-36,-36)

撰写回答