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

时间:2018-08-01 14:07:59

标签: python pyqt pyqt5 qwidget qmainwindow

我有一个用QMainWindow初始化的QWidget。我希望每次我在自己的New中按下按钮QMainWiindow时,它将临时打开QWidget(在我的情况下,直到释放鼠标按钮为止)。

我无法将QMainWindowQWidget进行交互。我尝试了很多选项,但似乎我尝试的所有操作都将QWidget绑定到QMainWindow屏幕,但我不希望这样做。

举个例子会更容易

TempWidgetMenu.py是我的QMainWindow班。当我按下New时,将出现QWidget,它将使屏幕变灰,并从按下按钮到释放按钮(例如在Windows截图工具中)为矩形着色。 / p>

我希望每次我按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选择另一个矩形,您将了解问题所在。

2 个答案:

答案 0 :(得分:1)

我不太了解会发生什么, 但是我添加并更改了一些代码行。 单击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()                         # +++

enter image description here

答案 1 :(得分:0)

如果我对您的理解正确,那么您希望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样式以使其看起来正确,但是我认为这将满足您的要求。