2015-06-01 2 views
0

Я пытаюсь написать приложение, которое работает как MS Paint или другой простой графический редактор. Моя цель - обеспечить такую ​​функциональность, как: различные инструменты (чертежные линии, рисунки и т. Д.), Возможность изменять цвета, ширину, размер и отмену/повторную функцию. Я думал, что самый простой способ сделать это - создать классы separete для рисования и просмотра объектов. К несчастью, он работает неправильно. Вот мой код:Добавление инструментов в приложение Scribble с PYQT4

import sys 
from PyQt4 import QtGui, QtCore 

class Example(QtGui.QWidget):  
    def __init__(self): 
     super(Example, self).__init__() 
     self.update() 

     self.view = View(self) 
     self.action = Action(self.view.scene) 

     self.UI() 

    def UI(self): 
     self.setGeometry(300,300,300,300) 

     self.setWindowTitle('Pen styles') 
     self.undo = QtGui.QPushButton("undo", self) 
     self.undo.clicked.connect(self.action.undoStack.undo) 
     self.redo = QtGui.QPushButton("redo", self) 
     self.redo.clicked.connect(self.action.undoStack.redo) 
     self.redo.move(0,50) 
     self.tool = QtGui.QPushButton("tool", self) 
     self.tool.setCheckable(True) 
     self.tool.clicked[bool].connect(self.new) 
     self.tool.move(0,100) 

     layout = QtGui.QVBoxLayout() 
     layout.addWidget(self.view) 
     self.setLayout(layout) 

     self.show() 

    def new(self):  
     pass 


class Action(QtGui.QGraphicsScene):  
    def __init__(self, scene):  
     QtGui.QGraphicsScene.__init__(self) 

     self.undoStack = QtGui.QUndoStack(self) 

     self.scene = scene 
     self.scene.addLine(0,0,150,150) 

     self.undoStack = QtGui.QUndoStack(self) 

    def mousePressEvent(self, event): 
     if event.button() == QtCore.Qt.LeftButton: 
      self.start = event.pos() 
      self.scene.addLine(0,0,150,250) 

    def mouseReleaseEvent(self, event): 
     start = QtCore.QPointF(self.mapToScene(self.start)) 
     end = QtCore.QPointF(self.mapToScene(event.pos())) 
     self.drawing(start, end) 

    def drawing(self, start, end): 
     self.line = QtGui.QGraphicsLineItem(QtCore.QLineF(start, end)) 
     self.line.setPen(QtGui.QPen(QtCore.Qt.blue,3, 
       QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)) 

     self.scene.addLine(0,0,150,300) 
     command = Draw(self.line, self.scene) 
     self.undoStack.push(command) 


class Draw(QtGui.QUndoCommand): 
    def __init__(self, line, scene): 
     QtGui.QUndoCommand.__init__(self) 

     self.line = line 
     self.scene = scene 

    def redo(self): 
     self.scene.addItem(self.line) 

    def undo(self): 
     self.scene.removeItem(self.line) 


class View(QtGui.QGraphicsView):  
    def __init__(self, parent):  
     QtGui.QGraphicsView.__init__(self, parent)  

     self.scene = QtGui.QGraphicsScene() 
     self.action = Action(self.scene) 
     self.setScene(self.scene) 
     self.setSceneRect(QtCore.QRectF(self.viewport().rect())) 


def main(): 
    app = QtGui.QApplication(sys.argv) 
    ex = Example() 

    sys.exit(app.exec_()) 


if __name__ == '__main__': 
    main() 

Моя проблема в том, что я не могу ничего рисовать с помощью мыши. Если класс Action и View объединены, все работает нормально, но когда я их убираю, ничего не происходит (ошибки тоже нет). Причина, по которой я сделал это разделение, состоит в том, что я просто хочу добавить другие классы с другими функциями (рисовать elipses, rects ...) и поменять их на Action class. Я добавил строку на сцену (в действии init) и ее раскрашивают по-разному, но MouseEvents не работают вообще. Кнопка «tool» была сделана для изменения инструмента рисования.

Этот способ, на мой взгляд, является наилучшим способом получить возможность рисовать различными инструментами на одном и том же холсте (сцена). Мой способ не подходит, поэтому я прошу помощи. Что я могу исправить этот код, поэтому он работает так, как я хочу? Где ошибки? или, может быть, весь подход ошибочен, и это нужно сделать другим путем? Я использую PYQT 4 и Python 3.4.

ответ

0

Ваш текущий код имеет два экземпляра QGraphicsScene, созданный внутри View.__init__. Один из них - стандарт QGraphicsScene, а другой - ваш подкласс Action. Но ваше мнение может быть привязано только к одной сцене, поэтому один из них избыточен и не работает правильно. Вы привязали его к QGraphicsScene, поэтому объект Action не работает.

Вместо этого вы должны убить пустую расточку QGraphicsScene и только создать экземпляр класса Action. Используйте экземпляр объекта Action в вызове view.setScene(). Аналогично, в классе Action нет необходимости проходить в другой сцене. Просто используйте себя (так что замените все экземпляры self.scene на self в классе Action)

+0

Спасибо за ваш совет. Я сделал то, что вы написали, и теперь я могу рисовать с помощью мыши, но функция отмены/повтора отключена ... Как я могу ее вернуть? Также у меня есть другой вопрос: как я могу добавить другие инструменты (прямоугольники, круги, элипсы и т. Д.), Чтобы я мог просто нажимать кнопку и быть в состоянии использовать их на текущей сцене (без потери объектов, которые уже есть)? Я пробовал разные апробации, и никто из них не работал (я думал, что могу просто поменять класс Action с помощью свойств инструмента). Я просто начал изучать python и программирование в целом, так что, возможно, я не понимаю то, что очевидно. – Boman

+0

@Boman этих вопросов следует задавать как новые вопросы о SO. Это становится слишком запутанным. –