IrvKalb / pygwidgets

A collection of user interface widgets in Python for use in programs using Pygame.
BSD 2-Clause "Simplified" License
11 stars 5 forks source link

Allow the instanciation of a TextButton without a loc defined #5

Closed monteiro-renato closed 1 year ago

monteiro-renato commented 1 year ago

I think it should be possible to initialize a button without passing the location at initialization. In my use case I need to know how wide the button will be before setting it's location.

Right now I have to do this:

self.btn = pygwidgets.TextButton(window=self.window, loc=(0, 0), ...)

and afterwards:

p1, p2 = <...> # do some calculations based on self.btn.rect
self.btn.setLoc((p1, p2))

I suppose this might be true for more components. Let me know your thoughts.

Thanks in advance.

IrvKalb commented 1 year ago

Thanks for your message. I had considered this type of a change for a number of widgets.

However, making a change like this for the loc argument also implies that I would also have to change the text argument to have a default value. I see in your file that you set the text argument to default to the empty string. While it might be OK for a single test button to have a default of an empty string (no text), that would not work well for the typical case of having multiple buttons in a typical user interface. And I could not change the order of the arguments now as this code is already in use by many programs.

Further, I want to be consistent for all the standard widgets. They all require a window and a loc value as the first two values for initialization.

As a suggestion, you could build your own subclass of TextButton. To do this, all you would need would be a new class that inherits from pygwidgets.TextButton. That way, you write just an init method with the arguments with the exact interface you want with a default for loc and text. The initialization would then just call the super class (pygwidgets.textButton), and pass in the values. It would look like this:

class RenatoTextButton(pygwidgets.TextButton): def init​​(window, loc(=0, 0), text='', <rest of args ...> super().init(window, loc, text, <rest of args ...>

(In the second line of code, it's really underscore underscore init underscore underscore) but my email program is interpreting it as italics.)

I believe that's all you need as all other methods would be inherited from pygwidgets.TextButton.

Irv


From: Renato Monteiro @.> Sent: Saturday, February 18, 2023 8:31 AM To: IrvKalb/pygwidgets @.> Cc: Subscribed @.***> Subject: [IrvKalb/pygwidgets] Allow the instanciation of a TextButton without a loc defined (PR #5)

I think it should be possible to initialize a button without passing the location at initialization. In my use case I need to know how wide the button will be before setting it's location.

Right now I have to do this:

self.btn = pygwidgets.TextButton(window=self.window, loc=(0, 0), ...)

and afterwards:

p1, p2 = <...> # do some calculations based on self.btn.rect self.btn.setLoc((p1, p2))

I suppose this might be true for more components. Let me know your thoughts.

Thanks in advance.


You can view, comment on, or merge this pull request online at:

https://github.com/IrvKalb/pygwidgets/pull/5

Commit Summary

File Changes

(1 filehttps://github.com/IrvKalb/pygwidgets/pull/5/files)

Patch Links:

— Reply to this email directly, view it on GitHubhttps://github.com/IrvKalb/pygwidgets/pull/5, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ABXUYSULVQUUT3I35T3ENLLWYD2MJANCNFSM6AAAAAAVAN5VY4. You are receiving this because you are subscribed to this thread.Message ID: @.***>

IrvKalb commented 1 year ago

Here is a test program that shows what I was talking about:

Import relevant packages and modules

import pygame from pygame.locals import * import pygwidgets import sys

WHITE = (255, 255, 255)

pygame.init() window = pygame.display.set_mode((640, 380))

New class where loc parameter is not required

class RenatoTextButton(pygwidgets.TextButton): def init(self, window, loc=(0, 0), text=''): print('loc', loc, 'text', text) super().init(window, loc, text)

Create first button, let it default to position (0, 0) and show there

button1 = RenatoTextButton(window, text='Button1')

Create second button, then change it's location to (100, 100)

(this is just a test, you can place it based on its rect)

button2 = RenatoTextButton(window, text='Button2') button2.setLoc((100, 100))

while True: for event in pygame.event.get():

Clicked the close button? Quit pygame and end the program

    if event.type == pygame.QUIT:
        pygame.quit()
        sys.exit()
    if button1.handleEvent(event):
        print('Button1 (at 0, 0), was pressed')
    if button2.handleEvent(event):
        print('Button2 (at 100, 100) was pressed')

button1.draw()
button2.draw()
pygame.display.update()

This allows you to do exactly what you want - create a TextButton, but without having to specify a location. You can do whatever calculations you want and set the location of the button based on your calculation.

Hope that helps,

Irv

monteiro-renato commented 1 year ago

Hi, sorry for the late response but I only have time on the weekends.

Indeed, subclassing would work but it's still a workaround. Changing TextButton to allow for this flexibility would be ideal in my opinion.

Is there any particular reason as to why you think having an empty string as the default value is not good? As you mentioned, it's probably not what is intended when building an UI but it also doesn't "break" the code.

I saw that DisplayText also had the loc and text parameters with default values and wondered if it would make sense to set those defaults in other widgets as well.

Thanks for the detailed reply!

IrvKalb commented 1 year ago

Hi,

Interesting find about DisplayText. You actually found something that I was not aware of.

My intention was to be highly consistent with all the widgets in the pygwidgets collection so they would all require both a window and a location as the first two parameters. The fact that DisplayText has a default location of (0, 0) was an oversight on my part. In fact, I may even change that back to not having a default value.

The default of the empty string for the "value" parameter does make more sense as it is often the case that you want an output field to be empty until you put something into it. So that one is fine. Further, if you have multiple fields, it is often the case that you want them all to be empty to start. The content of DisplayText fields can be changed easily with a call to the setValue() method.

As I said earlier, it wouldn't make as much sense to be able to create multiple TextButton objects, all with a default of an empty string as the label. There isn't a method to change the label on a TextButton (although that's not a bad idea for the future.)

I think your case is very unusual. I think that most users would want to set a location for a button and rarely, if ever, change it. And, if you want to change it, the setLoc() method already works for this. In your case, you can use the subclass approach, or just set the location to (0, 0) to start, and change it later.

Irv


From: Renato Monteiro @.> Sent: Saturday, February 25, 2023 6:04 AM To: IrvKalb/pygwidgets @.> Cc: irv furrypants.com @.>; State change @.> Subject: Re: [IrvKalb/pygwidgets] Allow the instanciation of a TextButton without a loc defined (PR #5)

Hi, sorry for the late response but I only have time on the weekends.

Indeed, subclassing would work but it's still a workaround. Changing TextButton to allow for this flexibility would be ideal in my opinion.

Is there any particular reason as to why you think having an empty string as the default value is not good? As you mentioned, it's probably not what is intended when building an UI but it also doesn't "break" the code.

I saw that DisplayText also had the loc and text parameters with default values and wondered if it would make sense to set those defaults in other widgets as well.

Thanks for the detailed reply!

— Reply to this email directly, view it on GitHubhttps://github.com/IrvKalb/pygwidgets/pull/5#issuecomment-1445127086, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ABXUYSRCMRAJAWQ3PVMI54TWZIGQFANCNFSM6AAAAAAVAN5VY4. You are receiving this because you modified the open/close state.Message ID: @.***>