首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用QLabel绘制从QLabel到PyQt的直线

用QLabel绘制从QLabel到PyQt的直线
EN

Stack Overflow用户
提问于 2022-01-31 16:54:55
回答 1查看 313关注 0票数 0

我对PyQt相当陌生,我正试图从1 QLabel画一条线到另一条。

我的2 QLabel位于另一个QLabel上,它在我的图形用户界面中充当图像。

我已经成功地跟踪了鼠标事件并移动了标签,但是我不能使用QPainter在它们之间划定界限。

(预先谢谢:)

这是我的MouseTracking课程

代码语言:javascript
复制
class MouseTracker(QtCore.QObject):
    positionChanged = QtCore.pyqtSignal(QtCore.QPoint)

    def __init__(self, widget):
        super().__init__(widget)
        self._widget = widget
        self.widget.setMouseTracking(True)
        self.widget.installEventFilter(self)

    @property
    def widget(self):
        return self._widget

    def eventFilter(self, o, e):
        if e.type() == QtCore.QEvent.MouseMove:
            self.positionChanged.emit(e.pos())
        return super().eventFilter(o, e)

这是我的DraggableLabel课程:

代码语言:javascript
复制
class DraggableLabel(QLabel):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.LabelIsMoving = False
        self.setStyleSheet("border-color: rgb(238, 0, 0); border-width : 2.0px; border-style:inset; background: transparent;")
        self.origin = None
        # self.setDragEnabled(True)

    def mousePressEvent(self, event):
        if not self.origin:
            # update the origin point, we'll need that later
            self.origin = self.pos()
        if event.button() == Qt.LeftButton:
            self.LabelIsMoving = True
            self.mousePos = event.pos()
            # print(event.pos())

    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            # move the box
            self.move(self.pos() + event.pos() - self.mousePos)

            # print(event.pos())

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            print(event.pos())

    def paintEvent(self, event):
        painter = QPainter()
        painter.setBrush(Qt.red)
        # painter.setPen(qRgb(200,0,0))
        painter.drawLine(10, 10, 200, 200)

这是我为QTabwigdet定制的类(因为每当用户添加/插入一个新选项卡时,我都需要控制和跟踪2 QLabels的位置)

代码语言:javascript
复制
class DynamicTab(QWidget):

    def __init__(self):
        super(DynamicTab, self).__init__()
        # self.count = 0
        self.setMouseTracking(True)
        self.setAcceptDrops(True)
        self.bool = True
        self.layout = QVBoxLayout(self)
        self.label = QLabel()
        self.layout.addChildWidget(self.label)

        self.icon1 = DraggableLabel(parent=self)
        #pixmap for icon 1
        pixmap = QPixmap('icon1.png')
        # currentTab.setLayout(QVBoxLayout())
        # currentTab.layout.setWidget(QRadioButton())
        self.icon1.setPixmap(pixmap)
        self.icon1.setScaledContents(True)
        self.icon1.setFixedSize(20, 20)

        self.icon2 = DraggableLabel(parent=self)
        pixmap = QPixmap('icon1.png')
        # currentTab.setLayout(QVBoxLayout())
        # currentTab.layout.setWidget(QRadioButton())
        self.icon2.setPixmap(pixmap)
        self.icon2.setScaledContents(True)
        self.icon2.setFixedSize(20, 20)
            #self.label.move(event.x() - self.label_pos.x(), event.y() - self.label_pos.y())

MainWindow和主要方法:

代码语言:javascript
复制
class UI_MainWindow(QMainWindow):

    def __init__(self):
        super(UI_MainWindow, self).__init__()
        self.setWindowTitle("QHBoxLayout")
        self.PictureTab = QTabWidget

    def __setupUI__(self):
        # super(UI_MainWindow, self).__init__()
        self.setWindowTitle("QHBoxLayout")
        loadUi("IIML_test2.ui", self)
        self.tabChanged(self.PictureTab)
        # self.tabChanged(self.tabWidget)
        self.changeTabText(self.PictureTab, index=0, TabText="Patient1")
        self.Button_ImportNew.clicked.connect(lambda: self.insertTab(self.PictureTab))
        # self.PictureTab.currentChanged.connect(lambda: self.tabChanged(QtabWidget=self.PictureTab))
        # self.tabWidget.currentChanged.connect(lambda: self.tabChanged(QtabWidget=self.tabWidget))

    def tabChanged(self, QtabWidget):
        QtabWidget.currentChanged.connect(lambda : print("Tab was changed to ", QtabWidget.currentIndex()))

    def changeTabText(self, QTabWidget, index, TabText):
        QTabWidget.setTabText(index, TabText)

    def insertTab(self, QtabWidget):
        # QFileDialog.getOpenFileNames(self, 'Open File', '.')
        QtabWidget.addTab(DynamicTab(), "New Tab")
        # get number of active tab
        count = QtabWidget.count()
        # change the view to the last added tab
        currentTab = QtabWidget.widget(count-1)
        QtabWidget.setCurrentWidget(currentTab)

        pixmap = QPixmap('cat.jpg')
        #currentTab.setLayout(QVBoxLayout())
        #currentTab.layout.setWidget(QRadioButton())

        # currentTab.setImage("cat.jpg")
        currentTab.label.setPixmap(pixmap)
        currentTab.label.setScaledContents(True)
        currentTab.label.setFixedSize(self.label.width(), self.label.height())
        tracker = MouseTracker(currentTab.label)
        tracker.positionChanged.connect(self.on_positionChanged)
        self.label_position = QtWidgets.QLabel(currentTab.label, alignment=QtCore.Qt.AlignCenter)
        self.label_position.setStyleSheet('background-color: white; border: 1px solid black')
        currentTab.label.show()
        # print(currentTab.label)

    @QtCore.pyqtSlot(QtCore.QPoint)
    def on_positionChanged(self, pos):
        delta = QtCore.QPoint(30, -15)
        self.label_position.show()
        self.label_position.move(pos + delta)
        self.label_position.setText("(%d, %d)" % (pos.x(), pos.y()))
        self.label_position.adjustSize()

    # def SetupUI(self, MainWindow):
    #
    #     self.setLayout(self.MainLayout)


    if __name__ == '__main__':
        app = QApplication(sys.argv)
        UI_MainWindow = UI_MainWindow()
        UI_MainWindow.__setupUI__()
        widget = QtWidgets.QStackedWidget()
        widget.addWidget(UI_MainWindow)
        widget.setFixedHeight(900)
        widget.setFixedWidth(1173)
        widget.show()
        try:
            sys.exit(app.exec_())
        except:
            print("Exiting")

My的概念:,我有一个DynamicTab (QTabWidget),它充当一个图片打开器(每当用户按Import )。这个Widget的子标签是3个Q标签: self.label是它自己的图片,另外两个Q标签是icon1和icon2,我正在尝试与它们交互/拖动(拖放标签)

我的问题:,我正试图跟踪我的鼠标移动,并定制相应的画家绘画。当我抓起标签并用鼠标移动它时,我就让画家类画出来(因此,是可拖动的)。但是,当我没有按住或点击我的左键时,我只能跟踪主QLabel (主图片)中的鼠标位置。如有任何帮助,我们将不胜感激。谢谢你们。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-02 10:11:34

绘制只能在小部件矩形内进行,因此不能在DraggableLabel的边界之外绘制。

解决方案是创建另一个共享同一个父部件的自定义小部件,然后画出连接另外两个父部件中心的线。

在下面的示例中,我在两个可拖放的标签上安装了一个事件筛选器,它将根据它们更新自定义小部件的大小(因此它的几何结构总是包含这两个几何图形),并调用self.update()来计划重新绘制。请注意,由于小部件是在其他两个部件之上创建的,因此它可能捕获为其他小部件设置的鼠标事件;为了防止这一点,必须设置Qt.WA_TransparentForMouseEvents属性。

代码语言:javascript
复制
class Line(QWidget):
    def __init__(self, obj1, obj2, parent):
        super().__init__(parent)
        self.obj1 = obj1
        self.obj2 = obj2

        self.obj1.installEventFilter(self)
        self.obj2.installEventFilter(self)

        self.setAttribute(Qt.WA_TransparentForMouseEvents)

    def eventFilter(self, obj, event):
        if event.type() in (event.Move, event.Resize):
            rect = self.obj1.geometry() | self.obj2.geometry()
            corner = rect.bottomRight()
            self.resize(corner.x(), corner.y())
            self.update()
        return super().eventFilter(obj, event)

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(painter.Antialiasing)
        painter.setPen(QColor(200, 0, 0))
        painter.drawLine(
            self.obj1.geometry().center(), 
            self.obj2.geometry().center()
        )


class DynamicTab(QWidget):
    def __init__(self):
        # ...
        self.line = Line(self.icon1, self.icon2, self)

备注:

为了简化事情,我只使用了conversion;

  • the (而不是setGeometry()),这样小部件总是放在父部件的左上角,我们可以直接得到另一个小部件的坐标,而不需要将它放在其他两个小部件之上,因为它是在它们之后添加的;如果您想将它放在它们下面,使用self.line.lower();画家必须始终使用画板设备参数初始化,否则不会发生画图(输出中会有很多错误);

  • 不使用layout.addChildWidget() (布局在内部使用),但是布局的适当addWidget()函数;

H 120样式表边框语法可以用insertTab的第一行缩短:currentTab = DynamicTab() QtabWidget.addTab(currentTab, "New Tab");

  • currentTab.label.setFixedSize(self.label.size())

  • QMainWindow通常用作顶级小部件,通常不鼓励将其添加到QStackedWidget中;请注意,如果您这样做是因为Youtube教程,则该教程以建议糟糕的实践(如最后的

  • /除块)而闻名,后者应该是 not 类,而常量应该是大写的名称,而不是以小写字母开头的变量和函数;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70929790

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档