Python Qt: Interactive Re-Sizable QGraphicsItem, mouse hover area not resizing -


i trying build python class around qgraphicsrectitem (pyside or pyqt4) provides mouse interaction through hover-overs, movable, , re-sizable. have pretty working except:

for reason, seems if mouse hover area not changing when item re-sized or moved. need solving issue.

maybe problem caused inverting y axis on qgraphicsview:

qgraphicsview.scale(1,-1) 

qgraphicsrectitem class:

class boxresizable(qtgui.qgraphicsrectitem):     def __init__(self, rect, parent = none, scene = none):         qtgui.qgraphicsrectitem.__init__(self, rect, parent, scene)          self.setzvalue(1000)         self._rect = rect         self._scene = scene         self.mouseover = false         self.resizehandlesize = 4.0          self.mousepresspos = none         self.mousemovepos = none         self.mouseispressed = false          self.setflags(qtgui.qgraphicsitem.itemisselectable|qtgui.qgraphicsitem.itemisfocusable)         self.setacceptshoverevents(true)          self.updateresizehandles()      def hoverenterevent(self, event):         self.updateresizehandles()         self.mouseover = true         self.preparegeometrychange()      def hoverleaveevent(self, event):         self.mouseover = false         self.preparegeometrychange()      def hovermoveevent(self, event):          if self.topleft.contains(event.scenepos()) or self.bottomright.contains(event.scenepos()):             self.setcursor(qtcore.qt.sizefdiagcursor)         elif self.topright.contains(event.scenepos()) or self.bottomleft.contains(event.scenepos()):             self.setcursor(qtcore.qt.sizebdiagcursor)         else:             self.setcursor(qtcore.qt.sizeallcursor)          qtgui.qgraphicsrectitem.hovermoveevent(self, event)      def mousepressevent(self, event):         """         capture mouse press events , find mosue pressed on object         """         self.mousepresspos = event.scenepos()         self.mouseispressed = true         self.rectpress = copy.deepcopy(self._rect)          # top left corner         if self.topleft.contains(event.scenepos()):             self.mousepressarea = 'topleft'         # top right corner                     elif self.topright.contains(event.scenepos()):             self.mousepressarea = 'topright'         #  bottom left corner                     elif self.bottomleft.contains(event.scenepos()):             self.mousepressarea = 'bottomleft'         # bottom right corner                     elif self.bottomright.contains(event.scenepos()):             self.mousepressarea = 'bottomright'         # entire rectangle         else:             self.mousepressarea = none          qtgui.qgraphicsrectitem.mousepressevent(self, event)      def mousereleaseevent(self, event):         """         capture nmouse press events.         """         self.mouseispressed = false          self.updateresizehandles()         self.preparegeometrychange()          qtgui.qgraphicsrectitem.mousereleaseevent(self, event)      def mousemoveevent(self, event):         """         handle mouse move events.         """         self.mousemovepos = event.scenepos()          if self.mouseispressed:             # move top left corner             if self.mousepressarea=='topleft':                 self._rect.settopleft(self.rectpress.topleft()-(self.mousepresspos-self.mousemovepos))             # move top right corner                         elif  self.mousepressarea=='topright':                 self._rect.settopright(self.rectpress.topright()-(self.mousepresspos-self.mousemovepos))             # move bottom left corner                         elif  self.mousepressarea=='bottomleft':                 self._rect.setbottomleft(self.rectpress.bottomleft()-(self.mousepresspos-self.mousemovepos))             # move bottom right corner                         elif  self.mousepressarea=='bottomright':                 self._rect.setbottomright(self.rectpress.bottomright()-(self.mousepresspos-self.mousemovepos))             # move entire rectangle, don't resize             else:                 self._rect.movecenter(self.rectpress.center()-(self.mousepresspos-self.mousemovepos))              self.updateresizehandles()             self.preparegeometrychange()          qtgui.qgraphicsrectitem.mousepressevent(self, event)      def boundingrect(self):         """         return bounding rectangle         """         return self._boundingrect      def updateresizehandles(self):         """         update bounding rectangle , resize handles         """         self.offset = self.resizehandlesize*(self._scene.graphicsview.maptoscene(1,0)-self._scene.graphicsview.maptoscene(0,1)).x()                  self._boundingrect = self._rect.adjusted(-self.offset, self.offset, self.offset, -self.offset)          # note: draws correctly on view inverted y axes. i.e. qgraphicsview.scale(1,-1)         self.topleft = qtcore.qrectf(self._boundingrect.topleft().x(), self._boundingrect.topleft().y() - 2*self.offset,                                      2*self.offset, 2*self.offset)         self.topright = qtcore.qrectf(self._boundingrect.topright().x() - 2*self.offset, self._boundingrect.topright().y() - 2*self.offset,                                      2*self.offset, 2*self.offset)         self.bottomleft = qtcore.qrectf(self._boundingrect.bottomleft().x(), self._boundingrect.bottomleft().y(),                                      2*self.offset, 2*self.offset)         self.bottomright = qtcore.qrectf(self._boundingrect.bottomright().x() - 2*self.offset, self._boundingrect.bottomright().y(),                                      2*self.offset, 2*self.offset)      def paint(self, painter, option, widget):         """         paint widget         """          # show boundingrect debug purposes         painter.setpen(qtgui.qpen(qtcore.qt.red, 0, qtcore.qt.dashline))         painter.drawrect(self._boundingrect)          # paint rectangle         painter.setpen(qtgui.qpen(qtcore.qt.black, 0, qtcore.qt.solidline))         painter.drawrect(self._rect)          # if mouse over, draw handles         if self.mouseover:             # if rect selected, fill in handles             if self.isselected():                 painter.setbrush(qtgui.qbrush(qtgui.qcolor(0,0,0)))             painter.drawrect(self.topleft)             painter.drawrect(self.topright)             painter.drawrect(self.bottomleft)             painter.drawrect(self.bottomright) 

