- fixed setup_ubuntu.sh to include the matplotlib package required by the Legacy (2D) graphic engine

- in legacy graphic engine, fixed issue where immediately after changing the mouse cursor snapping the mouse cursor shape was not updated
- in legacy graphic engine, fixed issue where while zooming the mouse cursor shape was not updated
- in legacy graphic engine, fixed issue where immediately after panning finished the mouse cursor shape was not updated
This commit is contained in:
Marius Stanciu 2019-09-24 15:47:33 +03:00
parent e042f6beed
commit 1ee7f9bf1e
3 changed files with 90 additions and 13 deletions

View File

@ -12,6 +12,10 @@ CAD program, and create G-Code for Isolation routing.
24.09.2019 24.09.2019
- fixed the fullscreen method to show the application window in fullscreen wherever the mouse pointer it is therefore on the screen we are working on; before it was showing always on the primary screen - fixed the fullscreen method to show the application window in fullscreen wherever the mouse pointer it is therefore on the screen we are working on; before it was showing always on the primary screen
- fixed setup_ubuntu.sh to include the matplotlib package required by the Legacy (2D) graphic engine
- in legacy graphic engine, fixed issue where immediately after changing the mouse cursor snapping the mouse cursor shape was not updated
- in legacy graphic engine, fixed issue where while zooming the mouse cursor shape was not updated
- in legacy graphic engine, fixed issue where immediately after panning finished the mouse cursor shape was not updated
23.09.2019 23.09.2019

View File

