python - update()后如何保存以前的矩形?

标签 python python-2.7 pyqt pyqt4

a1 a2

用户可以通过在灰色图片上单击两次来通过此应用程序绘制矩形。但是这个应用程序不保存最后的矩形,而是保存其绘制(更新)一个新的矩形 2 个下一个点。我该如何解决这个问题?我怎样才能保存以前的矩形?

class myQLabel(QLabel):
    def __init__(self,parent):
        super(myQLabel, self).__init__(parent)
        self.x = 0
        self.y = 0
        self.trafficlines = []

    def mousePressEvent(self, QMouseEvent):
        #print mode
        self.x = QMouseEvent.x()
        self.y = QMouseEvent.y()
        if self.x != 0 and self.y != 0:
            self.trafficlines.append(copy.deepcopy([self.x,self.y]))
        print "______"
        print self.x
        print self.y
        print "("+str(mode)+")"
        print "______"

    def paintEvent(self, QPaintEvent):
        super(myQLabel, self).paintEvent(QPaintEvent)
        painter = QPainter(self)
        if mode == 0:
            painter.setPen(QPen(Qt.red,3))
        elif mode == 1:
            painter.setPen(QPen(Qt.blue,3))
        elif mode == 2:
            painter.setPen(QPen(Qt.green,3))
        elif mode == 3:
            painter.setPen(QPen(Qt.magenta,3))
        if len(self.trafficlines)%2==1 and len(self.trafficlines)>0:
            painter.drawPoint(self.trafficlines[-1][0],self.trafficlines[-1][1])
        if len(self.trafficlines)%2==0 and len(self.trafficlines)>0 and mode!=0:
            painter.drawLine( self.trafficlines[-2][0],self.trafficlines[-2][1],self.trafficlines[-1][0],self.trafficlines[-1][1] )
        if len(self.trafficlines)%2==0 and len(self.trafficlines)>0 and mode==0:
            x1=self.trafficlines[-2][0]
            y1=self.trafficlines[-2][1]
            x2=self.trafficlines[-1][0]
            y2=self.trafficlines[-1][1]
            painter.drawLine( x1,y1,x1,y2)
            painter.drawLine( x1,y2,x2,y2)
            painter.drawLine( x2,y2,x2,y1)
            painter.drawLine( x2,y1,x1,y1)



        self.update()

这是全部代码:

from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys, os
import copy

mode = 5

