wxPython newbie ... gridbagsizer: all I want to do is replace a widget at a specific row and column with another widget

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

wxPython newbie ... gridbagsizer: all I want to do is replace a widget at a specific row and column with another widget

Just Me
Appreciate any answers to this question..

I am using a gridbagsizer to layout a grid ...this works I can put down static text and print out the grid

Now this should be simple and easy, all I want to do is replace a widget at a specific row and column with another widget and I am at a complete loss how to do this...after hours of googling and trying different things

E.g. Generate a placeholder grid

gs1 = wx.GridBagSizer()

for x in range (1,2):
            for y in range (1,9):
                gs1.Add(20, 20, pos = (x,y))

Now I can get the gbsizeritem like this

 Item = gs1.FindItemAtPosition(pos=(1,7))

but I can not find any way to replace the widget at 1,7 with another one!!!!

Any suggestions?

Background ... I am making an ancestor class and the idea is to add slots to place the widgets, this should make laying out forms easier.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxPython newbie ... gridbagsizer: all I want to do is replace a widget at a specific row and column with another widget

Dietmar Schwertberger-2
On 6/6/2018 8:30 PM, Just Me wrote:
> Any suggestions?

It's certainly possible. I'm doing it in wxGlade.

Try these two methods, at least one should work:

  - use Item.AssignWindow(new_widget)
         this would probably not allow to modify row/col span

  - detach the old item and then add the new widget as usual:

         gs1.Detach(widget) or gs1.Detach(Item.GetWindow())


If none of these work, please post example code.


Regards,

Dietmar


--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxPython newbie ... gridbagsizer: all I want to do is replace a widget at a specific row and column with another widget

Tim Roberts
In reply to this post by Just Me
On Jun 6, 2018, at 11:30 AM, Just Me <[hidden email]> wrote:

gs1 = wx.GridBagSizer()

for x in range (1,2):
            for y in range (1,9):
                gs1.Add(20, 20, pos = (x,y))

On a separate note, do you understand that this is only going to create a 1 x 8 array?  x will only be 1, and y will be 1, 2, 3, 4, 5, 6, 7, 8.  Is that what you intended?
— 
Tim Roberts, [hidden email]
Providenza & Boekelheide, Inc.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxPython newbie ... gridbagsizer: all I want to do is replace a widget at a specific row and column with another widget

Just Me
In reply to this post by Just Me
Appreciate the replies and Dietmar and Tim ... I sure wish the gridsizers had an add widget method something like I have now in my Slot class, seems like an obvious thing to have.

So this is what I came up with - it kind of works, still some funnies, and I am refining it, but I will appreciate any suggestions for improvement as I have only been learning python a few weeks (but I am an old software hand in other languages)

The slot panel class

class Slot_Panel(wx.Panel):
    __Col_Max       = 0   
    __Row_Max       = 0
    __Parent_Window = None
    __Sizer         = None
   
    def __init__(self,parent, max_slot_rows = 1, max_slot_cols = 1):
        Row       = 0       
        Col       = 0       
        Spacer    = None
                                       
        #assert isinstance(parent, ??),"parent must be wx.Frame" #TODO What is the object type of a wx.Frame?
        assert isinstance(max_slot_rows, int) and max_slot_rows,"max_slot_rows must be an integer > 0"
        assert isinstance(max_slot_cols, int) and max_slot_cols,"max_slot_cols must be an integer > 0"
       
        super().__init__(parent = parent)
       
        self.__Parent_Window = parent
        self.__Sizer = wx.GridBagSizer(max_slot_rows, max_slot_cols)
       
        self.__Col_Max = max_slot_cols
        self.__Row_Max = max_slot_rows

        for Row in range (1,max_slot_rows + 1):
            for Col in range (1,max_slot_cols + 1):               
                #for debug - write out slot number               
                Spacer = wx.StaticText(self, id = wx.ID_ANY, label = "Control Slot "+str(Row * Col))               
                #Spacer = wx.StaticText(self, -1, "")
                self.__Sizer.Add(Spacer, pos = (Row,Col), span = (1, 1), flag = wx.EXPAND|wx.ALL, border = 5)
               
    def Add_Control(self, new_widget,  slot_row =1, slot_col = 0):
       
        #assert isinstance(new_widget, ??),"new_widget must be wx.Control" #TODO What is the object type of a wx.control?
        assert isinstance(slot_row, int) and slot_row > 0 and slot_row <= self.__Row_Max,"slot row must be an integer > 0 and <= max_slot_rows"
        assert isinstance(slot_col, int) and slot_col > 0 and slot_col <= self.__Col_Max,"slot col must be an integer > 0 and <= max_slot_cols"
       
        Old_Widget = self.__Sizer.FindItemAtPosition(wx.GBPosition(slot_row,slot_col))
               
        self.__Sizer.Detach(Old_Widget.GetWindow())       
                               
        self.__Sizer.Add(new_widget, pos = (slot_row,slot_col), span = (1, 1), flag = wx.EXPAND|wx.ALL, border = 5)
        self.__Sizer.Layout()
       
       
