[Tutor] Python WX module program issues.
john fabiani
johnf at jfcomputer.com
Thu Mar 23 09:23:10 EDT 2023
You need to join the wxPython forum ( https://discuss.wxpython.org).
I'm sure they can answer your questions.
Johnf
On 3/23/23 2:14 AM, mhysnm1964 at gmail.com wrote:
> All,
>
>
>
> I have created a simple Python 3.10 app using WX module. There is a main
> frame and two horizontal panels. Panel1 has an edit object in it. Panel2 has
> a list box. The issues I cannot resolve:
> 1. I cannot add any new content to the status bar from the class EditPanel.
>
> 2. The RecordListPanel does not show any content and the database is
> populated.
>
> 3. F6 is meant to switch between the two panels and set the keyboard focus
> to the next panel.
>
>
>
> There is some issues with the saveDb method in the EditPanel Class which I
> am still working on. If record key publisher has no values, it receives
> "None". The Publisher table has unique records set to prevent duplication.
> The same applies to authors, genre, narrator.
>
>
>
> Can someone look at this code an let me know why point 1 to 3 isn't working?
>
>
>
>
>
> import wx, os, codecs, chardet
>
> from books_db import Book, Author, Narrator, Series, Publisher, Genre,
> Session
>
> from sqlalchemy.exc import IntegrityError
>
>
>
> from books_db import Book, Author, Narrator, Series, Publisher, Genre,
> Session
>
>
>
> class RecordListPanel(wx.Panel):
>
> def __init__(self, parent):
>
> wx.Panel.__init__(self, parent=parent)
>
>
>
> self.list_ctrl = wx.ListCtrl(self, style=wx.LC_REPORT)
>
> self.list_ctrl.InsertColumn(0, 'Title', width=200)
>
> self.list_ctrl.InsertColumn(1, 'Author', width=200)
>
> self.list_ctrl.InsertColumn(2, 'Genre', width=200)
>
> self.list_ctrl.InsertColumn(3, 'Narrator', width=200)
>
> self.list_ctrl.InsertColumn(4, 'Publisher', width=200)
>
> self.list_ctrl.InsertColumn(5, 'Series', width=200)
>
> self.list_ctrl.InsertColumn(6, 'Series No.', width=100)
>
> self.populate_list_ctrl()
>
> #sizer = wx.BoxSizer(wx.VERTICAL)
>
> #sizer.Add(self.list_ctrl, 1, wx.EXPAND)
>
> #self.SetSizer(sizer)
>
>
>
> def populate_list_ctrl(self):
>
> session = Session()
>
> books = session.query(Book).all()
>
>
>
> for book in books:
>
> row = [book.title]
>
>
>
> # authors
>
> authors = ', '.join([author.author for author in book.authors])
>
> row.append(authors)
>
>
>
> # genres
>
> genres = ', '.join([genre.genre for genre in book.genres])
>
> row.append(genres)
>
>
>
> # narrators
>
> narrators = ', '.join([narrator.narrator for narrator in
> book.narrators])
>
> row.append(narrators)
>
>
>
> row.append(book.publisher.publisher)
>
> row.append(book.series.series)
>
> row.append(str(book.series_no))
>
>
>
> self.list_ctrl.Append(row)
>
> session.close()
>
>
>
> class EditPanel(wx.Panel):
>
> def __init__(self, parent):
>
> wx.Panel.__init__(self, parent=parent)
>
>
>
> # Initialize variables
>
> self.books = []
>
> self.current_book_index = 0
>
> self.record = {}
>
>
>
> # Create controls
>
> self.edit = wx.TextCtrl(self,
> style=wx.TE_MULTILINE|wx.SUNKEN_BORDER)
>
> # Load the books
>
> self.load_books_paths()
>
> # Load the first book into the edit field
>
> self.load_book()
>
>
>
> #sizer = wx.BoxSizer(wx.VERTICAL)
>
> #sizer.Add(self.edit, 1, wx.EXPAND)
>
> #self.SetSizer(sizer)
>
>
>
> def load_books_paths(self):
>
> for root, dirs, files in os.walk("c:\\books"):
>
> for filename in files:
>
> if filename.endswith(".txt"):
>
> filepath = os.path.join(root, filename)
>
> self.books.append(filepath)
>
> print("loaded file paths ")
>
>
>
> def load_book(self):
>
> # Get the current book file path
>
> current_book = self.books[self.current_book_index]
>
> self.record['path'] = current_book
>
> with open(current_book, 'rb') as f:
>
> contents = f.read()
>
> encoding = chardet.detect(contents)['encoding']
>
>
>
> try:
>
> with codecs.open(current_book, "r", encoding=encoding) as f:
>
> contents = f.read()
>
> except UnicodeDecodeError:
>
> content = "Unknown file type for " + current_book
>
>
>
> # Load the contents of the file into the text box
>
> self.edit.SetValue(contents)
>
>
>
> def priorBook(self, event):
>
> self.record.clear() # initialize record.
>
> # Move to the prior book and load it
>
> self.current_book_index -= 1
>
> if self.current_book_index < 0: # cannot pass 0.
>
> dlg = wx.MessageDialog(self, "Beginning of book path",
> caption="Record Warning", style=wx.OK|wx.CENTER, pos=wx.DefaultPosition)
>
> dlg.ShowModal()
>
> return
>
> self.load_book()
>
> prior_file = self.books[self.current_book_index]
>
> self.GetTopWindow().SetStatusText(f"Prior file: {prior_file}")
>
>
>
> def nextBook(self, event=None):
>
> self.record.clear() # initialize record.
>
> # Move to the next book and load it
>
> self.current_book_index += 1
>
> if self.current_book_index >= len(self.books):
>
> dlg = wx.MessageDialog(self, "end of book path",
> caption="Record Warning", style=wx.OK|wx.CENTER, pos=wx.DefaultPosition)
>
> dlg.ShowModal()
>
> return
>
> self.load_book()
>
> # Update status bar with path of next file
>
> next_file = self.books[self.current_book_index]
>
> self.GetTopWindow().SetStatusText(f"Next file: {next_file}")
>
>
>
> def titleSave(self, event):
>
> selected_text = self.edit.GetStringSelection()
>
> self.record['title'] = selected_text.strip()
>
> self.GetTopWindow().SetStatusText(f"title: {selected_text}")
>
>
>
> def authorSave(self, event):
>
> selected_text = self.edit.GetStringSelection()
>
> if 'author' not in self.record:
>
> self.record['author'] = []
>
> self.record['author'].append(selected_text.strip())
>
> self.GetTopWindow().SetStatusText(f"Author: {selected_text}")
>
>
>
> def aboutAuthorSave(self, event):
>
> selected_text = self.edit.GetStringSelection()
>
> if 'about_author' not in self.record:
>
> self.record['about_author'] = selected_text.strip()
>
> else:
>
> self.record['about_author'] = self.record['about_author'] + '\n'
> + selected_text.strip()
>
> self.GetTopWindow().SetStatusText("About Author saved")
>
>
>
> def descriptionSave(self, event):
>
> selected_text = self.edit.GetStringSelection()
>
> if 'description' not in self.record:
>
> self.record['description'] = selected_text.strip()
>
> else:
>
> self.record['description'] = self.record['description'] + "\n" +
> selected_text.strip()
>
> self.GetTopWindow().SetStatusText("Description saved")
>
>
>
> def seriesSave(self, event):
>
> selected_text = self.edit.GetStringSelection()
>
> self.record['series'] = selected_text.strip()
>
> self.GetTopWindow().SetStatusText(f"Series: {selected_text}")
>
>
>
> def seriesNoSave(self, event):
>
> selected_text = self.edit.GetStringSelection()
>
> self.record['series_no'] = int(selected_text.strip())
>
> self.GetTopWindow().SetStatusText(f"Series Number: {selected_text}")
>
>
>
> def narratorSave(self, event):
>
> selected_text = self.edit.GetStringSelection()
>
> if 'narrator' not in self.record:
>
> self.record['narrator'] = []
>
> self.record['narrator'].append(selected_text.strip())
>
> self.GetTopWindow().SetStatusText(f"Narrator: {selected_text}")
>
>
>
> def miscSave(self, event):
>
> selected_text = self.edit.GetStringSelection()
>
> if 'misc' not in self.record:
>
> self.record['misc'] = selected_text.strip()
>
> else:
>
> self.record['misc'] = self.record['misc'] + "\n" +
> selected_text.strip()
>
> self.GetTopWindow().SetStatusText("Misc saved")
>
>
>
> def genreSave(self, event):
>
> selected_text = self.edit.GetStringSelection()
>
> if 'genre' not in self.record:
>
> self.record['genre'] = []
>
> self.record['genre'].append(selected_text.strip())
>
> self.GetTopWindow().SetStatusText(f"Genre: {selected_text}")
>
>
>
> def publisherSave(self, event):
>
> selected_text = self.edit.GetStringSelection()
>
> self.record['publisher'] = selected_text.strip()
>
> self.GetTopWindow().SetStatusText(f"Publisher: {selected_text}")
>
>
>
> def durationSave(self, event):
>
> selected_text = self.edit.GetStringSelection()
>
> self.record['duration'] = selected_text.strip()
>
> self.GetTopWindow().SetStatusText(f"Duration saved:
> {selected_text}")
>
>
>
> def releaseSave(self, event):
>
> selected_text = self.edit.GetStringSelection()
>
> self.record['release'] = selected_text.strip()
>
> self.GetTopWindow().SetStatusText(f"Release: {selected_text}")
>
>
>
> def copyrightSave(self, event):
>
> selected_text = self.edit.GetStringSelection()
>
> self.record['copyright'] = selected_text.strip()
>
> self.GetTopWindow().SetStatusText(f"Copyright: {selected_text}")
>
>
>
> def reviewDb(self, event):
>
> # review the dict
>
> print (self.record)
>
> msgString = ""
>
> for key, value in self.record.items():
>
> if isinstance(value, int):
>
> value = str(value)
>
> elif isinstance(value, list) and value:
>
> for v in value:
>
> v += "\n"
>
> msgString += " ".join([key, value]) + "\n"
>
> dlg = wx.MessageDialog(self, msgString, caption="Record Content",
> style=wx.OK|wx.CENTER, pos=wx.DefaultPosition)
>
> dlg.ShowModal()
>
>
>
> def saveDb(self, event):
>
> if self.record.get('title') is None or self.record.get('author') is
> None or self.record.get('description') is None:
>
> dlg = wx.MessageDialog(self, "Cannot save update database. Not
> all required fields have been defined.", caption="Record Warning",
> style=wx.OK|wx.CENTER, pos=wx.DefaultPosition)
>
> dlg.ShowModal()
>
> return
>
> elif self.record.get('genre') is None:
>
> self.record.get['genre'] = "None"
>
> elif self.record.get('narrator') is None:
>
> self.record['narrator'] = []
>
> self.record['narrator'].append("None")
>
> elif self.record.get('publisher') is None:
>
> self.record['publisher'] = "None"
>
> elif self.record.get('title') == '' or
> self.record.get('description') == '':
>
> dlg = wx.MessageDialog(self, "Title and description are
> required before record can be saved to the database. ", caption="Record
> Warning", style=wx.OK|wx.CENTER, pos=wx.DefaultPosition)
>
> dlg.ShowModal()
>
> return
>
>
>
> # establish session with database.
>
> session = Session()
>
> try:
>
> # create objects
>
> publisher =
> session.query(publisher).filter_by(publisher=self.record.get('publisher')).f
> irst()
>
> if publisher is None:
>
> publisher = Publisher(publisher=self.record.get('publisher',
> ''))
>
>
>
> # check if author exists
>
> authors = []
>
> for author_name in self.record.get('author', []):
>
> author =
> session.query(Author).filter_by(author=author_name).first()
>
> if author is None:
>
> author = Author(author=author_name,
> about_author=self.record.get('about_author', ''))
>
> authors.append(author)
>
>
>
> # check if genre exists
>
> genres = []
>
> for genre_name in self.record.get('genre', []):
>
> genre =
> session.query(Genre).filter_by(genre=genre_name).first()
>
> if genre is None:
>
> genre = Genre(genre=genre_name)
>
> genres.append(genre)
>
>
>
> # check if narrator exists
>
> narrators = []
>
> for narrator_name in self.record.get('narrator', []):
>
> narrator =
> session.query(Narrator).filter_by(narrator=narrator_name).first()
>
> if narrator is None:
>
> narrator = Narrator(narrator=narrator_name)
>
> narrators.append(narrator)
>
>
>
> series = Series(series=self.record.get('series', ''))
>
> book = Book(title=self.record.get('title', ''),
>
> path=self.record.get('path', ''),
>
> release=self.record.get('release', ''),
>
> duration=self.record.get('duration', ''),
>
> copyright=self.record.get('copyright', ''),
>
> description=self.record.get('description', ''),
>
> misc=self.record.get('misc', ''),
>
> series_no=self.record.get('series_no', 0))
>
>
>
> book.publisher = publisher
>
> book.authors = authors
>
> book.narrators = narrators
>
> book.genres = genres
>
> book.series = series
>
>
>
> # add objects to session
>
> session.add_all([book, publisher, series] + authors + narrators
> + genres)
>
> # commit changes
>
> session.commit()
>
> self.GetTopWindow().SetStatusText("Record saved successfully")
>
> except Exception as e:
>
> session.rollback()
>
> print(f"Error occurred: {e}")
>
> self.GetTopWindow().SetStatusText("Record did not saved
> successfully")
>
> finally:
>
> session.close()
>
>
>
> def clearRecord(self, event):
>
> self.record.clear()
>
> self.GetTopWindow().SetStatusText("Record in memory cleared
> successfully")
>
>
>
> class MyApp(wx.App):
>
> def OnInit(self):
>
> # Create the main frame
>
> self.frame = wx.Frame(None, title="Library", size=(1920, 1080 ))
>
> self.frame.Maximize()
>
> sizer_main = wx.BoxSizer(wx.VERTICAL)
>
> # Create the two panels
>
> self.panel1 = EditPanel(self.frame)
>
> self.panel2 = RecordListPanel(self.frame)
>
> # Create the horizontal box sizers for the panels
>
> sizer_panel1 = wx.BoxSizer(wx.HORIZONTAL)
>
> sizer_panel2 = wx.BoxSizer(wx.HORIZONTAL)
>
>
>
>
>
> # Create the menubar
>
> menubar = wx.MenuBar()
>
> # Create the "Options" menu
>
> options_menu = wx.Menu()
>
> save_record_item = options_menu.Append(wx.ID_ANY, "Save
> Record\tCtrl+S", "Save to database")
>
> self.Bind(wx.EVT_MENU,self.panel1.saveDb, save_record_item)
>
> next_file_item = options_menu.Append(wx.ID_ANY, "Next file\tCtrl+N",
> "Load next file")
>
> prior_file_item = options_menu.Append(wx.ID_ANY, "Prior
> file\tCtrl+P", "Load prior file")
>
> review_record_item = options_menu.Append(wx.ID_ANY, "Review
> Record\tCtrl+r", "Review record")
>
> self.Bind(wx.EVT_MENU,self.panel1.reviewDb, review_record_item)
>
> self.Bind(wx.EVT_MENU,self.panel1.nextBook, next_file_item)
>
> self.Bind(wx.EVT_MENU,self.panel1.priorBook, prior_file_item)
>
> clear_record_item = options_menu.Append(wx.ID_ANY, "Clear
> Record\Alt+I", "Clear record in memory")
>
> self.Bind(wx.EVT_MENU,self.panel1.clearRecord, clear_record_item)
>
> options_menu.Append(wx.ID_EXIT, "Exit", "Exit the program")
>
> menubar.Append(options_menu, "&Options")
>
>
>
> # Create the "Save to record" menu
>
> save_menu = wx.Menu()
>
> title_item = save_menu.Append(wx.ID_ANY, "Title\tAlt+T", "Save book
> title")
>
> self.Bind(wx.EVT_MENU,self.panel1.titleSave, title_item)
>
> author_item = save_menu.Append(wx.ID_ANY, "Author\tAlt+A", "Save
> book author")
>
> self.Bind(wx.EVT_MENU,self.panel1.authorSave, author_item)
>
> series_item = save_menu.Append(wx.ID_ANY, "Series\tAlt+S", "Save
> book Series")
>
> self.Bind(wx.EVT_MENU,self.panel1.seriesSave, series_item)
>
> seriesNo_item = save_menu.Append(wx.ID_ANY, "SeriesNo\tCtrl+3",
> "Save Series No")
>
> self.Bind(wx.EVT_MENU,self.panel1.seriesNoSave, seriesNo_item)
>
> genre_item = save_menu.Append(wx.ID_ANY, "Genre\tAlt+G", "Save book
> genre")
>
> self.Bind(wx.EVT_MENU,self.panel1.genreSave, genre_item)
>
> description_item = save_menu.Append(wx.ID_ANY, "Description\tAlt+D",
> "Save book description")
>
> self.Bind(wx.EVT_MENU,self.panel1.descriptionSave, description_item)
>
> aboutAuthor_item = save_menu.Append(wx.ID_ANY, "About
> Author\tAlt+B", "Save about author")
>
> self.Bind(wx.EVT_MENU,self.panel1.aboutAuthorSave, aboutAuthor_item)
>
> narrator_item = save_menu.Append(wx.ID_ANY, "Narrator\tAlt+N", "Save
> book narrator")
>
> self.Bind(wx.EVT_MENU,self.panel1.narratorSave, narrator_item)
>
> release_item = save_menu.Append(wx.ID_ANY, "Release Date\tAlt+R",
> "Save book release date")
>
> self.Bind(wx.EVT_MENU,self.panel1.releaseSave, release_item)
>
> duration_item = save_menu.Append(wx.ID_ANY, "Duration\tCtrl+D",
> "Save book duration")
>
> self.Bind(wx.EVT_MENU,self.panel1.durationSave, duration_item)
>
> copyright_item = save_menu.Append(wx.ID_ANY, "Copyright\tAlt+C",
> "Save book copyright")
>
> self.Bind(wx.EVT_MENU,self.panel1.copyrightSave, copyright_item)
>
> publisher_item = save_menu.Append(wx.ID_ANY, "Publisher\tAlt+P",
> "Save book publisher")
>
> self.Bind(wx.EVT_MENU,self.panel1.publisherSave, publisher_item)
>
> misc_item = save_menu.Append(wx.ID_ANY, "Misc\tAlt+M", "Save book
> misc")
>
> self.Bind(wx.EVT_MENU,self.panel1.miscSave, misc_item)
>
> menubar.Append(save_menu, "Sa&ve to record")
>
>
>
> self.frame.SetMenuBar(menubar)
>
>
>
> # Create the status bar
>
> self.frame.CreateStatusBar()
>
> #self.statusbar.SetFieldsCount(3)
>
> #self.statusbar.SetStatusWidths([-2, -1, -1])
>
>
>
> # Set up the panel switching
>
> self.currentPanel = self.panel1
>
> self.panel1.SetFocus()
>
> self.frame.Bind(wx.EVT_KEY_DOWN, self.onKeyDown)
>
> self.frame.Show()
>
> self.SetTopWindow(self.frame)
>
>
>
> return True
>
>
>
> def onKeyDown(self, event):
>
> if event.GetKeyCode() == wx.WXK_F6:
>
> if self.currentPanel == self.panel1:
>
> self.currentPanel = self.panel2
>
> self.panel2.SetFocus()
>
> else:
>
> self.currentPanel = self.panel1
>
> self.panel1.SetFocus()
>
> else:
>
> event.Skip()
>
>
>
> # set focus to the current panel.
>
> self.currentPanel.SetFocus()
>
>
>
> if __name__ == '__main__':
>
> # Create the wx
>
> app = MyApp()
>
>
>
> # Start the main event loop
>
> app.MainLoop()
>
> _______________________________________________
> Tutor maillist -Tutor at python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor
More information about the Tutor
mailing list