Sometimes selected features in QGIS are hidden behind other (non-selected) features in the same layer, for example when there are a lot of coincident points. So I was looking for a way to force the selected features to be rendered on top, something like this:
In the QGIS layer style properties, there is an option at the bottom to "Control feature rendering order" where you can order by the values in a column, or by an expression. The problem is that there is currently no way to access the selection status. Clicking the expression symbol takes us to the expression editor. I was hoping that there would be a $selected function under Record, but there isn't.
So I started looking into how to create a custom function in QGIS using Python, and eventually came up with this:
""" isSelected() is a custom function for QGIS that will tell you if a feature is selected (true) or not (false) Use it for custom styling, render ordering, or sub-selecting """ from qgis.core import * from qgis.gui import * from qgis.utils import iface @qgsfunction(args=0, group='Custom') def isSelected(value1,feature, parent): selected_ids = [f.id() for f in iface.activeLayer().selectedFeatures()] return feature.id() in selected_ids
From the Expression dialog, switch to the "Function Editor" tab, paste in that code and click "Load". This will register the new function with QGIS. When you switch back to the "Expression" tab, look under the "Custom" group, and you should see the new "isSelected" function.
Now you can sort the rendering order by isSelected() ascending, which will cause selected features to be drawn last, on top. This seems to work pretty well, but may be too slow to be practicable for larger datasets.
You could also use this function as the "column" for a categorized map style, for example to make selected points larger. (The selected feature will automatically take the selection color as defined in the project properties.)