class Example(QWidget):

    def __init__(self,parent):
        super(Example, self).__init__()
        self.main_image_name="C:\Python27\project\main_image.png"

        self.initUI()

    def initUI(self):
        File_name = QLabel('Setup file name')
        File_name_edit = QLineEdit()
        QToolTip.setFont(QFont('SansSerif', 10))
        #QMainWindow.statusBar().showMessage('Ready')
        self.setGeometry(300, 300, 250, 150)
        self.resize(640, 360)
        #self.setFixedSize(640, 360)
        self.center()
        self.main_image = myQLabel(self)
        self.main_image.setPixmap(QPixmap(self.main_image_name))
        btn = QPushButton("Make setup file")
        btn.setToolTip('Press <b>Detect</b> button for detecting objects by your settings')
        btn.resize(btn.sizeHint())
        btn.clicked.connect(QCoreApplication.instance().quit)
        btn_browse = QPushButton("Browse")
        btn_browse.clicked.connect(self.browse)
        btn_set = QPushButton("Set name")
        #fullscreen
        #self.main_image.setScaledContents(True)
        #just centered
        self.main_image.setAlignment(Qt.AlignCenter)



        #Layout
        box_File_name = QHBoxLayout()
        box_File_name.addWidget(File_name)
        box_File_name.addWidget(File_name_edit)
        box_File_name.addWidget(btn_set)
        grid = QGridLayout()
        grid.setSpacing(10)
        grid.addLayout(box_File_name, 1, 0)
        #grid.addWidget(File_name_edit, 1, 1)
        grid.addWidget(self.main_image, 2, 0)
        grid.addWidget(btn_browse, 3 , 0)
        grid.addWidget(btn, 4, 0)

        box_number = QVBoxLayout()
        number_group=QButtonGroup() # Number group
        r0=QRadioButton("Traffic Lights")
        number_group.addButton(r0)
        r1=QRadioButton("Direction")
        number_group.addButton(r1)
        r2=QRadioButton("Traffic Lines H")
        number_group.addButton(r2)
        r3=QRadioButton("Traffic Lines V")
        number_group.addButton(r3)
        box_number.addWidget(r0)
        box_number.addWidget(r1)
        box_number.addWidget(r2)
        box_number.addWidget(r3)

        r0.toggled.connect(self.radio0_clicked)
        r1.toggled.connect(self.radio1_clicked)
        r2.toggled.connect(self.radio2_clicked)
        r3.toggled.connect(self.radio3_clicked)

        box_road_sign = QHBoxLayout()
        road_sign_label = QLabel('Road signs', self)
        road_sign = QComboBox()
        road_sign.addItem("None")
        road_sign.addItem("ex1")
        road_sign.addItem("ex2")
        road_sign.addItem("ex3")
        road_sign.addItem("ex4")
        road_sign.addItem("ex5")
        box_road_sign.addWidget(road_sign_label)
        box_road_sign.addWidget(road_sign)
        grid.addLayout(box_road_sign, 1, 1)
        grid.addLayout(box_number, 2, 1)
        self.setLayout(grid)

        self.show()
    def browse(self):
        w = QWidget()
        w.resize(320, 240)
        w.setWindowTitle("Select Picture")
        filename = QFileDialog.getOpenFileName(w, 'Open File', '/')
        self.main_image_name = filename
        self.main_image.setPixmap(QPixmap(self.main_image_name))

    def center(self):

        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())


    def radio0_clicked(self, enabled):
        if enabled:
            print("0")
            global mode
            mode=0

    def radio1_clicked(self, enabled):
        if enabled:
            print("1")
            global mode
            mode=1

    def radio2_clicked(self, enabled):
        if enabled:
            print("2")
            global mode
            mode=2

    def radio3_clicked(self, enabled):
        if enabled:
            print("3")
            global mode
            mode=3


class myQLabel(QLabel):
    def __init__(self,parent):
        super(myQLabel, self).__init__(parent)
        self.x = 0
        self.y = 0
        self.trafficlines = []

    def mousePressEvent(self, QMouseEvent):
        #print mode
        self.x = QMouseEvent.x()
        self.y = QMouseEvent.y()
        if self.x != 0 and self.y != 0:
            self.trafficlines.append(copy.deepcopy([self.x,self.y]))
        print "______"
        print self.x
        print self.y
        print "("+str(mode)+")"
        print "______"

    def paintEvent(self, QPaintEvent):
        super(myQLabel, self).paintEvent(QPaintEvent)
        painter = QPainter(self)
        if mode == 0:
            painter.setPen(QPen(Qt.red,3))
        elif mode == 1:
            painter.setPen(QPen(Qt.blue,3))
        elif mode == 2:
            painter.setPen(QPen(Qt.green,3))
        elif mode == 3:
            painter.setPen(QPen(Qt.magenta,3))
        if len(self.trafficlines)%2==1 and len(self.trafficlines)>0:
            painter.drawPoint(self.trafficlines[-1][0],self.trafficlines[-1][1])
        if len(self.trafficlines)%2==0 and len(self.trafficlines)>0 and mode!=0:
            painter.drawLine( self.trafficlines[-2][0],self.trafficlines[-2][1],self.trafficlines[-1][0],self.trafficlines[-1][1] )
        if len(self.trafficlines)%2==0 and len(self.trafficlines)>0 and mode==0:
            x1=self.trafficlines[-2][0]
            y1=self.trafficlines[-2][1]
            x2=self.trafficlines[-1][0]
            y2=self.trafficlines[-1][1]
            painter.drawLine( x1,y1,x1,y2)
            painter.drawLine( x1,y2,x2,y2)
            painter.drawLine( x2,y2,x2,y1)
            painter.drawLine( x2,y1,x1,y1)



        self.update()

class menubarex(QMainWindow):
    def __init__(self, parent=None):
        super(menubarex, self).__init__(parent)
        self.form_widget = Example(self)
        self.setCentralWidget(self.form_widget)

        self.initUI()

    def initUI(self):
        exitAction = QAction(QIcon('exit.png'), '&Exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit application')
        exitAction.triggered.connect(qApp.quit)
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(exitAction)

        #self.toolbar = self.addToolBar('Exit')
        #self.toolbar.addAction(exitAction)

        self.statusBar().showMessage('Ready')
        self.setWindowTitle('mi ban')
        self.setWindowIcon(QIcon('C:\Python27\project\icon.png'))

    def closeEvent(self, event):

        reply = QMessageBox.question(self, 'Message',
            "Are you sure to quit?", QMessageBox.Yes |
            QMessageBox.No)

        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

def main():
    app = QApplication(sys.argv)
    #ex = Example()
    menubar = menubarex()
    menubar.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

最佳答案

paintEvent() 重新绘制整个小部件,因此它不会节省先前绘制的内存,因此不会保存矩形或先前的线条。解决方案是存储这些状态并再次重新绘制所有内容,为此我们可以将模式和点存储在 trafficlines 中,如下所示:

class myQLabel(QLabel):
    def __init__(self,parent):
        super(myQLabel, self).__init__(parent)
        self.trafficlines = []
        self.mode = 0
        self.start_point = QPoint()

    def setMode(self, mode):
        self.mode = mode

    def mousePressEvent(self, event):
        if self.start_point.isNull():
            self.start_point = event.pos()
        else:
            self.trafficlines.append((self.mode,[self.start_point, event.pos()]))
            self.start_point = QPoint()
        self.update()

    def paintEvent(self, event):
        super(myQLabel, self).paintEvent(event)
        painter = QPainter(self)

        colors = [Qt.red, Qt.blue, Qt.green, Qt.magenta]

        for mode, points in self.trafficlines:
            painter.setPen(QPen(colors[mode],3))
            if mode != 0:
                painter.drawLine(*points)
            else:
                rect = QRect(*points)
                painter.drawRect(rect)

        if not self.start_point.isNull():
            painter.setPen(QPen(colors[self.mode],3))
            painter.drawPoint(self.start_point)
<小时/>

注意:不要使用全局变量,它们很难调试,而且会出现不必要的多次。

此外,我还冒昧地改进了您的代码,以更少的行数使其更具可读性。完整的代码如下:

import sys
import os

from PyQt4.QtGui import *
from PyQt4.QtCore import *

