PyGObject (GTK4) – Как мне настроить автоматическое обновление раскрывающихся списков при изменениях в списке элементов?Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 PyGObject (GTK4) – Как мне настроить автоматическое обновление раскрывающихся списков при изменениях в списке элементов?

Сообщение Anonymous »

Я пытаюсь создать раскрывающийся список в приложении GTK4, но у меня возникли проблемы с тем, как заставить раскрывающийся список работать.
Я нашел и использую это Пример раскрывающегося списка Python GTK4, и он изначально работает, но когда dict, используемый liststore, обновляется, раскрывающийся список не меняется.
Поскольку я не уверен, что правильно подойдя к решению проблемы, я собираюсь представить упрощенную версию реальной проблемы.
@dataclass
class Coffee:
"""
Represents a coffee entry in the db
"""
coffee_id:int
name:str
description:str
# date/time added (as unix time)
date_added:datetime

Окно моего приложения хранит «список кофе» с помощью self.coffees:list[Coffees] и отслеживает «активный в данный момент» кофе с помощью self.curr_coffee: Кофе. Список обновляется другими частями приложения.
Моя цель — Gtk.Dropdown, состоящий из названий кофе s в этом списке, и когда пользователь делает выбор, self.curr_coffee обновляется.
Я использую упрощенный пример раскрывающегося списка с небольшими изменениями.Затем я создаю dict, self.coffees_dict:dict для перехода в раскрывающийся список. Этот текст обновляется при каждом обновлении self.coffee. (да, я знаю, что это не очень хорошо; я просто хочу, чтобы это работало)
for c in self.coffees:
self.coffees_dict[c.coffee_id] = c.name

Затем создается раскрывающийся список с использованием примера класса:
self.coffee_setting_dropdown = DropDown(data=self.appstate.localDB.coffees_dict,
itemSelectNotifyMethod=self._on_coffee_changed_notify)
self.dropDownBox = self.coffee_setting_dropdown.getDropDownElementWithBoxAndLabel("Coffee:")

Однако, несмотря на обновление Coffee_dict, новые дополнения к БД не отражаются в раскрывающемся списке. Должен быть более простой способ сделать это — как мне создать раскрывающийся список GTK4 из названий кофе и обновлять его при добавлении новых?

Ниже приведен рабочий однофайловый пример базового случая, адаптированный из примера, приведенного выше.
import gi
from dataclasses import dataclass

gi.require_version("Adw", "1")
gi.require_version("Gtk", "4.0")

from gi.repository import Adw, Gio, GObject, Gtk

@dataclass
class Coffee:
"""
Represents a coffee entry in the db
"""
coffee_id: int
name: str
description: str

# used to generate example list[Coffee]
EXAMPLE_COFFEES_LIST = [
"Espresso",
"Americano",
"Latte",
"Cappuccino",
"Mocha",
"Macchiato",
"Flat White",
"Affogato",
"Cold Brew",
"Nitro Coffee",
"Turkish Coffee",
"Irish Coffee",
"Ristretto",
"Doppio",
"Café au Lait",
"Vienna Coffee",
"Café con Leche",
"Iced Coffee",
"Breve",
"Coffee Milk",
]

# DropDown classes are from
# https://github.com/ksaadDE/GTK4PythonEx ... plified.md
class DataDropDownChild(GObject.Object):
__gtype_name__ = "DataDropDownChild"

def __init__(self, key, value):
super().__init__()

self.k = key
self.v = value

@GObject.Property
def key(self):
return self.k

@GObject.Property
def value(self):
return self.v

def getKey(
self,
):
return self.k

def getValue(
self,
):
return self.v

class DropDown:
def __init__(
self,
data=[],
factoryBindSetupMethod=None,
factoryBindMethod=None,
itemSelectNotifyMethod=None,
):
self.box = None
self.data = data
self.model = Gio.ListStore(item_type=DataDropDownChild)
for k in data.keys():
self.model.append(DataDropDownChild(key=k, value=data[k]))

# Set up the factory
self.factory = Gtk.SignalListItemFactory()
if factoryBindSetupMethod is None:
self.factory.connect("setup", self._on_factory_setup)
else:
self.factory.connect("setup", factoryBindSetupMethod)

if factoryBindMethod is None:
self.factory.connect("bind", self._on_factory_bind)
else:
self.factory.connect("bind", factoryBindMethod)

self.dd = Gtk.DropDown(model=self.model, factory=self.factory, hexpand=True)

if itemSelectNotifyMethod is None:
self.dd.connect("notify::selected-item", self._on_selected_item_notify)
else:
self.dd.connect("notify::selected-item", itemSelectNotifyMethod)

def getDropDownElement(
self,
):
return self.dd

def getDropDownElementWithBox(self, labelText="Select Object:"):
self.box = Gtk.Box(spacing=12, hexpand=True, vexpand=True)
self.box.props.margin_start = 12
self.box.props.margin_end = 12
# self.box.props.margin_top = 6
# self.box.props.margin_bottom = 6
# self.box.append(Gtk.Label(label=labelText))
self.box.append(self.getDropDownElement())
self.box.set_vexpand(False)
return self.box

# Set up the child of the list item; this can be an arbitrarily
# complex widget but we use a simple label now
def _on_factory_setup(self, factory, list_item):
label = Gtk.Label()
list_item.set_child(label)

# Bind the item in the model to the row widget; again, since
# the object in the model can contain multiple properties, and
# the list item can contain any arbitrarily complex widget, we
# can have very complex rows instead of the simple cell renderer
# layouts in GtkComboBox
def _on_factory_bind(self, factory, list_item):
label = list_item.get_child()
item = list_item.get_item()
label.set_text(str(item.v))

# The notify signal is fired when the selection changes
def _on_selected_item_notify(self, dropdown, _):
item = dropdown.get_selected_item()
print(item.getKey(), item.getValue())

def update_liststore(self, data):
# naive (and rather stupid) way of updating items in dropdown. will not scale
self.data = data
self.model = Gio.ListStore(item_type=DataDropDownChild)
for k in data.keys():
self.model.append(DataDropDownChild(key=k, value=data[k]))

class ExampleWindow(Gtk.ApplicationWindow):
def __init__(self, app):
super().__init__(application=app, title="DropDown")

# generate example data
self.coffees: list[Coffee] = []
for idx, item in enumerate(EXAMPLE_COFFEES_LIST):
self.coffees.append(Coffee(idx, item, ""))

self.coffees_dict: dict = {}
for c in self.coffees:
self.coffees_dict[c.coffee_id] = c.name

# not used in this example, here for reference
self.curr_coffee:Coffee = None

self.dd = DropDown(
data=self.coffees_dict, itemSelectNotifyMethod=self.onItemChangeNotify
)
self.dropDownBox = self.dd.getDropDownElementWithBox(labelText="Coffees:")

self.set_child(self.dropDownBox)

def onItemChangeNotify(self, dropdown, _):
item = dropdown.get_selected_item()
print("22:", item.getKey(), item.getValue())

class ExampleApp(Adw.Application):
def __init__(self):
super().__init__()
self.window = None

def do_activate(self):
if self.window is None:
self.window = ExampleWindow(self)
self.window.present()
app = ExampleApp()
app.run([])



Подробнее здесь: https://stackoverflow.com/questions/791 ... -list-of-i
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»