2016-02-07 81 views
2

我的问题很难解释,但我尽我所能。在这方面请帮助我。如何从主窗口打开子窗口

我在QtDesigner中设计了一个gui,并将.ui文件转换为.py文件.py main_window.py。现在为了避免在main_window.py中改变,我为侦听器创建了另一个类。

class Main():  
    window = None 
    app = None 

    def __init__(self): 
     self.launch() 
     self.attach_listener() 
     self.execute() 

    ''' Launch GUI ''' 
    def launch(self): 
     self.app = QtGui.QApplication(sys.argv) 
     self.window = Ui_MainWindow() 
     self.window.show() 

    ''' Execute Window ''' 
    def execute(self): 
     sys.exit(self.app.exec_()) 

    ''' Attach Listeners ''' 
    def attach_listener(self): 
     self.window.add_button.clicked.connect(self.add_listener) 
     self.window.delete_button.clicked.connect(self.delete_listener) 
     self.window.update_button.clicked.connect(self.update_listener) 
     self.window.connect(self.window.combo_box, QtCore.SIGNAL('activated(QString)'), self.logout_listener) 

我有另一个child_window.py具有相同的结构,但由于QApplication,我无法打开该窗口。我搜索了答案,但无法应用于我的代码。这些答案适用于从QtGui.QMainWindow或QtGui.QWidget扩展类,但我的情况是不同的。

回答

3

您正在将Ui_MainWindow对象与实际的窗口对象(QMainWindow,QDialog,QWidget等)混合在一起。self.window = Ui_MainWindow()不会执行任何操作,因为您将它附加到的类不是Window。您需要创建一个窗口并将Ui_MainWindow应用于其中。

显然你可以make this work,但它看起来不漂亮。您需要通过findChild访问您的小部件。我可以看到的唯一好处是,在设计师更改表格后,您不会跑到侧面,这很容易。

更简单的方法

当您使用pyuic/pyside-UIC它转换的.ui文件.py文件。 您不应编辑.py,因为下次您使用QtDesigner时它们将被覆盖。您需要创建一个窗口类并将UI类应用到它。

建立一种新的形式

  • 产生QtDesigner文件mainWinui.ui - 类名,主窗口
  • 转换与pyside-UIC -o mainWinui.py mainWinui.ui。 mainWinui.py从不手动编辑
  • 创建mainWinClass.py加载ui.py,做所有的自定义UI工作
  • 声明信号和槽,在mainWinClass.py
使用.connect等。

这些模块名称中的一部分可能看起来有些尴尬,但我已经解决了它们,因为在过去,我在模块和类之间发生名称冲突时遇到了问题;由于我不了解Qt Designer如何处理它的命名。

如果你看那个pyside-UIC创建的文件,它的顶部包含您需要在您的mainWinClass.py使用

mainWinui.py

# -*- coding: utf-8 -*- 

# Form implementation generated from reading ui file 'mainWinui.ui' 
# 
# Created: Sun Feb 7 14:22:09 2016 
#  by: pyside-uic 0.2.15 running on PySide 1.2.4 
# 
# WARNING! All changes made in this file will be lost! 

from PySide import QtCore, QtGui 

class Ui_MainWindow(object): 
    def setupUi(self, MainWindow): 
     MainWindow.setObjectName("MainWindow") 
正确的类和方法名

创建一个新的mainwinClass.py并将正确的导入和类名复制到它,再加上一些样板来加载.ui。

它看起来像这样:

mainWinClass。PY

from mainWinui import Ui_MainWindow 
from PySide import QtGui 


class MainWin(QtGui.QMainWindow): 
    def __init__(self, parent=None): 
     QtGui.QMainWindow.__init__(self, parent) 
     self.ui = Ui_MainWindow() 
     self.ui.setupUi(self) 
     self.setup_signals() 

# Is this is the same as your Listeners ?? 
def setup_signals(self): 
    # Signal for updating the lineedits from the grid 
    self.ui.tabWidget.currentChanged.connect(self.onTabChanged) 
    # Connect the "Add Staff" button to the addStaffMember method 
    self.ui.btnAddStaff.clicked.connect(self.addStaffMember) 

然后用另一个文件,启动应用程序本身,并保持应用程序的一些非GUI方面,如更新程序或全局日志。 我见过所有的子窗口在这里实例化的代码,但我没有(通常)这样做。我将它们保留在主表单中。这取决于你打算如何设计应用程序。

appname.py

from PySide import QtGui, QtCore 
from mainwinClass import MainWin 
import sys 


if __name__ == '__main__': 
    app = QtGui.QApplication(sys.argv) 
    mainWin = MainWin() 

    mainWin.show() 
    sys.exit(app.exec_()) 

    # Nothing else _needed_ in here 

现在对于任何子窗口再次遵循相同。

模式窗体

在Qt Designer中创建一个新的 '对话与按键底部'。 根据需要添加小部件并另存为dialogAddStaffui.ui。

运行

pyside-uic -o dialogAddStaffui.py dialogAddStaffui.ui. 

创建一个名为dialogAddStaffClass.py和使用 dialogAddStaffui.ui作为类名等编辑dialogAddStaffClass.py参考一个新的空文本文档看起来像这样:

dialogAddStaffClass

from dialogAddStaffui import Ui_DialogAddStaff 
from PySide import QtCore, QtGui 


class DialogAddStaff(QtGui.QDialog): 
    def __init__(self, parent=None): 
     QtGui.QDialog.__init__(self, parent) 
     self.ui = Ui_DialogAddStaff() 
     self.ui.setupUi(self) 
     # Your own init stuff 

