PyQt5截图工具完成截图后残留矩形框问题求助
Got it, let's tackle that annoying leftover rectangle issue in your snipping tool! The root problem is simple: after you finish a snip, your SnippingWidget doesn't reset the selection coordinates (start_point and end_point). So when you activate snipping again, the old coordinates are still there, and the paintEvent draws the previous rectangle.
Here are two clean ways to fix this:
Option 1: Reset Coordinates When Showing the Widget (Recommended)
Add a showEvent method to your SnippingWidget class. This ensures every time you open the snipping tool, it starts with a blank slate—no matter how you exited last time.
Update your SnippingWidget code like this:
class SnippingWidget(QtWidgets.QMainWindow): closed = QtCore.pyqtSignal() def __init__(self, parent=None): super(SnippingWidget, self).__init__(parent) self.setAttribute(QtCore.Qt.WA_NoSystemBackground, True) self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True) self.setStyleSheet("background:transparent;") self.setWindowFlags(QtCore.Qt.FramelessWindowHint) self.outsideSquareColor = "red" self.squareThickness = 2 self.start_point = QtCore.QPoint() self.end_point = QtCore.QPoint() def showEvent(self, event): # Reset selection points and trigger a repaint to clear old drawings self.start_point = QtCore.QPoint() self.end_point = QtCore.QPoint() self.update() super().showEvent(event) # Keep your existing mousePressEvent, mouseMoveEvent, mouseReleaseEvent, paintEvent methods here
Option 2: Reset Coordinates After Snip + Handle ESC Cancel
If you want extra control (like letting users cancel with ESC and clearing the rectangle immediately), add a keyPressEvent and reset coordinates in mouseReleaseEvent:
class SnippingWidget(QtWidgets.QMainWindow): closed = QtCore.pyqtSignal() def __init__(self, parent=None): # ... your existing __init__ code ... def mouseReleaseEvent(self, QMouseEvent): r = QtCore.QRect(self.start_point, self.end_point).normalized() self.hide() img = ImageGrab.grab(bbox=r.getCoords()) img.save("snips/testImage.png") QApplication.restoreOverrideCursor() # Reset points after capturing the snip self.start_point = QtCore.QPoint() self.end_point = QtCore.QPoint() self.closed.emit() def keyPressEvent(self, event): if event.key() == QtCore.Qt.Key_Escape: # Reset points and clear the rectangle if user cancels with ESC self.start_point = QtCore.QPoint() self.end_point = QtCore.QPoint() self.update() self.hide() QApplication.restoreOverrideCursor() self.closed.emit() # Keep your other existing methods here
Either approach will eliminate the lingering rectangle. Option 1 is more robust because it guarantees a fresh state every time you activate snipping, while Option 2 adds a nice cancel feature for users.
内容的提问来源于stack exchange,提问作者Brett La Pierre

