TexText.make_number_changeable will not work properly
- Vorherrschende Sprache
- Python
- Sterne
- 93.8k
- Forks
- 7.7k
- PR-Merge-Kennzahlen
- PR-Kennzahlen ausstehend
Beschreibung
### Describe the bug
Today I try the UpdatersExample in example_scenes.py.
```python
class UpdatersExample(Scene):
def construct(self):
square = Square()
square.set_fill(BLUE_E, 1)
# On all frames, the constructor Brace(square, UP) will
# be called, and the mobject brace will set its data to match
# that of the newly constructed object
brace = always_redraw(Brace, square, UP)
label = TexText("Width = 0.00")
number = label.make_number_changeable("0.00", replace_all=True)
# This ensures that the method deicmal.next_to(square)
# is called on every frame
label.always.next_to(brace, UP)
# You could also write the following equivalent line
# label.add_updater(lambda m: m.next_to(brace, UP))
# If the argument itself might change, you can use f_always,
# for which the arguments following the initial Mobject method
# should be functions returning arguments to that method.
# The following line ensures thst decimal.set_value(square.get_y())
# is called every frame
number.f_always.set_value(square.get_width)
# You could also write the following equivalent line
# number.add_updater(lambda m: m.set_value(square.get_width()))
self.add(square, brace, label)
# Notice that the brace and label track with the square
self.play(
square.animate.scale(2),
rate_func=there_and_back,
run_time=2,
)
self.wait()
self.play(
square.animate.set_width(5, stretch=True),
run_time=3,
)
self.wait()
self.play(
square.animate.set_width(2),
run_time=3
)
self.wait()
# In general, you can alway call Mobject.add_updater, and pass in
# a function that you want to be called on every frame. The function
# should take in either one argument, the mobject, or two arguments,
# the mobject and the amount of time since the last frame.
now = self.time
w0 = square.get_width()
square.add_updater(
lambda m: m.set_width(w0 * math.sin(self.time - now) + w0)
)
self.wait(4 * PI)
```
and it raises IndexError: list index out of range
(I am not sure if others encounter it)

During 3 hours further exploring, I believe that it raises because the ` label = TexText("Width = 0.00")` has a `self.submobjects=[]`. So the next line `number = label.make_number_changeable("0.00", replace_all=True)` will raise Error here in last 2 lines.
```
def make_number_changeable(
self,
value: float | int | str,
index: int = 0,
replace_all: bool = False,
**config,
) -> VMobject:
substr = str(value)
parts = self.select_parts(substr)
if len(parts) == 0:
log.warning(f"{value} not found in Tex.make_number_changeable call")
return VMobject()
if index > len(parts) - 1:
log.warning(f"Requested {index}th occurance of {value}, but only {len(parts)} exist")
return VMobject()
if not replace_all:
parts = [parts[index]]
from manimlib.mobject.numbers import DecimalNumber
decimal_mobs = []
for part in parts:
if "." in substr:
num_decimal_places = len(substr.split(".")[1])
else:
num_decimal_places = 0
decimal_mob = DecimalNumber(
float(value),
num_decimal_places=num_decimal_places,
**config,
)
decimal_mob.replace(part)
decimal_mob.match_style(part)
if len(part) > 1:
self.remove(*part[1:])
+++++ self.replace_submobject(self.submobjects.index(part[0]), decimal_mob) <======== the part[0] will raise Error, because it has no submobjects!
decimal_mobs.append(decimal_mob)
```
So how did the empty part generate?we can see `parts = self.select_parts(substr)`
the select_parts will fall back into `select_unisolated_substring` in this case, finally produced by last 2 lines of it.
```python
def select_unisolated_substring(self, pattern: str | re.Pattern) -> VGroup:
if isinstance(pattern, str):
pattern = re.compile(re.escape(pattern))
result = []
for match in re.finditer(pattern, self.string):
index = match.start()
start = self.substr_to_path_count(self.string[:index])
substr = match.group()
end = start + self.substr_to_path_count(substr)
+++ result.append(self[start:end]) // <====== here, the self[start:end] has no elements(submobjects)!
return VGroup(*result)
```
because StringMObject's __get_item___ magic function will eventually fall back into MObject's __get_item__ magic function:
```python
def __getitem__(self, value: int | slice) -> Mobject:
if isinstance(value, slice):
GroupClass = self.get_group_class()
return GroupClass(*self.split().__getitem__(value))
return self.split().__getitem__(value)
def split(self) -> list[Self]:
return self.submobjects
```
and `self.submobjects` of ` label = TexText("Width = 0.00")` is `[]`. that's all.
there are 2 ways to solve problems. First, modify TexText's __init__ function to initialize its submobjects. Second, modify StringMObject's __getitem__ magic to return correct submobjects before it falls back into MObject's.
**Code**:
To reproduce the bug:
```powershell
git clone https://github.com/3b1b/manim.git
cd manim
pip install -e .
manimgl example_scenes.py UpdatersExample
```
**Wrong display or Error traceback**:

### Additional context
Beitragsleitfaden
Für dieses Repository ist kein Beitragsleitfaden indexiert
Bewertung
Dieses Issue wurde noch nicht bewertet.