Re: Custom Dialog Problems and Observations

Lawrence Gray <[email protected]> Sat, 25 Apr 2020 13:54:41 -0400
Newsgroups gmane.comp.python.wxglade
Message-ID <CAJFU_Kp1YsPu6WhaT+Aky2-vQA0-YK08Fg1Rt0Lu3eJDJUtWWA@mail.gmail.com>
Again, thanks for the prompt reply. You wrote:

> You can use Ctrl+X, Ctrl+C, Ctrl+I, Ctrl+R to edit. I'm not sure whether a
> spin button or so would look nice.
>
Using "Code to be inserted after" is probably the easier way, though, as
> you can just copy and paste example code from the documentation and the
> demos.
>
I don't want to get into a discussion of "Aesthetics vs Ergonomics" of the
user interface. I have another suggestion that might pique your interest
which should not affect the visual aspect of the extra property section of
the code panel. Since the properties and their values can be selected,
provide a 'right-click' menu with items 'move up' and 'move down'. There
seems to be a distinction with selecting the list cells and selecting the
content of the cells an the 'tool-tip' pops up inconveniently blocking the
ability to right-click.

> The new structure is not enforced.
>
Sorry, I misspoke, I meant that it was created by default. You certainly
can change it afterwards

> not include class functions __set_properties and __set_layout. Everything
>> is rolled up into the __init__ function. I am not a fan of this style and I
>> hope this is not a permanent change or have I missed a toggle in the
>> wxglade application to alter this behaviour. I like the organization these
>> class functions provide.
>>
>
> Have you ever created a GUI manually? I doubt that you have splitted it
> this way as it's almost impossible to read and maintain.
>
No, I haven't tried. I have always depended on an application such as
wxGlade and before that boaConstructor which I believe had wxGlade embedded
in it. I am relatively new to GUI programming and still trying to get my
head around OO programming in general and event-based programming
specifically. Most of my programming experience has been with CLI  in
python, basic or C. Always very linear. I always tried to compartmentalize
my code so I could see the flow and understand what I had written at a
later time. This is why I like the separation of the __init__,
__set_properties and __set_layout functions. This compartmentalization has,
in my simple example, turned on the light-bulb in my head. I am beginning
to understand what is going on.

> Also it breaks the association of controls with their labels and therefore
> makes it difficult to use screen readers.
>
I'm not sure I see this. I found it easier to see the associations. Screen
readers-difficult? I use notepad++ to view the generated code and the
code-folding makes it easy to hide functions and classes

> In addition, without the split it's possible to achieve almost anything
> with the "Code to be inserted" properties. With the split the results are
> more or less unpredictable.
>
Again, I don't see this, but that might be true for a more complicated  GUI
layout. In my original example. I placed comment lines at the beginning and
end of the pre and post-fabrication code blocks. The consequence was that I
could immediately see where the code was placed and understand the
significance of its placement. wxGlade automatically places markers around
the extra code before the class definition. I will go so far as to suggest
that wxGlade should do the same for the pre and post-fabrication code
blocks; including the widget name in the marker. eg., '#begin speedmeter_1
pre-fabrication code'. Until I better understand and become more agile in
creating GUI applications, I will probably do this manually all the time. I
have attached a python example. I like the organization of the resulting
code layout. Although there is some code duplication that results from
duplicating the speedmeter widget, I like the fact that I can see where
everything in the output code derives from within wxGlade.

> I thought about a 'create_gui' and 'create_menu' method, but with these
> it's difficult for the user to see how the extra code properties are to be
> used. (Mainly because then the frame extra code would be in a different
> method.)
>
 I'm not sure that I understand what you are getting at. I prefer the
layout of the code from v0.9.5 rather than 0.9.9pre for reasons given above.

> I read in one of your replies on the issue trackers that you were planning
> to provide, in v1.1, complete listing of event types in the event panel.
> Are you considering the same for all available properties for widgets? I'm
> sure you have.
>
>
> I don't have such plans. I would accept a pull request, though. This would
> require someone to extend the wconfig.py files with lists of supported
> properties. Then, a dir(widget) minus the supported properties could be
> shown for the user to select. Maybe together with a help button to open the
> wxPython documentation.
>
> My focus for 1.0 is the internal structure. For 1.1 Undo and Re-do are on
> the list and most likely the event editor. With the events, the difficult
> part is to find a proper structure / grouping such that the user is able to
> find the relevant events without being overwhelmed by the sheer number of
> available events.
>
Noted. I am not at a sufficient level of understanding that I dare get that
deep in the weeds. Your positive response and attention to my issue is
encouraging.
Regards
-- 
------------------------------

*Lawrence Gray *
------------------------------


On Sat, 25 Apr 2020 at 07:02, Dietmar Schwertberger <
[email protected]> wrote:

