0

I am trying to plot 1D txt files in a part of the window created using wxpython. For this purpose, a directory selection tool was included which lists all txt files. Now, I would like to select a txt file and plot it in a panel on the right side.

Further, I am thinking to implement a button that does some operations on the data and replot again.

What I have tried is this :

import os
import wx
import numpy as np
import matplotlib
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
 
 
class mainFrame (wx.Frame):
    def __init__(self):
        super().__init__(None, id=wx.ID_ANY, title=u" test  ",
                         size=wx.Size(854, 698),
                         style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)
 
        self.SetSizeHints(wx.Size(600, -1), wx.DefaultSize)
 
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.panel = MainPanel(self, style=wx.TAB_TRAVERSAL)
        self.Layout()
 
        sizer.Add(self.panel, 1, wx.EXPAND, 0)
        self.SetSizer(sizer)
        self.Layout()
        self.Centre()
 
        # Connect Events
        self.panel.dirPicker.Bind(wx.EVT_DIRPICKER_CHANGED, self.dirPickerOnDirChanged)
        self.panel.listBox.Bind(wx.EVT_LISTBOX, self.listBoxOnListBox)
 
        # ------------ Add widget program settings
 
        # ------------ Call Populates
 
        self.Show()
 
    # Virtual event handlers, override them in your derived class
    def dirPickerOnDirChanged(self, event):
        self.FilePath = event.GetPath()
        self.populateFileList()
 
    def populateFileList(self):
        self.panel.listBox.Clear()
        allFiles = os.listdir(self.FilePath)
 
        for file in allFiles:
            if file.endswith('.txt'):
                self.panel.listBox.Append(file)
 
    def listBoxOnListBox(self, event):
        try:
            selected_file = event.GetString()
            file_address = os.path.join(self.FilePath, selected_file)
 
            # load file
            data = np.loadtxt(file_address)
 
            # select the first column
            if isinstance(data, np.ndarray):
                print("\tdata is np.array")
                dim = data.ndim
                if dim == 2:
                    input1D = data[:, 0]
                else:
                    input1D = data
 
                print(input1D.shape)
                # plot here
            else:
                print("\tdata is not np.array")
        except:  # Do not use bare except
            print("Some error.")
 
 
