qt - Painting using PYQT -
i trying implement program paint in pyqt. trying use code of scribble example in pyqt package can found in: c:\python26\lib\site-packages\pyqt4\examples\widgets. regarding have 2 questions:
- in scribble program, when painting, paint doesn't updated visually in real-time holding mouse button , scribbling. found out problem comes function drawlineto class scribblearea, line:
self.update(qtcore.qrect(self.lastpoint, endpoint).normalized().adjusted(-rad, -rad, +rad, +rad))
now if replace line
self.update()
the problem solved, cursor not in exact location paintin happens.
do know parameters can add in self.update() solves both problems?
- i want open image scribble , paint on , save paint blank lets white background (without original image in ground). can tell me how this?
i appreciate answer either of questions.
thanks!
just learning pyqt, modified code take care of cursor mismatch problem (and modified openimage method keep image size in sync window):
#!/usr/bin/env python ############################################################################# ## ## copyright (c) 2010 riverbank computing limited. ## copyright (c) 2010 nokia corporation and/or subsidiary(-ies). ## rights reserved. ## ## file part of examples of pyqt. ## ## $qt_begin_license:bsd$ ## may use file under terms of bsd license follows: ## ## "redistribution , use in source , binary forms, or without ## modification, permitted provided following conditions ## met: ## * redistributions of source code must retain above copyright ## notice, list of conditions , following disclaimer. ## * redistributions in binary form must reproduce above copyright ## notice, list of conditions , following disclaimer in ## documentation and/or other materials provided ## distribution. ## * neither name of nokia corporation , subsidiary(-ies) nor ## names of contributors may used endorse or promote ## products derived software without specific prior written ## permission. ## ## software provided copyright holders , contributors ## "as is" , express or implied warranties, including, not ## limited to, implied warranties of merchantability , fitness ## particular purpose disclaimed. in no event shall copyright ## owner or contributors liable direct, indirect, incidental, ## special, exemplary, or consequential damages (including, not ## limited to, procurement of substitute goods or services; loss of use, ## data, or profits; or business interruption) caused , on ## theory of liability, whether in contract, strict liability, or tort ## (including negligence or otherwise) arising in way out of use ## of software, if advised of possibility of such damage." ## $qt_end_license$ ## ############################################################################# # these needed python v2 harmless python v3. import sip sip.setapi('qstring', 2) sip.setapi('qvariant', 2) pyqt4 import qtcore, qtgui class scribblearea(qtgui.qwidget): """ scales image it's not good, many refreshes mess up!!! """ def __init__(self, parent=none): super(scribblearea, self).__init__(parent) self.setattribute(qtcore.qt.wa_staticcontents) self.modified = false self.scribbling = false self.mypenwidth = 1 self.mypencolor = qtcore.qt.blue imagesize = qtcore.qsize(500, 500) # self.image = qtgui.qimage() self.image = qtgui.qimage(imagesize, qtgui.qimage.format_rgb32) self.lastpoint = qtcore.qpoint() def openimage(self, filename): loadedimage = qtgui.qimage() if not loadedimage.load(filename): return false w = loadedimage.width() h = loadedimage.height() self.mainwindow.resize(w, h) # newsize = loadedimage.size().expandedto(self.size()) # self.resizeimage(loadedimage, newsize) self.image = loadedimage self.modified = false self.update() return true def saveimage(self, filename, fileformat): visibleimage = self.image self.resizeimage(visibleimage, self.size()) if visibleimage.save(filename, fileformat): self.modified = false return true else: return false def setpencolor(self, newcolor): self.mypencolor = newcolor def setpenwidth(self, newwidth): self.mypenwidth = newwidth def clearimage(self): self.image.fill(qtgui.qrgb(255, 255, 255)) self.modified = true self.update() def mousepressevent(self, event): # print "self.image.width() = %d" % self.image.width() # print "self.image.height() = %d" % self.image.height() # print "self.image.size() = %s" % self.image.size() # print "self.size() = %s" % self.size() # print "event.pos() = %s" % event.pos() if event.button() == qtcore.qt.leftbutton: self.lastpoint = event.pos() self.scribbling = true def mousemoveevent(self, event): if (event.buttons() & qtcore.qt.leftbutton) , self.scribbling: self.drawlineto(event.pos()) def mousereleaseevent(self, event): if event.button() == qtcore.qt.leftbutton , self.scribbling: self.drawlineto(event.pos()) self.scribbling = false def paintevent(self, event): painter = qtgui.qpainter(self) painter.drawimage(event.rect(), self.image) def resizeevent(self, event): # print "resize event" # print "event = %s" % event # print "event.oldsize() = %s" % event.oldsize() # print "event.size() = %s" % event.size() self.resizeimage(self.image, event.size()) # if self.width() > self.image.width() or self.height() > self.image.height(): # newwidth = max(self.width() + 128, self.image.width()) # newheight = max(self.height() + 128, self.image.height()) # print "newwidth = %d, newheight = %d" % (newwidth, newheight) # self.resizeimage(self.image, qtcore.qsize(newwidth, newheight)) # self.update() super(scribblearea, self).resizeevent(event) def drawlineto(self, endpoint): painter = qtgui.qpainter(self.image) painter.setpen(qtgui.qpen(self.mypencolor, self.mypenwidth, qtcore.qt.solidline, qtcore.qt.roundcap, qtcore.qt.roundjoin)) painter.drawline(self.lastpoint, endpoint) self.modified = true # rad = self.mypenwidth / 2 + 2 # self.update(qtcore.qrect(self.lastpoint, endpoint).normalized().adjusted(-rad, -rad, +rad, +rad)) self.update() self.lastpoint = qtcore.qpoint(endpoint) def resizeimage(self, image, newsize): if image.size() == newsize: return # print "image.size() = %s" % repr(image.size()) # print "newsize = %s" % newsize # resizes canvas without resampling image newimage = qtgui.qimage(newsize, qtgui.qimage.format_rgb32) newimage.fill(qtgui.qrgb(255, 255, 255)) painter = qtgui.qpainter(newimage) painter.drawimage(qtcore.qpoint(0, 0), image) ## resampled image gets messed many events... ## painter.setrenderhint(qtgui.qpainter.smoothpixmaptransform, true) ## painter.setrenderhint(qtgui.qpainter.highqualityantialiasing, true) # # newimage = qtgui.qimage(newsize, qtgui.qimage.format_rgb32) # newimage.fill(qtgui.qrgb(255, 255, 255)) # painter = qtgui.qpainter(newimage) # srcrect = qtcore.qrect(qtcore.qpoint(0,0), image.size()) # dstrect = qtcore.qrect(qtcore.qpoint(0,0), newsize) ## print "srcrect = %s" % srcrect ## print "dstrect = %s" % dstrect # painter.drawimage(dstrect, image, srcrect) self.image = newimage def print_(self): printer = qtgui.qprinter(qtgui.qprinter.highresolution) printdialog = qtgui.qprintdialog(printer, self) if printdialog.exec_() == qtgui.qdialog.accepted: painter = qtgui.qpainter(printer) rect = painter.viewport() size = self.image.size() size.scale(rect.size(), qtcore.qt.keepaspectratio) painter.setviewport(rect.x(), rect.y(), size.width(), size.height()) painter.setwindow(self.image.rect()) painter.drawimage(0, 0, self.image) painter.end() def ismodified(self): return self.modified def pencolor(self): return self.mypencolor def penwidth(self): return self.mypenwidth class mainwindow(qtgui.qmainwindow): def __init__(self): super(mainwindow, self).__init__() self.saveasacts = [] self.scribblearea = scribblearea(self) self.scribblearea.clearimage() self.scribblearea.mainwindow = self # maybe not using this? self.setcentralwidget(self.scribblearea) self.createactions() self.createmenus() self.setwindowtitle("scribble") self.resize(500, 500) def closeevent(self, event): if self.maybesave(): event.accept() else: event.ignore() def open(self): if self.maybesave(): filename = qtgui.qfiledialog.getopenfilename(self, "open file", qtcore.qdir.currentpath()) if filename: self.scribblearea.openimage(filename) def save(self): action = self.sender() fileformat = action.data() self.savefile(fileformat) def pencolor(self): newcolor = qtgui.qcolordialog.getcolor(self.scribblearea.pencolor()) if newcolor.isvalid(): self.scribblearea.setpencolor(newcolor) def penwidth(self): newwidth, ok = qtgui.qinputdialog.getinteger(self, "scribble", "select pen width:", self.scribblearea.penwidth(), 1, 50, 1) if ok: self.scribblearea.setpenwidth(newwidth) def about(self): qtgui.qmessagebox.about(self, "about scribble", "<p>the <b>scribble</b> example shows how use " "qmainwindow base widget application, , how " "to reimplement of qwidget's event handlers receive " "the events generated application's widgets:</p>" "<p> reimplement mouse event handlers facilitate " "drawing, paint event handler update application " "and resize event handler optimize application's " "appearance. in addition reimplement close event " "handler intercept close events before terminating " "the application.</p>" "<p> example demonstrates how use qpainter " "draw image in real time, repaint " "widgets.</p>") def createactions(self): self.openact = qtgui.qaction("&open...", self, shortcut="ctrl+o", triggered=self.open) format in qtgui.qimagewriter.supportedimageformats(): format = str(format) text = format.upper() + "..." action = qtgui.qaction(text, self, triggered=self.save) action.setdata(format) self.saveasacts.append(action) self.printact = qtgui.qaction("&print...", self, triggered=self.scribblearea.print_) self.exitact = qtgui.qaction("e&xit", self, shortcut="ctrl+q", triggered=self.close) self.pencoloract = qtgui.qaction("&pen color...", self, triggered=self.pencolor) self.penwidthact = qtgui.qaction("pen &width...", self, triggered=self.penwidth) self.clearscreenact = qtgui.qaction("&clear screen", self, shortcut="ctrl+l", triggered=self.scribblearea.clearimage) self.aboutact = qtgui.qaction("&about", self, triggered=self.about) self.aboutqtact = qtgui.qaction("about &qt", self, triggered=qtgui.qapp.aboutqt) def createmenus(self): self.saveasmenu = qtgui.qmenu("&save as", self) action in self.saveasacts: self.saveasmenu.addaction(action) filemenu = qtgui.qmenu("&file", self) filemenu.addaction(self.openact) filemenu.addmenu(self.saveasmenu) filemenu.addaction(self.printact) filemenu.addseparator() filemenu.addaction(self.exitact) optionmenu = qtgui.qmenu("&options", self) optionmenu.addaction(self.pencoloract) optionmenu.addaction(self.penwidthact) optionmenu.addseparator() optionmenu.addaction(self.clearscreenact) helpmenu = qtgui.qmenu("&help", self) helpmenu.addaction(self.aboutact) helpmenu.addaction(self.aboutqtact) self.menubar().addmenu(filemenu) self.menubar().addmenu(optionmenu) self.menubar().addmenu(helpmenu) def maybesave(self): if self.scribblearea.ismodified(): ret = qtgui.qmessagebox.warning(self, "scribble", "the image has been modified.\n" "do want save changes?", qtgui.qmessagebox.save | qtgui.qmessagebox.discard | qtgui.qmessagebox.cancel) if ret == qtgui.qmessagebox.save: return self.savefile('png') elif ret == qtgui.qmessagebox.cancel: return false return true def savefile(self, fileformat): initialpath = qtcore.qdir.currentpath() + '/untitled.' + fileformat filename = qtgui.qfiledialog.getsavefilename(self, "save as", initialpath, "%s files (*.%s);;all files (*)" % (fileformat.upper(), fileformat)) if filename: return self.scribblearea.saveimage(filename, fileformat) return false if __name__ == '__main__': import sys app = qtgui.qapplication(sys.argv) window = mainwindow() window.show() sys.exit(app.exec_())
Comments
Post a Comment