简体   繁体   中英

Passing information from a widget module to the main window

If I have a very simple (self contained, reproducible) program as follows:

import sys
from PyQt4 import QtCore, QtGui, Qt

class mainWrapper(QtGui.QMainWindow):

  def __init__(self):
    super(mainWrapper, self).__init__()
    self.resize(800, 600)    
    self.statusBar().showMessage('Welcome to my 1st project')

    self.tw = testWidget()
    fileName = self.tw.open()

    self.setCentralWidget(Qt.QLabel(str(fileName)))
    self.statusBar().showMessage("Showing file " + str(fileName))

  def open(self):
    fileName = QtGui.QFileDialog.getOpenFileName(self, "Open File",
        QtCore.QDir.currentPath())
    if fileName.isNull():
      QtGui.QMessageBox.information(self, "test project",
         "Cannot load %s." % fileName)
    print fileName
    return fileName 

  if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    mw = mainWrapper()
    mw.show()
    sys.exit(app.exec_())  

then the filename is printed in the main window and in the status bar, as required. If I modify the code to split it into 2 modules, in order to start having some building blocks for a larger project (in the long term...), then I get:

testMainWindow.py

import sys
from PyQt4 import QtCore, QtGui, Qt

from testWidget import testWidget_widget

class mainWrapper(QtGui.QMainWindow):

  def __init__(self):
  super(mainWrapper, self).__init__()
  self.resize(800, 600)    
  self.statusBar().showMessage('Welcome to my 1st project')

  self.tw = testWidget()
  fileName = self.tw.open()

  self.setCentralWidget(Qt.QLabel(str(fileName)))
  self.statusBar().showMessage("Showing file " + str(fileName))

if __name__ == '__main__':
  app = QtGui.QApplication(sys.argv)
  mw = mainWrapper()
  mw.show()
  sys.exit(app.exec_())   

testWidget.py

from PyQt4 import QtCore, QtGui, Qt

class testWidget(QtGui.QWidget):

def __init__(self):
  super(testWidget, self).__init__()
  print "ImageViewer_widget called successfully"

def open(self):
  fileName = QtGui.QFileDialog.getOpenFileName(self, "Open File",
        QtCore.QDir.currentPath())
  if fileName.isNull():
    QtGui.QMessageBox.information(self, "test project",
         "Cannot load %s." % fileName)
  print fileName
  return fileName 

then I still get the filename printed in the main window and on the status bar as expected. However, this is only self.tw.open() . What I'd really like to do is set the content in the widget module, and have as little code as possible in my method for calling the widget, with the rationale for that being when these modules get more important, I want to keep all the code to do with testWidget in that module. However, given that setCentralWidget is only a method of QMainWindow , what's the best way to achieve this?

Of course, it is possible I've totally missed the point about PyQt, and that I've totally mis-designed how my modules work. If this is the case, feel free to nudge me back in the right direction...

The question is a little bit nebulous, if only because you will have to make some design decisions about how the user will interact with the GUI. A first attempt might involve some of these things:

1) Add a signal to your widget, have it set its own name. When it changes its name, also emit a signal of the new name.

class testWidget(QtGui.QLabel):

    textChanged = QtCore.pyqtSignal(object)

    def open(self):
        fileName = QtGui.QFileDialog.getOpenFileName(self, "Open File",
                                                QtCore.QDir.currentPath())
        if fileName.isNull():
            QtGui.QMessageBox.information(self, "test project",
                                          "Cannot load %s." % fileName)
        self.setText(fileName)
        self.textChanged.emit(fileName)

2) Add the widget, and connect its signal to a slot (callback) in the main window to update its status bar.

class mainWrapper(QtGui.QMainWindow):

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

  def init_ui(self):
    self.resize(800, 600)    
    self.statusBar().showMessage('Welcome to my 1st project')
    self.tw = testWidget()
    self.setCentralWidget(self.tw)
    self.tw.textChanged.connect(self.update_status_bar)
    self.tw.open()

  def update_status_bar(self, f):
    self.statusBar().showMessage("Showing file " + f)

if __name__ == '__main__':
  app = QtGui.QApplication(sys.argv)
  mw = mainWrapper()
  mw.show()
  mw.init_ui()
  sys.exit(app.exec_())  

** As you can see, this is really only good for one display widget. If you want to add more widgets, you will have to make the central widget a generic widget, set its layout, and add the additional widgets to its layout.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM