繁体   English   中英

PyQt5-在QMainMenu中,如何(暂时)使QWidget成为父级?

[英]PyQt5 - in a QMainMenu, how to make a QWidget the parent (temporarily)?

我有一个使用QWidget初始化的QMainWindow 我希望每次我在QMainWiindow按下New按钮时,它将临时打开QWidget (就我而言,直到释放鼠标按钮)。

我在将QMainWindowQWidget交互时遇到麻烦。 我尝试了很多选项,但似乎所有尝试将QWidget绑定到QMainWindow屏幕的操作,我都不想这样做。

一个例子会更容易:

TempWidgetMenu.py是我的QMainWindow类。 当我按下New ,将出现一个QWidget ,它将为屏幕着色灰色,并为从按钮按下到按钮释放之间的矩形着色(就像在Windows截图工具中一样)。

我希望每次我按New ,都可以从屏幕的每个点绘制一个矩形,所以它是第一次。 当我第二次(或之后)按“ New ”时,它将为除主菜单屏幕之外的所有内容着色,并且将不响应按钮操作。

我希望小部件在每次按下按钮时都成为屏幕上程序的“父级”。

TempWidgetMenu.py (主要):

import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QAction
from PyQt5.QtGui import QPixmap, QPainter
import TempWidget


class Menu(QMainWindow):

    def __init__(self):
        super().__init__()
        newAct = QAction('New', self)
        newAct.triggered.connect(self.new_image_window)
        self.toolbar = self.addToolBar('Exit')
        self.toolbar.addAction(newAct)
        self.opac_rect = TempWidget.TempOpacWidget()
        self.image = QPixmap("background.png")
        self.setGeometry(100, 100, 500, 300)
        self.resize(self.image.width(), self.image.height())
        self.show()

    def new_image_window(self):
        self.opac_rect.start()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.drawPixmap(self.rect(), self.image)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainMenu = Menu()
    sys.exit(app.exec_())

TempWidget.py

import tkinter as tk
from PyQt5 import QtWidgets, QtCore, QtGui


class TempOpacWidget(QtWidgets.QWidget):

    def __init__(self):
        super().__init__()
        root = tk.Tk()
        screen_width = root.winfo_screenwidth()
        screen_height = root.winfo_screenheight()
        self.setGeometry(0, 0, screen_width, screen_height)
        self.setWindowTitle(' ')
        self.begin = QtCore.QPoint()
        self.end = QtCore.QPoint()
        self.busy = False

    def start(self):

        self.busy = True
        self.setWindowOpacity(0.3)
        self.show()

    def paintEvent(self, event):
        if self.busy:
            brush_color = (128, 128, 255, 100)
            opacity = 0.3
        else:
            brush_color = (0, 0, 0, 0)
            opacity = 0

        self.setWindowOpacity(opacity)
        qp = QtGui.QPainter(self)
        qp.setBrush(QtGui.QColor(*brush_color))
        qp.drawRect(QtCore.QRectF(self.begin, self.end))

    def mousePressEvent(self, event):
        self.begin = event.pos()
        self.end = self.begin
        self.update()

    def mouseMoveEvent(self, event):
        self.end = event.pos()
        self.update()

    def mouseReleaseEvent(self, event):
        self.busy = False
        self.repaint()

我意识到我一开始就初始化了TempOpacWidget 我只想初始化一次,因为它在做同样的事情。

我该如何解决它,以便每次我给他打电话时, TempOpacWidget都将成为父项?

编辑:如果不清楚,请运行代码,这将是非常合理的。 按“ New ,选择一个矩形(使用鼠标),然后再次按“ New以选择另一个矩形,您将了解问题所在。

我不太了解会发生什么,但是我添加并更改了一些代码行。 单击New按钮,然后绘制一个矩形。 您应该有新想法。 祝好运。

TempWidgetMenu.py

import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QAction
from PyQt5.QtGui     import QPixmap, QPainter
from PyQt5.QtCore    import Qt                             # +++
import TempWidget