class Example(QWidget):

    def __init__(self,parent):
        super(Example, self).__init__()
        self.main_image_name="C:\Python27\project\main_image.png"
        self.initUI()

    def initUI(self):
        File_name = QLabel('Setup file name')
        File_name_edit = QLineEdit()
        self.resize(640, 360)
        self.center()
        self.main_image = myQLabel(self)
        self.main_image.setPixmap(QPixmap(self.main_image_name))
        btn = QPushButton("Make setup file")
        btn.setToolTip('Press <b>Detect</b> button for detecting objects by your settings')
        btn.resize(btn.sizeHint())
        btn.clicked.connect(QCoreApplication.instance().quit)
        btn_browse = QPushButton("Browse")
        btn_browse.clicked.connect(self.browse)
        btn_set = QPushButton("Set name")
        self.main_image.setAlignment(Qt.AlignCenter)

        #Layout
        box_File_name = QHBoxLayout()
        box_File_name.addWidget(File_name)
        box_File_name.addWidget(File_name_edit)
        box_File_name.addWidget(btn_set)
        grid = QGridLayout(self)
        grid.setSpacing(10)
        grid.addLayout(box_File_name, 1, 0)
        #grid.addWidget(File_name_edit, 1, 1)
        grid.addWidget(self.main_image, 2, 0)
        grid.addWidget(btn_browse, 3 , 0)
        grid.addWidget(btn, 4, 0)

        box_number = QVBoxLayout()
        number_group = QButtonGroup(self) # Number group

        for i, text in enumerate(["Traffic Lights", "Direction", "Traffic Lines H", "Traffic Lines V"]):
            rb = QRadioButton(text)
            box_number.addWidget(rb)
            number_group.addButton(rb, i)
        number_group.buttonClicked[int].connect(self.main_image.setMode)
        number_group.button(0).setChecked(True)

        box_road_sign = QHBoxLayout()
        road_sign_label = QLabel('Road signs', self)
        road_sign = QComboBox()
        road_sign.addItems(["None", "ex1", "ex2","ex3", "ex4", "ex5"])
        box_road_sign.addWidget(road_sign_label)
        box_road_sign.addWidget(road_sign)
        grid.addLayout(box_road_sign, 1, 1)
        grid.addLayout(box_number, 2, 1)

    def browse(self):
        filename = QFileDialog.getOpenFileName(self, 'Open File', '/')
        self.main_image_name = filename
        self.main_image.setPixmap(QPixmap(self.main_image_name))

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

class myQLabel(QLabel):
    def __init__(self,parent):
        super(myQLabel, self).__init__(parent)
        self.trafficlines = []
        self.mode = 0
        self.start_point = QPoint()

    def setMode(self, mode):
        self.mode = mode

    def mousePressEvent(self, event):
        if self.start_point.isNull():
            self.start_point = event.pos()
        else:
            self.trafficlines.append((self.mode,[self.start_point, event.pos()]))
            self.start_point = QPoint()
        self.update()

    def paintEvent(self, event):
        super(myQLabel, self).paintEvent(event)
        painter = QPainter(self)

        colors = [Qt.red, Qt.blue, Qt.green, Qt.magenta]

        for mode, points in self.trafficlines:
            painter.setPen(QPen(colors[mode],3))
            if mode != 0:
                painter.drawLine(*points)
            else:
                rect = QRect(*points)
                painter.drawRect(rect)

        if not self.start_point.isNull():
            painter.setPen(QPen(colors[self.mode],3))
            painter.drawPoint(self.start_point)


class menubarex(QMainWindow):
    def __init__(self, parent=None):
        super(menubarex, self).__init__(parent)
        self.form_widget = Example(self)
        self.setCentralWidget(self.form_widget)

        self.initUI()

    def initUI(self):
        exitAction = QAction(QIcon('exit.png'), '&Exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit application')
        exitAction.triggered.connect(qApp.quit)
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(exitAction)
        self.statusBar().showMessage('Ready')
        self.setWindowTitle('mi ban')
        self.setWindowIcon(QIcon('C:\Python27\project\icon.png'))

    def closeEvent(self, event):
        reply = QMessageBox.question(self, 'Message',
            "Are you sure to quit?", QMessageBox.Yes |
            QMessageBox.No)

        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

def main():
    app = QApplication(sys.argv)
    #ex = Example()
    menubar = menubarex()
    menubar.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

关于python - update()后如何保存以前的矩形?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49283580/

相关文章:

python - Zapier 操作代码 : Python will not run with input_data variable

python - 使用样式解包多行

python - PyQt:将 partial() 用于插槽时,moveToThread 不起作用

python - PyQt4 到 PyQt5 -> mainFrame() 已弃用,需要修复才能加载网页

python - 如果不卡住主线程,我怎么能等

python - 使用 python 将 xml 数据转储到 csv 文件中的单元格中

python - 带有喜欢和日期的 Pandas 查询功能

python - 从 mac 地址转换为十六进制字符串,反之亦然 - python 2 和 3

Python Import 即使在 __init__ 之后也找不到 packge

python - 在单独的线程中运行 pyQT GUI 主应用程序