rest of code functioning example:

class graphicsscene(qtgui.qgraphicsscene):     def __init__ (self, parent = none):         qtgui.qgraphicsscene.__init__(self, parent)     def setgraphicsview(self, view):         self.graphicsview = view  app = qtgui.qapplication(sys.argv) app.setstyle('gtk') mainwindow = qtgui.qmainwindow()  scene = graphicsscene() scene.setscenerect(-100,-100, 200, 200)  # set view properties view = qtgui.qgraphicsview() view.setscene(scene) view.scale(1,-1) view.setrenderhint(qtgui.qpainter.antialiasing) view.setviewportupdatemode(qtgui.qgraphicsview.boundingrectviewportupdate)  view.sethorizontalscrollbarpolicy ( qtcore.qt.scrollbaralwaysoff ) view.setverticalscrollbarpolicy ( qtcore.qt.scrollbaralwaysoff ) view.setupdatesenabled(true) view.setmousetracking(true)  view.setcachemode(qtgui.qgraphicsview.cachebackground)  view.settransformationanchor(qtgui.qgraphicsview.anchorundermouse)  scene.setgraphicsview(view)  # add box boxresizable(qtcore.qrectf(-50, 50, 100.0, -100.0), parent = none, scene = scene)  mainwindow.setcentralwidget(view) mainwindow.show()  app.exec_()  app.deletelater() sys.exit() 

adding above class qgraphicsscene , subsequent inverted y axis qgraphicsview produce this:

enter image description here

any or suggestions appreciated! thanks!

found part of problem: if over-ride shape function (add function class) with:

    def shape(self):         path = qtgui.qpainterpath()         path.addrect(self.boundingrect())         return path 

the hover area changes size , position box sometimes. acoording docs qgraphicsitem.shape():

the default implementation calls boundingrect() return simple rectangular shape...

is bug in pyqt4?

second problem: think boundingrect , shape rectangle need have positive widths , heights? done adding:

self._rect = self._rect.normalized() 

to mousereleaseevent function.


Comments

Popular posts from this blog

c# - How to get the current UAC mode -

postgresql - Lazarus + Postgres: incomplete startup packet -

javascript - Ajax jqXHR.status==0 fix error -