geeb.24
geeb.24

Reputation: 557

Python Method and Classes in GUI Error

I am attempting to create a GUI using Python classes. Because I'm new to Python, I'm still learning to troubleshoot my errors. Below, I wish to create a class called Plot_Seismo, and create a GUI that has a listbox, a quit button, and a "Plot" button. I am having trouble with the "Plot_button" within the class. What I want this button to do is read in the seismogram and then plot the selected seismogram from the listbox. I have a feeling my syntax is incorrect (due to my naivete). I can get this to work when this function isn't in a class, but when I put it in a class as a method, I get slightly confused. The error message is shown below:

#!/usr/bin/env python
from Tkinter import *
from obspy.core import read
import math


class Plot_Seismo:
    def __init__(self, parent):
        self.master = parent
        top = Frame(parent, width=500, height=300)
        top.pack(side='top')

        # create frame to hold the first widget row:
        hwframe = Frame(top)
        # this frame (row) is packed from top to bottom (in the top frame):
        hwframe.pack(side='top')
        # create label in the frame:
        font = 'times 18 bold'
        hwtext = Label(hwframe, text='Seismogram Reader GUI', font=('Arial',18,'bold'), fg="red")
        hwtext.pack(side='top')

        ### ListBox
        List1 = Listbox(root, width=50, height= 10)
        List1.insert(1,"trace1.BHZ")
        List1.insert(2,"trace2.BHZ")
        List1.pack(padx=20, pady=20)


        plot_button = Button(top, text='Plot Seismogram', command=self.plot_seis)
        plot_button.pack(side='top', anchor='w', padx=45, pady=20)
        self.event = read(List1.get(List1.curselection()[0]))

        # finally, make a quit button and a binding of q to quit:
        quit_button = Button(top, text='Quit Seismo-Reader GUI', command=self.quit)
        quick_button.pack(side='top', anchor='w', padx=20, pady=20)
        self.master.bind('<q>', self.quit)

    def quit(self, event=None):
        self.master.quit()

    def plot_seis(self, event=None):
        self.event.plot()

root = Tk()
Plot_Seismo = Plot_Seismo(root)
root.mainloop()

Error Message:
Traceback (most recent call last):
  File "plot_seismogram.py", line 46, in <module>
    Plot_Seismo = Plot_Seismo(root)
  File "plot_seismogram.py", line 31, in __init__
    self.event = read(List1.get(List1.curselection()[0]))
IndexError: tuple index out of range

Upvotes: 0

Views: 275

Answers (1)

albert
albert

Reputation: 8633

Since I do not have obspy module installed, I had to shrink down your code a bit, but you should get the point.

Since I only have Python3 running on my machine, I rewrote your code to Python3 which is not a big deal. The only differences should be (tkinter instead of Tkinter and print() instead of print).

I changed some parts of your code: The listbox is no populated using a list, which make this a bit easier and it became a class attribute to access it in plot_seis.

Since .curselection() returns a tuple with the listboxes entry index, we have to get the according text entry as described in the docs and in this answer.

Buttons and maybe the listbox provide some event handling features which are making the listbox an class attribute by using self. kind of ugly somehow, but it does the job:

#!/usr/bin/env python3
# coding: utf-8

from tkinter import *
# from obspy.core import read
import math


class Plot_Seismo:
    def __init__(self, parent):
        self.master = parent
        top = Frame(parent, width=500, height=300)
        top.pack(side='top')

        # create frame to hold the first widget row:
        hwframe = Frame(top)
        # this frame (row) is packed from top to bottom (in the top frame):
        hwframe.pack(side='top')
        # create label in the frame:
        font = 'times 18 bold'
        hwtext = Label(hwframe, text='Seismogram Reader GUI', font=('Arial',18,'bold'), fg="red")
        hwtext.pack(side='top')

        ### ListBox
        self.List1 = Listbox(root, width=50, height= 10)
        # populate listbox using a list with desired entries
        self.list_entries = ["trace1.BHZ", "trace2.BHZ"]
        for i, element in enumerate(self.list_entries):
            self.List1.insert(i, element)
        self.List1.pack(padx=20, pady=20)

        plot_button = Button(top, text='Plot Seismogram', command=self.plot_seis)
        plot_button.pack(side='top', anchor='w', padx=45, pady=20)

        # finally, make a quit button and a binding of q to quit:
        quit_button = Button(top, text='Quit Seismo-Reader GUI', command=self.quit)
        quit_button.pack(side='top', anchor='w', padx=20, pady=20)
        self.master.bind('<q>', self.quit)

    def quit(self, event=None):
        self.master.quit()

    def plot_seis(self, event=None):
        selection_index = self.List1.curselection()[0]
        selection_text = self.List1.get(selection_index)
        print(selection_text)

        # do something with `read` from the `obspy.core` module
        # read(selection_text)


root = Tk()
Plot_Seismo = Plot_Seismo(root)
root.mainloop()

Upvotes: 3

Related Questions