kxgames / glooey

An object-oriented GUI library for pyglet.
MIT License
91 stars 6 forks source link

Error while running the code from text input tutorial #55

Open cklkevin127 opened 2 years ago

cklkevin127 commented 2 years ago

I've got an error while trying to run the code from the tutorial:

#!/usr/bin/env python3

import glooey
import pyglet

pyglet.font.add_file('form/Lato-Regular.ttf')
pyglet.font.load('Lato Regular')

class WesnothForm(glooey.Form):
    custom_alignment = 'center'

    class Label(glooey.EditableLabel):
        custom_font_name = 'Lato Regular'
        custom_font_size = 10
        custom_color = '#b9ad86'
        custom_alignment = 'top left'
        custom_horz_padding = 5
        custom_top_padding = 5
        custom_width_hint = 200

    class Base(glooey.Background):
        custom_center = pyglet.resource.texture('form_center.png')
        custom_left = pyglet.resource.image('form_left.png')
        custom_right = pyglet.resource.image('form_right.png')

window = pyglet.window.Window()
gui = glooey.Gui(window)

form = WesnothForm()
form.push_handlers(on_unfocus=lambda w: print(f"Form input: '{w.text}'"))
gui.add(form)

pyglet.app.run()
Traceback (most recent call last):
  File "c:\Users\cklke\Desktop\test_pyglet\form\form_test.py", line 33, in <module>
    pyglet.app.run()
  File "C:\Users\cklke\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pyglet\app\__init__.py", line 107, in run
    event_loop.run()
  File "C:\Users\cklke\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pyglet\app\base.py", line 169, in run
    timeout = self.idle()
  File "C:\Users\cklke\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pyglet\app\base.py", line 245, in idle
    window.dispatch_event('on_draw')
  File "C:\Users\cklke\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pyglet\window\__init__.py", line 1352, in dispatch_event
    if EventDispatcher.dispatch_event(self, *args) != False:
  File "C:\Users\cklke\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pyglet\event.py", line 408, in dispatch_event     
    if handler(*args):
  File "C:\Users\cklke\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\glooey\root.py", line 120, in on_draw
    self.batch.draw()
  File "C:\Users\cklke\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pyglet\graphics\__init__.py", line 564, in draw   
    func()
  File "C:\Users\cklke\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pyglet\text\layout.py", line 603, in set_state    
    glScissor(self._clip_x, self._clip_y - self._clip_height, self._clip_width, self._clip_height)
ctypes.ArgumentError: argument 1: <class 'TypeError'>: wrong type

How to fix this error? I'm using Python 3.9.7, pyglet 1.5.21 and glooey 0.3.6.

Rahuum commented 2 years ago

I get the same error. Commenting out the custom_alignment = 'center' in the WesnothForm class removes the error, but also removes the center alignment, as you can imagine.

kalekundert commented 2 years ago

Sorry, this dropped off my radar. I'll try to look into in this weekend.

Rahuum commented 2 years ago

Specifically, I've narrowed it down to EditableLabel as what's causing the issue. Even trying to use it on its own causes the ArgumentError. Replacing the EditableLabel in Form with Label also causes Form to stop breaking (though it does cause Form not to work in the expected manner).

Rahuum commented 2 years ago

OK, so the specific issue here is that in pyglet's text/layout.py, a glScissor is called with (float, float, int, int), instead of (int, int, int, int). That is because the _clip_x and _clip_y, which is set from the rect, is float values. They're float values because in widget.py, line 1447, you do aligned_rect.round(), saying it rounds the rectable to the nearest integer pixel.

That's incorrect- if you look at vecrec/shapes.py line 709, which is Rect's round() function, it's this:

    def round(self, digits=0):
        """ Round the dimensions of the given rectangle to the given number of digits. """
        self._left = round(self._left, digits)
        self._bottom = round(self._bottom, digits)
        self._width = round(self._width, digits)
        self._height = round(self._height, digits)

round(<float>, 0) will give you a float.

>>> round(5.3, 0)
5.0

What we actually need is for line 1447 to be replaced with

aligned_rect._bottom = int(aligned_rect._bottom)
aligned_rect._height = int(aligned_rect._height)
aligned_rect._left = int(aligned_rect._left)
aligned_rect._width = int(aligned_rect._width)