如何在QSabel上选择具有QRubberBand的区域,如KSnapshot?

时间:2015-12-11 09:37:45

标签: drag-and-drop pyqt qgraphicsview qpainter qlabel

我正在用PyQt编写一个截图实用程序,其想法是截取整个桌面,然后将其显示在QLabel中,使窗口全屏显示,用户通过鼠标选择一个区域。

是否可以使用QLabel高效地完成此操作?我希望橡皮筋留在屏幕上,它仍然可以调整。在这种情况下,我是否必须使用QGraphicsScene?

期望效果: http://gfycat.com/SkinnyObeseAquaticleech

enter image description here

这是我到目前为止所拥有的

import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import Qt, QPoint, QRect, QSize
from PyQt4.QtGui import QPixmap, QApplication, QLabel, QRubberBand


class MyLabel(QLabel):

    def __init__(self, parent=None):

        QLabel.__init__(self, parent)
        self.rubberBand = QRubberBand(QRubberBand.Rectangle, self)
        self.origin = QPoint()

    def mousePressEvent(self, event):

        if event.button() == Qt.LeftButton:

            self.origin = QPoint(event.pos())
            self.rubberBand.setGeometry(QRect(self.origin, QSize()))
            self.rubberBand.show()

    def mouseMoveEvent(self, event):

        if not self.origin.isNull():
            self.rubberBand.setGeometry(
                QRect(self.origin, event.pos()).normalized())

    def mouseReleaseEvent(self, event):

        if event.button() == Qt.LeftButton:
            self.rubberBand.hide()


class mainUI(QtGui.QWidget):

    def __init__(self):
        super(mainUI, self).__init__()
        self.initUI()

    def initUI(self):

        layout = QtGui.QVBoxLayout(self)

        label = MyLabel(self)
        pixmap = QPixmap.grabWindow(app.desktop().winId())
        label.setPixmap(pixmap)
        layout.addWidget(label)

        self.setLayout(layout)

        geometry = app.desktop().availableGeometry()

        self.setFixedSize(geometry.width(), geometry.height())

        # self.setWindowFlags( self.windowFlags() | Qt.FramelessWindowHint)
        self.show()


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)

    window = mainUI()

    sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:3)

你的方法已经相当远了,我认为用QLabel实现你想要的东西是可能的。我扩展了你的例子,即使释放鼠标后橡皮筋也会停留在屏幕上,你可以拖动它的左上角和右下角。

您可以进一步扩展它以拖动其他角落和侧面并显示大小在中间的标签。

在图片中,您可以看到没有按下鼠标的选择。 enter image description here

from PyQt4 import QtGui, QtCore

class RubberbandEnhancedLabel(QtGui.QLabel):

    def __init__(self, parent=None):
        QtGui.QLabel.__init__(self, parent)
        self.selection = QtGui.QRubberBand(QtGui.QRubberBand.Rectangle, self)

    def mousePressEvent(self, event):
        '''
            Mouse is pressed. If selection is visible either set dragging mode (if close to border) or hide selection.
            If selection is not visible make it visible and start at this point.
        '''

        if event.button() == QtCore.Qt.LeftButton:

            position = QtCore.QPoint(event.pos())
            if self.selection.isVisible():
                # visible selection
                if (self.upper_left - position).manhattanLength() < 20:
                    # close to upper left corner, drag it
                    self.mode = "drag_upper_left"
                elif (self.lower_right - position).manhattanLength() < 20:
                    # close to lower right corner, drag it
                    self.mode = "drag_lower_right"
                else:
                    # clicked somewhere else, hide selection
                    self.selection.hide()
            else:
                # no visible selection, start new selection
                self.upper_left = position
                self.lower_right = position
                self.mode = "drag_lower_right"
                self.selection.show()

    def mouseMoveEvent(self, event):
        '''
            Mouse moved. If selection is visible, drag it according to drag mode.
        '''
        if self.selection.isVisible():
            # visible selection
            if self.mode is "drag_lower_right":
                self.lower_right = QtCore.QPoint(event.pos())
            elif self.mode is "drag_upper_left":
                self.upper_left = QtCore.QPoint(event.pos())
            # update geometry
            self.selection.setGeometry(QtCore.QRect(self.upper_left, self.lower_right).normalized())

app = QtGui.QApplication([])

screen_pixmap = QtGui.QPixmap.grabWindow(app.desktop().winId())

window = QtGui.QWidget()
layout = QtGui.QVBoxLayout(window)
label = RubberbandEnhancedLabel()
label.setPixmap(screen_pixmap)
layout.addWidget(label)
geometry = app.desktop().availableGeometry()
window.setFixedSize(geometry.width(), geometry.height())
window.show()
app.exec_()