SQLAlchemy Date Problem

@mfones

I see the example I mentioned the other day wasn’t enlightening (again, horse hockey or ?)
so let’s try it less juicy (or more alchemistic ?)
there would usually be a main sizer for a GUI page (Frame) constituting the graphical concept (without concept :cold_sweat:) and sort of inside all the controls are placed (of course wrapped by an appropriate sizer to make it fill the space)
luckily there are only a few of them, just like the data types of sqlite, and the number of parameters are very small and almost identical
play around with them & enjoy how nice they do their duty :cowboy_hat_face:

@da-dada I don’t understand your first sentence. Actually a lot of your expressions don’t translate. What is your native language? That aside…

I’m almost there, there are so many combinations with sizers it’s a chore to keep track of them.
I’m trying to get three elements into a single notebook tab. The search, Olv and CRUD.

With Notebooks can you confirm that a panel needs to be created or can the notebooks parent be self?
Here’s what I have currently

panel = wx.Panel(self)

The notebook addition, please confirm is self or panel needs to used here, or does it matter as long as your consistant?

notebook = wx.Notebook(self, style=wx.NB_TOP)
notebook_sizer = wx.BoxSizer(wx.HORIZONTAL)
notebook_sizer.Add(notebook, 1, wx.ALL | wx.EXPAND , 5)

Had to use this to get the notebook visible and I can’t explain why. Any idea?

panel.SetSizer(notebook_sizer)

I have sizers for all three, with CRUD buttons grouped into a single sizer.

main_sizer = wx.BoxSizer(wx.VERTICAL)
search_sizer = wx.BoxSizer(wx.HORIZONTAL)
btn_sizer = wx.BoxSizer(wx.HORIZONTAL)

Creating the tab’s

tabOne = wx.Panel(notebook)
notebook.AddPage(tabOne, 'Ledger')
tabTwo = wx.Panel(notebook)
notebook.AddPage(tabTwo, 'Budget')

olv_sizer

olv_sizer = wx.BoxSizer(wx.HORIZONTAL)
olv_sizer.Add(self.ledger_results_olv, 1, wx.ALL | wx.EXPAND, 5)

One of the CRUD buttons, they just repeat the same format and added to btn_sizer

btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
add_record_btn = wx.Button(tabOne, label="Add")
add_record_btn.Bind(wx.EVT_BUTTON, self.add_record)
btn_sizer.Add(add_record_btn, 0, wx.ALL, 5)

Now the main sizer.

main_sizer = wx.BoxSizer(wx.VERTICAL)
main_sizer.Add(search_sizer, 1, wx.ALL | wx.EXPAND, 1)
main_sizer.Add(olv_sizer, 1, wx.ALL | wx.EXPAND, 1)
main_sizer.Add(btn_sizer, 1, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 1)
main_sizer.Add(panel, 0, wx.ALL | wx.EXPAND, 5)
self.SetSizer(main_sizer)

Wondering if something is obviously wrong and I’m not seeing it. This is such a rabbits hole now. I think I’m confusing things. The order of main_sizer is critical. If I comment out the Add panel in main_sizer there’s no display. Here’s what I have so far.


I think that the order is incorrect but I just can’t see it. The coloring is just for reference. Blue is the tab, pink is the panel and the dark yellow is the notebook.
Anyone see anything obviously wrong? Olv is not displaying. Set to vertically stretchable (1) using a Horizontal BoxSizer, but main_sizer is a Vertical BoxSizer. Is there a conflict there? I’ve tried both.
What am I missing?

I find that wxGlade is very useful for designing the layout of a UI. It allows you to easily test how the UI responds to resizing of a frame or dialog.

I have attempted to create a similar layout to what you show. wxGlade does not have direct support for ObjectListView controls, so for simplicity I have substituted a ListCtrl as it has a similar appearance.

Here is the code it generates:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
#
# generated by wxGlade 1.0.5 on Thu Apr 13 08:58:42 2023
#

import wx

# begin wxGlade: dependencies
# end wxGlade

# begin wxGlade: extracode
# end wxGlade