An MDI Child using this class
  
class MDI_Child(wx.MDIChildFrame):
    Win_Id = ["",0]
   
    def __init__(self,frame,id=-1,title = ""):
        super().__init__(frame,id,title)
       
       
        Control_Panel = Slot_Panel(self,max_slot_rows = 8, max_slot_cols = 8 )
        Button_Panel  = Slot_Panel(self,max_slot_rows = 1, max_slot_cols = 8 )
                       
        Button_Panel.Add_Control(wx.Button(Button_Panel,label = "Ok"),slot_row = 1, slot_col = 6)
        Button_Panel.Add_Control(wx.Button(Button_Panel,label = "Cancel"),slot_row = 1, slot_col = 7)
        Button_Panel.Add_Control(wx.Button(Button_Panel,label = "Append"),slot_row = 1, slot_col = 8)
       
        Control_Panel.SetBackgroundColour('light blue')
        Button_Panel.SetBackgroundColour('blue')
                               
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(Control_Panel, 1, wx.EXPAND)
        sizer.Add(Button_Panel, 1, wx.EXPAND)
        self.SetSizer(sizer)

In the program this looks like this -



--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxPython newbie ... gridbagsizer: all I want to do is replace a widget at a specific row and column with another widget

Tim Roberts
Just Me wrote:

So this is what I came up with - it kind of works, still some funnies, and I am refining it, but I will appreciate any suggestions for improvement as I have only been learning python a few weeks (but I am an old software hand in other languages)
...
        for Row in range (1,max_slot_rows + 1):
            for Col in range (1,max_slot_cols + 1):               
                #for debug - write out slot number               
                Spacer = wx.StaticText(self, id = wx.ID_ANY, label = "Control Slot "+str(Row * Col))               
                #Spacer = wx.StaticText(self, -1, "")
                self.__Sizer.Add(Spacer, pos = (Row,Col), span = (1, 1), flag = wx.EXPAND|wx.ALL, border = 5)

I'm still wondering why you start the ranges at 1.  Every language has its "native" starting point for arrays and ranges.  In Visual Basic, for example, the natural starting point is 1.  But in Python, like C and C++, things almost always start with 0.  If a GridBagSizer has 5 rows and 5 columns, those rows and columns are numbered 0 through 4.  That's why range(5) returns [0,1,2,3,4].  It's just the way Python is done.

If you did that, you'd need to change your StaticText to something like "Control Slot %d,%d" % (Row,Col).
-- 
Tim Roberts, [hidden email]
Providenza & Boekelheide, Inc.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxPython newbie ... gridbagsizer: all I want to do is replace a widget at a specific row and column with another widget

Dietmar Schwertberger-2
In reply to this post by Just Me
Maybe you should write what you actually want to accomplish.
There are not too many use cases where on-the-fly modifications like
these make sense.
I know that it's possible to do these as I'm working on wxGlade and for
a GUI builder it actually makes sense to change the layout.
For 'normal' user programs it seems hard to imagine such a use case. If
you need dynamic dialogs / forms, just create, destroy and re-create
them on the fly instead of re-using parts of it.

Regards,
Dietmar

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxPython newbie ... gridbagsizer: all I want to do is replace a widget at a specific row and column with another widget

Just Me
In reply to this post by Tim Roberts
Hi Tim,

I start at 1 in the ranges because I find it easier to think of screen form layouts as starting at row 1, col 1. For example, I might put the Save button at Row 1 Col 3. Perhaps this is odd, as I am comfortable with zero based arrays and such like from other languages!!

Appreciate the feedback, as always

On Thursday, 7 June 2018 14:20:30 UTC-4, Tim Roberts wrote:
Just Me wrote:

So this is what I came up with - it kind of works, still some funnies, and I am refining it, but I will appreciate any suggestions for improvement as I have only been learning python a few weeks (but I am an old software hand in other languages)
...
        for Row in range (1,max_slot_rows + 1):
            for Col in range (1,max_slot_cols + 1):               
                #for debug - write out slot number               
                Spacer = wx.StaticText(self, id = wx.ID_ANY, label = "Control Slot "+str(Row * Col))               
                #Spacer = wx.StaticText(self, -1, "")
                self.__Sizer.Add(Spacer, pos = (Row,Col), span = (1, 1), flag = wx.EXPAND|wx.ALL, border = 5)

I'm still wondering why you start the ranges at 1.  Every language has its "native" starting point for arrays and ranges.  In Visual Basic, for example, the natural starting point is 1.  But in Python, like C and C++, things almost always start with 0.  If a GridBagSizer has 5 rows and 5 columns, those rows and columns are numbered 0 through 4.  That's why range(5) returns [0,1,2,3,4].  It's just the way Python is done.

