Макет изображений Kivy Bing

Я пытаюсь сделать что-то вроде макета «Bing images».

Это:

  • Изображения разделены на несколько столбцов одинаковой ширины.
  • Все изображения одинаковой ширины.
  • Изображения добавляются таким образом, что изображения, добавленные первыми, вверху макета.
  • Макет можно добавить в ScrollView для прокрутки колесом мыши

Я не нашел способа сделать это с помощью Stack Layout, поэтому решил создать свой собственный макет.

Я остановился здесь:

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
from kivy.properties import NumericProperty
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.scrollview import ScrollView

KV = '''
#:import Window kivy.core.window.Window

ScrollView

    size_hint: (1, None)
    size: Window.size

    MyLayout
        id:my_l
        Button
            text:'1'
        Button
            size_hint_y: None
            height: 900
            text:'2'
        Button
            text:'3'
        Button
            text:'4'
        Button
            text:'5'
            size_hint_y: None
            height: 900

<MyLayout>:
    #height: self.minimum_height

    cols: 3
    spacing: 10
    size_hint_y:None
    row_width: 300
'''

class MyLayout(FloatLayout):
    def __init__(self, **kwargs):

        super(MyLayout, self).__init__(**kwargs)

    cols = NumericProperty(3)
    row_width = NumericProperty(300)
    spacing = NumericProperty(0)

    def do_layout(self, *args):

        self.i = 0
        self.last_x = [self.height]*self.cols
        for child in self.children[::-1]:

            child.width = self.row_width

            if isinstance(child, Image):
                child.height = child.width / child.image_ratio

            child.size_hint_y= None
            child.size_hint_x= None

            self.i+=1
            if self.i == self.cols+1: self.i = 1


            child.x = self.x+(self.i-1)*(self.row_width+self.spacing)

            child.y = self.last_x[self.i-1]-child.height
            self.last_x[self.i-1]-=child.height+self.spacing



        def on_pos(self, *args):
            self.do_layout()

        def on_size(self, *args):
            self.do_layout()

        def add_widget(self, widget):
            super(SuperGrid, self).add_widget(widget)
            self.do_layout()

        def remove_widget(self, widget):
            super(SuperGrid, self).remove_widget(widget)
            self.do_layout()



class MyApp(App):
    def build(self):
        self.root = Builder.load_string(KV)
        Window.bind(on_dropfile=self.add)

    def add(self, *args):

        name= list(args)[1]
        self.root.ids.my_l.add_widget(Image(source=name))

MyApp().run()

Он уже частично работает (вы можете запустить его и перетащить некоторые изображения из своих папок, чтобы увидеть, о чем я), но проблема в том, что я не понимаю, как подключить к нему ScrollView.

Похоже, мне нужно добавить строку с чем-то вроде height: self.minimum_height в строку KV. но непонятно, где в классе макета мне нужно рассчитывать minimum_height.

Как заставить код работать со ScrollView?

Для чего нужны все эти кнопки? Следует ли расположить изображения вокруг этих кнопок? Похоже на чехол для GridLayout.

John Anderson 28.11.2018 18:30

Кнопки только для примера. Не могли бы вы попробовать перетащить несколько изображений в приложение (и, возможно, удалить эти кнопки из строки KV), и станет ясно, как должен работать макет. Основная проблема в моем коде заключается в том, что я не знаю, как подключить этот макет к макету просмотра прокрутки, чтобы я мог прокручивать изображения.

me2 beats 28.11.2018 18:46
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
2
48
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам просто нужно рассчитать height вашего экземпляра MyLayout. В вашем файле kv добавьте:

size_hint: (1, None)

в вашем разделе MyLayout

Затем с помощью метода do_layout вычислите height вашего MyLayout. Сделайте self.height = только один раз в конце do_layout (чтобы избежать бесконечного цикла из-за метода on_size). Например, вот модифицированная версия вашего do_layout:

def do_layout(self, *args):

    self.i = 0
    col_heights = [0] * self.cols    # keeps track of the height of each column
    self.last_x = [self.height]*self.cols
    for child in self.children[::-1]:

        child.width = self.row_width

        if isinstance(child, Image):
            child.height = child.width / child.image_ratio

        child.size_hint_y= None
        child.size_hint_x= None

        self.i+=1
        if self.i == self.cols+1:
            self.i = 1

        col_heights[self.i-1] += child.height + self.spacing
        child.x = self.x+(self.i-1)*(self.row_width+self.spacing)

        child.y = self.last_x[self.i-1]-child.height
        self.last_x[self.i-1]-=child.height+self.spacing

    if len(self.children) > 0:
        self.height = max(col_heights)

Я пробовал self.height = self.last_x [self.i-1] в конце метода do_layout, это вызывает критическое значение: слишком много итераций. Не могли бы вы проверить это в своей системе? Что случилось? size_hint: (1, None) уже используется, потому что у меня size_hint_y: None.

me2 beats 29.11.2018 03:45

Я не понимаю, что такое ваш массив self.last_x, но оператор self.height = self.last_x[self.i-1] устанавливает высоту на отрицательное число. Установка self.height будет запускать метод on_size всякий раз, когда размер отличается от текущего размера. Ваш оператор запускает тот on_size, который вызывает do_layout, который вычисляет другой self.height, который запускает on_size ... до бесконечности. Я добавлю информацию к своему ответу выше.

John Anderson 29.11.2018 04:38

Кроме того, size_hint_y: None или size_hint: (1, None) должны находиться непосредственно под MyLayout, а не под Button.

John Anderson 29.11.2018 04:55

Другие вопросы по теме