2016-02-07 8 views
2

Мой вопрос трудно объяснить, но я стараюсь изо всех сил. Пожалуйста, помогите мне в этом.Как открыть дочернее окно из главного окна

Я разработал gui в QtDesigner и преобразовал файлы .ui в .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() ничего не делает, потому что класс, к которому вы его привязываете, не является окном. Вам нужно создать окно и применить к нему Ui_MainWindow.

Видимо, вы можете make this work, но это не выглядит красиво. Вам нужно получить доступ к своим виджетам с помощью findChild. Единственное, что я вижу, это то, что вы не запускаете pyside-uic после изменения формы в дизайнере, и это довольно легко.

Более простой путь

При использовании pyuic/PySide-UIC он преобразует .ui файлы .py файлы. Вы не должны редактировать .py, так как они будут перезаписаны при следующем использовании QtDesigner. Вам нужно создать класс окна и применить к нему класс пользовательского интерфейса.

Настройка новой формы

  • Производят файл mainWinui.ui в QtDesigner - имя класса MainWindow
  • Преобразовать с PySide-UIC -o mainWinui.py mainWinui.ui. mainWinui.py никогда не отредактирован вручную
  • Создания mainWinClass.py для загрузки ui.py и делать всю работу пользовательского интерфейса
  • DECLARE сигналов и слоты, использовать .Подай и т.д. в mainWinClass.py

Некоторые из этих имен модулей могут показаться немного неудобными, но я решил, что в прошлом у меня были проблемы с конфликтами имен между модулями и классами; вызванный тем, что я не понял, как 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.ру

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.

Run

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 и форма была «Диалог с кнопками Bottom»

Для этих простых форм, у них есть принять метод, проверяет достоверность данных, которые пользователь ввел и закрывает с помощью 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, чтобы принять огонь. Я просто переопредел этот метод.

Если вы хотите установить связь между родителем и ребенком, вы можете либо установить свойство для дочернего элемента, которое ссылается на родителя, либо прочитать свойства дочернего элемента после его закрытия, но до того, как его переменная получает сбор мусора. Могут возникнуть проблемы с созданием циклических ссылок, поэтому будьте осторожны.

Поскольку новая форма является модальной, пользователь не может взаимодействовать с основной формой, пока не закрыл дочернюю форму, и функция, запускающая окно chil d, остановится, пока дочернее окно не будет закрыто, поэтому все в порядке для использования локальной переменной для хранения дочернего класса.

Кнопка «Добавить персонал» подключена к функции addStaffMember.

mainWinClass.ру

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.

  • Создание sisterWinui.ui в Qt Designer - набор Objectname SisterWin
  • PySide-UIC -o sisterWinui.py sisterWinui.ui
  • Создать файл sisterwinClass.py - установить это импорт и инициализации
  • Сделать переменный, чтобы держать его в долгоживущем месте (сам MainWin, использовать себя. исй атрибут)
  • сделать кнопку запуска для него и подключить его к методу в 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") 

Run МСЖД

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 Happy hacking :-)

+0

Вы очень хорошо объяснили. Но я хочу знать, что если мне нужно запустить новое окно из mainWinClass.py? например пользователь нажимает кнопку и появляется новое окно. Кроме того, новое окно похоже на предыдущее означает, что оно преобразуется из .ui в ui.py и наследует QtGui.QtMainWindow и т. Д. В этом случае следует просто создать экземпляр ** newWindowClass.py ** и вызвать это ** mainWinClass.py **? – ubuntu

+0

Я пробовал писать код по-своему, но когда я пишу в mainWinClass.py, self.ui.hide() он ничего не делает. Зачем? – ubuntu

+0

Пожалуйста, помогите, (... Я действительно застрял на этом этапе. – ubuntu