enthought / enthought/pyface

DataView gets slow when a lot of elements are selected

Open
#879 8 comments 0 reactions 0 assignees View on GitHub
type: bug
Dominant language
Python
Stars
115
Forks
54
PR merge metrics
No merged PRs in 30d

Description

Hi there ! It seems that upon using `DataView` with a large amount of data, the app using it becomes quite slow if a lot of items are selected in the tree. Basically scrolling through the data, resizing the app, or other actions involving the `DataView` widget are slowed down. You can check this using the code snippet hereafter (this snippet is just [this example in pyface](https://github.com/enthought/pyface/blob/master/examples/data_view/row_table_example.py), modified to select random elements before showing the UI (you can also check that selecting only one item restores a smooth behaviour, for instance when scrolling or resizing the window).

Tested with pyface 7.2 and Traits 6.1 on MacOS X 10.15.7.

```Python3
import logging
from random import randint

from traits.api import Bool, Dict, HasStrictTraits, Instance, Int, Str, List

from pyface.api import ApplicationWindow, GUI, Image, ImageResource
from pyface.ui_traits import PyfaceColor
from pyface.data_view.data_models.api import (
AttributeDataAccessor, RowTableDataModel
)
from pyface.data_view.api import DataViewWidget, IDataViewWidget
from pyface.data_view.value_types.api import (
BoolValue, ColorValue, IntValue, TextValue
)

from example_data import (
any_name, family_name, favorite_color, age, street, city, country
)

logger = logging.getLogger(__name__)

flags = {
'Canada': ImageResource('ca.png'),
'UK': ImageResource('gb.png'),
'USA': ImageResource('us.png'),
}

# The data model

class Address(HasStrictTraits):

street = Str()

city = Str()

country = Str()

class Person(HasStrictTraits):

name = Str()

age = Int()

favorite_color = PyfaceColor()

contacted = Bool()

address = Instance(Address, ())

class CountryValue(TextValue):

flags = Dict(Str, Image, update_value_type=True)

def has_image(self, model, row, column):
value = model.get_value(row, column)
return value in self.flags

def get_image(self, model, row, column):
value = model.get_value(row, column)
return self.flags[value]

row_header_data = AttributeDataAccessor(
title='People',
attr='name',
value_type=TextValue(),
)

column_data = [
AttributeDataAccessor(
attr="age",
value_type=IntValue(minimum=0),
),
AttributeDataAccessor(
attr="favorite_color",
value_type=ColorValue(),
),
AttributeDataAccessor(
attr="contacted",
value_type=BoolValue(),
),
AttributeDataAccessor(
attr="address.street",
value_type=TextValue(),
),
AttributeDataAccessor(
attr="address.city",
value_type=TextValue(),
),
AttributeDataAccessor(
attr="address.country",
value_type=CountryValue(flags=flags),
),
]

class MainWindow(ApplicationWindow):
""" The main application window. """

#: A collection of People.
data = List(Instance(Person))

#: The data view widget.
data_view = Instance(IDataViewWidget)

def _create_contents(self, parent):
""" Creates the left hand side or top depending on the style. """

self.data_view = DataViewWidget(
parent=parent,
data_model=RowTableDataModel(
data=self.data,
row_header_data=row_header_data,
column_data=column_data
),
)
self.data_view._create()

logger.info("Starting selection")
selection = [
((randint(0, 9999),), ()) for _ in range(1000)
]
self.data_view.control._widget.selection = selection
logger.info("Selection done")

return self.data_view.control

def _data_default(self):
logger.info("Initializing data")
people = [
Person(
name='%s %s' % (any_name(), family_name()),
age=age(),
favorite_color=favorite_color(),
address=Address(
street=street(),
city=city(),
country=country(),
),
)
for i in range(10000)
]
logger.info("Data initialized")
return people

def destroy(self):
self.data_view.destroy()
super().destroy()

if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)

# Create the GUI (this does NOT start the GUI event loop).
gui = GUI()

# Create and open the main window.
window = MainWindow()
window.open()

# Start the GUI event loop!
gui.start_event_loop()
logger.info("Shutting down")
```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.