代码之家  ›  专栏  ›  技术社区  ›  TheCrystalShip

PyQt5-在qmain菜单中,如何使QWidget成为父级(临时)?

  •  0
  • TheCrystalShip  · 技术社区  · 6 年前

    我有一个 QMainWindow 我用一个 QWidget . 我想每次按下按钮 New 在我的 QMainWiindow ,它将打开 QWidget公司 暂时(在我的情况下,直到鼠标按钮释放)。

    我在互动上有困难 Q主窗口 QWidget公司 . 我试过很多选择,但似乎我试过的每一件事 QWidget公司 Q主窗口 屏幕,我不想要。

    举个例子会更容易:

    TempWidgetMenu.py 是我的 Q主窗口 上课。当我按下 新的 ,一个 QWidget公司 将出现,它将使屏幕颜色变灰,并将一个矩形从按钮按下,到按钮释放(如在windows剪贴工具)。

    每次我按的时候都要这个 新的 ,我将能够从屏幕的每个点绘制一个矩形,因此它第一次可以这样做。 当我按下 新的 第二次(或之后),它将为除主菜单屏幕以外的所有内容上色,并且不会响应按钮操作。

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

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

    临时窗口小部件.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公司 我每次给他打电话都会做他的父母吗?

    编辑:如果有些东西不清楚,运行代码,这将是完美的意义。压力机 新的 ,选择一个矩形(用鼠标),然后按 新的 再次选择另一个矩形,你就会明白问题所在。

    2 回复  |  直到 6 年前
        1
  •  1
  •   S. Nick    6 年前

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

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

    临时窗口小部件.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

        2
  •  0
  •   buck54321    6 年前

    如果我没听错的话 Menu.opac_rect 在按下鼠标按钮时在单独的窗口中打开。我看到了一些问题。首先,如果你想 QWidget 要在单独的窗口中打开,您应该通过 Qt.windowFlags 对…的争论 QWidget公司 建造师,即。

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

    别忘了导入 QtCore 命名空间。

    其次, QAction 没有你需要的信号。仅继承自 QWidget公司 会有 mousePressEvent mouseReleaseEvent . 如果你必须把东西放在工具栏上, QToolBar QToolBar.addWidget ,所以你可以使用 QLabel 而不是 行动 ,并覆盖必要的事件处理程序。

    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)
    

    你可能得摆弄一下 基拉贝尔 造型,使它看起来正确,但我认为这将完成你正在寻找的。