Search code examples
pythonpyglet

How do I make text in Pyglet's ScrollableTextLayout scroll upwards, rather than down? .view_y doesn't seem to have the effect listed in the docs


I'm trying to figure out how to make text scroll upwards in Pyglet's ScrollableTextLayout, rather than down. For sake of clarity, here's a quick snapshot to show what I mean by "up." (Just in case)

How it currently behaves

How I would like it to behave:

enter image description here

According to the docs, this behavior can be achieved via the view_y property, but I've tried all kinds of different values, but all with no noticeable change.

The code:

import pyglet

class LoadDialog(pyglet.sprite.Sprite):
    def __init__(self):
        self.lbatch = pyglet.graphics.Batch()

        self.loading_window = pyglet.image.load('..\\resources\\loading_base.png')
        super(LoadDialog, self).__init__(self.loading_window, batch=self.lbatch)


        self.doc = pyglet.text.decode_text('Hello world!'.ljust(40))
        self.doc.set_style(0,12, dict(font_name='Arial', font_size=12,
                                    color=(0,0,0,255)))

        self.layout = pyglet.text.layout.ScrollableTextLayout(self.doc, 
                                            width=self.load_animation.width, 
                                            height=100, multiline=True, batch=self.lbatch)
        self.layout.x = 220
        self.layout.y = 160
        self.layout.view_y = -80

    def update(self, dx):
        self.doc.insert_text(0, "New line".ljust(40))






sprite = LoadDialog()
window = pyglet.window.Window(width=640, height=480)

pyglet.gl.glClearColor(1, 1, 1, 1)

@window.event
def on_draw():
    window.clear()
    sprite.lbatch.draw()
    sprite.layout.draw()

@window.event
def update(dx):
    sprite.update(dx)

pyglet.clock.schedule_interval(update, 1.0)
pyglet.app.run()

I've tried tons of values for layout.view_y, from -1 to absurd values like -3000, or 500 just to see if something changes. But it always gives the exact behavior as shown in the first image.

What am I doing wrong?


Solution

  • First, your example depends on an image file and its width (not provided), which complicated testing slightly.

    Second, you are creating an UnformattedDocument by calling pyglet.text.decode_text, and then you repeatedly insert text into the UnformattedDocument explicitly at position 0 (the start) on this line:

    def update(self, dx):
        self.doc.insert_text(0, "New line".ljust(40))
    

    If you want the text to appear at the end, as you imply in your graphics, insert it at the end!

    def update(self, dx):
        # Fix the implied bug
        self.doc.insert_text(-1, "New line".ljust(40))
    

    Third, lets answer your actual stated question. If you read the API documentation for the property ScrollableTextLayout.view_y you will find that...

    Values outside of the range [height - content_height, 0] are automatically clipped in range.

    ...so setting view_y to -80 when content_height is 0, results in view_y getting clipped to 0 and then you never try setting view_y again. The solution to your scrolling problem is to set view_y each time that your content height changes. For a simple fix, you could simply set view_y such that the bottom of your content will always be scrolled up to the bottom of your frame:

    def update(self, dx):
        # Fix the implied bug
        self.doc.insert_text(-1, "New line".ljust(40))
        # The answer to the stated question
        self.layout.view_y = -self.layout.content_height