2016-02-07 109 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

相關問題