这两个进口的上只需要在这里。 如果你要复制这一点,认识到在Qt设计我有

windowModality = ApplicationModal和形式是一个“对话与按钮下方的”

对于这些简单的形式,他们有一个接受方法用self.done(1)检查用户输入和关闭的数据的有效性。 如果你想看看如何验证和关闭的处理:

dialogAddStaffClass

def validate(self): 
    retval = True 
    if not self.ui.editLname.text(): 
     retval = False 
     QtGui.QMessageBox.information(self, 'Invalid Last name', 
             "Last Name must not be blank") 
     self.ui.editLname.setFocus() 
    return retval 

def accept(self): 
    if self.validate(): 
     self.done(1) 

有了这些对话形式的Qt已经自动设置OK按钮发射接受。我只是否定了这种方法。

如果你想要父母和孩子之间的沟通,你可以在引用父母的孩子上设置一个属性,或者在孩子关闭后读取孩子的属性,但在它变量被垃圾收集之前。创建循环引用可能存在问题,所以要小心。

由于新窗体为模态,用户无法与主窗体进行交互,直到他们关闭子窗体,并且启动窗口窗口的功能将暂停,直到子窗口关闭,因此它没关系使用局部变量来保存子类。

'Add Staff'按钮连接到addStaffMember函数。

mainWinClass。PY

from dialogAddStaffClass import DialogAddStaff 


def addStaffMember(self): 
    addStaffForm = DialogAddStaff() 
     res = addStaffForm.exec_() # exec_ waits, show would continue 
     # Function waits here for the Modal form to close. 
     if res: # child was closed with OK and validated correctly 
      print(addStaffForm.ui.editLname.text()) 
      # Saveing other Staff data happens here 

因为孩子形式与exec_运行,主要形式等待,直到子窗体,然后再继续关闭。当函数退出时,addStaffForm变量被垃圾收集,因此不再有任何对子窗体属性的引用。 (可能没有任何形式......)

如果你想打开一个长住窗体,你可以将它实例化到更持久的地方。

非模态形成

这里是一个SisterForm的一个例子。它是在“主窗口”类型的设计器中创建的(它有自己的菜单和状态栏等)。如果您不需要这些装饰,请使用对话窗体,但将它的窗口模式设置为NonModal。

  • 在Qt Designer中创建sisterWinui.ui - 设置对象名SisterWin
  • pyside-UIC -o sisterWinui.py sisterWinui.ui
  • 创建一个文件sisterwinClass.py - 建立它的进口和初始化
  • 做一个变量来保存它在一个长住的地方(的MainWin本身,使用自。ref属性)
  • 作出启动按钮,它和它的的MainWin类
连接方法

sisterWinui.ui

# -*- coding: utf-8 -*- 

# Form implementation generated from reading ui file 'sisterWinui.ui' 
# 
# Created: Mon Feb 8 12:05:37 2016 
#  by: pyside-uic 0.2.15 running on PySide 1.2.4 
# 
# WARNING! All changes made in this file will be lost! 

from PySide import QtCore, QtGui 

class Ui_SisterWin(object): 
    def setupUi(self, SisterWin): 
     SisterWin.setObjectName("SisterWin") 

运行UIC

pyside-uic -o sisterWinui.py sisterWinui.ui 

创建一个文件sisterwinClass.py - 建立它的进口和初始化

sisterwinClass.py

from sisterWinui import Ui_SisterWin 
from PySide import QtCore, QtGui 


class SisterWin(QtGui.QMainWindow): 
    def __init__(self, parent=None): 
     QtGui.QMainWindow.__init__(self, parent) 
     self.ui = Ui_SisterWin() 
     self.ui.setupUi(self) 
     # Your custom stuff after this 

在Qt Designer中,向主窗体添加一个按钮或者其他东西来启动sisterForm。然后对mainwinClass进行一些编辑。 请一个变量来保存它在一个长住的地方

mainwinClass

from sisterwinClass import SisterWin 
# no other new imports needed, just the stuff you had before 


class MainWin(QtGui.QMainWindow): 
    def __init__(self, parent=None): 
     # These three lines were already there 
     QtGui.QMainWindow.__init__(self, parent) 
     self.ui = Ui_MainWindow() 
     self.ui.setupUi(self) 
     # Add a long lived attribute to hold the class instance 
     self.sisterWin = None 
     # Next line was already there 
     self.setup_signals() 

def setup_signals(self): 
    # Connect button to openSisterWin 
    self.ui.btnSisterwin.clicked.connect(self.openSisterWin) 
    # You probably have other connects after this 


# This toggles the window 
def openSisterWin(self): 
    if not self.sisterWin: 
     self.sisterWin = SisterWin() 
    if self.sisterWin.isVisible(): 
     print('Hiding') 
     self.sisterWin.hide() 
     # hide or close, it's your choice 
     # self.sisterWin.close() 
    else: 
     print('Showing') 
     self.sisterWin.show() 

我希望覆盖你要找的呢? 如果试图找出如何隐藏主窗口,看看here 快乐黑客:-)

+0

你解释得很好。但我想知道如果我需要从mainWinClass.py启动一个新窗口?例如用户点击一个按钮,弹出一个新窗口。此外,新窗口就像上一个窗口一样,意味着它从.ui转换为ui.py并继承QtGui.QtMainWindow等。在这种情况下,我应该只创建** newWindowClass.py **的实例并调用这是** mainWinClass.py **? – ubuntu

+0

我试图用自己的方式编写代码,但是当我在mainWinClass.py中写入self.ui.hide()时,它什么也不做。为什么? – ubuntu

+0

请别人帮忙;(...我真的被困在这一点 – ubuntu

相关问题