class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: MyFrame.__init__
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((750, 550))
        self.SetTitle("frame")

        # Menu Bar
        self.frame_menubar = wx.MenuBar()
        wxglade_tmp_menu = wx.Menu()
        wxglade_tmp_menu.Append(wx.ID_ANY, "Exit", "")
        self.frame_menubar.Append(wxglade_tmp_menu, "File")
        self.SetMenuBar(self.frame_menubar)
        # Menu Bar end

        self.frame_statusbar = self.CreateStatusBar(1)
        self.frame_statusbar.SetStatusWidths([-1])
        # statusbar fields
        frame_statusbar_fields = ["frame_statusbar"]
        for i in range(len(frame_statusbar_fields)):
            self.frame_statusbar.SetStatusText(frame_statusbar_fields[i], i)

        self.main_panel = wx.Panel(self, wx.ID_ANY)

        main_sizer = wx.BoxSizer(wx.VERTICAL)

        self.notebook = wx.Notebook(self.main_panel, wx.ID_ANY)
        main_sizer.Add(self.notebook, 1, wx.EXPAND, 0)

        self.ledger_pane = wx.Panel(self.notebook, wx.ID_ANY)
        self.notebook.AddPage(self.ledger_pane, "Ledger")

        ledger_main_sizer = wx.BoxSizer(wx.VERTICAL)

        ledger_search_sizer = wx.BoxSizer(wx.HORIZONTAL)
        ledger_main_sizer.Add(ledger_search_sizer, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 4)

        ledger_search_label = wx.StaticText(self.ledger_pane, wx.ID_ANY, "Search By:")
        ledger_search_sizer.Add(ledger_search_label, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 2)

        self.ledger_search_combo_box = wx.ComboBox(self.ledger_pane, wx.ID_ANY, choices=[], style=wx.CB_DROPDOWN)
        ledger_search_sizer.Add(self.ledger_search_combo_box, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 4)

        self.ledger_search_text_ctrl = wx.TextCtrl(self.ledger_pane, wx.ID_ANY, "")
        ledger_search_sizer.Add(self.ledger_search_text_ctrl, 0, wx.ALIGN_CENTER_VERTICAL, 0)

        self.ledger_list_ctrl = wx.ListCtrl(self.ledger_pane, wx.ID_ANY, style=wx.LC_HRULES | wx.LC_REPORT | wx.LC_VRULES)
        self.ledger_list_ctrl.AppendColumn("A", format=wx.LIST_FORMAT_LEFT, width=-1)
        self.ledger_list_ctrl.AppendColumn("B", format=wx.LIST_FORMAT_LEFT, width=-1)
        self.ledger_list_ctrl.AppendColumn("C", format=wx.LIST_FORMAT_LEFT, width=-1)
        ledger_main_sizer.Add(self.ledger_list_ctrl, 1, wx.ALL | wx.EXPAND, 4)

        ledger_button_sizer = wx.BoxSizer(wx.HORIZONTAL)
        ledger_main_sizer.Add(ledger_button_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.BOTTOM | wx.TOP, 4)

        self.ledger_add_button = wx.Button(self.ledger_pane, wx.ID_ANY, "Add")
        ledger_button_sizer.Add(self.ledger_add_button, 0, wx.RIGHT, 8)

        self.ledger_edit_button = wx.Button(self.ledger_pane, wx.ID_ANY, "Edit")
        ledger_button_sizer.Add(self.ledger_edit_button, 0, wx.RIGHT, 8)

        self.ledger_delete_button = wx.Button(self.ledger_pane, wx.ID_ANY, "Delete")
        ledger_button_sizer.Add(self.ledger_delete_button, 0, wx.RIGHT, 8)

        self.ledger_show_all_button = wx.Button(self.ledger_pane, wx.ID_ANY, "Show All")
        ledger_button_sizer.Add(self.ledger_show_all_button, 0, 0, 0)

        self.ledger_pane.SetSizer(ledger_main_sizer)

        self.main_panel.SetSizer(main_sizer)

        self.Layout()
        # end wxGlade

# end of class MyFrame

class MyApp(wx.App):
    def OnInit(self):
        self.frame = MyFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True

