【问题标题】:How to select a region with QRubberBand on a QLabel like in KSnapshot?如何在 KSnapshot 中的 QLabel 上选择带有 QRubberBand 的区域?
【发布时间】:2016-03-17 04:10:10
【问题描述】:

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

是否可以使用 QLabel 有效地做到这一点?我希望橡皮筋留在屏幕上,它仍然可以调整。在这种情况下,我必须使用 QGraphicsScene 吗?

想要的效果: http://gfycat.com/SkinnyObeseAquaticleech

这是我目前所拥有的

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_())

【问题讨论】:

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


    【解决方案1】:

    您的方法已经很远了,我认为使用 QLabel 可以实现您想要的。我扩展了您的示例,以便即使在释放鼠标后,橡皮筋仍会留在屏幕上,并且您可以拖动它的左上角和右下角。

    您可以进一步扩展它以拖动其他角和边,并在中间显示一个大小为标签的标签。

    在图片中,您可以看到选择在没有按下鼠标的情况下保持不变。

    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_()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-31
      • 1970-01-01
      • 1970-01-01
      • 2013-07-01
      • 2021-03-09
      • 2012-08-23
      • 1970-01-01
      相关资源
      最近更新 更多