The trick is to create a function that access QGIS graphical interface, and that is piped to the query of the virtual layer.
- Open a function editor (from anywhere, including from field calculator) and create a new function that reads the canvas extent and returns it as a geometry.
from qgis.core import *
from qgis.gui import *
from qgis.utils import iface
@qgsfunction(args='auto', group='Custom')
def currentExtent(feature, parent):
return QgsGeometry.fromRect(iface.mapCanvas().extent())
- Create a new virtual layer and use the new function, selecting features that intersects the displayed area. To get features entirely within the displayed area, use
ST_Within() instead.
SELECT *
FROM mylayer
WHERE st_intersects(mylayer.geometry, currentExtent());
Note that if you have the attribute table open, you would need to click the refresh icon after panning the map.
st_intersects, features that are partially displayed will be returned. One can change the query and useST_Withininstead (or any other spatial predicate) – JGH Apr 26 '19 at 18:19*, the original (complete) geometry will be returned – JGH Apr 26 '19 at 18:21currentExtentfunction + virtual layer in an attempt to improve display performance of a big layer... and it had 0 effect – JGH Apr 26 '19 at 19:41geometryby the real field name – JGH Apr 29 '19 at 11:53currentExtentfunction (each time) and filters the data accordingly. The same occurs when opening/refreshing the attribute table. – JGH Apr 29 '19 at 12:16_search_frame_in the query: https://docs.qgis.org/3.22/en/docs/user_manual/managing_data_source/create_layers.html#use-of-indexes – bugmenot123 Sep 13 '22 at 08:42