0

I'm writing an application using PyQt4 to analyze data as it acquired from our data acquisition software. The application will consist of a few widgets:

  • a widget to display what files have been imported (and what data channels are in those files); this widget will also contain the file watcher that is looking for data files as they are generated
  • a widget that will plot certain data channels as they are imported
  • multiple other widgets that perform different analysis and display the results of that analysis

All of these widgets would be contained within a QMainWindow

So basically, the main routine will be: file generated (external to application) -> file imported into pandas dataframe -> data plotted / analyzed

What I'm unclear about is where in the application would be the best place to actually run the import function (and therefore where the actual pandas dataframes will be held).

The two places that make sense to me are either in the first widget mentioned (that one that is doing the file watching / displaying of what has been imported) or the actual QMainWindow itself.

I understand how to tell all the widgets currently in the QMainWindow that a file has been imported using signals / slots. So, for example, the file watcher widget will emit a signal every time a file is imported. This would be connected to slots in the other widgets that would tell them to update the current plot, or run some analysis, or whatever.

But the point of uncertainty I'm running in to how to make the data that is imported available to all of the widgets currently in the QMainWindow. Which is what I mean by asking where the import function should actually be run.

Hopefully what I'm asking is clear; if not let me know.

Edit:

Reading a bit more about MVC design in Qt, it's unclear to me whether it's appropriate here. I would like to make the parts of the application as independent as possible, so the idea behind using MVC is very appealing, but I'm having trouble understanding how it would be implemented in my case. All of the examples that I have been able to find seem to deal with updating, for example, a TreeWidget and a ComboBox so that when the data for one is edited it remains in sync with the data for the other (i.e. they both change since the data is held in one place).

In my case the data itself is never modified by anything after it has been imported. Analysis may be run on it, but that would be independent to each widget and would have no effect on the actual raw data that has been imported into the application. Each widget is essentially independent, with anything occurring within that widget having no effect on any other widget in the application. Every widget currently active in the main application simply needs to have access to the data that has been imported, and needs to know when a new piece of data has been added (this is envisioned as a dictionary of file names matched to pandas dataframes)

As suggested, keeps the data in the main application and connecting to each of the widgets to indicate that a new piece of data is now available is straightforward, so I get how that would work.

I'm just very unclear about what I would gain by going to MVC route.

dan_g
  • 2,712
  • 5
  • 25
  • 44

1 Answers1

1

You essentially only have one event firing, which is the new file found, and every other process is kicked off in turn. Therefore you could just put all of the code within your main window class given that your process at least on the surface sounds somewhat simple. The data would be shared via a class variable and a timer is used to check for files (and is the only event trigger). This would give you a main window class with a basic structure something like this (pseudocode):

class MainWindow(QtGui.QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.build_ui()
        self.imported_data = {}
        timer = QTimer()
        timer.timeout.connect(check_for_files)
        timer.start(10000)  # periodically check for new files

    def build_ui(self):
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

    def check_for_files(self):
        # check for new files here
        if new_file:
            self.import_data(file_name)
            self.ui.filename_list.addItem(file_name)  # add file name widget
            self.plot_data(file_name)             

    def import_data(self, file_name):
        # open file and read data to file_data
        self.ui.imported_data[file_name] = file_data

    def plot_data(self, file_name):
        self.ui.graph.add_plot(self.imported_data[file_name])

That could get ugly if your program grows larger but should work. If you wanted a more scalable design where the main window, processing, and data are in separate classes you could check out a model-view-controller design and place the processing in a controller class and the data in the model class.

Community
  • 1
  • 1
101
  • 8,514
  • 6
  • 43
  • 69
  • Thanks. I will look more into the MVC design idea, as this application is likely to grow rather quickly once I get the basic aspects of it figured out. – dan_g Jan 07 '15 at 15:55
  • Please see edit in OP, as the comment is a point of clarification that is too long to put here. – dan_g Jan 07 '15 at 23:36
  • @user3014097 MVC is just one of many design patterns that could suit your application, as it will lend itself well to separating user inputs, logic, and data storage. It sounds like you are a little confused between MVC design pattern (as in the link) and Qt's implementation of views and models within some of their widgets; the two aren't really the same thing (and the latter isn't so relevant to my answer). A simple path to trying MVC would be following the template in the link and understanding a minimal process flow through the program. – 101 Jan 12 '15 at 10:27
  • Yes, I was getting the two confused. Reading through the link again I get the gist of the idea. For my case I'd probably end up combining the views and controllers. Where would you suggest the actual file watching go on? I can see putting it in the model or putting it in the main application, and simply telling the model to import the file when the file watcher indicates that a new file is available for import – dan_g Jan 12 '15 at 19:26
  • @user3014097 combining the the views and controllers is a good way to start, if needed you can separate them later. Personally I'd put the file watcher in a view as it's just another user input of sorts. – 101 Jan 12 '15 at 20:36
  • That's what I was leaning towards - putting it into the main window view/controller. Thanks for the help – dan_g Jan 13 '15 at 17:20