PyQt5从主窗口打开第二个窗口

时间:2020-04-09 14:45:37

标签: python-3.x pyqt5 designer

您好,我是python的新手(直到第3课和MIT 6001计算机科学与编程入门

在Python中),我仍然开始使用PyQt5和Designer(在Linux上为Python3,PyQt5)玩。

我读了一些有关PyQt5的内容,但是对面向对象编程和Qt的了解不多

文档也像克林贡一样。无法弄清楚为什么此脚本test.py无法打开第二个

窗口,实际上它确实打开了它,我可以在第一个窗口前短暂看到它消失了

当我按下退出按钮时?有什么帮助吗?以及任何容易找到

逻辑的资源

Qt的不同类和app循环像我这样的未受过教育的人。

test.py

!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Apr  8 14:25:12 2020

@author: Pietro
"""

import sys

from PyQt5 import QtWidgets, uic

from PyQt5.QtWidgets import QDesktopWidget


def main():

    class quitto(QtWidgets.QMainWindow):

        def __init__(self):

            super(quitto, self).__init__()

            uic.loadUi('exitmain.ui', self)

            self.center()

            self.show()

            print('inside quitting2 ' *5)

        def center(self):

            qr = self.frameGeometry()

            cp = QDesktopWidget().availableGeometry().center()

            qr.moveCenter(cp)

            self.move(qr.topLeft())



    class menu(QtWidgets.QMainWindow):


        def __init__(self):

            super(menu, self).__init__()

            uic.loadUi('main.ui', self)


            self.ButtonQ.clicked.connect(self.QPushButtonQPressed) 

            self.center()

            self.show() 

        def center(self):

            qr = self.frameGeometry()

            cp = QDesktopWidget().availableGeometry().center()

            qr.moveCenter(cp)

            self.move(qr.topLeft())     


        def QPushButtonQPressed(self):

            #This is executed when the button is pressed

            print('buttonB pressed' *5)

            pippo=quitto()

            pippo.show()




    app = QtWidgets.QApplication(sys.argv)


    window=menu()

    app.exec_()


if __name__ == '__main__':

和main.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="windowModality">
   <enum>Qt::WindowModal</enum>
  </property>
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>520</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <property name="windowIcon">
   <iconset resource="resource001.qrc">
    <normaloff>:/main/python.png</normaloff>
    <normalon>:/main/python.png</normalon>
    <disabledoff>:/main/python.png</disabledoff>
    <disabledon>:/main/python.png</disabledon>
    <activeoff>:/main/python.png</activeoff>
    <activeon>:/main/python.png</activeon>
    <selectedoff>:/main/python.png</selectedoff>
    <selectedon>:/main/python.png</selectedon>:/main/python.png</iconset>
  </property>
  <property name="styleSheet">
   <string notr="true">QPushButton{
    background-color: #9de650;
}


QPushButton:hover{
    background-color: green;
}

QPushButton#ButtonQ{
    background-color: orange;
}


QPushButton#ButtonQ:hover{
    background-color: red;
}</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QLabel" name="label">
    <property name="geometry">
     <rect>
      <x>20</x>
      <y>0</y>
      <width>471</width>
      <height>71</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>16</pointsize>
      <weight>75</weight>
      <bold>true</bold>
      <underline>true</underline>
     </font>
    </property>
    <property name="text">
     <string>House-Buying-Menu</string>
    </property>
    <property name="alignment">
     <set>Qt::AlignCenter</set>
    </property>
   </widget>
   <widget class="QPushButton" name="ButtonA">
    <property name="geometry">
     <rect>
      <x>170</x>
      <y>100</y>
      <width>151</width>
      <height>81</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>20</pointsize>
      <weight>75</weight>
      <bold>true</bold>
     </font>
    </property>
    <property name="text">
     <string>A</string>
    </property>
   </widget>
   <widget class="QPushButton" name="ButtonB">
    <property name="geometry">
     <rect>
      <x>170</x>
      <y>210</y>
      <width>151</width>
      <height>81</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>20</pointsize>
      <weight>75</weight>
      <bold>true</bold>
     </font>
    </property>
    <property name="text">
     <string>B</string>
    </property>
   </widget>
   <widget class="QPushButton" name="ButtonC">
    <property name="geometry">
     <rect>
      <x>170</x>
      <y>320</y>
      <width>151</width>
      <height>81</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>20</pointsize>
      <weight>75</weight>
      <bold>true</bold>
     </font>
    </property>
    <property name="text">
     <string>C</string>
    </property>
   </widget>
   <widget class="QPushButton" name="ButtonQ">
    <property name="geometry">
     <rect>
      <x>170</x>
      <y>450</y>
      <width>151</width>
      <height>81</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>20</pointsize>
      <weight>75</weight>
      <bold>true</bold>
     </font>
    </property>
    <property name="text">
     <string>QUIT</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>520</width>
     <height>29</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources>
  <include location="resource001.qrc"/>
 </resources>
 <connections/>
</ui>

和mainexit.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>631</width>
    <height>496</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QDialogButtonBox" name="buttonBox">
    <property name="geometry">
     <rect>
      <x>200</x>
      <y>310</y>
      <width>174</width>
      <height>33</height>
     </rect>
    </property>
    <property name="standardButtons">
     <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>631</width>
     <height>29</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

3 个答案:

答案 0 :(得分:1)

该行为的原因是您正在创建的quitto实例是“垃圾收集”。像许多高级语言一样,Python具有一个自动管理内存的系统,并负责释放它“认为”不再有用的对象的内存。

在函数中创建的任何局部变量总是会在函数返回后立即删除,除非以某种方式引用了持久对象。

以下示例以一种更简单的方式对其进行了解释:在function中创建了“ my_variable”,但是一旦完成(返回),python就会删除该变量,这很好,因为如果不这样做, t您将很容易耗尽内存:

class DeletingObject(object):
    '''
    A basic class that prints a message whenever any of its instances
    is going to be deleted.
    '''
    def __del__(self):
        print('Goodbye cruel world...')

def function():
    my_variable = DeletingObject()
    print(my_variable)

>>> function()
<__main__.DeletingObject object at 0xb593a46c>
Goodbye cruel world...

在您的情况下,也会发生同样的事情:您创建了quitto,但没有持久引用,因此创建它的函数返回后,就会将其删除。

在类中创建对象时,最避免这种情况的方法是将新对象设置为 instance属性

    def QPushButtonQPressed(self):
        self.pippo = quitto()
        self.pippo.show()

现在不再删除新对象,并且不再破坏窗口。


由于您刚刚开始研究所有这些内容,因此我想分享一些有关您的示例的建议:

  • 类不应在函数中声明;在某些情况下可以做到这一点,但是在非常特殊的情况下,通常不需要通用使用(主要原因是应该可以从任何地方访问类,以便可以在任何时候创建其实例,但这也是因为定义函数中的类意味着每次运行该函数时都会声明它,这对性能不是很好);
  • 仅在分隔代码的逻辑片段时才在函数中使用空白行,而不是在每一行之间使用
  • 大多数语言的通用约定是使用大写字母表示类的名称,并使用小写字母表示函数,变量和实例的名称,有关更多信息,请参见官方style guide for Python(又称PEP-8);
  • 虽然从技术上讲它没有什么问题,但通常最好不要混用从模块导入的方式,尤其是当子模块有多个级别时(例如PyQt):您可以像在第一个中那样导入子模块行(from PyQt5 import QtWidgets)或您将要使用的单个类,就像您在第二次导入(from PyQt5.QtWidgets import QDesktopWidget)中所做的一样;第二种方法通常适用于简单的情况,但是如果代码增长很多,您可能会发现自己需要手动导入数十个类,并且尽管可以执行from PyQt5.QtWidgets import *,但通常最好导入子模块,从那里访问课程:
from PyQt5 import QtWidgets
# ...
cp = QtWidgets.QDesktopWidget().availableGeometry().center()
  • QDesktopWidget已过时,请改用QScreen

答案 1 :(得分:0)

@musicamante感谢您冗长而详细的帖子(我投了赞成票,但不算对不起),不确定我是否必须就下一个问题发表另一篇文章,但与上面的问题有关。我一直试图使我的脚本正常工作,但最终得到了:

test2.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Apr  8 14:25:12 2020

@author: Pietro
"""

import sys
from PyQt5 import QtWidgets, uic
#import resource


def main():

    class Quitto(QtWidgets.QDialog):

        def quitbuttonboxquit(self):
            print('system exit')
            app.quit()            

        def quitbuttonboxnonquit(self):
            print('return to main')
            window.show()
            self.close()    

        def __init__(self):
            super(Quitto, self).__init__()
            uic.loadUi('exitdialog2.ui', self)
            self.center()
            self.show()
            print('inside quitting2 ' *5)
            self.QuitbuttonBox.accepted.connect(self.quitbuttonboxquit)
            self.QuitbuttonBox.rejected.connect(self.quitbuttonboxnonquit)

        def center(self):
            qr = self.frameGeometry()
            cp = QtWidgets.QDesktopWidget().availableGeometry().center()
            qr.moveCenter(cp)
            self.move(qr.topLeft())

        def closeEvent(self, event): 
                event.ignore()

    class Menu(QtWidgets.QMainWindow):

        def __init__(self): 
            super(Menu, self).__init__()
            uic.loadUi('main.ui', self)
            self.ButtonQ.clicked.connect(self.qpushbuttonqpressed) 
            self.center()
            self.show() 

        def center(self):
            qr = self.frameGeometry()
            cp = QtWidgets.QDesktopWidget().availableGeometry().center()
            qr.moveCenter(cp)
            self.move(qr.topLeft())   


        def qpushbuttonqpressed(self): #This is executed when the button is pressed
            print('buttonB pressed' *5)
            window.hide()
            pippo=Quitto()
            pippo.exec_()


        def closeEvent(self, event): #Your desired functionality here 
                event.ignore()




    app = QtWidgets.QApplication(sys.argv)

    sshFile="coffee.qss"
    with open(sshFile,"r") as fh:
        app.setStyleSheet(fh.read())
    window=Menu()
    app.exec_()

