diff --git a/Orange/widgets/visualize/owscatterplotgraph.py b/Orange/widgets/visualize/owscatterplotgraph.py index 7cc505f5d6c..4497abadfa9 100644 --- a/Orange/widgets/visualize/owscatterplotgraph.py +++ b/Orange/widgets/visualize/owscatterplotgraph.py @@ -405,7 +405,7 @@ def __init__(self, scatter_widget, parent=None, view_box=ViewBox): self.plot_widget.scene().installEventFilter(self._tooltip_delegate) self.view_box.sigTransformChanged.connect(self.update_density) - self._timer = QTimer() + self.timer = None def _create_legend(self, anchor): legend = LegendItem() @@ -487,6 +487,9 @@ def clear(self): self.plot_widget.clear() self.density_img = None + if self.timer is not None and self.timer.isActive(): + self.timer.stop() + self.timer = None self.scatterplot_item = None self.scatterplot_item_sel = None self.labels = [] @@ -730,34 +733,38 @@ def update_sizes(self): self.master, "impute_sizes", self.default_impute_sizes) size_imputer(size_data) - if self._timer.isActive(): - self._timer.stop() + if self.timer is not None and self.timer.isActive(): + self.timer.stop() + self.timer = None - current_size_data = self.scatterplot_item.data["size"] + current_size_data = self.scatterplot_item.data["size"].copy() diff = size_data - current_size_data + widget = self class Timeout: - n_iter = 5 + # 0.5 - np.cos(np.arange(0.17, 1, 0.17) * np.pi) / 2 + factors = [0.07, 0.26, 0.52, 0.77, 0.95, 1] - def __init__(self, diff_=diff, item=self.scatterplot_item, - item_sel=self.scatterplot_item_sel): + def __init__(self): self._counter = 0 - self._step = diff_ / self.n_iter - self._scatter_item, self._scatter_item_sel = item, item_sel def __call__(self): + factor = self.factors[self._counter] self._counter += 1 - size = current_size_data + self._step - if self.n_iter == self._counter: - tmr.stop() + size = current_size_data + diff * factor + if len(self.factors) == self._counter: + widget.timer.stop() + widget.timer = None size = size_data - self._scatter_item.setSize(size) - self._scatter_item_sel.setSize(size + SELECTION_WIDTH) + widget.scatterplot_item.setSize(size) + widget.scatterplot_item_sel.setSize(size + SELECTION_WIDTH) if np.sum(current_size_data) / self.n_valid != -1 and np.sum(diff): - self._timer = tmr = QTimer(self.scatterplot_item, interval=50) - self._timer.timeout.connect(Timeout()) - self._timer.start() + # If encountered any strange behaviour when updating sizes, + # implement it with threads + self.timer = QTimer(self.scatterplot_item, interval=50) + self.timer.timeout.connect(Timeout()) + self.timer.start() else: self.scatterplot_item.setSize(size_data) self.scatterplot_item_sel.setSize(size_data + SELECTION_WIDTH) diff --git a/Orange/widgets/visualize/tests/test_owscatterplotbase.py b/Orange/widgets/visualize/tests/test_owscatterplotbase.py index 02899fc0712..dd6cd626b41 100644 --- a/Orange/widgets/visualize/tests/test_owscatterplotbase.py +++ b/Orange/widgets/visualize/tests/test_owscatterplotbase.py @@ -17,9 +17,6 @@ from Orange.widgets.widget import OWWidget -DEFAULT_TIMEOUT = 5000 - - class MockWidget(OWWidget): name = "Mock" @@ -167,7 +164,8 @@ def test_sampling(self): master.get_label_data = lambda: \ np.array([str(x) for x in d], dtype=object) graph.reset_graph() - self.process_events(until=lambda: not self.graph._timer.isActive()) + self.process_events(until=lambda: not ( + self.graph.timer is not None and self.graph.timer.isActive())) # Check proper sampling scatterplot_item = graph.scatterplot_item @@ -195,7 +193,8 @@ def test_sampling(self): # Check that sample is extended when sample size is changed graph.set_sample_size(4) - self.process_events(until=lambda: not self.graph._timer.isActive()) + self.process_events(until=lambda: not ( + self.graph.timer is not None and self.graph.timer.isActive())) scatterplot_item = graph.scatterplot_item x, y = scatterplot_item.getData() data = scatterplot_item.data @@ -235,7 +234,8 @@ def test_sampling(self): # Enable sampling when data is already present and not sampled graph.set_sample_size(3) - self.process_events(until=lambda: not self.graph._timer.isActive()) + self.process_events(until=lambda: not ( + self.graph.timer is not None and self.graph.timer.isActive())) scatterplot_item = graph.scatterplot_item x, y = scatterplot_item.getData() data = scatterplot_item.data @@ -271,7 +271,8 @@ def test_sampling(self): np.arange(100, 105, dtype=float)) d = self.xy[0] - 100 graph.reset_graph() - self.process_events(until=lambda: not self.graph._timer.isActive()) + self.process_events(until=lambda: not ( + self.graph.timer is not None and self.graph.timer.isActive())) scatterplot_item = graph.scatterplot_item x, y = scatterplot_item.getData() self.assertEqual(len(x), 3) @@ -376,7 +377,8 @@ def test_size_with_nans(self): d[4] = np.nan graph.update_sizes() - self.process_events(until=lambda: not self.graph._timer.isActive()) + self.process_events(until=lambda: not ( + self.graph.timer is not None and self.graph.timer.isActive())) sizes2 = scatterplot_item.data["size"] self.assertEqual(sizes[1] - sizes[0], sizes2[1] - sizes2[0]) diff --git a/Orange/widgets/visualize/utils/widget.py b/Orange/widgets/visualize/utils/widget.py index 6362cad4cea..d05c6a33225 100644 --- a/Orange/widgets/visualize/utils/widget.py +++ b/Orange/widgets/visualize/utils/widget.py @@ -583,6 +583,7 @@ def onDeleteWidget(self): super().onDeleteWidget() self.graph.plot_widget.getViewBox().deleteLater() self.graph.plot_widget.clear() + self.graph.clear() class OWAnchorProjectionWidget(OWDataProjectionWidget):