Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Table events not always firing #3269

Open
JDarsley opened this issue Mar 18, 2025 · 1 comment
Open

Table events not always firing #3269

JDarsley opened this issue Mar 18, 2025 · 1 comment
Labels
bug A crash or error in behavior. good first issue Is this your first time contributing? This could be a good place to start! windows The issue relates to Microsoft Windows support.

Comments

@JDarsley
Copy link

Describe the bug

This may be related to issue 3265, but I thought it better to raise it as a separate report.

Clicking on a table doesn't always fire the table's on_select handler. This arises when I construct and display a list of separate tables. (I've also checked to see whether this arises if the tables aren't elements of a list, and yes, same behaviour.)

events2.py:

import toga
from toga.style import Pack
from toga.style.pack import CENTER, COLUMN, ROW, START, RIGHT, TOP, BOTTOM, SERIF, BOLD

class Jotter(toga.App):

    def startup(self):
        self.main_window = toga.MainWindow()

        self.lstTables = []

        for n in [1, 2]:

            lstDetail = [
                {"Detail": f"Subject Heading {n}"},
                {"Detail": f"Date and time {n}"},
                {"Detail": f"Note text {n}"}
            ]

            tblNoteDetails = toga.Table(
                headings=None,
                accessors=["Detail"],
                data=lstDetail,
                on_select=self.onSelect
            )

            self.lstTables.append(tblNoteDetails)

        self.main_window.content = toga.Box(
            style=Pack(direction=COLUMN,
                       align_items=START,
                       gap=2
            ),
            children=self.lstTables
        )

        self.countOnSelect = 0

        self.main_window.show()

    def onSelect(self, widget, **kwargs):
        self.countOnSelect += 1
        print(f"\nSelect handler - call {self.countOnSelect}")
        print({widget.data[0]})
        print({widget.data[1]})
        print({widget.data[2]})
        
if __name__ == '__main__':
    app = Jotter("Events", "org.jd.jotter")
    app.main_loop()        

I can see this might be considered a bit of an edge case. I've added a few thoughts under "Expected Behavior" below.

Steps to reproduce

  1. Open a console.
  2. python events2.py
  3. Click on "Subject Heading 1", and the console should show that the on_select event fired.
  4. Click on "Subject Heading 2", and the console should again show that the on_select event fired.
  5. Click again on "Subject Heading 1", and the on_select event doesn't fire.

Expected behavior

Should the event fire each time?

I can see that eg "Subject Heading 1" was already the selected row in the first table, and might therefore be considered to have not been reselected on the later click. On the other hand, these are table-level events, and by clicking on "Subject Heading 2", haven't we deselected the first table anyway? Certainly, clicking on a different row is treated as reselecting a table and fires the event.

Screenshots

No response

Environment

  • Operating System: Windows 11 24H2
  • Python version: 3.12.6
  • Software versions:
    • Briefcase: 0.3.22
    • Toga: 0.5.0
    • ...

Logs


Additional context

I already have a workaround on this, but it made me wonder, is there a way to programatically explicitly remove focus/selection from a table or other widget?

@JDarsley JDarsley added the bug A crash or error in behavior. label Mar 18, 2025
@freakboy3742 freakboy3742 added good first issue Is this your first time contributing? This could be a good place to start! windows The issue relates to Microsoft Windows support. labels Mar 19, 2025
@freakboy3742
Copy link
Member

Thanks for the report (and for making it a separate issue).

As you've hinted in the "Expected behavior" section, this is the expected beheavior of the Table. When you select "Subject Heading 1" for the second time, you're not changing the selection of the Table - you're only giving focus back to the existing table. If you were to select "Date and Time 1" on the third click, you would get an event (or several, because of #3265). The selected row is independent of focus - you can read the selected row from a non-focussed table, because the table's state still knows the selected row. You can see this by using Tab to shift focus between widgets without using the mouse.

This isn't necessarily obvious from the way Winforms is rendering the table; It's a lot more obvious on other platforms, because the selected row on a widget without focus is visible - for example, on macOS:

Image

macOS uses "zebra stripes" to make rows easier to differentiate, but the "selected but non-focussed" Subject Heading 1 is darker than "Note text 1".

From the look of it, this is a case of a "weird default" for Winforms - if we add self.native.HideSelection = False around L50 of the Winforms Table implementation, a selected row on a non-focussed table is rendered in grey:

Image

If you want to turn that into a pull request, I'll gladly merge the change.

As for the other I'm not a aware of a way to prevent a widget that can nominally take focus from doing so - AIUI, that would be an accessibility issue, because keyboard navigation and screen readers need to be able to select the widget to be able to read the content.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A crash or error in behavior. good first issue Is this your first time contributing? This could be a good place to start! windows The issue relates to Microsoft Windows support.
Projects
None yet
Development

No branches or pull requests

2 participants