2014-01-16 64 views
0

我想知道如何從我用QtDesigner創建的.ui文件生成OOP風格的Python代碼。針對OOP風格的Qt .ui文件的Python代碼生成器?

我想說的是,pyuic4生成的代碼不是OOP風格:小部件不會成爲QtGui類的子類。代碼很難閱讀和擴展。

我想要封裝所有子窗口小部件,佈局和函數的類。

我們來看一個簡單的例子。這個主窗口包含一個滑塊和一個液晶顯示器,並且它們以明顯的方式相連。

首先,這是由pyuic4生成的代碼:

from PyQt4 import QtCore, QtGui 

class Ui_MainWindow(object): 
    def setupUi(self, MainWindow): 
     MainWindow.setObjectName("MainWindow") 
     MainWindow.resize(268, 186) 
     self.centralwidget = QtGui.QWidget(MainWindow) 
     self.centralwidget.setObjectName("centralwidget") 
     self.gridLayout = QtGui.QGridLayout(self.centralwidget) 
     self.gridLayout.setObjectName("gridLayout") 
     self.horizontalSlider = QtGui.QSlider(self.centralwidget) 
     self.horizontalSlider.setOrientation(QtCore.Qt.Vertical) 
     self.horizontalSlider.setObjectName("horizontalSlider") 
     self.gridLayout.addWidget(self.horizontalSlider, 0, 1, 1, 1) 
     self.lcdNumber = QtGui.QLCDNumber(self.centralwidget) 
     self.lcdNumber.setObjectName("lcdNumber") 
     self.gridLayout.addWidget(self.lcdNumber, 0, 2, 1, 1) 
     MainWindow.setCentralWidget(self.centralwidget) 
     self.menubar = QtGui.QMenuBar(MainWindow) 
     self.menubar.setGeometry(QtCore.QRect(0, 0, 268, 25)) 
     self.menubar.setObjectName("menubar") 
     MainWindow.setMenuBar(self.menubar) 
     self.statusbar = QtGui.QStatusBar(MainWindow) 
     self.statusbar.setObjectName("statusbar") 
     MainWindow.setStatusBar(self.statusbar) 

     self.retranslateUi(MainWindow) 
     QtCore.QObject.connect(self.horizontalSlider, QtCore.SIGNAL("valueChanged(int)"), self.lcdNumber.display) 
     QtCore.QMetaObject.connectSlotsByName(MainWindow) 

    def retranslateUi(self, MainWindow): 
     MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8)) 


if __name__ == "__main__": 
    import sys 
    app = QtGui.QApplication(sys.argv) 
    MainWindow = QtGui.QMainWindow() 
    ui = Ui_MainWindow() 
    ui.setupUi(MainWindow) 
    MainWindow.show() 
    sys.exit(app.exec_()) 

我手動編輯的,以我的風格麼:

from PyQt4 import QtCore, QtGui 

class MainWindow(QtGui.QMainWindow): 
    def __init__(self): 
     QtGui.QMainWindow.__init__(self) 

     self.setObjectName("MainWindow") 
     self.resize(268, 186) 
     self.centralwidget = QtGui.QWidget(self) 
     self.centralwidget.setObjectName("centralwidget") 
     self.gridLayout = QtGui.QGridLayout(self.centralwidget) 
     self.gridLayout.setObjectName("gridLayout") 
     self.horizontalSlider = QtGui.QSlider(self.centralwidget) 
     self.horizontalSlider.setOrientation(QtCore.Qt.Vertical) 
     self.horizontalSlider.setObjectName("horizontalSlider") 
     self.gridLayout.addWidget(self.horizontalSlider, 0, 1, 1, 1) 
     self.lcdNumber = QtGui.QLCDNumber(self.centralwidget) 
     self.lcdNumber.setObjectName("lcdNumber") 
     self.gridLayout.addWidget(self.lcdNumber, 0, 2, 1, 1) 
     self.setCentralWidget(self.centralwidget) 
     self.menubar = QtGui.QMenuBar(self) 
     self.menubar.setGeometry(QtCore.QRect(0, 0, 268, 25)) 
     self.menubar.setObjectName("menubar") 
     self.setMenuBar(self.menubar) 
     self.statusbar = QtGui.QStatusBar(self) 
     self.statusbar.setObjectName("statusbar") 
     self.setStatusBar(self.statusbar) 

     self.retranslateUi() 

     QtCore.QObject.connect(self.horizontalSlider, QtCore.SIGNAL("valueChanged(int)"), self.lcdNumber.display) 
     QtCore.QMetaObject.connectSlotsByName(self) 

    def retranslateUi(self): 
     self.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8)) 


if __name__ == "__main__": 
    import sys 
    app = QtGui.QApplication(sys.argv) 
    main_window = MainWindow() 
    main_window.show() 
    sys.exit(app.exec_()) 

可以由代碼生成器來完成,而不需要枯燥的編輯。我的問題是:是否有這樣的代碼生成器可用?

+2

你應該** **不修改自動生成的文件。 「代碼很難閱讀和擴展。」做**不**保留,因爲你**不**應該觸摸該代碼*在所有*。由'pyuic'產生的輸出意味着被用作父類。在你的情況下,你可以使用'class MainWindow(QMainWindow,Ui_MainWindow):'然後在你的'__init__'中調用'setupUi(self)',這樣就完成了。無需查看生成的代碼。 – Bakuriu

+0

@Bakuriu,謝謝你的回答! :)「MainWindow類(QMainWindow,Ui_MainWindow)'是令人驚訝但非常好的! – user3202179

+0

我不明白爲什麼這是「不是OOP風格」。一個好的面向對象設計規則是贊成構造而不是繼承,這正是這樣做的。當前模式實際上是在Qt4中引入的,與Qt3相反,在Qt3中生成的小部件是子類。有關更多信息,請參閱http://qt-project.org/doc/qt-4.8/porting4-designer.html。 –

回答

2

您可以使用多重繼承來代替(見Using Qt Designer in PyQt4可能的方法):

from PyQt4.QtGui import QDialog 
from ui_imagedialog import Ui_ImageDialog 

class ImageDialog(QDialog, Ui_ImageDialog): 
    def __init__(self): 
     QDialog.__init__(self) 

     # Set up the user interface from Designer. 
     self.setupUi(self) 

     # Make some local modifications. 
     self.colorDepthCombo.addItem("2 colors (1 bit per pixel)") 

     # Connect up the buttons. 
     self.okButton.clicked.connect(self.accept) 
     self.cancelButton.clicked.connect(self.reject) 

然而,這兩種方法都是OOP風格。他們每個人都有優點和缺點。

而且不要讀取或編輯自動生成的文件。

+0

謝謝你!:)另一個更愚蠢的問題是:你們如何在沒有閱讀ui_-files的情況下找到你的孩子小部件的名字?從Qt設計器? (你不記得任何事情,是嗎?) – user3202179

+0

我使用自動完成的C++代碼(在Qt Creator中)。我不知道如何讓它適用於Python,但我認爲可能有一種方法。 –

+0

@ user3202179。我確定我重置了我感興趣的所有小部件的'objectName'屬性,併爲我的所有PyQt應用程序使用一致的命名風格。當然,自動完成也是有幫助的;-) – ekhumoro

1

你甚至不必產生從UI文件蟒蛇文件:使用uic模塊

import os 
from PyQt4 import QtGui, QtCore, uic 

class MyMainWindow(QtGui.QMainWindow): 
    def __init__(self, parent): 
    QtGui.QMainWindow.__init__(self, parent) 
    # We want to inheritate from MyMainWindow.ui 
    uic.loadUi(os.path.join(os.path.dirname(os.path.abspath(__file__)),"MyMainWindow.ui"), self) 

    # All widgets are available as classic attributes: 
    self.okButton.clicked.connect(self.accept) 
+0

除非我遺漏了某些東西,否則不需要將'uic.loadUI()'的結果賦值給某個東西。例如,我認爲你的例子應該閱讀'self.ui = uic.loadUi(...)'和'self.ui.okButton.clicked.connect(self.accept)' –

+0

@three_pineapples。你錯過了一些東西:'loadUi'的'baseinstance'參數(在這種情況下是'self')。它繞過了通常的'setupUi'鍋爐廢話,並將ui直接注入通過的實例中。 – ekhumoro

+0

@ekhumoro哦...我必須滾動才能看到,並沒有注意到正在使用baseinstance參數。哎呀! –