> On 25.04.2020 06:44, Lawrence Gray wrote:
>
> matter as they are all predetermined. But rather than having to revise the
> list of properties and values manually, I was suggesting/hoping for some
> way to move up/down the list with selectors or some other means.
>
> You can use Ctrl+X, Ctrl+C, Ctrl+I, Ctrl+R to edit. I'm not sure whether a
> spin button or so would look nice.
>
> Using "Code to be inserted after" is probably the easier way, though, as
> you can just copy and paste example code from the documentation and the
> demos.
>
>
> With regards to the sequence I have been using
> Frame->sizer->panel->sizer.... except in this case of the speedmeter where
> I started with what was provided. I notice that wxGlade-0,9,9pre enforces
> the paradigm you suggested. No argument from me. I also noted that the code
> generated by 0.9.9pre does
>
> The new structure is not enforced. You still can use any combination you
> want:
>     Frame -> sizer -> panel -> sizer
>     Frame -> panel -> sizer     (this is the recommended way and available
> from the creation dialog)
>     Frame -> sizer      (absolutely not recommended for Windows)
>     Frame -> sizer - > Notebook     (a particularly ugly structure)
>     Frame -> Notebook
>
>
> not include class functions __set_properties and __set_layout. Everything
> is rolled up into the __init__ function. I am not a fan of this style and I
> hope this is not a permanent change or have I missed a toggle in the
> wxglade application to alter this behaviour. I like the organization these
> class functions provide.
>
> Have you ever created a GUI manually? I doubt that you have splitted it
> this way as it's almost impossible to read and maintain. Also it breaks the
> association of controls with their labels and therefore makes it difficult
> to use screen readers.
> In addition, without the split it's possible to achieve almost anything
> with the "Code to be inserted" properties. With the split the results are
> more or less unpredictable.
>
> I thought about a 'create_gui' and 'create_menu' method, but with these
> it's difficult for the user to see how the extra code properties are to be
> used. (Mainly because then the frame extra code would be in a different
> method.)
>
> I read in one of your replies on the issue trackers that you were planning
> to provide, in v1.1, complete listing of event types in the event panel.
> Are you considering the same for all available properties for widgets? I'm
> sure you have.
>
> I don't have such plans. I would accept a pull request, though. This would
> require someone to extend the wconfig.py files with lists of supported
> properties. Then, a dir(widget) minus the supported properties could be
> shown for the user to select. Maybe together with a help button to open the
> wxPython documentation.
>
> My focus for 1.0 is the internal structure. For 1.1 Undo and Re-do are on
> the list and most likely the event editor. With the events, the difficult
> part is to find a proper structure / grouping such that the user is able to
> find the relevant events without being overwhelmed by the sheer number of
> available events.
>
>
> Regards,
>
> Dietmar
>
>
> _______________________________________________
> wxGlade-general mailing list
> wxGlade-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
> https://lists.sourceforge.net/lists/listinfo/wxglade-general
>

_______________________________________________
wxGlade-general mailing list
wxGlade-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/wxglade-general
speedmeter 2.py (text/plain, 6.1 KB)
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#
# generated by wxGlade 0.9.5 on Sat Apr 25 13:24:27 2020 from "D:\Lawrence Gray\My Documents\Python\wxGlade\speedmeter test 2.wxg"
#

import wx

# begin wxGlade: dependencies
import gettext
# end wxGlade

# begin wxGlade: extracode
"""
An initial attempt at creating a speedmeter with more functions enabled.
A learning container for understanding how to implement a custom widget and
use the features of wxglade
"""
import wx.lib.agw.speedmeter as SM
from math import pi, sqrt
# 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((600, 300))
        self.panel_2 = wx.Panel(self, wx.ID_ANY)
        # begin <speedmeter_2> pre-fabrication code
        SMStyle=(SM.SM_DRAW_HAND |
                 SM.SM_DRAW_SECTORS | 
                 SM.SM_DRAW_MIDDLE_TEXT | 
                 SM.SM_DRAW_SECONDARY_TICKS)
        # end <speedmeter_2> pre-fabrication code
        self.speedmeter_2 = SM.SpeedMeter(self.panel_2, wx.ID_ANY, agwStyle=SMStyle)
        # begin <speedmeter_2> post-fabrication code
        self.Intervals = range(0,201,20)
        self.NumIntervals = len(self.Intervals)-1
        self.ticks = [str(interval) for interval in self.Intervals]
        self.speedmeter_2.DrawExternalArc(False)
        # end <speedmeter_2> post-fabrication code
        self.slider_2 = wx.Slider(self.panel_2, wx.ID_ANY, 150, 0, 200, style=wx.SL_HORIZONTAL | wx.SL_MIN_MAX_LABELS)
        self.panel_1 = wx.Panel(self, wx.ID_ANY)
        # begin pre-fabrication code
        SMStyle=(SM.SM_DRAW_HAND |
                 SM.SM_DRAW_SECTORS | 
                 SM.SM_DRAW_MIDDLE_TEXT | 
                 SM.SM_DRAW_SECONDARY_TICKS)
        # end pre-fabrication code
        self.speedmeter_1 = SM.SpeedMeter(self.panel_1, wx.ID_ANY, agwStyle=SMStyle)
        # begin <speedmeter_1> post-fabrication code
        self.Intervals = range(0,201,20)
        self.NumIntervals = len(self.Intervals)-1
        self.ticks = [str(interval) for interval in self.Intervals]
        self.speedmeter_1.DrawExternalArc(False)
        # end <speedmeter_1> post-fabrication code
        self.slider_1 = wx.Slider(self.panel_1, wx.ID_ANY, 90, 0, 200, style=wx.SL_HORIZONTAL | wx.SL_MIN_MAX_LABELS)

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_COMMAND_SCROLL, lambda event: self.speedmeter_2.SetSpeedValue(event.GetEventObject().GetValue()), self.slider_2)
        self.Bind(wx.EVT_COMMAND_SCROLL, lambda event: self.speedmeter_1.SetSpeedValue(event.GetEventObject().GetValue()), self.slider_1)
        # end wxGlade

    def __set_properties(self):
        # begin wxGlade: MyFrame.__set_properties
        self.SetTitle(_("frame_1"))
        self.speedmeter_2.SetAngleRange(-pi/6,7*pi/6)
        self.speedmeter_2.SetHandColour(wx.Colour(0,50,255))
        self.speedmeter_2.SetIntervals(self.Intervals)
        self.speedmeter_2.SetIntervalColours([wx.BLACK]*self.NumIntervals)
        self.speedmeter_2.SetMiddleText("km/h")
        self.speedmeter_2.SetMiddleTextColour(wx.WHITE)
        self.speedmeter_2.SetMiddleTextFont(wx.Font(8,wx.FONTFAMILY_SWISS,wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
        self.speedmeter_2.SetNumberOfSecondaryTicks(4)
        self.speedmeter_2.SetSpeedValue(150)
        self.speedmeter_2.SetTicks(self.ticks)
        self.speedmeter_2.SetTicksColour(wx.WHITE)
        self.speedmeter_2.SetTicksFont(wx.Font(7,wx.FONTFAMILY_SWISS,wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
        self.speedmeter_1.SetAngleRange(-pi/6,7*pi/6)
        self.speedmeter_1.SetHandColour(wx.Colour(255,50,0))
        self.speedmeter_1.SetIntervals(self.Intervals)
        self.speedmeter_1.SetIntervalColours([wx.BLACK]*self.NumIntervals)
        self.speedmeter_1.SetMiddleText("km/h")
        self.speedmeter_1.SetMiddleTextColour(wx.WHITE)
        self.speedmeter_1.SetMiddleTextFont(wx.Font(8,wx.FONTFAMILY_SWISS,wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
        self.speedmeter_1.SetNumberOfSecondaryTicks(4)
        self.speedmeter_1.SetSpeedValue(90)
        self.speedmeter_1.SetTicks(self.ticks)
        self.speedmeter_1.SetTicksColour(wx.WHITE)
        self.speedmeter_1.SetTicksFont(wx.Font(7,wx.FONTFAMILY_SWISS,wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: MyFrame.__do_layout
        sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_3 = wx.BoxSizer(wx.VERTICAL)
        sizer_4 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_5 = wx.BoxSizer(wx.VERTICAL)
        sizer_6 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_5.Add(self.speedmeter_2, 1, wx.ALL | wx.EXPAND, 5)
        label_2 = wx.StaticText(self.panel_2, wx.ID_ANY, _("Amount"))
        sizer_6.Add(label_2, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
        sizer_6.Add(self.slider_2, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL | wx.EXPAND, 5)
        sizer_5.Add(sizer_6, 0, wx.EXPAND, 0)
        self.panel_2.SetSizer(sizer_5)
        sizer_1.Add(self.panel_2, 1, wx.EXPAND, 0)
        sizer_3.Add(self.speedmeter_1, 1, wx.ALL | wx.EXPAND, 5)
        label_1 = wx.StaticText(self.panel_1, wx.ID_ANY, _("Amount"))
        sizer_4.Add(label_1, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
        sizer_4.Add(self.slider_1, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL | wx.EXPAND, 5)
        sizer_3.Add(sizer_4, 0, wx.EXPAND, 0)
        self.panel_1.SetSizer(sizer_3)
        sizer_1.Add(self.panel_1, 1, wx.EXPAND, 0)
        self.SetSizer(sizer_1)
        self.Layout()
        # end wxGlade

# end of class MyFrame

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

# end of class MyApp

if __name__ == "__main__":
    gettext.install("Speedmeter") # replace with the appropriate catalog name

    Speedmeter = MyApp(0)
    Speedmeter.MainLoop()