Python PyQt5-在QMainMenu中,如何使QWidget成为父项(临时)?

Python PyQt5-在QMainMenu中,如何使QWidget成为父项(临时)?,python,pyqt,pyqt5,qwidget,qmainwindow,Python,Pyqt,Pyqt5,Qwidget,Qmainwindow,我有一个QMainWindow,我用QWidget初始化它。我希望每次在我的QMainWiindow中按下按钮New,它都会临时打开QWidget(在我的情况下,直到松开鼠标按钮) 我与QWidget交互QMainWindow时遇到问题。我尝试了许多选项,但似乎我尝试的所有方法都将QWidget绑定到QMainWindow屏幕上,我不希望这样 举个例子会更容易: TempWidgetMenu.py是我的QMainWindow类。当我按下New时,会出现一个QWidget,它会将屏幕涂成灰色,并将

我有一个
QMainWindow
,我用
QWidget
初始化它。我希望每次在我的
QMainWiindow
中按下按钮
New
,它都会临时打开
QWidget
(在我的情况下,直到松开鼠标按钮)

我与
QWidget
交互
QMainWindow
时遇到问题。我尝试了许多选项,但似乎我尝试的所有方法都将
QWidget
绑定到
QMainWindow
屏幕上,我不希望这样

举个例子会更容易:

TempWidgetMenu.py
是我的
QMainWindow
类。当我按下
New
时,会出现一个
QWidget
,它会将屏幕涂成灰色,并将从按下按钮到释放按钮的矩形涂成灰色(就像在windows剪贴工具中一样)

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

我希望每次按下按钮时,小部件都是屏幕上程序的“父级”

TempWidgetMenu.py(主):

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
选择另一个矩形,您就会明白问题所在。

如果我理解正确,您希望在按下鼠标按钮时在单独的窗口中打开
菜单。opac\u rect
。我认为这有几个问题。首先,如果希望在单独的窗口中打开
QWidget
,则应将
Qt.windowFlags
参数传递给
QWidget
构造函数,即

self.opac_rect = TempWidget.TempOpacWidget(None, QtCore.Qt.Window)
不要忘记导入
QtCore
名称空间

其次,
QAction
没有您需要的信号。只有从
QWidget
继承的对象才会具有
mousePressEvent
mouseereleaseevent
。如果必须在工具栏中保留内容,
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
样式以使其看起来正确,但我认为这将实现您所寻找的功能。

我不太明白会发生什么, 但我添加并更改了一些代码行。 单击
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()                         # +++
将tkinter作为tk导入
从PyQt5导入QtWidgets、QtCore、QtGui
从PyQt5.QtCore导入Qt#+++
类TempOpacWidget(qtwidget.QWidget):
#定义初始化(自):
#super()。\uuuu init\uuuuu()
def uuu init uuu(self,parent=None):
super(TempOpacWidget,self)。uuu init_uuu()35; no(父级)
self.parent=parent#+++
打印(“self=`{}`,\nPart=`{}`.”格式(self,self.parent))
self.setWindowFlags(Qt.WindowStaysOnTopHint)#+++
root=tk.tk()
screen\u width=root.winfo\u screenwidth()
screen\u height=root.winfo\u screenheight()
self.setGeometry(0,0,屏幕宽度,屏幕高度)
#self.setWindowTitle(“”)
self.begin=QtCore.QPoint()
self.end=QtCore.QPoint()
self.busy=False
def启动(自):
self.setWindowFlags(Qt.WindowStaysOnTopHint)#+++
self.busy=True
self.setWindowOpacity(0.5)#0.3
self.show()
def paintEvent(自身,事件):
如果self.busy:
画笔颜色=(128、128、255、100)
不透明度=0.5#0.3
其他:
画笔颜色=(0,0,0,0)

不透明度=0.5#0不完全相同。当我按下“新建”按钮时,我希望它为整个屏幕上色,只有在释放不同的按钮(与按下“新建”按钮无关)后,屏幕才会恢复正常。我更改了代码示例,如果您运行它,它将更有意义。@TheCrystalShip与新闻发布联系起来,而不是单击,这有多重要?彩色小部件(部分透明)是否覆盖了您正在绘制的图像?这非常重要。我更新了我的代码。按“新建”,选择一个矩形,然后再次按“新建”,您将了解问题所在。
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()                         # +++