@ -8,12 +8,13 @@
############################################################ ############################################################
from PyQt5 import QtGui, QtCore, QtWidgets from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import pyqtSignal
# Prevent conflict with Qt5 and above. # Prevent conflict with Qt5 and above.
from matplotlib import use as mpl_use from matplotlib import use as mpl_use
mpl_use("Qt5Agg") mpl_use("Qt5Agg")
from matplotlib.figure import Figure from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from matplotlib.backends.backend_agg import FigureCanvasAgg from matplotlib.backends.backend_agg import FigureCanvasAgg
from matplotlib.widgets import Cursor from matplotlib.widgets import Cursor
@ -26,6 +27,7 @@ from shapely.geometry import Polygon, LineString, LinearRing, Point, MultiPolygo
import FlatCAMApp import FlatCAMApp
from copy import deepcopy from copy import deepcopy
import logging import logging
import traceback
import gettext import gettext
import FlatCAMTranslation as fcTranslate import FlatCAMTranslation as fcTranslate
@ -113,6 +115,33 @@ class CanvasCache(QtCore.QObject):
# log.debug("A new object is available. Should plot it!") # log.debug("A new object is available. Should plot it!")
class FigureCanvas(FigureCanvasQTAgg):
"""
Reimplemented this so I can emit a signal when the idle drawing is finished and display the mouse shape
"""
idle_drawing_finished = pyqtSignal()
def __init__(self, figure):
super().__init__(figure=figure)
def _draw_idle(self):
if self.height() < 0 or self.width() < 0:
self._draw_pending = False
if not self._draw_pending:
return
try:
self.draw()
except Exception:
# Uncaught exceptions are fatal for PyQt5, so catch them instead.
traceback.print_exc()
finally:
self._draw_pending = False
# I reimplemented this class only to launch this signal
self.idle_drawing_finished.emit()
class PlotCanvasLegacy(QtCore.QObject): class PlotCanvasLegacy(QtCore.QObject):
""" """
Class handling the plotting area in the application. Class handling the plotting area in the application.
@ -209,6 +238,9 @@ class PlotCanvasLegacy(QtCore.QObject):
# signal if there is a doubleclick # signal if there is a doubleclick
self.is_dblclk = False self.is_dblclk = False
# pay attention, this signal should be connected only after the self.canvas and self.mouse is declared
self.canvas.idle_drawing_finished.connect(lambda: self.draw_cursor(x_pos=self.mouse[0], y_pos=self.mouse[1]))
def graph_event_connect(self, event_name, callback): def graph_event_connect(self, event_name, callback):
""" """
Attach an event handler to the canvas through the Matplotlib interface. Attach an event handler to the canvas through the Matplotlib interface.
@ -256,9 +288,20 @@ class PlotCanvasLegacy(QtCore.QObject):
# c = MplCursor(axes=axes, color='black', linewidth=1) # c = MplCursor(axes=axes, color='black', linewidth=1)
c = FakeCursor() c = FakeCursor()
try:
c.mouse_state_updated.connect(self.clear_cursor)
except Exception as e:
print(str(e))
return c return c
def clear_cursor(self, state):
if state is True:
self.draw_cursor(x_pos=self.mouse[0], y_pos=self.mouse[1])
else:
self.canvas.restore_region(self.background)
self.canvas.blit(self.axes.bbox)
def on_key_down(self, event): def on_key_down(self, event):
""" """
@ -571,9 +614,12 @@ class PlotCanvasLegacy(QtCore.QObject):
# Clear pan flag # Clear pan flag
self.panning = False self.panning = False
# And update the cursor
self.draw_cursor(x_pos=self.mouse[0], y_pos=self.mouse[1])
def on_mouse_move(self, event): def on_mouse_move(self, event):
""" """
Mouse movement event hadler. Stores the coordinates. Updates view on pan. Mouse movement event handler. Stores the coordinates. Updates view on pan.
:param event: Contains information about the event. :param event: Contains information about the event.
:return: None :return: None
@ -591,23 +637,44 @@ class PlotCanvasLegacy(QtCore.QObject):
# Update pan view on mouse move # Update pan view on mouse move
if self.panning is True: if self.panning is True:
# x_pan, y_pan = self.app.geo_editor.snap(event.xdata, event.ydata)
# self.app.app_cursor.set_data(event, (x_pan, y_pan))
for a in self.pan_axes: for a in self.pan_axes:
a.drag_pan(1, event.key, event.x, event.y) a.drag_pan(1, event.key, event.x, event.y)
# x_pan, y_pan = self.app.geo_editor.snap(event.xdata, event.ydata)
# self.draw_cursor(x_pos=x_pan, y_pos=y_pan)
# Async re-draw (redraws only on thread idle state, uses timer on backend) # Async re-draw (redraws only on thread idle state, uses timer on backend)
self.canvas.draw_idle() self.canvas.draw_idle()
# #### Temporary place-holder for cached update ##### # #### Temporary place-holder for cached update #####
self.update_screen_request.emit([0, 0, 0, 0, 0]) self.update_screen_request.emit([0, 0, 0, 0, 0])
x, y = self.app.geo_editor.snap(x, y) self.draw_cursor(x_pos=x, y_pos=y)
if self.app.app_cursor.enabled is True:
# self.canvas.blit(self.axes.bbox)
def draw_cursor(self, x_pos, y_pos):
"""
Draw a cursor at the mouse grid snapped position
:param x_pos: mouse x position
:param y_pos: mouse y position
:return:
"""
# there is no point in drawing mouse cursor when panning as it jumps in a confusing way
if self.app.app_cursor.enabled is True and self.panning is False:
try:
x, y = self.app.geo_editor.snap(x_pos, y_pos)
# Pointer (snapped) # Pointer (snapped)
elements = self.axes.plot(x, y, 'k+', ms=40, mew=2, animated=True) elements = self.axes.plot(x, y, 'k+', ms=40, mew=2, animated=True)
for el in elements: for el in elements:
self.axes.draw_artist(el) self.axes.draw_artist(el)
except Exception as e:
# this happen at app initialization since self.app.geo_editor does not exist yet
# I could reshuffle the object instantiating order but what's the point? I could crash something else
# and that's pythonic, too
pass
self.canvas.blit(self.axes.bbox) self.canvas.blit(self.axes.bbox)
@ -656,13 +723,17 @@ class PlotCanvasLegacy(QtCore.QObject):
return width / xpx, height / ypx return width / xpx, height / ypx
class FakeCursor: class FakeCursor(QtCore.QObject):
""" """
This is a fake cursor to ensure compatibility with the OpenGL engine (VisPy). This is a fake cursor to ensure compatibility with the OpenGL engine (VisPy).
This way I don't have to chane (disable) things related to the cursor all over when This way I don't have to chane (disable) things related to the cursor all over when
using the low performance Matplotlib 2D graphic engine. using the low performance Matplotlib 2D graphic engine.
""" """
mouse_state_updated = pyqtSignal(bool)
def __init__(self): def __init__(self):
super().__init__()
self._enabled = True self._enabled = True
@property @property
@ -672,6 +743,7 @@ class FakeCursor:
@enabled.setter @enabled.setter
def enabled(self, value): def enabled(self, value):
self._enabled = value self._enabled = value
self.mouse_state_updated.emit(value)
def set_data(self, pos, **kwargs): def set_data(self, pos, **kwargs):
"""Internal event handler to draw the cursor when the mouse moves.""" """Internal event handler to draw the cursor when the mouse moves."""

View File

@ -30,3 +30,4 @@ pip3 install --upgrade fontTools
pip3 install --upgrade rasterio pip3 install --upgrade rasterio
pip3 install --upgrade lxml pip3 install --upgrade lxml
pip3 install --upgrade ezdxf pip3 install --upgrade ezdxf
pip3 install --upgrade matplotlib