MyreMylar / pygame_gui

A GUI system for pygame.
MIT License
680 stars 78 forks source link

If UITextBox is disabled, do not switch to text cursor #604

Closed scribblecrumb closed 1 day ago

scribblecrumb commented 3 months ago

Is your feature request related to a problem? Please describe. Currently the only way I know of to prevent text selection on a UITextbox is by disabling it (do let me know if there's another way, though!) However, even though you're unable to select the text, the cursor still changes to the text cursor when you hover over the text, which implies you can select it.

Describe the solution you'd like I would like to see the disabling of the text box also prevent the text cursor switch.

Describe alternatives you've considered I don't know of any other way to prevent text selection besides creating a UITextBox subclass.

rbaltrusch commented 3 weeks ago

Last week I ran into the same issue and wanted to report it here. I'm hiding the real mouse cursor and replacing it with a custom image. This works fine until I open a window with a disabled TextBox, at which point it switches to the text select cursor.

However, upon working out a minimal reproducible example, I actually found the solution (to my problem). The problem turned out to be the method I used to hide the system mouse was the archaic and cryptic pygame.mouse.set_cursor((8, 8), (0, 0), (0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0)). Using the more modern way from the pygame docs: pygame.mouse.set_visible(False)

If you do not mind having to manage cursors via custom images yourself, the following minimal example works as expected:

import pygame
from pygame_gui import UIManager
from pygame_gui.elements.ui_text_box import UITextBox
from pygame_gui.elements.ui_window import UIWindow

pygame.init()
screen = pygame.display.set_mode((800, 600))
clock = pygame.Clock()

pygame.mouse.set_visible(False)
# ==> do not hide cursor like this: pygame.mouse.set_cursor((8, 8), (0, 0), (0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0))
cursor = pygame.image.load("custom_cursor.png")

manager = UIManager((800, 600))
window = UIWindow(pygame.Rect(10, 10, 400, 400), manager=manager, resizable=False, draggable=False, always_on_top=True)
UITextBox("text", pygame.Rect(10, 10, 400, 400), manager=manager, parent_element=window, container=window).disable()

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    delta = clock.tick(60)
    screen.fill((0, 0, 0))
    manager.update(delta)
    manager.draw_ui(screen)
    screen.blit(cursor, pygame.mouse.get_pos())
    pygame.display.flip()

Of course, an actual fix to the problem inside the library would be nice. In the meantime, maybe my solution helps you or somebody else.

rbaltrusch commented 3 weeks ago

Hi @MyreMylar, could you assign me this issue and review my PR?

With the following minimal example, the bug is no longer reproducible:

import pygame
from pygame_gui import UIManager
from pygame_gui.elements.ui_text_box import UITextBox

pygame.init()
screen = pygame.display.set_mode((800, 600))
clock = pygame.Clock()
manager = UIManager((800, 600))
text_box = UITextBox("text", pygame.Rect(10, 10, 400, 200), manager=manager)
text_box.disable()

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    delta = clock.tick(60)
    manager.update(delta / 1000)
    manager.draw_ui(screen)
    pygame.display.flip()