PYTHON3+PYQT5 customization and interaction of graphic items--implementing page designer Application

Source: Internet
Author: User
Tags wrapper

This paper uses PYTHON3+PYQT5 to implement the page designer application of the Python Qt Gui fast program, using Qgraphicsview,qgraphicsscene,qgraphicsitem, This program contains multiple pages of text, pictures and boxes. Some graphics classes are obsolete in PyQt5, so this code changes a lot. The changes to the main class or method are as follows:
Qmatrix==>qtransform
Setmatrix==>settransform
Rotate ==> setrotation
In this case, the Wheelevent method is overridden because Event.delta () is obsolete:

    def wheelevent (self, event):
        #factor = 1.41 * * (-event.delta ()/240.0) 
        #factor = 1.41 * * (-abs (EVENT.STARTX ()-eve NT.Y ())/240.0)
        factor = Event.angledelta (). Y ()/120.0
        if Event.angledelta (). Y ()/120.0 > 0:
            factor=2
        else:
            factor=0.5
        Self.scale (factor, factor)

To keep the code readable, add a class:

Class Graphicspixmapitem (Qgraphicspixmapitem):        #add by Yangrongdong
    def __init__ (self,pixmap):
        Super (Qgraphicspixmapitem, self). __init__ (Pixmap)

In this case there is also a button that contains a menu:

            if text = = "&align":
                menu = Qmenu (self) for
                text, Arg in (
                        ("Align &left", Qt.alignleft),
                        ("Align &right ", Qt.alignright),
                        (" Align &top ", Qt.aligntop),
                        (" Align &bottom ", Qt.alignbottom)):
                    Wrapper = Functools.partial (Self.setalignment, Arg)
                    self.wrapped.append (wrapper)
                    menu.addaction (text, Wrapper)
                Button.setmenu (menu)

In this case, the qstyleoptiongraphicsitem.levelofdetail is also obsolete and is rewritten as follows:
Option.levelofdetailfromtransform (Self.transform ())
The following is the complete code:

#!/usr/bin/env python3 Import functools import random import sys from pyqt5.qtcore import (Qbytearray, Qdatastream, Qfil  E, Qfileinfo, Qiodevice, Qpoint, qpointf, QRECTF, Qt) from pyqt5.qtwidgets import (Qapplication, Qdialog, Qdialogbuttonbox, Qfiledialog, Qfontcombobox, qgraphic
                             Sitem, Qgraphicspixmapitem, Qgraphicsscene, Qgraphicstextitem, Qgraphicsview, Qgridlayout, Qhboxlayout, Qlabel, Qmenu, Qmessagebox,qpushbutton, Qspinbox, QSt YLE, Qtextedit, qvboxlayout) from Pyqt5.qtgui import Qfont,qcursor,qfontmetrics,qtransform,qpainter,qpen,qpixmap from Pyqt5.qtprintsupport import Qprinter,qprintdialog MAC = True try:from Pyqt5.qtgui import Qt_mac_set_native_menubar E Xcept Importerror:mac = False #PageSize = (595, 842) # A4 in points PageSize = (612, 792) # US letter in points Poin Tsize = MagicNumber = 0x70616765 FileVersion = 1 Dirty = False class Textitemdlg (qdialog): Def __init__ (self, item=none, Position=none, SC Ene=none, Parent=none): Super (Qdialog, self). __init__ (parent) Self.item = Item Self.position = PO
        Sition self.scene = Scene self.editor = Qtextedit () self.editor.setAcceptRichText (False)
        Self.editor.setTabChangesFocus (True) Editorlabel = Qlabel ("&text:") Editorlabel.setbuddy (Self.editor) Self.fontcombobox = Qfontcombobox () Self.fontComboBox.setCurrentFont (Qfont ("Times", pointsize)) fo
        Ntlabel = Qlabel ("&font:") Fontlabel.setbuddy (self.fontcombobox) Self.fontspinbox = Qspinbox () Self.fontSpinBox.setAlignment (qt.alignright| Qt.alignvcenter) Self.fontSpinBox.setRange (6, 280) Self.fontSpinBox.setValue (pointsize) Fontsizela Bel = Qlabel ("&size:") Fontsizelabel.setbuddy (self.fontspinbox) Self.buttonbox =Qdialogbuttonbox (qdialogbuttonbox.ok|  Qdialogbuttonbox.cancel) Self.buttonBox.button (Qdialogbuttonbox.ok). setenabled (False) if Self.item is not None:self.editor.setPlainText (Self.item.toPlainText ()) Self.fontComboBox.setCurrentFont (self.ite M.font ()) Self.fontSpinBox.setValue (Self.item.font (). pointsize ()) layout = Qgridlayout () layo Ut.addwidget (editorlabel, 0, 0) layout.addwidget (self.editor, 1, 0, 1, 6) layout.addwidget (Fontlabel, 2, 0 ) Layout.addwidget (Self.fontcombobox, 2, 1, 1, 2) layout.addwidget (Fontsizelabel, 2, 3) Layout.add


        Widget (Self.fontspinbox, 2, 4, 1, 2) layout.addwidget (Self.buttonbox, 3, 0, 1, 6) self.setlayout (layout) Self.fontComboBox.currentFontChanged.connect (Self.updateui) self.fontSpinBox.valueChanged.connect (self.up
   Dateui) Self.editor.textChanged.connect (Self.updateui)     Self.buttonBox.accepted.connect (self.accept) self.buttonBox.rejected.connect (self.reject) Self.setwi Ndowtitle ("Page Designer-{0} Text Item". Format ("Add" if Self.item is None else "Edit") self.up Dateui () def updateui (self): Font = Self.fontComboBox.currentFont () font.setpointsize (self.fontspinb Ox.value ()) self.editor.document (). Setdefaultfont (font) Self.buttonBox.button (Qdialogbuttonbox.ok). Setenab LED (BOOL (Self.editor.toPlainText ())) def accept (self): if Self.item is None:se Lf.item = Textitem ("", Self.position, self.scene) font = Self.fontComboBox.currentFont () font.setpointsize   
        (Self.fontSpinBox.value ()) Self.item.setFont (font) self.item.setPlainText (Self.editor.toPlainText ()) Self.item.update () global Dirty Dirty = True qdialog.accept (self) class Textitem (Qgraphics Textitem): Def __iniT__ (self, text, position, scene, Font=qfont ("Times", Pointsize), Matrix=qtransform ()): Super (text
                      Item, self). __init__ (text) self.setflags (qgraphicsitem.itemisselectable|
        qgraphicsitem.itemismovable) Self.setfont (font) self.setpos (position) self.settransform (matrix)  Scene.clearselection () Scene.additem (self) self.setselected (True) Global Dirty Dirty
        = True def parentwidget (self): return Self.scene (). Views () [0] def itemchange (self, Change, variant): If change!= QGraphicsItem.ItemSelectedChange:global Dirty Dirty = True return QG Raphicstextitem.itemchange (self, change, variant) def mousedoubleclickevent (Self, event): Dialog = Textitemd LG (self, Self.parentwidget ()) dialog.exec_ () class Graphicspixmapitem (Qgraphicspixmapitem): #add by Yang
   Rongdong def __init__ (self,pixmap):     Super (Qgraphicspixmapitem, self). __init__ (Pixmap) class Boxitem (Qgraphicsitem): Def __init__ (self, position, s
        Cene, Style=qt.solidline, Rect=none, Matrix=qtransform ()): Super (Boxitem, self). __init__ ()
                      Self.setflags (qgraphicsitem.itemisselectable|
                      qgraphicsitem.itemismovable| qgraphicsitem.itemisfocusable) If rect is None:rect = QRECTF ( -10 * pointsize,-pointsize, * PointS ize, 2 * pointsize) Self.rect = rect Self.style = Style Self.setpos (posi tion) self.settransform (matrix) scene.clearselection () Scene.additem (self) self.setselecte D (True) Self.setfocus () global Dirty Dirty = True def parentwidget (self): return sel F.scene (). Views () [0] def boundingrect (self): return self.rect.adjusted ( -2,-2, 2, 2) def paint (self, p
Ainter, option, widget):        Pen = Qpen (Self.style) pen.setcolor (Qt.black) pen.setwidth (1) if Option.state & Qstyle . State_Selected:pen.setColor (qt.blue) painter.setpen (pen) painter.drawrect (Self.rect) de
            F ItemChange (self, Change, variant): If change!= QGraphicsItem.ItemSelectedChange:global Dirty Dirty = True return Qgraphicsitem.itemchange (self, change, variant) def contextmenuevent (self, event) : wrapped = [] menu = Qmenu (Self.parentwidget ()) for text, param in (("&solid
                ", Qt.solidline), (" &dashed ", Qt.dashline), (" d&otted ", Qt.dotline), ("d&ashdotted", Qt.dashdotline), ("dashdo&tdotted", Qt.dashdotdotline)): wrapper =
        Functools.partial (Self.setstyle, param) wrapped.append (wrapper) menu.addaction (text, wrapper) MENU.EXEC_ (Event.scReenpos ()) def setStyle (self, style): Self.style = Style self.update () global Dirty Dirty = True def keypressevent (Self, event): Factor = POINTSIZE/4 changed = False if event . Modifiers () & Qt.ShiftModifier:if event.key () = = Qt.Key_Left:self.rect.setRight (self.re Ct.right ()-factor) changed = True elif Event.key () = = Qt.Key_Right:self.rec
                T.setright (Self.rect.right () + factor) changed = True elif Event.key () = = Qt.key_up: Self.rect.setBottom (Self.rect.bottom ()-factor) changed = True elif event.key () = Qt. Key_Down:self.rect.setBottom (Self.rect.bottom () + factor) changed = True if Chang Ed:self.update () global Dirty Dirty = True else:QGraphicsItem.ke Ypressevent (self, event)


Class Graphicsview (Qgraphicsview): Def __init__ (self, Parent=none): Super (Graphicsview, self). __init__ (Par ENT) Self.setdragmode (Qgraphicsview.rubberbanddrag) self.setrenderhint (qpainter.antialiasing) Self . Setrenderhint (qpainter.textantialiasing) def wheelevent (Self, event): #factor = 1.41 * * (-event.delta ()/2
        40.0) factor = Event.angledelta (). Y ()/120.0 if Event.angledelta (). Y ()/120.0 > 0:factor=2  else:factor=0.5 Self.scale (factor, Factor) class MainForm (Qdialog): Def __init__ (self, Parent=none): Super (MainForm, self). __init__ (parent) Self.filename = "" Self.copieditem = Qbytea 

        Rray () Self.pasteoffset = 5 Self.prevpoint = Qpoint () Self.addoffset = 5 Self.borders = [] Self.printer = Qprinter (qprinter.highresolution) self.printer.setPageSize (qprinter.letter) Self
 . View = Graphicsview ()       Self.scene = Qgraphicsscene (self) self.scene.setSceneRect (0, 0, pagesize[0], pagesize[1]) self.addb Orders () Self.view.setScene (self.scene) self.wrapped = [] # Needed to keep wrappers (alive) buttonl Ayout = Qvboxlayout () for text, slot in (("Add &text", Self.addtext), ("Add & Amp
                Box ", Self.addbox), (" Add pi&xmap ", Self.addpixmap), (" &align ", None),
                ("&copy", Self.copy), ("C&ut", Self.cut), ("&paste", Self.paste), ("&delete ...", Self.delete), ("&rotate", Self.rotate), ("Pri&nt ..."), Self.print_), ("&open ...", Self.open), ("&save", Self.save), ("&am P Quit ", self.accept)): Button = Qpushbutton (text) if not MAC:button.setFocusPolicy
     (Qt.nofocus)       If slot is not None:button.clicked.connect (slot) if text = "&align":
                        menu = Qmenu (self) for text, Arg in (("Align &left", Qt.alignleft),
                        ("Align &right", Qt.alignright), ("Align &top", Qt.aligntop), ("Align &bottom", Qt.alignbottom)): wrapper = Functools.partial (Self.setalignment, ARG) self.wrapped.append (wrapper) menu.addaction (text, wrapper) BU Tton.setmenu (menu) if text = = "Pri&nt ...": Buttonlayout.addstretch (5) if text = = "&quit": Buttonlayout.addstretch (1) Buttonlayout.addwidget (button) buttonlayout . Addstretch () layout = Qhboxlayout () layout.addwidget (Self.view, 1) layout.addlayout (buttonlayout ) self.setlayout(layout) fm = Qfontmetrics (Self.font ()) Self.resize (Self.scene.width () + fm.width ("Delete ...) ") + self.scene.height () +) Self.setwindowtitle (" Page Designer ") def addborders (s ELF): Self.borders = [] rect = QRECTF (0, 0, pagesize[0], pagesize[1]) self.borders.append (self.sce
                Ne.addrect (Rect, qt.yellow)) margin = 5.25 * pointsize self.borders.append (Self.scene.addRect ( rect.adjusted (margin, margin,-margin,-margin), Qt.yellow)) def removeborders (self): W


    Hile self.borders:item = Self.borders.pop () Self.scene.removeItem (item) del item


    Def reject (self): self.accept () def accept (self): Self.offersave () qdialog.accept (self) def offersave (self): if (Dirty and qmessagebox.question (self, page designer-uns
                    Aved Changes ",        "Save unsaved changes?", qmessagebox.yes| qmessagebox.no) = = Qmessagebox.yes): Self.save () def position (self): point = Self.ma Pfromglobal (Qcursor.pos ()) if not Self.view.geometry (). Contains (point): Coord = Random.randint (36, 144 Point = Qpoint (coord, coord) else:if point = = Self.prevPoint:point = Qpoint (Self.addoffset, self.addoffset) Self.addoffset = 5 ELSE:SELF.ADDOFFSE t = 5 Self.prevpoint = point return Self.view.mapToScene (point) def addtext (self): D Ialog = Textitemdlg (Position=self.position (), Scene=self.scene, parent=self) dialog.e Xec_ () def addbox (self): Boxitem (Self.position (), Self.scene) def addpixmap (self): path = (qfi
 Leinfo (self.filename). Path () if self.filename else "."       Fname,filetype = Qfiledialog.getopenfilename (self, page designer-add pixmap, Path, "Pixmap Files (*.bmp *.jpg *.png *.xpm)") If not Fname:return Self.createpixmapitem (QPIXM AP (fname), Self.position ()) def createpixmapitem (self, pixmap, position, Matrix=qtransform ()): item = Graphi
                      Cspixmapitem (pixmap) item.setflags (qgraphicsitem.itemisselectable| qgraphicsitem.itemismovable) Item.setpos (position) item.settransform (matrix) Self.scene.clearSelec tion () Self.scene.addItem (item) item.setselected (True) global Dirty Dirty = True r
            Eturn Item def selecteditem (self): items = Self.scene.selectedItems () If len (items) = 1:
            Return items[0] Return to none def copy (self): item = Self.selecteditem () If Item is None:
Return Self.copiedItem.clear ()        Self.pasteoffset = 5 stream = Qdatastream (Self.copieditem, qiodevice.writeonly) self.writeitemtost
        Ream (Stream, item) def cut (self): item = Self.selecteditem () The If item is None:return Self.copy () Self.scene.removeItem (item) del item def paste (self): if self.copiedItem.is Empty (): Return stream = Qdatastream (Self.copieditem, qiodevice.readonly) self.readitemfromstr EAM (Stream, Self.pasteoffset) Self.pasteoffset + + 5 def setalignment (self, Alignment): # Items are R
        Eturned in arbitrary order items = Self.scene.selectedItems () If Len (items) <= 1:return
            # Gather coordinate data leftxs, Rightxs, topys, Bottomys = [], [], [], [] for item in items: Rect = Item.sceneboundingrect () leftxs.append (Rect.x ()) Rightxs.append (Rect.x () + rect.width ()) Topys.apPend (Rect.y ()) Bottomys.append (Rect.y () + rect.height ()) # perform alignment if alignment = = Q T.alignleft:xalig

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.