if __name__ == '__main__':
    main()


和exitdialog.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Dialog</class>
 <widget class="QDialog" name="Dialog">
  <property name="windowModality">
   <enum>Qt::WindowModal</enum>
  </property>
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>586</width>
    <height>522</height>
   </rect>
  </property>
  <property name="font">
   <font>
    <italic>true</italic>
   </font>
  </property>
  <property name="windowTitle">
   <string>Dialog</string>
  </property>
  <property name="styleSheet">
   <string notr="true"/>
  </property>
  <widget class="QDialogButtonBox" name="QuitbuttonBox">
   <property name="geometry">
    <rect>
     <x>40</x>
     <y>460</y>
     <width>341</width>
     <height>32</height>
    </rect>
   </property>
   <property name="font">
    <font>
     <pointsize>18</pointsize>
     <weight>75</weight>
     <bold>true</bold>
    </font>
   </property>
   <property name="styleSheet">
    <string notr="true">QPushButton{                 
    background-color: #17eb3e;
}



QPushButton:hover{                 
    background-color: red;
}


</string>
   </property>
   <property name="orientation">
    <enum>Qt::Horizontal</enum>
   </property>
   <property name="standardButtons">
    <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
   </property>
  </widget>
  <widget class="QLabel" name="label">
   <property name="geometry">
    <rect>
     <x>50</x>
     <y>30</y>
     <width>491</width>
     <height>341</height>
    </rect>
   </property>
   <property name="styleSheet">
    <string notr="true">image: url(:/main/alert.png);</string>
   </property>
   <property name="text">
    <string/>
   </property>
  </widget>
  <widget class="QLabel" name="label_2">
   <property name="geometry">
    <rect>
     <x>170</x>
     <y>400</y>
     <width>271</width>
     <height>41</height>
    </rect>
   </property>
   <property name="font">
    <font>
     <pointsize>18</pointsize>
     <weight>75</weight>
     <italic>false</italic>
     <bold>true</bold>
    </font>
   </property>
   <property name="styleSheet">
    <string notr="true">QLabel { 
    color : red
 }</string>
   </property>
   <property name="text">
    <string>Are you sure to Quit ?!?</string>
   </property>
  </widget>
 </widget>
 <resources>
  <include location="resource001.qrc"/>
 </resources>
 <connections>
  <connection>
   <sender>QuitbuttonBox</sender>
   <signal>accepted()</signal>
   <receiver>Dialog</receiver>
   <slot>accept()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>248</x>
     <y>254</y>
    </hint>
    <hint type="destinationlabel">
     <x>157</x>
     <y>274</y>
    </hint>
   </hints>
  </connection>
  <connection>
   <sender>QuitbuttonBox</sender>
   <signal>rejected()</signal>
   <receiver>Dialog</receiver>
   <slot>reject()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>316</x>
     <y>260</y>
    </hint>
    <hint type="destinationlabel">
     <x>286</x>
     <y>274</y>
    </hint>
   </hints>
  </connection>
 </connections>
</ui>

稍后,我将尝试拆分函数和类(首先我需要弄清楚类) 尽管如此,我还是将类Quitto更改为:

class Quitto(QtWidgets.QDialog)

并更改:

        def qpushbuttonqpressed(self): #This is executed when the button is pressed
            print('buttonB pressed' *5)
            window.hide()
            pippo=Quitto()
            pippo.exec_() 

在上一个脚本中使用:

-window.hide()在短暂显示两个窗口后关闭了所有程序

使用

-pippo.exec()而不是pippo.show()在

顶部显示了新的第二个窗口

其他,关闭它们后,我得到了:

AttributeError: 'quitto' object has no attribute 'exec_'

在第二个脚本中使用pippo.show()都不起作用,但是pippo.exe_()起作用了

把戏。它如何绕过垃圾收集???

为什么将类Quitto()更改为QtWidgets.QMainWindow却出现属性错误?

答案 2 :(得分:0)

在我的项目中,我使用它从主窗口打开另一个窗口。我粘贴了具有额外中心功能的全功能脚本,该脚本将主窗口置于屏幕中间。在Designer中,创建两个文件“ UIMain.ui”(主窗口)和第二个窗口“ notes.ui”并保存。

# Open Second Window/Dialog/Form from Main Window

from PyQt5 import uic
from PyQt5.QtWidgets import (
                            QMainWindow,
                            QApplication,
                            QDesktopWidget
                            )

form_2, base_2 = uic.loadUiType('notes.ui')


class MainNotes(base_2, form_2):
    def __init__(self, parent=None):
        super(base_2, self).__init__(parent)
        self.setupUi(self)


class MainApp(QMainWindow):
    """ Main Class
    """
    def __init__(self):
        super(MainApp, self).__init__()
        self.mainnotes = MainNotes()
        self.ui = uic.loadUi('UIMain.ui', self)

        self.initapp()

    def initapp(self):
        self.ui.bt_notes.clicked.connect(self.notes)

    def notes(self):
        """
        Put your code here
        """
        self.mainnotes.show()

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())


def main():
    import sys
    try:
        myapp = QApplication([])
        mywindow = MainApp()
        mywindow.center()
        mywindow.show()
        myapp.exec_()
    except SystemExit:
        sys.exit(0)


if __name__ == '__main__':
    main()