python-3.x 我的ScrollView在Android上无法正常工作,当我松开手指时,它会滚动回顶部

wgeznvg7  于 2023-03-04  发布在  Python
关注(0)|答案(1)|浏览(86)

我需要我的应用程序的主屏幕是一个可滚动的屏幕,这样我就可以查看所有的卡添加,但目前我的屏幕工作像一个Spring。我张贴的代码卡,屏幕和滚动视图,我希望它有助于理解我错了。
下面是我的.py:

# app screens
class JanelaGerenciadora(ScreenManager):
    pass

class CustomScrollView(ScrollView):
    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):
            return super().on_touch_down(touch)
    def on_touch_up(self, touch):
        if self.collide_point(*touch.pos):
            return super().on_touch_up(touch)
        return False

    
class NovelCard(MDCard):
    def __init__(self, title, url, image_data, **kwargs):
        super().__init__(**kwargs)
        self.title = title
        self.size_hint = (None, None)
        self.size = ("160dp", "280dp")
        self.radius = ["15dp", "15dp", "15dp", "15dp"]
        self.padding = ["10dp", "10dp", "10dp", "10dp"]
        self.spacing = "10dp"

        self.orientation = "vertical"

        # create a temporary file to save the image data
        with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
            tmp_file.write(image_data)
            tmp_filename = tmp_file.name

        # create the AsyncImage widget
        image_ratio = 1  # adjust this value to fit your images
        image_widget = AsyncImage(source=tmp_filename,
                                size_hint=(None, None),
                                size=("140dp", "210dp"),
                                allow_stretch=True,
                                keep_ratio=False)

        # create the Label widget
        title_widget = MDLabel(text=title, halign="center", font_size="10sp", size_hint_y=None, height="40dp")

        # add the widgets to the card
        self.add_widget(image_widget)
        self.add_widget(title_widget)

        # bind the on_release event to open the URL in a browser
        def open_url(*args):
            webbrowser.open(url)

        self.canvas.before.clear()
        with self.canvas.before:
            Color(0, 0, 0, 0)  # make the rectangle transparent
            self.rect = Rectangle(pos=self.pos, size=self.size)
        self.bind(pos=self.update_rect, size=self.update_rect)
        self.bind(on_release=open_url)

    def update_rect(self, *args):
        self.rect.pos = self.pos
        self.rect.size = self.size

