selection


make 2 different selection-tools coexist in pyside


I am writing a program that lets users select items among a bunch of polygons in a QGraphicsScene.
PySide provides a handy rubber-band selection tool but I wanted to be able to select items by drawing a polygon on the scene. To implement this I had to redefined mouse events such as mousePressEvent. This works, great! ...but of course it disabled the rubber-band and the possibility of selecting objects by merely clicking on them.
Now, what I would like to do is to be able to switch between those tools. Either Let users choose one (with, let say, a ctrl modifier) or force them to use any one of them depending on the context.
Has anyone an idea about how this could be achieved? Would be truly grateful for any tips.
Thanks
/Romain
Here comes a not-so-minimal working example of what I did:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PySide import QtGui, QtCore
########### Item class creates polygon items
class Geometry(QtGui.QGraphicsItem):
def __init__(self, pen):
super(Geometry, self).__init__()
self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable )
self.brush = None
self.pen = pen
self.create_rectangle()
def create_rectangle(self, w = 0, h= 0, x = 0, z = 0):
self.xmin = x
self.xmax = w
self.ymin = z
self.ymax = h
self.polygon = QtGui.QPolygonF([QtCore.QPointF(self.xmax, self.ymax), QtCore.QPointF(self.xmax, self.ymin), QtCore.QPointF(self.xmin, self.ymin), QtCore.QPointF(self.xmin, self.ymax)])
def shape(self):
path = QtGui.QPainterPath()
path.addPolygon(self.polygon)
return path
def paint(self, painter, option, widget):
painter.setPen(self.pen)
if self.brush:
painter.setBrush(self.brush)
if self.isSelected ():
pen = QtGui.QPen(QtCore.Qt.gray, 2, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
painter.setPen( pen )
boundRect = self.boundingRect ()
painter.drawRect( boundRect )
painter.drawPolygon(self.polygon)
def setBrush(self, brush):
self.brush = brush
def boundingRect(self):
return self.polygon.boundingRect()
###########################################################################################################
########### polygon for selection
class Selector(QtGui.QGraphicsItem):
def __init__(self, point):
super(Selector, self).__init__()
self.polygon = QtGui.QPainterPath(point)
def add_point(self, point):
self.polygon.lineTo(point)
def boundingRect(self):
return self.polygon.boundingRect()
def to_polygon(self):
self.polygon.closeSubpath()
def paint(self, painter, option, widget):
painter.drawPath(self.polygon)
def path(self):
return self.polygon
#############################################################################################################
########### View class , creates a view, scene initialized a scene and integrated to view inside this class
class View(QtGui.QGraphicsView):
default = True
def __init__(self):
super(View, self).__init__()
self.setWindowTitle("Custom item")
self.setDragMode(QtGui.QGraphicsView.RubberBandDrag)
self.scene = QtGui.QGraphicsScene()
self.clickclick = 0
self.old_selector = None
def create_domain(self , x = 0 , z = 0):
pen = QtGui.QPen(QtCore.Qt.black, 0, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
self.item = Geometry(pen)
self.item.create_rectangle(x,z)
self.item.setZValue(1)
self.item.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, False)
self.scene.addItem(self.item)
self.scene.mode = "cells"
self.setScene(self.scene)
self.line = None
def discretize_domain(self , nb_x = 1 , nb_z = 1):
pen = QtGui.QPen(QtCore.Qt.gray, 1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
self.cell_dict = {}
self.count = 0
dx = domain_x / nb_x
dz = domain_z / nb_z
for i in range(0,nb_z):
self.min_z = i*dz
self.max_z = (i+1)*dz
for j in range(0,nb_x):
self.min_x = j*dx
self.max_x = (j+1)*dx
self.cell_item = Geometry(pen)
self.cell_item.create_rectangle(self.max_x, self.max_z, self.min_x, self.min_z)
self.scene.addItem(self.cell_item)
self.cell_dict[self.cell_item] = [self.count , "button0" ]
self.count += 1
global cell_dict
cell_dict = self.cell_dict
self.setScene(self.scene)
def mousePressEvent(self, event):
self._start = self.mapToScene(event.pos())
if self.clickclick :
self.scene.removeItem(self.selector)
self.selector.add_point(self.mapToScene(event.pos()))
else :
self.selector = Selector(self._start)
self.scene.addItem( self.selector )
self.clickclick += 1
def mouseReleaseEvent(self, event):
if not self.clickclick:
self.scene.removeItem(self.old_selector)
def mouseDoubleClickEvent(self , event):
self.scene.removeItem(self.selector)
self.selector.to_polygon()
self.scene.addItem(self.selector)
self.old_selector = self.selector
self.clickclick = 0
self.scene.setSelectionArea(self.selector.path(),QtCore.Qt.ContainsItemShape)
############################################################################################################
############
############ Main window (not in use so far)
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.initUI()
def initUI(self):
# Create Buttons
self.start_bt = QtGui.QPushButton('Start', self)
self.start_bt.setEnabled(False)
#Creates a horizontal box with buttons at the start and stretch at the end
hbox = QtGui.QHBoxLayout()
hbox.addWidget(self.start_bt)
hbox.addStretch(1)
self.view = View()
# create a vertical box with hbox at the top and stretch at the bottom
self.vbox = QtGui.QVBoxLayout()
self.vbox.addLayout(hbox)
self.vbox.addWidget(self.view)
# Puts vbox in widget
self.main_widget = QtGui.QWidget()
self.main_widget.setLayout(self.vbox)
# Integrate main widget in window
self.setCentralWidget(self.main_widget)
# Defines window position and size
self.setGeometry(1800, 110, 700, 500)
self.setWindowTitle('FutureLearn kick-ass software')
self.setWindowIcon(QtGui.QIcon('glass.jpg'))
self.firststart = 0
global domain_x, domain_z
domain_x = 500
domain_z = 200
self.view.create_domain(domain_x, domain_z)
global nb_x, nb_z #, k_matrix, value_matrix
nb_x = 30
nb_z = 20
self.view.discretize_domain(nb_x + 1 , nb_z)
self.set_scene(self.view)
def on_key_d(self):
selectedItems = Self.scene
def set_scene(self,view):
self.view.setParent(None)
self.vbox.addWidget(view)
#############################################################################################################
############################################## Mr Main ######################################################
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
main_win = Window()
main_win.show()
sys.exit(app.exec_())
To answer my own question, here is the way I solved it:
def mousePressEvent(self, event):
modifiers = QtGui.QApplication.keyboardModifiers()
if modifiers == QtCore.Qt.ControlModifier:
...
Do_this()
do that()
...
else:
super(View, self).mousePressEvent(event)
super() allows you to import the original parent method. So you can redefine the event only if a condition is satisfied (in my case ctrl is pressed) and use the inherited method otherwise.
Cheers
\Romain

Related Links

UICollectionView Tap Selects More Than One Cell
Should this be selection or projection
Deselecting cells programmatically in NSMatrix does not work
Sublime Text 2 multiple selection at boundaries of selection (Mac OS X)
How should Stochastic Universal Sampling be combined with Elitism in Genetic Programming?
Sencha Chart 2.0 - Multiple Selection
Why Rangy library doesn't work with contenteditable in Opera?
Function inside selection condition in relational algebra
What is the fastest way of selecting an photoshop object (layer)?
tournament selection
SpreadsheetApp.getActiveSheet().getActiveSelection() broken
CSS multiple class selection
Retrieve point of selection in Eclipse GEF
Strange behavior of Property.valueChangeListener of Select UI / Vaadin 6.7.3
(ABAP) How to know whether initial screen (selection-screen) is filled or not
Aptana Studio 3.0.6 block mode select broken

Categories

HOME
artificial-intelligence
user-interface
yaml
antd
hdfs
initialization
jersey-2.0
cypher
biztalk-2010
jint
firebase-database
pyresttest
getopenfilename
live-streaming
bundler
dhcp
complexity-theory
google-tasks-api
pygobject
android-5.1.1-lollipop
uima
web-deployment
fosuserbundle
maven-plugin
string-formatting
spam
multiple-tables
cmake-gui
azure-machine-learning
tableview
el
kamailio
liferay-6.2
acl
uri
crud
hevc
network-analysis
ccavenue
macromedia
bonita
cube
instructions
commonsware-cwac
actframework
bootstrap-sass
creation
autoencoder
redgate
elastica
slideshow
plane
angular-datatables
fluid-mac-app-engine
spooler
jqgrid-asp.net
liteide
wysihtml5
section508
image-registration
dymola
bpms
haraka
nvda
zynq
between
urbit
flask-security
pack
odesk
msgpack
cfwheels
green-threads
tkx
uno
flurry-analytics
windows-rt
webmethod
csslint
ivalueconverter
django-settings
iirf
notifyjs
sly-scroller
monocross
exponent
quartz-core
differentiation
motodev-studio
azure-acs
fragment-identifier
qcar-sdk
dip
tessellation
icicles
aspbutton
firephp
wmd-editor
icon-language
activex-exe
code-camp
error-detection

Resources

Database Users
RDBMS discuss
Database Dev&Adm
javascript
java
csharp
php
android
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App