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()