2013-06-30 2 views
2

사용자가 QGraphicsScene에서 다각형 중에서 항목을 선택할 수있게 해주는 프로그램을 작성 중입니다.두 개의 다른 선택 도구가 pyside에 공존합니다.

PySide는 편리한 고무 밴드 선택 도구를 제공하지만 장면에 다각형을 그려 항목을 선택할 수 있기를 원했습니다. 이를 구현하기 위해 mousePressEvent와 같은 마우스 이벤트를 다시 정의해야했습니다. 이 작품은 훌륭합니다! ... 물론 고무 밴드와 개체를 클릭하기 만하면 해당 개체를 선택할 수 없습니다.

자, 내가하고 싶은 것은 그 도구들 사이를 전환 할 수 있다는 것입니다. 사용자가 컨텍스트에 따라 컨텍스트 중 하나를 사용하도록하거나 (Ctrl 키 수정자를 사용하여) 하나를 선택하도록합니다.

달성 방법에 대한 아이디어가 누구에게 있습니까? 모든 팁에 정말 감사 할 것입니다.

감사 /로맹 여기

은 그리 최소한의 작업 내가 무슨 짓을했는지의 예를 제공 :

#!/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_()) 

답변

2

내 자신의 질문에 대답하기를, 여기에 내가 그것을 해결 방법은 다음과 같습니다

def mousePressEvent(self, event): 
    modifiers = QtGui.QApplication.keyboardModifiers() 
    if modifiers == QtCore.Qt.ControlModifier: 

     ... 
     Do_this() 
     do that() 
     ... 

    else: 
     super(View, self).mousePressEvent(event) 

super()를 사용하면 원래 상위 메소드를 가져올 수 있습니다. 따라서 조건이 만족 될 경우에만 이벤트를 재정의 할 수 있습니다 (내 경우 Ctrl 키를 누른 상태에서). 그렇지 않은 경우 상속 된 메서드를 사용하십시오.

건배 로맹

\