class JanelaPrincipal(Screen):
    grid_layout_width = NumericProperty(0)
    grid_layout_height = NumericProperty(0)
    cols = NumericProperty(0)
    
    def __init__(self, **kwargs):
        super(JanelaPrincipal, self).__init__(**kwargs)

        # connect to the database and retrieve the data (working fine)
        conn = mysql.connector.connect(
                user='removedforsafety',
                password='removedforsafety',
                host='removedforsafety',
                database='removedforsafety'
            )
        cursor = conn.cursor()

        # execute an SQL query to retrieve data
        query = "SELECT title, url, image FROM novels"
        cursor.execute(query)

        # fetch all the rows of data
        rows = cursor.fetchall()

        # close the cursor and connection
        cursor.close()
        conn.close()

        # create a card for each row of data
        self.grid_layout = GridLayout(cols=2, spacing="10dp", padding=(10, 56, 10, 50))
        self.update_cols(self.grid_layout.width)
        for title, url, image in rows:
            # create a NovelCard for the data
            image_bytes = io.BytesIO(image)
            pil_image = Image.open(image_bytes)
            pil_image = pil_image.transpose(Image.FLIP_TOP_BOTTOM) #needed because my image was showing upside down for some reason
            buffer = io.BytesIO()
            pil_image.save(buffer, format='PNG')
            image_data = buffer.getvalue()
            card = NovelCard(title=title, url=url, image_data=image_data)
            self.grid_layout.add_widget(card)

        # wrap the GridLayout in a FloatLayout and center it
        float_layout = FloatLayout(size_hint_y=None)
        float_layout.add_widget(self.grid_layout)
        self.grid_layout.bind(minimum_width=self.update_grid_layout_width,
                              minimum_height=self.update_grid_layout_height)
        self.bind(size=self.update_grid_layout_pos_hint)
        float_layout.bind(size=self.update_cols)

        # set the FloatLayout height to the total height of its contents
        num_rows = len(self.grid_layout.children) // self.grid_layout.cols + 1
        card_height = 280  # the height of a card
        spacing = 30  # the spacing between cards
        top_padding = 75
        bottom_padding = 20
        float_layout.height = num_rows * (card_height + spacing) + top_padding + bottom_padding
        float_layout.size_hint_y = None

        # wrap the FloatLayout in a ScrollView
        scroll_view = CustomScrollView()
        scroll_view.add_widget(float_layout)

        # add the ScrollView to the screen
        self.add_widget(scroll_view)

    def update_grid_layout_pos_hint(self, instance, value):
        screen_width, screen_height = value
        self.grid_layout_pos_hint = {'center_x': 0.5, 'center_y': 0.5}
        self.grid_layout_pos_hint['center_x'] = (screen_width - self.grid_layout_width) / (2 * screen_width)
        self.grid_layout_pos_hint['center_y'] = (screen_height - self.grid_layout_height) / (2 * screen_height)

    def update_grid_layout_width(self, instance, value):
        self.grid_layout_width = value

    def update_grid_layout_height(self, instance, value):
        self.grid_layout_height = value

    def update_cols(self, *_):
        # calculate the maximum number of columns that can fit on the screen
        max_card_width = 170  # the maximum width of a card
        spacing = 20  # the spacing between cards
        total_width = self.grid_layout.width - self.grid_layout.spacing[0] * (self.grid_layout.cols - 1)
        card_width = (total_width - spacing) / 2

        if card_width > max_card_width:
            # set the number of columns to the maximum that can fit
            self.grid_layout.cols = 2
            self.grid_layout.spacing = [spacing, spacing]
            self.grid_layout.col_force_default = True
            self.grid_layout.col_default_width = card_width
        else:
            # set the number of columns to 1 and adjust the card size
            self.grid_layout.cols = 2
            self.grid_layout.spacing = [15, 15]
            self.grid_layout.col_force_default = False
            self.grid_layout.col_default_width = total_width

    
    def update_screen(self):
        # remove all existing NovelCard widgets
        self.grid_layout.clear_widgets()

        # connect to the database and retrieve the data
        conn = mysql.connector.connect(
                user='removedforsafety',
                password='removedforsafety',
                host='removedforsafety',
                database='removedforsafety'
            )
        cursor = conn.cursor()

        # execute an SQL query to retrieve data
        query = "SELECT title, url, image FROM novels"
        cursor.execute(query)

        # fetch all the rows of data
        rows = cursor.fetchall()

        # close the cursor and connection
        cursor.close()
        conn.close()

        # create a card for each row of data
        for title, url, image in rows:
            # create a NovelCard for the data
            image_bytes = io.BytesIO(image)
            pil_image = Image.open(image_bytes)
            pil_image = pil_image.transpose(Image.FLIP_TOP_BOTTOM)
            buffer = io.BytesIO()
            pil_image.save(buffer, format='PNG')
            image_data = buffer.getvalue()
            card = NovelCard(title=title, url=url, image_data=image_data)
            self.grid_layout.add_widget(card)

        # update the size of the grid layout
        self.update_grid_layout_pos_hint(self, self.size

这是我的.kv:

#:kivy 2.1.0
#:import Factory kivy.factory.Factory
#:import json json
#:import base64 base64
#:import GridLayout kivy.uix.gridlayout.GridLayout
#:import Window kivy.core.window.Window

JanelaGerenciadora:
    JanelaPrincipal:
    Janela1:
    JanelaDelete:

<JanelaPrincipal>
    name: "janelaprincipal"

    FloatLayout:

        ActionBar:
            pos_hint: {"top": 1}

            ActionView:
                use_separator: True
                ActionPrevious:
                    title: 'My Novel Bib'
                    with_previous: False
                    app_icon: 'iconlib.png' # Add this line
                ActionGroup:
                    text: 'Menu' 
                    mode: 'spinner'
                    ActionButton:
                        text: 'Adicionar'
                        on_release:
                            app.root.current = 'janela1'
                    ActionButton:
                        text: 'Remover'
                        on_release:
                            app.root.current = 'janeladelete'

目前,我在我的buildozer.spec上将我的KivyMD设置为1.0.2,因为1.1.1由于一些未知的原因无法与MDRaisedButton一起工作。
我的buildozer.spe文件:(删除了大部分的评论行,以便张贴更小,但我使用它与#)

[app]

# (str) Title of your application
title = My Novel bib

# (str) Package name
package.name = novelbib

# (str) Package domain (needed for android/ios packaging)
package.domain = org.test

# (str) Source code where the main.py live
source.dir = .

# (list) Source files to include (let empty to include all the files)
source.include_exts = py,png,jpg,kv,atlas

# (str) Application versioning (method 1)
version = 0.1

# (list) Application requirements
requirements = python3,kivy==2.1.0,kivymd==1.0.2,Pillow,mysql-connector-python,certifi,urllib3

# (list) Supported orientations
orientation = portrait

# change the major version of python used by the app
osx.python_version = 3

# Kivy version to use
osx.kivy_version = 2.1.0

#
# Android specific
#

# (bool) Indicate if the application should be fullscreen or not
fullscreen = 0

# (list) Permissions
android.permissions = INTERNET, WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE

# (list) The Android archs to build for, choices: armeabi-v7a, arm64-v8a, x86, x86_64
android.archs = arm64-v8a, armeabi-v7a

# (bool) enables Android auto backup feature (Android API >=23)
android.allow_backup = True

#
# iOS specific
#

# (str) Path to a custom kivy-ios folder
ios.kivy_ios_url = https://github.com/kivy/kivy-ios
ios.kivy_ios_branch = master

# Another platform dependency: ios-deploy
ios.ios_deploy_url = https://github.com/phonegap/ios-deploy
ios.ios_deploy_branch = 1.10.0

# (bool) Whether or not to sign the code
ios.codesign.allowed = false

[buildozer]

# (int) Log level (0 = error only, 1 = info, 2 = debug (with command output))
log_level = 2

# (int) Display warning if buildozer is run as root (0 = False, 1 = True)
warn_on_root = 1

我是kivy的新手,但在stackoverflow、youtube等网站上尝试了无数的解决方案。我想我错过了一些基本的东西,因为我缺乏知识,所以我决定问一问。
我只希望屏幕可以滚动,在我抬起手指的地方停止,就像大多数应用程序一样。

b1payxdu

b1payxdu1#

您的.kv文件中没有滚动视图。不要忘记添加它!

相关问题