If you did that, you'd need to change your StaticText to something like "Control Slot %d,%d" % (Row,Col).
-- 
Tim Roberts, <a href="javascript:" target="_blank" gdf-obfuscated-mailto="aSHTS7ITAgAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">ti...@...
Providenza & Boekelheide, Inc.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxPython newbie ... gridbagsizer: all I want to do is replace a widget at a specific row and column with another widget

Just Me
In reply to this post by Dietmar Schwertberger-2
I find it easier to design screen forms as a grid -   that is why I like slots as I can lay the form out by specifying the slot in which each control element is placed.

By building the ancestor Slot_Panel, and encapsulating most of the grunt work , I can inherit from that and layout my form quickly, by doing what I did with the posted example - one control on each line  I still have to add spanning and a few other things to get the magic I want.  This should lead to faster/shorter coding with fewer bugs.

Thank you for pointing me in the right direction :-)




On Thursday, 7 June 2018 14:36:43 UTC-4, Dietmar Schwertberger wrote:
Maybe you should write what you actually want to accomplish.
There are not too many use cases where on-the-fly modifications like
these make sense.
I know that it's possible to do these as I'm working on wxGlade and for
a GUI builder it actually makes sense to change the layout.
For 'normal' user programs it seems hard to imagine such a use case. If
you need dynamic dialogs / forms, just create, destroy and re-create
them on the fly instead of re-using parts of it.

Regards,
Dietmar

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxPython newbie ... gridbagsizer: all I want to do is replace a widget at a specific row and column with another widget

Dietmar Schwertberger-2
On 6/7/2018 8:49 PM, Just Me wrote:
> I find it easier to design screen forms as a grid -   that is why I
> like slots as I can lay the form out by specifying the slot in which
> each control element is placed.

It seems that you actually prefer to place widgets by pixels instead of
using sizers. You just plan to use a grid sizer instead of pixel
coordinates. wxPython does not require a sizer. You could place by
pixels if you absolutely want.

Honestly, this does not sound like a good plan. wx has a quite useful
set of sizers for different purposes. The gridbag sizer is the one that
I have never needed at all during 18 years of using wx. The box, static
box and flex grid sizers are probably all you will ever need.

Still, this does not yet explain why you want to replace widgets within
a gridbag sizer. If your plan is to "design" your layout on the command
line by changing it on the fly, then I would recommend using a GUI
builder like wxGlade. These are actually made for designing visually. No
need to re-invent the wheel.


Regards,

Dietmar


--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxPython newbie ... gridbagsizer: all I want to do is replace a widget at a specific row and column with another widget

Tim Roberts
In reply to this post by Just Me
Just Me wrote:
>
> I start at 1 in the ranges because I find it easier to think of screen
> form layouts as starting at row 1, col 1. For example, I might put the
> Save button at Row 1 Col 3.

Yes, but the grid itself starts counting at 0.  Your grid size HAS a row
0 and column 0, and I'm afraid at some point you're going to get burned
because you have an inaccurate mental model.

I guess it's just something to think about.

--
Tim Roberts, [hidden email]
Providenza & Boekelheide, Inc.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxPython newbie ... gridbagsizer: all I want to do is replace a widget at a specific row and column with another widget

Just Me
In reply to this post by Dietmar Schwertberger-2

Hi Dietmar,

I have done many applications with pixel placed widgets in other languages and toolkits, but they often do not play nice when Windows are resized.  An array of slots does seem like a good and obvious way to layout a form - without absolute pixel positioning - and I am hoping that by using slots as hints and the gridbagsizer to manage resizing then Windows resizing will not be as big an issue.

As a wx newbie, I will say choosing the right sizer and getting sizers to position things where one wants is anything but obvious - for me using slots, solves this problem as I am now getting the layout I want.  And I have done a lot of wx reading in the last couple of days!

I did look at wxGlade but was not all that happy with the tool ... but I will not dig into that here

At any rate, I guess we all do everything a  little different.

On Thursday, 7 June 2018 15:08:28 UTC-4, Dietmar Schwertberger wrote:
On 6/7/2018 8:49 PM, Just Me wrote:
> I find it easier to design screen forms as a grid -   that is why I
> like slots as I can lay the form out by specifying the slot in which
> each control element is placed.

It seems that you actually prefer to place widgets by pixels instead of
using sizers. You just plan to use a grid sizer instead of pixel
coordinates. wxPython does not require a sizer. You could place by
pixels if you absolutely want.

Honestly, this does not sound like a good plan. wx has a quite useful
set of sizers for different purposes. The gridbag sizer is the one that
I have never needed at all during 18 years of using wx. The box, static
box and flex grid sizers are probably all you will ever need.

Still, this does not yet explain why you want to replace widgets within
a gridbag sizer. If your plan is to "design" your layout on the command
line by changing it on the fly, then I would recommend using a GUI
builder like wxGlade. These are actually made for designing visually. No
need to re-invent the wheel.


Regards,

Dietmar


--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.