Python Forum
Perfectly proportioned 3 frame wxpython application template
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Perfectly proportioned 3 frame wxpython application template
#1
Here is a framework for a three panel wxpython (phoenix) application. With
proper sizing. The aspect ratio of 1.779 to 1 is supposed to be the proper ratio
for visually correct window size.

All initial individual panel widths and heights are based on the size of the main wx.Frame.
If you modify this size, all panels should follow suit.

The bottom frame contains two widgets, so a vertical sizer is used to keep them in perspective.

The TextCtrl on the right panel has it's own sizer, and uses the proportion flag, and expand flag.
This sizer is needed or the TextCtrl will not expand properly.

The bottom panel also needs a vertical sizer to keep the button on the bottom (two widgets in this pane).

The AUI Manager is used, which automatically gives you docking panels and maintains pane resizing automatically.

*** Update Feb 11, 2020 ***

I had a need to use this framework, and when testing noted that some of the size code was depreciated.
wxpython now requires all sizes be integers.
Changes are in line 44 to 70 (cast to integer)
so here's corrected code:
import wx
import wx.aui as aui
import wx.lib.agw.aui as aui


class TryMethods(wx.Frame):
    """
    Initialize - inherits from wx.Frame. Instantiates all widgets and variables for application

    :param parent: (wx.Window) The window parent. This may be, and often is, None. If it is not None, the frame
                   will be minimized when its parent is minimized and restored when it is restored (although it
                   will still be possible to minimize and restore just this frame itself).

    :param id:     (wx.WindowID) The window identifier. It may take a value of -1 to indicate a default value.

    :param title:  (string)  The caption to be displayed on the frame’s title bar.

    :param pos:    (wx.point) The window position. The value DefaultPosition indicates a default position,
                   chosen by either the windowing system or wxWidgets, depending on platform.

    :param size:   (wx.Size) – The window size. The value DefaultSize indicates a default size, chosen by either
                   the windowing system or wxWidgets, depending on platform. Here use properly proportioned
                   (according to the window size gods) width and height.

    :param style:  (long) – The window style. See wx.Frame class description.

    :param name:   (string) The name of the window. This parameter is used to associate a name with the item,
                   allowing the application user to set Motif resource values for individual windows.
    """

    def __init__(self, parent, id=wx.ID_ANY, title="Try PuMuPDF methods", pos=wx.DefaultPosition,
                 size=(1200, 675), style=wx.DEFAULT_FRAME_STYLE, name='TryMethods'):
        # ideal size: width = height x 1.77864583 or height = width / 1.77864583
        self.main_width = size[0]
        self.main_height = size[1]

        app = wx.App()
        wx.Frame.__init__(self, parent, id, title, pos, size, style)
        app.SetTopWindow(self)
        # self.pnl = pnl = MainPanel(self)
        self._mgr = aui.AuiManager(self)

        # This is 30% of main width
        left_panel_width = int(self.main_width * .3)
        # This is 75% of main height
        left_panel_height = int(self.main_height * .75)
        left_panel_sz = left_panel_width, left_panel_height  # combined for widget size

        right_panel_width = self.main_width - \
            left_panel_width  # which is 70% of main width
        right_panel_height = left_panel_height  # Keep same height as left panel
        right_panel_sz = right_panel_width, right_panel_height

        bottom_panel_width = self.main_width  # full width
        bottom_panel_height = int(
            self.main_height * .20)  # 20 % of main height
        bottom_panel_sz = bottom_panel_width, bottom_panel_height

        self.left_panel = wx.Panel(self, id=wx.ID_ANY, size=left_panel_sz)
        self.right_panel = wx.Panel(self, id=wx.ID_ANY, size=right_panel_sz)
        self.bottom_panel = wx.Panel(self, id=wx.ID_ANY, size=bottom_panel_sz)

        self.pdf_selector = wx.ListCtrl(self.left_panel, id=wx.ID_ANY, style=wx.NO_BORDER | wx.TE_MULTILINE,
                                        size=left_panel_sz, name='PDF Selector')

        self.pdf_selector.InsertColumn(
            0, 'PDF Id', width=int(left_panel_width * .25))
        self.pdf_selector.InsertColumn(
            1, 'Title', width=int(left_panel_width * .75))
        self.pdf_selector.SetMinSize(left_panel_sz)

        self.pdf_selector_load()

        hsizer = wx.BoxSizer(wx.HORIZONTAL)
        self.detail_win = wx.TextCtrl(self.right_panel, id=wx.ID_ANY, value="Choose Methods",
                                      pos=wx.DefaultPosition, size=right_panel_sz,
                                      style=wx.NO_BORDER | wx.TE_MULTILINE, name='PdfSummary')

        hsizer.Add(self.detail_win, proportion=1, flag=wx.EXPAND)
        hsizer.SetSizeHints(self.right_panel)
        self.right_panel.SetSizer(hsizer)

        self.optionList = ['Importing the Bindings', 'Opening a Document', 'Document Methods and Attributes',
                           'Accessing Meta Data', 'Working with Outlines', 'Working with Pages',
                           'Inspecting the Links of a Page', 'Rendering a Page', 'Saving the Page Image in a File',
                           'Displaying the Image in Dialog Managers', 'Extracting Text', 'Searching Text',
                           'PDF Maintenance', 'Modifying, Creating, Re-arranging and Deleting Pages',
                           'Joining and Splitting PDF Documents', 'Saving', 'Closing']

        vsizer = wx.BoxSizer(wx.VERTICAL)
        self.method_selector = wx.RadioBox(self.bottom_panel, id=wx.ID_ANY, choices=self.optionList,
                                           majorDimension=4, style=wx.RA_SPECIFY_COLS)
        vsizer.Add(self.method_selector, 0, 0, 0)

        self.method_button = wx.Button(
            self.bottom_panel, id=wx.ID_ANY, label='Show Method')
        vsizer.Add(self.method_button, 0, 0, 0)
        self.method_button.Bind(wx.EVT_BUTTON, self.method_selected)

        vsizer.SetSizeHints(self.bottom_panel)
        self.bottom_panel.SetSizer(vsizer)

        self._mgr.AddPane(
            self.left_panel, aui.AuiPaneInfo().Left().Caption("Left Panel"))
        self._mgr.AddPane(self.right_panel,
                          aui.AuiPaneInfo().Center().Caption("Right Panel"))
        self._mgr.AddPane(self.bottom_panel,
                          aui.AuiPaneInfo().Bottom().Caption("Bottom Panel"))

        self._mgr.Update()
        self.Show()

        app.MainLoop()

    def pdf_selector_load(self):
        pass

    def method_selected(self, event):
        radio_index = self.method_selector.GetSelection()
        print(f'Selected Method: {self.optionList[radio_index]}')


if __name__ == '__main__':
    tm = TryMethods(None)
   

Updated 27 Feb 2020 - Removed depreciated code as it was easily confused with new code
Reply
#2
Small error here
    def method_selected(self, event):
        radio_index = self.method_selector.GetSelection()
        print(f'Selected Method: {self.optionList[radio_index]}')
 
comma missing
    def method_selected(self, event):
        radio_index = self.method_selector.GetSelection()
        print(f,'Selected Method: {self.optionList[radio_index]}')
 
Otherwise great example, thanks
Reply
#3
:-) it's not an error but f-string, available in Python 3.6+
https://www.python.org/dev/peps/pep-0498/

With comma you will get NameError, f is not defined
Reply
#4
I think I should look at wx.

1.618 ratio?
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#5
Quote:1.618 ratio?
Or something like that
Reply
#6
I just looked for other 3 frame wxpython examples, here's the results:
yahoo: https://goo.gl/VfuKdh
google: https://goo.gl/JQLiXy
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020