class Menu(QMainWindow):
    def __init__(self):
        super().__init__()
        newAct = QAction('New', self)
        newAct.triggered.connect(self.new_image_window)
        self.toolbar = self.addToolBar('Exit')
        self.toolbar.addAction(newAct)

        self.opac_rect = TempWidget.TempOpacWidget(self)   # +++ self

        self.imageShow()                                   # +++  

    def imageShow(self):
        self.setWindowFlags(Qt.WindowStaysOnTopHint)       # +++ 

        self.image = QPixmap("background.png")
        self.setGeometry(100, 100, 500, 300)
        self.resize(self.image.width(), self.image.height())
        self.show()

    def new_image_window(self):
        self.opac_rect.start()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.drawPixmap(self.rect(), self.image)

    # +++    
    def closeEvent(self, event):
        self.opac_rect.close()
        event.accept()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainMenu = Menu()
    sys.exit(app.exec_())

TempWidget.py

import tkinter as tk
from PyQt5        import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import Qt                                 # +++

class TempOpacWidget(QtWidgets.QWidget):

#    def __init__(self):
#        super().__init__()
    def __init__(self, parent=None):
        super(TempOpacWidget, self).__init__()              # no (parent)
        self.parent = parent                                # +++
        print("self=`{}`, \nparent=`{}`".format(self, self.parent))
        self.setWindowFlags(Qt.WindowStaysOnTopHint)        # +++

        root = tk.Tk()
        screen_width  = root.winfo_screenwidth()
        screen_height = root.winfo_screenheight()
        self.setGeometry(0, 0, screen_width, screen_height)
#        self.setWindowTitle('')
        self.begin = QtCore.QPoint()
        self.end   = QtCore.QPoint()
        self.busy  = False

    def start(self):
        self.setWindowFlags(Qt.WindowStaysOnTopHint)        # +++
        self.busy = True
        self.setWindowOpacity(0.5) # 0.3
        self.show()

    def paintEvent(self, event):
        if self.busy:
            brush_color = (128, 128, 255, 100)
            opacity = 0.5          # 0.3
        else:
            brush_color = (0, 0, 0, 0)

            opacity = 0.5          # 0       <<<---------
            # or try  `0`, how suits you !?  <<<---------
            #opacity = 0                    #<<<--------- 

        self.setWindowOpacity(opacity)
        qp = QtGui.QPainter(self)
        qp.setBrush(QtGui.QColor(*brush_color))
        qp.drawRect(QtCore.QRectF(self.begin, self.end))

    def mousePressEvent(self, event):
        #self.parent.hide()
        self.begin = event.pos()
        self.end   = self.begin
        self.update()

    def mouseMoveEvent(self, event):
        self.end = event.pos()
        self.update()

    def mouseReleaseEvent(self, event):
        print("def mouseReleaseEvent(self, event):---")
        self.busy = False
        self.repaint()
        self.parent.imageShow()                         # +++

在此处输入图片说明

如果我理解正确,则希望Menu.opac_rect在按下鼠标按钮时在单独的窗口中打开。 我看到与此有关的几个问题。 首先,如果要在单独的窗口中打开QWidget ,则应将Qt.windowFlags参数传递给QWidget构造函数,即

self.opac_rect = TempWidget.TempOpacWidget(None, QtCore.Qt.Window)

不要忘记导入QtCore命名空间。

其次, QAction没有您需要的信号。 仅继承自QWidget对象将具有mousePressEventmouseReleaseEvent 如果必须将其保留在工具栏中,则QToolBar具有QToolBar.addWidget ,因此可以使用QLabel而不是QAction ,并覆盖必要的事件处理程序。

self.opac_rect = TempWidget.TempOpacWidget(None, QtCore.Qt.Window)
newAct = QLabel('New')
newAct.mousePressEvent = lambda e: self.opac_rect.start()
newAct.mouseReleaseEvent = lambda e: self.opac_rect.stop() # You'll need to write this
self.toolbar.addWidget(newAct)

您可能必须摆弄QLabel样式以使其看起来正确,但是我认为这将实现您想要的功能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM