2012-11-25 16 views
6

Tôi là người mới đối với PySide.I có một đối tượng cửa sổ chính hiển thị một tiện ích tại một thời điểm. Tôi đã cố gắng thay đổi widget trung tâm của lớp QMainWindow để thay thế Widget hiển thị trong cửa sổ khi nhấn một nút. Vấn đề là nút được nhấn nằm trong lớp Widget, không phải trong lớp cửa sổ chính.Thay thế CentralWidget trong MainWindow

nói ...

class App(QtGui.QMainWindow): 

    def __init__(self): 
     super(App, self).__init__() 

     self.initUI() 

    def initUI(self): 

     self.statusBar().showMessage('Listo.') #Status Bar 
     self.login_screen = LoginScreen() 
     self.logged_in_screen = LoggedInScreen() 

     self.setCentralWidget(self.login_screen) 

     self.setGeometry(300, 300, 450, 600) #Window Size 
     self.setWindowTitle('PyTransactio - Client') #Window Title 
     self.setWindowIcon(QtGui.QIcon('icon.png')) #App Icon 
     self.show() 

Nút nhấn là trong login_screen dụ. Phương pháp gọi khi nút được click là bên trong lớp LoginScreen:

def login(self): 
     """ Send login data to the server in order to log in """ 

     #Process 

     self.setParent(None) 

Thiết widget mẹ để None loại bỏ các widget (login_screen) từ cửa sổ chính. Tôi nên làm gì để nhận tiện ích con khác (ví dụ: logged_in_screen) làm tiện ích con trung tâm của cửa sổ chính khi nhấn loginButton (bên trong tiện ích login_screen)?

Có thể phương thức đăng nhập phải nằm trong lớp cửa sổ chính? Nếu vậy, làm cách nào tôi có thể kết nối các nút được nhấn trong login_screen bằng phương pháp của cửa sổ chính?

Trả lời

10

Bạn có thể sử dụng QStackedWidget làm tiện ích con trung tâm và thêm cả màn hình đăng nhập lẫn màn hình "đăng nhập" vào màn hình đó.

Một cách sử dụng ví dụ:

from PyQt4 import QtCore, QtGui 


class MainWindow(QtGui.QMainWindow): 
    def __init__(self, parent=None): 
     super(MainWindow, self).__init__(parent) 
     self.central_widget = QtGui.QStackedWidget() 
     self.setCentralWidget(self.central_widget) 
     login_widget = LoginWidget(self) 
     login_widget.button.clicked.connect(self.login) 
     self.central_widget.addWidget(login_widget) 
    def login(self): 
     logged_in_widget = LoggedWidget(self) 
     self.central_widget.addWidget(logged_in_widget) 
     self.central_widget.setCurrentWidget(logged_in_widget) 


class LoginWidget(QtGui.QWidget): 
    def __init__(self, parent=None): 
     super(LoginWidget, self).__init__(parent) 
     layout = QtGui.QHBoxLayout() 
     self.button = QtGui.QPushButton('Login') 
     layout.addWidget(self.button) 
     self.setLayout(layout) 
     # you might want to do self.button.click.connect(self.parent().login) here 


class LoggedWidget(QtGui.QWidget): 
    def __init__(self, parent=None): 
     super(LoggedWidget, self).__init__(parent) 
     layout = QtGui.QHBoxLayout() 
     self.label = QtGui.QLabel('logged in!') 
     layout.addWidget(self.label) 
     self.setLayout(layout) 



if __name__ == '__main__': 
    app = QtGui.QApplication([]) 
    window = MainWindow() 
    window.show() 
    app.exec_() 

Nếu bạn không muốn sử dụng widget này, sau đó tôi nghĩ rằng bạn sẽ phải gọi QMainWindow.setCentralWidget mỗi khi bạn thay đổi các widget trung ương.

Để biết phương pháp login, tùy thuộc vào điều kiện nào. Có lẽ bạn có thể định nghĩa một giao diện đơn giản cho mainwindow của bạn để thêm/xóa/hiển thị các widget trung tâm cụ thể và gọi nó từ phương thức login của LoginScreen. Bằng cách này, lớp LoginScreen không cần phải biết về chi tiết triển khai, chẳng hạn như nếu widget trung tâm thực sự là một QStackedWidget hoặc điều này được thực hiện theo cách khác.

+1

** QStackedWidget ** đã làm điều. Ngoài ra, tôi không bao giờ nghĩ về 'self.parent(). Login'. Đoán tôi sẽ phải làm việc trên OOP của tôi. Cảm ơn nhiều! –

+0

Khi đặt làm tiện ích con trung tâm, QMainWindow sẽ sở hữu tiện ích đó. Khi đặt tiện ích con khác làm tiện ích con trung tâm, tiện ích con đầu tiên bị hủy, điều đó rất tệ. –

+0

@ HrvojeT Vâng, đó là lý do tại sao câu trả lời của tôi sử dụng 'QStackedWidget' và không phải là hack, mà có thể yêu cầu một số mã xấu xí để hoạt động đúng. – Bakuriu

-2

Bạn có thể sử dụng QMainWindow.setCentralWidget để làm điều này (nhiều lần):

#! /usr/bin/env python3 

from PySide import QtGui 
from PySide import QtCore 

import sys 

app = QtGui.QApplication(sys.argv) 
mw = QtGui.QMainWindow() 
w2 = QtGui.QWidget() 
pb = QtGui.QPushButton('push me', w2) 

l1 = QtGui.QLabel('orig') 
l2 = QtGui.QLabel('changed') 
mw.setCentralWidget(l1) 
pb.clicked.connect(lambda: mw.setCentralWidget(l2)) 
mw.show() 
w2.show() 
sys.exit(app.exec_()) 
+0

Tôi biết đây là một cách giải quyết có thể xảy ra, nhưng phá hủy central_widget cuối cùng là một tác dụng phụ khủng khiếp ... –