-
Hi! So i have a little project that is trying to implement simple data saving / tracking.
On the input screen I have 3 widgets (Header, InputContent, Footer). The user can add numbers and with pressing enter the program will save the fresh input into a json file. def is_positive(value: str) -> bool:
try:
res = int(value) > 0
except:
return False
return res
class InputContent(Widget):
def compose(self) -> ComposeResult:
with Center():
yield Container(
Horizontal(Label("ADD YOUR SPENDINGS", id="spendings-title"), id="center-title"),
Input(
placeholder="12345",
id="spendings-input",
validators=[
Function(is_positive, "Value is not positive or a number.")
],
),
Pretty([]),
classes="top-align",
id="top-container"
)
yield Container(
Label("New spendings:"),
ListView(),
classes="top-align",
id="bottom-container"
)
self.disable_messages(InputContent.Update)
@on(Input.Changed)
def show_invalid_reasons(self, event: Input.Changed) -> None:
# Updating the UI to show the reasons why validation failed
if not event.validation_result.is_valid:
self.query_one(Pretty).update(event.validation_result.failure_descriptions)
else:
self.query_one(Pretty).update([])
@on(Input.Submitted)
def on_input_submitted(self, event: Input.Submitted) -> None:
if event.validation_result.is_valid:
self.query_one("ListView").append(ListItem(Label(f"{int(event.value):,} Ft")))
self.query_one("Input").value = ""
self.save_spending(int(event.value))
class Update(Message):
def __init__(self) -> None:
super().__init__()
def save_spending(self, value: int):
current_data = None
with open("spendings.data", "r", encoding="utf-8") as f:
current_data = f.readline()
with open("spendings.data", "w+") as f:
if len(current_data) == 0:
data = json.loads("{\"data\": []}")
else:
data = json.loads(current_data)
print(data["data"].append(value))
f.write(json.dumps(data))
self.post_message(InputContent.Update())
class InputScreen(Screen):
def compose(self) -> ComposeResult:
yield Header()
yield InputContent()
yield Footer() On the ListingScreen there are also 3 widgets (Header, ListingContent, Footer). Here the user can see what effectivly is in the json file that the InputScreen writes. def get_data():
data = None
with open("spendings.data", "r", encoding="utf-8") as f:
data = json.loads(f.readline())
return [ListItem(Label(f"{int(x):,} Ft")) for x in data["data"]]
class ListContent(Widget):
def compose(self) -> ComposeResult:
yield Container(
ListView(
*get_data(),
id="listed-items"
),
classes="top-align"
)
@on(InputContent.Update)
def update(self):
self.query_one("#listed-items").clear()
self.query_one("#listed-items").extend(get_data())
class ListScreen(Screen):
def compose(self) -> ComposeResult:
yield Header()
yield ListContent()
yield Footer() Here is the problem:when the ListingScreen is pushed to the app on the first run it will read the content of the json file. I would like to make it so that whenever the user added a new value to the json (pressed enter and the save_spending function is called) the ListContent would read out the content of the json file again. I'm trying to achive this with messageing between the widgets, but the handeler never gets called. (I know there are better wways to solve this problem, but at this point I'm emotionally invested in solving it with messages.) Any clue on why the haneler would not be called at all? Here's my app if it helps: class SpendWisely(App[None]):
CSS_PATH = "main.css"
SCREENS = {
"input": InputScreen,
"list": ListScreen
}
BINDINGS = [
Binding("ctrl+q", "quit", "Quit", True),
Binding("ctrl+y", "switch_screen('input')", "Add", True),
Binding("ctrl+x", "switch_screen('list')", "Show", True)
]
TITLE = "Spend Wisely"
def on_mount(self) -> None:
self.push_screen(InputScreen())
self.push_screen(ListScreen())
self.push_screen(MainScreen()) |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
This is just a quick visit to my keyboard, and I'll admit I'm struggling to follow the code a little bit (when asking questions it's best to try and distil a problem down to a small stand-alone example, that others can run and test and play with, if possible), but as I glance at the code the reason would seem to be that you're posting the message inside The message is going to bubble |
Beta Was this translation helpful? Give feedback.
This is just a quick visit to my keyboard, and I'll admit I'm struggling to follow the code a little bit (when asking questions it's best to try and distil a problem down to a small stand-alone example, that others can run and test and play with, if possible), but as I glance at the code the reason would seem to be that you're posting the message inside
InputContent
, an instance of which is composed intoInputScreen
. On the other hand you appear to have the message handler on an instance of an unrelated widget (ListContent
) on an unrelated screenListScreen
.The message is going to bubble
InputContent
->InputScreen
->SpendWisely
;…