# end of class MyApp

if __name__ == "__main__":
    app = MyApp(0)
    app.MainLoop()

For the parent/child hierarchy:
The Frame is the parent of the main Panel.
The main Panel is the parent of the Notebook.
The Notebook is the parent of the Panels that comprise its panes/pages.
Each pane is the parent of all the controls it contains.

When adding an item or sizer to a vertical BoxSizer, the proportion argument specifies how the much that item will be stretched vertically. In my example only the ListCtrl needs to be stretched vertically, so its proportion argument is set to one. The search sizer and button sizer do not need to stretch vertically, so their proportion arguments are set to zero.

I hope you can adapt ideas from this example to your design.

Tested using Python 3.10.6 + wxPython 4.2.0 gtk3 (phoenix) wxWidgets 3.2.0 on Linux Mint 21.1

1 Like

Copy and pasted the code and to my delight it’s exactly what I was hoping to accomplish. I’ll need some time to compare your code to mine. I suspect my problem is with the parent/child hierarchy in part. I’ll have a look at wxGlade. Thanks for your extra effort on my question. This has been really frustrating. Armed with this information I can hopefully get closer to the answer. I really appreciate this.
Can you tell me a little bit about the programming work you do? Do you do this for a living? Very impressive to me that you are able to decipher what I was struggling with and provide working code.
If direct messaging is more suitable, feel free to message me directly. Not sure how this works on this platform. Sticking to the forum is ok too.

Best regards.

I started doing software development while working for the UK Met Office. In 1996 I moved to the UK division of a US owned multinational IT company which was later bought by another US owned multinational IT company. That work was initially in C and Motif, but I started specialising in Python programming in 2000. I retired from work in 2014, but have continued to develop a number of my own applications purely for personal use and also to try to keep my brain active.

The retirement picture is getting clearer for me. I can retire now but unless I win a lottery, I’ll hold off for another 5 years. I work in electrical utility Engineering in Canada. Love to program for the same reason you mentioned, keeping the brain active. But not my core function. Hoping to have this project to keep adding features to. I am hoping to use it to manage the financials of a hockey team that I manage in my spare time. Currently using way too many spreadsheets that are prone to error. Moving from a spreadsheet concept to a database seemed like a logical step.
Your experience is valuable. Love to touch base with you offline if you can spare some time.

@mfones sorry for my untranslatables (my mother never listened :unamused:)

I can assure you that is a value in itself and every professional accountant will hug you for it (in Europe there seems to be much less of this spreadsheet madness), but a very big hurdle is translating historically grown spreadsheets into a somewhat correct relational database
the Gui afterwards is less problematic unless the faults of the base penetrate :sweat_smile:

@da-data no worries on the translation. What is your native language?

unlike @RichardT I started off with ALGOL & punched card (it was compulsory :rage: & I was interested in philosophy)

What is your native language?

After time spent learning wxGlade, creating the GUI again, success! With one small problem …


So a couple of details: panel is defined in the frame class, however panel is again defined in the class that has the majority of the GUI. That is the “guts” of the display, everything inside panel as it were. The pink box comes from this:

panel = wx.Panel(self)
panel_sizer = wx.BoxSizer(wx.VERTICAL
panel.SetBackgroundColour((175, 58, 148)) # OneNote Pink

I’ve tied to locate a sizer that is not fully expanded, nothing. Maybe an accumulation of margins? I’ve used 5 for all my spacers. Looks like the square might be 20 or 25. I believe the grey color in the back is the frame. So I gave the frame the OneNote Pink background. Still the same problem. The corner of the box encroaches into the Ledger tab.
Not sure it this helps but here are the last sizer calls. There is no tabTwo sizer.

tabOne.SetSizer(tabOne_sizer)
self.SetSizer(panel_sizer)
self.Layout()
self.Centre()

Any thoughts?

My first programming course in 1976 was for FORTRAN using punched cards. However, my employers then decided I should become a weather forecaster. Fortunately by the time I did eventually switch to IT work, the technology had advanced significantly.

I had something similar to this once when I used a wx.StaticBoxSizer with its label set to an empty string, instead of a plain wx.BoxSizer.

However, if that is not the case, could you please upload the .wxg file and I will take a look at it?

Note: if you use the forum’s Upload option instead of pasting the file, you will need to zip the file first as .wxg is not one of the accepted file types.

No wx.StaticBoxSizers in the project. There is one in the wxGlade layout but not the project.wxAccMan-master.zip (635.2 KB)
The entire project is in the zip. There is a folder wxGlade with the wxGlade layout. The final version in the srcreen capture is wxAccManGlade.py

@da-dada

I spent many a wet afternoon punching paper tape loops, by hand, for a Messer Griesheim cutting machine and punching cards, by hand, on a tiny machine like a manual typewriter.
Somewhere, I still have the paper tape punching widget. It’s about the size of a matchbox.
Ah, the bad old days, thank goodness we can look back on them! :wink:

GOSUB 200

Thanks for uploading the code.

In wxAccManGlade.py in the following code:

class LedgerPanel(wx.Panel):
    """
    The main display of the UI. Displaying the db records. Checks to see if db 
    is present, if not it's created.
    Search By: drop down, search text box. 
    The 4 buttons in the bottom middle under the view panel, Add, Edit, Delete
    and Show All.
    """
    def __init__(self, parent):
        super().__init__(parent)


        panel = wx.Panel(self)  # <--- this is not used?
        panel_sizer = wx.BoxSizer(wx.VERTICAL)
        panel.SetBackgroundColour((175, 58, 148)) # OneNote Pink

You create a wx.Panel object and assign it to the name panel. Apart from setting its background colour to highlight it, nothing else happens to it. I’m not sure why it is there, but it doesn’t appear to be necessary so just deleting it should solve the problem.

Yep, that’s got it. I was confused on the use of panel. I understood that a panel needed to be created in the frame and that all the guts would be placed in the frames panel. However as you probably noticed panel is defined in the previous class. Thats one of things what confused me. Not that it takes much to confuse me. I can now move on to breaking something else.

This brings up another question for me regarding documentation. How do you capture all these little bits of information? I have so many notes now that I need indexes to find anything. I use OneNote for the most part. Once you solve a problem how do you document it? I have put notes in the code itself, but the code can be become overwhelmed with notes making them a distraction. What method did you use in your professional career? How about with your personal projects?
Speaking of personal projects, do you have anything you can share? Interested to see what you’ve created.

Best regards.

Mike.

Hi Mike,

Good to hear the problem was fixed.

On the last project I worked on before I retired we had our own local Wiki which had the advantage of a built in search function that made it easier to find information. However, updating the Wiki wasn’t an official task, so not many people bothered adding information to it.

I agree that adding lots of comments and long docstrings can be counter-productive. From experience I find that most people don’t actually read them, or bother updating them when the code has been changed.

Over the years I have tried various things such as making notes in text editors and word processors. However the enthusiasm has never lasted long and the notes have ended up being abandoned.

One technique I still use is to write notes by hand in a notebook. However, this is more an aid to the ongoing thought process, rather than a repository for future reference. I do occasionally look back on earlier entries and sometimes find something useful, but it is often difficult to find what I am looking for.

Another technique I have used for a long time is to build up a separate directory structure for small experiments. That directory contains a hierarchy of folders on different topics. For each topic there could be several files that demonstrate particular features of a topic, e.g. how to apply styles in a RichTextCtrl. Alternatively some of the files demonstrate how not to do something.

If I want to find a particular piece of information but can’t remember which sub-folder it might be in, I will run a command line tool to do a recursive search of the experiments directory for a word or phrase. If that search comes up empty, I try again in the parent directory of my personal projects.

I’m sorry but I would rather not share my personal projects. They are not designed to be portable and most of them would only run on linux. My health is not good at the moment and I am concerned about having to answer a lot of additional questions about them.

Best Regards,
Richard

Sorry to hear about your health. I do hope that your condition gets better. I’ve only started to pick you brain. Guaranteed that I would inundate you with questions on your personal projects. I agree it’s a good idea to keep your projects close to your chest. :grinning:
Take care and get well soon.

Best regards,
Mike