class MainPanel(wx.Panel):
    def __init__(self, parent, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.FONT_11 = wx.Font(11, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL,
                               wx.FONTWEIGHT_NORMAL, False, "Consolas")
        self.FONT_12 = wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL,
                               wx.FONTWEIGHT_NORMAL, False, wx.EmptyString)
        self.FONT_13 = wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL,
                               wx.FONTWEIGHT_NORMAL, False, wx.EmptyString)
        self.FONT_14 = wx.Font(14, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL,
                               wx.FONTWEIGHT_BOLD, False, "Consolas")
        self.FONT_16 = wx.Font(16, wx.FONTFAMILY_SCRIPT, wx.FONTSTYLE_NORMAL,
                               wx.FONTWEIGHT_BOLD, False, wx.EmptyString)
 
        sizer = wx.BoxSizer(wx.VERTICAL)
 
        quick_display = self._quick_display()
        directory_sizer = self._directory_sizer()
        list_box_sizer = self._list_box_sizer()
        self.text_details = self._detail_input()
        details_sizer = self._details_sizer()
        status_sizer = self._status_sizer()
 
        message_sizer = wx.BoxSizer(wx.VERTICAL)
        message_sizer.Add(details_sizer, 1, wx.EXPAND, 5)
        message_sizer.Add(status_sizer, 1, wx.EXPAND, 5)
 
        sizer.Add(quick_display, 0, wx.EXPAND, 0)
        sizer.Add(directory_sizer, 0, wx.EXPAND, 0)
        sizer.Add(list_box_sizer, 1, wx.EXPAND, 0)
        sizer.Add(message_sizer, 1, wx.EXPAND, 5)
 
        self.SetSizer(sizer)
 
    def _quick_display(self):
        quick_display = wx.StaticText(self, label=u"quick display")
        quick_display.Wrap(-1)
        quick_display.SetFont(self.FONT_16)
        return quick_display
 
    def _directory_sizer(self):
        sbSizerDir = wx.StaticBoxSizer(wx.StaticBox(self, label=u" working directory"))
        self.dirPicker = wx.DirPickerCtrl(sbSizerDir.GetStaticBox(), message=u"Select a folder")
        sbSizerDir.Add(self.dirPicker, 0, wx.ALL | wx.EXPAND, 5)
        return sbSizerDir
 
    def _list_box(self):
        listBoxChoices = []
        self.listBox = wx.ListBox(self, size=wx.Size(300, -1), choices=listBoxChoices)
        self.listBox.SetMinSize(wx.Size(250, -1))
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.listBox, 1, wx.ALL, 10)
        return sizer
 
    def _plot_sizer(self):
        self.panelPlot = PlotPanel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.panelPlot, 1, wx.EXPAND | wx.ALL, 5)
        return sizer
 
    def _list_box_sizer(self):
        file_list_sizer = self._list_box()
        bSizer_plot = self._plot_sizer()
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(file_list_sizer, 1, wx.EXPAND, 0)
        sizer.Add(bSizer_plot, 1, wx.EXPAND, 5)
        bSizerSplitHor = wx.BoxSizer(wx.HORIZONTAL)
        bSizerSplitHor.Add(sizer, 1, wx.EXPAND, 2)
        bSizerSplit = wx.BoxSizer(wx.VERTICAL)
        bSizerSplit.Add(bSizerSplitHor, 1, wx.EXPAND, 0)
        return bSizerSplit
 
    def _detail_label(self):
        detail_label = wx.StaticText(self, label="Details")
        detail_label.Wrap(-1)
        detail_label.SetFont(self.FONT_14)
        return detail_label
 
    def _detail_input(self):
        text_details = wx.TextCtrl(self, size=wx.Size(250, -1))
        text_details.SetFont(self.FONT_11)
        return text_details
 
    def _button_sizer(self):
        self.button = wx.Button(self, label=u"do some operation")
        self.button.SetFont(self.FONT_13)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.button, 0, wx.ALL, 5)
        return sizer
 
    def _details_sizer(self):
        detail_label = self._detail_label()
        button_sizer = self._button_sizer()
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(detail_label, 0, wx.ALL, 5)
        sizer.Add(self.text_details, 1, wx.EXPAND, 5)
        sizer.Add(button_sizer, 1, wx.EXPAND, 5)
        return sizer
 
    def _status_sizer(self):
        self.staticline3 = wx.StaticLine(self)
        self.status_label = wx.StaticText(self, label=u"Status bar")
        self.status_label.Wrap(-1)
        self.status_label.SetFont(self.FONT_12)
        self.staticline4 = wx.StaticLine(self)
        self.textCtrl_status = wx.TextCtrl(self)
        self.textCtrl_status.SetFont(self.FONT_11)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.staticline3, 0, wx.EXPAND | wx.ALL, 5)
        sizer.Add(self.status_label, 0, wx.ALL, 5)
        sizer.Add(self.staticline4, 0, wx.EXPAND | wx.ALL, 5)
        sizer.Add(self.textCtrl_status, 0, wx.ALL | wx.EXPAND, 5)
        status_sizer = wx.BoxSizer(wx.VERTICAL)
        status_sizer.Add(sizer, 1, wx.EXPAND, 5)
        return status_sizer
 
 
class PlotPanel(wx.Panel):
    def __init__(self, parent, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.SetMinSize(wx.Size(100, -1))
 
 
if __name__ == "__main__":
    app = wx.App(False)
    frame = mainFrame()
    app.MainLoop()
 

This creates a window as follows :

wx test window

The right portion is assigned as a panel, and I not sure how to place the matplotlib plot in it. Thank you.


There are several good questions on SE probing this topic, such as Q1 and Q2; however, most are limited to the plot being shown on the main window.

ankit7540
  • 315
  • 5
  • 20
  • 1
    IMHO your code is confused and certainly does not conform to [PEP8](https://pep8.org). This is not mandatory, but it is a standard the most python developers will find easier to read and possibly more willing to reply. (I've not corrected all your camelCase). I have refactored your code [here](https://pastebin.com/hZ7LXpe5). I have adapted most of the spaghetti and placed the panel in a class on its own rather than have everything in one class. It might be easier to see what is going on. – Psionman Apr 03 '22 at 13:49
  • Possibly you have too much detail; consider providing a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) – Psionman Apr 03 '22 at 13:53

1 Answers1

0

wxGlade includes some wxPython / matplotlib examples. Use these as starting point. https://github.com/wxGlade/wxGlade/tree/master/examples