[wxPython] Strange wxGridSizer behaviour under MS Windows

Hi guys,

I'm having a lot of trouble getting my wxGridSizer to work properly in my
application. It works fine under Linux, but as soon as I try to run my program
under Windows, the wxGridSizer seems to go haywire.

My program is using a wxGridSizer to lay out a number of "Job Lists"
(basically a wxPanel containing a heading and a wxGrid) into a matrix-like
pattern in the window. When the window is resized, the number of lists which
will fit across the window is recalculated, and a new wxGridSizer is created
with that number of columns (there doesn't seem to be any way of dynamically
changing the number of rows and/or columns for a wxGridSizer, so I have to
create a new one from scratch), and then all the lists are created and added to
the wxGridSizer in order. The result is that the window shows as many lists
across as the window will fit, but will use a vertical scrollbar if there are
more lists than can be shown in the window at one time.

My program allows for job lists to be created and removed on the fly -- each
time a list is created or removed, I'm calling my rebuild() routine to recreate
all the remaining lists and lay them out again, so that no holes are left as
the job lists are laid out in the window.

Anyway, as I say all this works beautifully under Linux, but for some reason
wxGridSizer seems to misbehave when running under Windows. Below is a
simplified program which shows up the problem -- try clicking on "Add" several
times in succession. Under Linux, each call to doAdd() causes the window to be
laid out correctly. Under Windows, the items are all laid out one on top of
the other, and only occasionally do they lay out correctly. The same thing
happens when you try to resize the window...

It's quite interesting to compare the behaviour under Linux and Windows --
they're quite different! Can anyone suggest a workaround for getting my
wxGridSizer to work properly under Windows? I'm quite desperate to get this
fixed, as my program *needs* to run under Windows and with this layout logic
broken my entire program is unusable -- and I've got people waiting to test it.
I'd be *really* grateful if someone could help me figure out how to fix this...

Thanks in advance,

- Erik.

#--------- Python Code Follows ----------------------------------------------

from wxPython.wx import *
import whrandom

class TestFrame(wxFrame):
    def __init__(self, parent, id, title):
        wxFrame.__init__(self, parent, id, title)

        self.SetAutoLayout(true)

        btnPanel = wxPanel(self, -1)
        btnSizer = wxBoxSizer(wxVERTICAL)

        btnAdd = wxButton(btnPanel, 1001, "Add")
        btnRemove = wxButton(btnPanel, 1002, "Remove")

        btnSizer.Add(btnAdd, 0, wxALL, 5)
        btnSizer.Add(btnRemove, 0, wxALL, 5)

        btnPanel.SetAutoLayout(true)
        btnPanel.SetSizer(btnSizer)
        btnSizer.Fit(btnPanel)

        EVT_BUTTON(self, 1001, self.doAdd)
        EVT_BUTTON(self, 1002, self.doRemove)

        self.scroller = wxScrolledWindow(self, -1)
        self.scroller.SetAutoLayout(true)
        self.scroller.EnableScrolling(false, true)

        self.panel = wxPanel(self.scroller, -1)
        self.panel.SetAutoLayout(true)

        self.sizer = None

        topSizer = wxBoxSizer(wxHORIZONTAL)
        topSizer.Add(btnPanel, 0, wxALL, 5)
        topSizer.Add(self.scroller, 1, wxEXPAND | wxALL, 5)

        self.SetAutoLayout(true)
        self.SetSizer(topSizer)
        self.SetSizeHints(minW=100, minH=200)
        self.SetSize(wxSize(600, 400))

        EVT_SIZE(self, self.OnSizeWindow)

        self.items = {}
        self.rebuild()

    def doAdd(self, event):
        itemNum = len(self.items.keys()) + 1
        self.items[itemNum] = None
        self.rebuild()

    def doRemove(self, event):
        if len(self.items.keys()) > 0:
            keys = self.items.keys()
            itemNum = self.items.keys()[whrandom.randint(0, len(keys)-1)]
            if self.items[itemNum] != None: self.items[itemNum].Destroy()
            del self.items[itemNum]
            self.rebuild()

    def rebuild(self):
        for itemNum in self.items.keys():
            item = self.items[itemNum]
            if item != None:
                item.Destroy()
                self.items[itemNum] = None

        self.scroller.Scroll(0, 0)
        self.sizer = None

        items = self.items.keys()
        items.sort()

        for itemNum in items:
            item = wxButton(self.panel, -1, str(itemNum))
            item.SetSize(wxSize(100, 50))
            item.SetSizeHints(100, 50)

            if self.sizer == None:
                itemWidth = item.GetSize().width
                totWidth = self.scroller.GetClientSize().width
                numCols = totWidth / (itemWidth + 10)
                if numCols < 1: numCols = 1
                self.sizer = wxGridSizer(0, numCols, 10, 10)

            self.sizer.Add(item, 0, wxALIGN_TOP)
            self.items[itemNum] = item

        if self.sizer != None:
            self.panel.SetSizer(self.sizer)
            self.sizer.Fit(self.panel)
            height = self.panel.GetSize().height
            self.scroller.SetScrollbars(20, 20, 0, (height + 20) / 20)

    def OnSizeWindow(self, event):
        event.Skip()
        self.rebuild()

class TestApp(wxApp):
    def OnInit(self):
        frame = TestFrame(NULL, -1, "Test")
        self.SetTopWindow(frame)
        frame.Show(TRUE)
        return TRUE

# Main program:

app = TestApp(0)
app.MainLoop()

I'm having a lot of trouble getting my wxGridSizer to work properly in my
application. It works fine under Linux, but as soon as I try to run my

program

under Windows, the wxGridSizer seems to go haywire.

        if self.sizer != None:
            self.panel.SetSizer(self.sizer)
            self.sizer.Fit(self.panel)
            height = self.panel.GetSize().height
            self.scroller.SetScrollbars(20, 20, 0, (height + 20) / 20)

Add this line here:

              self.panel.Layout()

On wxGTK the panel is probably getting a size event as a result of the stuff
happening in rebuild() but on wxMSW it is not. The default size event
handler will call Layout so that's why it's working on wxGTK.

But you've probably noticed a lot of flicker as you destroy everything and
recreate it in the new sizer... I've attached an alternative
(gridsizer2.py) that doesn't destory the windows and just adds the existing
ones to the new sizer. Works a bit better.

(there doesn't seem to be any way of dynamically
changing the number of rows and/or columns for a wxGridSizer, so I have to
create a new one from scratch),

Ah, but there is. There is a SetCols method that will do it for you. I've
also attached gridsizer3.py that shows how to do it this way.

···

--
Robin Dunn
Software Craftsman
robin@AllDunn.com Java give you jitters?
http://wxPython.org Relax with wxPython!

begin 666 gridsizer2.py
M#0IF<F]M('=X4'ET:&]N+G=X(&EM<&]R=" J#0II;7!O<G0@=VAR86YD;VT-
M"@T*8VQA<W,@5&5S=$9R86UE*'=X1G)A;64I.@T*(" @(&1E9B!?7VEN:71?
M7RAS96QF+"!P87)E;G0L(&ED+"!T:71L92DZ#0H@(" @(" @('=X1G)A;64N
M7U]I;FET7U\H<V5L9BP@<&%R96YT+"!I9"P@=&ET;&4I#0H-"B @(" @(" @
M<V5L9BY3971!=71O3&%Y;W5T*'1R=64I#0H-"B @(" @(" @8G1N4&%N96P@
M/2!W>%!A;F5L*'-E;&8L("TQ*0T*(" @(" @("!B=&Y3:7IE<B ]('=X0F]X
M4VEZ97(H=WA615)424-!3"D-"@T*(" @(" @("!B=&Y!9&0@(" @/2!W>$)U
M='1O;BAB=&Y086YE;"P@,3 P,2P@(D%D9"(I#0H@(" @(" @(&)T;E)E;6]V
M92 ]('=X0G5T=&]N*&)T;E!A;F5L+" Q,# R+" B4F5M;W9E(BD-"@T*(" @
M(" @("!B=&Y3:7IE<BY!9&0H8G1N061D+" @(" P+"!W>$%,3"P@-2D-"B @
M(" @(" @8G1N4VEZ97(N061D*&)T;E)E;6]V92P@,"P@=WA!3$PL(#4I#0H-
M"B @(" @(" @8G1N4&%N96PN4V5T075T;TQA>6]U="AT<G5E*0T*(" @(" @
M("!B=&Y086YE;"Y39713:7IE<BAB=&Y3:7IE<BD-"B @(" @(" @8G1N4VEZ
M97(N1FET*&)T;E!A;F5L*0T*#0H@(" @(" @($565%]"55143TXH<V5L9BP@
M,3 P,2P@<V5L9BYD;T%D9"D-"B @(" @(" @15947T)55%1/3BAS96QF+" Q
M,# R+"!S96QF+F1O4F5M;W9E*0T*#0H@(" @(" @('-E;&8N<V-R;VQL97(@
M/2!W>%-C<F]L;&5D5VEN9&]W*'-E;&8L("TQ*0T*(" @(" @("!S96QF+G-C
M<F]L;&5R+E-E=$%U=&],87EO=70H=')U92D-"B @(" @(" @<V5L9BYS8W)O
M;&QE<BY%;F%B;&538W)O;&QI;F<H9F%L<V4L('1R=64I#0H-"B @(" @(" @
M<V5L9BYP86YE;" ]('=X4&%N96PH<V5L9BYS8W)O;&QE<BP@+3$I#0H@(" @
M(" @('-E;&8N<&%N96PN4V5T0F%C:V=R;W5N9$-O;&]U<BAW>$),544I#0H@
M(" @(" @('-E;&8N<&%N96PN4V5T075T;TQA>6]U="AT<G5E*0T*#0H@(" @
M(" @('-E;&8N<VEZ97(@/2!.;VYE#0H@(" @(" @('-E;&8N;G5M0V]L<R ]
M(# -"@T*(" @(" @("!T;W!3:7IE<B ]('=X0F]X4VEZ97(H=WA(3U))6D].
M5$%,*0T*(" @(" @("!T;W!3:7IE<BY!9&0H8G1N4&%N96PL(# L('=X04Q,
M+" U*0T*(" @(" @("!T;W!3:7IE<BY!9&0H<V5L9BYS8W)O;&QE<BP@,2P@
M=WA%6%!!3D0@?"!W>$%,3"P@-2D-"@T*(" @(" @("!S96QF+E-E=$%U=&],
M87EO=70H=')U92D-"B @(" @(" @<V5L9BY39713:7IE<BAT;W!3:7IE<BD-
M"B @(" @(" @<V5L9BY39713:7IE2&EN=',H;6EN5STQ,# L(&UI;D@],C P
M*0T*(" @(" @("!S96QF+E-E=%-I>F4H=WA3:7IE*#8P,"P@-# P*2D-"@T*
M(" @(" @("!%5E1?4TE:12AS96QF+"!S96QF+D]N4VEZ95=I;F1O=RD-"@T*
M(" @(" @("!S96QF+FET96US(#T@>WT-"B @(" @(" @(W-E;&8N<F5B=6EL
M9"@I#0H-"B @("!D968@9&]!9&0H<V5L9BP@979E;G0I.@T*(" @(" @("!I
M=&5M3G5M(#T@;&5N*'-E;&8N:71E;7,N:V5Y<R@I*2 K(#$-"B @(" @(" @
M:71E;2 ]('=X0G5T=&]N*'-E;&8N<&%N96PL("TQ+"!S='(H:71E;4YU;2DI
M#0H@(" @(" @(&ET96TN4V5T4VEZ92AW>%-I>F4H,3 P+" U,"DI#0H@(" @
M(" @(&ET96TN4V5T4VEZ94AI;G1S*#$P,"P@-3 I#0H@(" @(" @('-E;&8N
M:71E;7-;:71E;4YU;5T@/2!I=&5M#0H-"B @(" @(" @:68@<V5L9BYS:7IE
M<CH-"B @(" @(" @(" @('-E;&8N<VEZ97(N061D*&ET96TL(# L('=X04Q)
M1TY?5$]0*0T*(" @(" @(" @(" @<V5L9BYP86YE;"Y,87EO=70H*0T*(" @
M(" @("!S96QF+G)E8G5I;&13:7IE<B@I#0H-"@T*(" @(&1E9B!D;U)E;6]V
M92AS96QF+"!E=F5N="DZ#0H@(" @(" @(&EF(&QE;BAS96QF+FET96US+FME

7,H*2D@/B P.@T*(" @(" @(" @(" @:V5Y<R ]('-E;&8N:71E;7,N:V5Y

M<R@I#0H@(" @(" @(" @("!I=&5M3G5M(#T@<V5L9BYI=&5M<RYK97ES*"E;
M=VAR86YD;VTN<F%N9&EN="@P+"!L96XH:V5Y<RDM,2E=#0H@(" @(" @(" @
M("!I9B!S96QF+FET96US6VET96U.=6U=("$]($YO;F4Z('-E;&8N:71E;7-;
M:71E;4YU;5TN1&5S=')O>2@I#0H@(" @(" @(" @("!D96P@<V5L9BYI=&5M
M<UMI=&5M3G5M70T*(" @(" @(" @(" @<V5L9BYR96)U:6QD*"D-"@T*#0H@
M(" @9&5F(')E8G5I;&13:7IE<BAS96QF*3H-"B @(" @(" @<V5L9BYS8W)O
M;&QE<BY38W)O;&PH,"P@,"D-"@T*(" @(" @("!K97ES(#T@<V5L9BYI=&5M
M<RYK97ES*"D-"B @(" @(" @:68@:V5Y<SH-"B @(" @(" @(" @(&ME>7,N
M<V]R="@I#0H-"B @(" @(" @(" @(&%N271E;2 ]('-E;&8N:71E;7-;:V5Y
M<ULP75T-"B @(" @(" @(" @(&ET96U7:61T:" ](&%N271E;2Y'9713:7IE
M*"DN=VED=&@-"B @(" @(" @(" @('1O=%=I9'1H(" ]('-E;&8N<V-R;VQL
M97(N1V5T0VQI96YT4VEZ92@I+G=I9'1H#0H@(" @(" @(" @("!N=6U#;VQS
M(#T@=&]T5VED=&@@+R H:71E;5=I9'1H("L@,3 I#0H@(" @(" @(" @("!I
M9B!N=6U#;VQS(#P@,3H@;G5M0V]L<R ](#$-"@T*(" @(" @(" @(" @:68@
M<V5L9BYS:7IE<B ]/2!.;VYE(&]R(&YU;4-O;',@(3T@<V5L9BYN=6U#;VQS
M.@T*(" @(" @(" @(" @(" @('!R:6YT(")N97<@<VEZ97(N+BXB#0H@(" @
M(" @(" @(" @(" @<V5L9BYN=6U#;VQS(#T@;G5M0V]L<PT*(" @(" @(" @
M(" @(" @('-E;&8N<VEZ97(@/2!W>$=R:613:7IE<B@P+"!N=6U#;VQS+" Q
M,"P@,3 I#0H@(" @(" @(" @(" @(" @9F]R(&ME>2!I;B!K97ES.@T*(" @
M(" @(" @(" @(" @(" @("!I=&5M(#T@<V5L9BYI=&5M<UMK97E=#0H@(" @
M(" @(" @(" @(" @(" @('-E;&8N<VEZ97(N061D*&ET96TL(# L('=X04Q)
M1TY?5$]0*0T*#0H@(" @(" @(" @(" @(" @<V5L9BYP86YE;"Y39713:7IE
M<BAS96QF+G-I>F5R*0T*(" @(" @(" @(" @<V5L9BYS:7IE<BY&:70H<V5L
M9BYP86YE;"D-"B @(" @(" @(" @(&AE:6=H=" ]('-E;&8N<&%N96PN1V5T
M4VEZ92@I+FAE:6=H= T*(" @(" @(" @(" @<V5L9BYS8W)O;&QE<BY39713
M8W)O;&QB87)S*#(P+" R,"P@,"P@*&AE:6=H=" K(#(P*2 O(#(P*0T*(" @
M(" @(" @(" @<V5L9BYP86YE;"Y,87EO=70H*0T*#0H-"B @("!D968@3VY3
M:7IE5VEN9&]W*'-E;&8L(&5V96YT*3H-"B @(" @(" @:68@<V5L9BY'971!
M=71O3&%Y;W5T*"DZ#0H@(" @(" @(" @("!S96QF+DQA>6]U="@I#0H@(" @
M(" @('-E;&8N<F5B=6EL9%-I>F5R*"D-"@T*#0IC;&%S<R!497-T07!P*'=X
M07!P*3H-"B @("!D968@3VY);FET*'-E;&8I.@T*(" @(" @("!F<F%M92 ]
M(%1E<W1&<F%M92A.54Q,+" M,2P@(E1E<W0B*0T*(" @(" @("!S96QF+E-E
M=%1O<%=I;F1O=RAF<F%M92D-"B @(" @(" @9G)A;64N4VAO=RA44E5%*0T*
M(" @(" @("!R971U<FX@5%)510T*#0HC($UA:6X@<')O9W)A;3H-"@T*87!P
C(#T@5&5S=$%P<"@P*0T*87!P+DUA:6Y,;V]P*"D-"@T*#0H`
`
end

begin 666 gridsizer3.py
M#0IF<F]M('=X4'ET:&]N+G=X(&EM<&]R=" J#0II;7!O<G0@=VAR86YD;VT-
M"@T*8VQA<W,@5&5S=$9R86UE*'=X1G)A;64I.@T*(" @(&1E9B!?7VEN:71?
M7RAS96QF+"!P87)E;G0L(&ED+"!T:71L92DZ#0H@(" @(" @('=X1G)A;64N
M7U]I;FET7U\H<V5L9BP@<&%R96YT+"!I9"P@=&ET;&4I#0H-"B @(" @(" @
M<V5L9BY3971!=71O3&%Y;W5T*'1R=64I#0H-"B @(" @(" @8G1N4&%N96P@
M/2!W>%!A;F5L*'-E;&8L("TQ*0T*(" @(" @("!B=&Y3:7IE<B ]('=X0F]X
M4VEZ97(H=WA615)424-!3"D-"@T*(" @(" @("!B=&Y!9&0@(" @/2!W>$)U
M='1O;BAB=&Y086YE;"P@,3 P,2P@(D%D9"(I#0H@(" @(" @(&)T;E)E;6]V
M92 ]('=X0G5T=&]N*&)T;E!A;F5L+" Q,# R+" B4F5M;W9E(BD-"@T*(" @
M(" @("!B=&Y3:7IE<BY!9&0H8G1N061D+" @(" P+"!W>$%,3"P@-2D-"B @
M(" @(" @8G1N4VEZ97(N061D*&)T;E)E;6]V92P@,"P@=WA!3$PL(#4I#0H-
M"B @(" @(" @8G1N4&%N96PN4V5T075T;TQA>6]U="AT<G5E*0T*(" @(" @
M("!B=&Y086YE;"Y39713:7IE<BAB=&Y3:7IE<BD-"B @(" @(" @8G1N4VEZ
M97(N1FET*&)T;E!A;F5L*0T*#0H@(" @(" @($565%]"55143TXH<V5L9BP@
M,3 P,2P@<V5L9BYD;T%D9"D-"B @(" @(" @15947T)55%1/3BAS96QF+" Q
M,# R+"!S96QF+F1O4F5M;W9E*0T*#0H@(" @(" @('-E;&8N<V-R;VQL97(@
M/2!W>%-C<F]L;&5D5VEN9&]W*'-E;&8L("TQ*0T*(" @(" @("!S96QF+G-C
M<F]L;&5R+E-E=$%U=&],87EO=70H=')U92D-"B @(" @(" @<V5L9BYS8W)O
M;&QE<BY%;F%B;&538W)O;&QI;F<H9F%L<V4L('1R=64I#0H-"B @(" @(" @
M<V5L9BYP86YE;" ]('=X4&%N96PH<V5L9BYS8W)O;&QE<BP@+3$I#0H@(" @
M(" @('-E;&8N<&%N96PN4V5T0F%C:V=R;W5N9$-O;&]U<BAW>$),544I#0H@
M(" @(" @('-E;&8N<&%N96PN4V5T075T;TQA>6]U="AT<G5E*0T*#0H@(" @
M(" @('-E;&8N<VEZ97(@/2!W>$=R:613:7IE<B@P+" Q+" Q,"P@,3 I#0H@
M(" @(" @('-E;&8N;G5M0V]L<R ](#$-"B @(" @(" @<V5L9BYP86YE;"Y3
M9713:7IE<BAS96QF+G-I>F5R*0T*#0H@(" @(" @('1O<%-I>F5R(#T@=WA"
M;WA3:7IE<BAW>$A/4DE:3TY404PI#0H@(" @(" @('1O<%-I>F5R+D%D9"AB
M=&Y086YE;"P@,"P@=WA!3$PL(#4I#0H@(" @(" @('1O<%-I>F5R+D%D9"AS
M96QF+G-C<F]L;&5R+" Q+"!W>$584$%.1"!\('=X04Q,+" U*0T*#0H@(" @
M(" @('-E;&8N4V5T075T;TQA>6]U="AT<G5E*0T*(" @(" @("!S96QF+E-E
M=%-I>F5R*'1O<%-I>F5R*0T*(" @(" @("!S96QF+E-E=%-I>F5(:6YT<RAM
M:6Y7/3$P,"P@;6EN2#TR,# I#0H@(" @(" @('-E;&8N4V5T4VEZ92AW>%-I

F4H-C P+" T,# I*0T*#0H@(" @(" @($565%]325I%*'-E;&8L('-E;&8N

M3VY3:7IE5VEN9&]W*0T*#0H@(" @(" @('-E;&8N:71E;7,@/2![?0T*(" @
M(" @(" C<V5L9BYR96)U:6QD*"D-"@T*(" @(&1E9B!D;T%D9"AS96QF+"!E
M=F5N="DZ#0H@(" @(" @(&ET96U.=6T@/2!L96XH<V5L9BYI=&5M<RYK97ES
M*"DI("L@,0T*(" @(" @("!I=&5M(#T@=WA"=71T;VXH<V5L9BYP86YE;"P@
M+3$L('-T<BAI=&5M3G5M*2D-"B @(" @(" @:71E;2Y39713:7IE*'=X4VEZ
M92@Q,# L(#4P*2D-"B @(" @(" @:71E;2Y39713:7IE2&EN=',H,3 P+" U
M,"D-"B @(" @(" @<V5L9BYI=&5M<UMI=&5M3G5M72 ](&ET96T-"@T*(" @
M(" @("!I9B!S96QF+G-I>F5R.@T*(" @(" @(" @(" @<V5L9BYS:7IE<BY!
M9&0H:71E;2P@,"P@=WA!3$E'3E]43U I#0H@(" @(" @(" @("!S96QF+G!A
M;F5L+DQA>6]U="@I#0H@(" @(" @('-E;&8N<F5B=6EL9%-I>F5R*"D-"@T*
M#0H@(" @9&5F(&1O4F5M;W9E*'-E;&8L(&5V96YT*3H-"B @(" @(" @:68@
M;&5N*'-E;&8N:71E;7,N:V5Y<R@I*2 ^(# Z#0H@(" @(" @(" @("!K97ES
M(#T@<V5L9BYI=&5M<RYK97ES*"D-"B @(" @(" @(" @(&ET96U.=6T@/2!S
M96QF+FET96US+FME>7,H*5MW:')A;F1O;2YR86YD:6YT*# L(&QE;BAK97ES
M*2TQ*5T-"B @(" @(" @(" @(&EF('-E;&8N:71E;7-;:71E;4YU;5T@(3T@
M3F]N93H@<V5L9BYI=&5M<UMI=&5M3G5M72Y$97-T<F]Y*"D-"B @(" @(" @
M(" @(&1E;"!S96QF+FET96US6VET96U.=6U=#0H@(" @(" @(" @("!S96QF
M+G)E8G5I;&0H*0T*#0H-"B @("!D968@<F5B=6EL9%-I>F5R*'-E;&8I.@T*
M(" @(" @("!S96QF+G-C<F]L;&5R+E-C<F]L;"@P+" P*0T*#0H@(" @(" @
M(&ME>7,@/2!S96QF+FET96US+FME>7,H*0T*(" @(" @("!I9B!K97ES.@T*
M(" @(" @(" @(" @:V5Y<RYS;W)T*"D-"@T*(" @(" @(" @(" @86Y)=&5M
M(#T@<V5L9BYI=&5M<UMK97ES6S!=70T*(" @(" @(" @(" @:71E;5=I9'1H
M(#T@86Y)=&5M+D=E=%-I>F4H*2YW:61T: T*(" @(" @(" @(" @=&]T5VED
M=&@@(#T@<V5L9BYS8W)O;&QE<BY'971#;&EE;G13:7IE*"DN=VED=&@-"B @
M(" @(" @(" @(&YU;4-O;',@/2!T;W17:61T:" O("AI=&5M5VED=&@@*R Q
M,"D-"B @(" @(" @(" @(&EF(&YU;4-O;',@/" Q.B!N=6U#;VQS(#T@,0T*
M#0H@(" @(" @(" @("!I9B!N=6U#;VQS("$]('-E;&8N;G5M0V]L<SH-"B @
M(" @(" @(" @(" @("!P<FEN=" B<F5C;VQU;6YI>FEN9R!S:7IE<BXN+B(-
M"B @(" @(" @(" @(" @("!S96QF+FYU;4-O;',@/2!N=6U#;VQS#0H@(" @
M(" @(" @(" @(" @<V5L9BYS:7IE<BY3971#;VQS*&YU;4-O;',I#0H-"B @
M(" @(" @(" @('-E;&8N<VEZ97(N1FET*'-E;&8N<&%N96PI#0H@(" @(" @
M(" @("!H96EG:'0@/2!S96QF+G!A;F5L+D=E=%-I>F4H*2YH96EG:'0-"B @
M(" @(" @(" @('-E;&8N<V-R;VQL97(N4V5T4V-R;VQL8F%R<R@R,"P@,C L
M(# L("AH96EG:'0@*R R,"D@+R R,"D-"B @(" @(" @(" @('-E;&8N<&%N
M96PN3&%Y;W5T*"D-"@T*#0H@(" @9&5F($]N4VEZ95=I;F1O=RAS96QF+"!E
M=F5N="DZ#0H@(" @(" @(&EF('-E;&8N1V5T075T;TQA>6]U="@I.@T*(" @
M(" @(" @(" @<V5L9BY,87EO=70H*0T*(" @(" @("!S96QF+G)E8G5I;&13
M:7IE<B@I#0H-"@T*8VQA<W,@5&5S=$%P<"AW>$%P<"DZ#0H@(" @9&5F($]N
M26YI="AS96QF*3H-"B @(" @(" @9G)A;64@/2!497-T1G)A;64H3E5,3"P@
M+3$L(")497-T(BD-"B @(" @(" @<V5L9BY39714;W!7:6YD;W<H9G)A;64I
M#0H@(" @(" @(&9R86UE+E-H;W<H5%)512D-"B @(" @(" @<F5T=7)N(%12
M544-"@T*(R!-86EN('!R;V=R86TZ#0H-"F%P<" ](%1E<W1!<' H,"D-"F%P
2<"Y-86EN3&]O<"@I#0H-"@T*
`
end

It's quite interesting to compare the behaviour under Linux and
Windows -- they're quite different! Can anyone suggest a
workaround for getting my wxGridSizer to work properly under
Windows? I'm quite desperate to get this fixed, as my program
*needs* to run under Windows and with this layout logic broken my
entire program is unusable -- and I've got people waiting to test
it. I'd be *really* grateful if someone could help me figure out
how to fix this...

Well, here's a *vile* hack that you can use as a fall-back position
(it's also an interesting symptom of what's wrong, if you care to dig)
Windows displays the whole grid when there is one more item than will
fit across the last row; that is if n items will fit across a row, and
the total number of items is m, when n%m == 1. So calculate the
number of items that will fit across the window for the current window
size, and then always pad your grid so that n % m == 1.

:stuck_out_tongue:

--Patricia

Hi Robin,

Add this line here:

              self.panel.Layout()

On wxGTK the panel is probably getting a size event as a result of the stuff
happening in rebuild() but on wxMSW it is not. The default size event
handler will call Layout so that's why it's working on wxGTK.

Thanks! I was getting rather desperate trying to figure out what on earth was going wrong...

But you've probably noticed a lot of flicker as you destroy everything and
recreate it in the new sizer... I've attached an alternative
(gridsizer2.py) that doesn't destory the windows and just adds the existing
ones to the new sizer. Works a bit better.

> (there doesn't seem to be any way of dynamically
> changing the number of rows and/or columns for a wxGridSizer, so I have to
> create a new one from scratch),

Ah, but there is. There is a SetCols method that will do it for you. I've
also attached gridsizer3.py that shows how to do it this way.

Wow!!! Thank you a million times over -- this is way beyond the sort of reply I was hoping for. Given how critical this code is to the operation of the program I'm working on, getting this to work smoothly is absolutely vital. I'm truly in your debt for this -- if there's ever anything I can do for you, please just let me know...

- Erik.

Hello,

Here's a package ready for wider use and testing.
The gui_thread package runs wxPython in a secondary thread leaving, the
Python command line interpreter running in the primary thread. It allows
users to create and interact with any type of wxPython window from the
Python command line.

The event based mumbo-jumbo needed to interact between threads is handled by
creating proxy classes that wrap around wxPython classes. See the page for
more details.

It is designed to work on Windows, Linux, and hopefully other platforms.

http://www.scipy.org/Members/eric/gui_thread

Consider the code alpha, and please report an bug fixes you find --
especially you Linux gurus.

thanks,

eric

>But you've probably noticed a lot of flicker as you destroy everything

and

>recreate it in the new sizer... I've attached an alternative
>(gridsizer2.py) that doesn't destory the windows and just adds the

existing

>ones to the new sizer. Works a bit better.
>
> > (there doesn't seem to be any way of dynamically
> > changing the number of rows and/or columns for a wxGridSizer, so I

have to

> > create a new one from scratch),
>
>Ah, but there is. There is a SetCols method that will do it for you.

I've

>also attached gridsizer3.py that shows how to do it this way.

Wow!!! Thank you a million times over -- this is way beyond the sort of
reply I was hoping for.

I just rented Guido's time machine and went back and added the method for
you, no big deal. <grin>

Given how critical this code is to the operation
of the program I'm working on, getting this to work smoothly is absolutely
vital. I'm truly in your debt for this -- if there's ever anything I can
do for you, please just let me know...

I'll send you a bill... <wink>

···

--
Robin Dunn
Software Craftsman
robin@AllDunn.com Java give you jitters?
http://wxPython.org Relax with wxPython!

Robin,
  How is your thread guy doing working on the thread safety problems?

Eric,
  I suggested a possible way to fix the problem you are seeing with import
  of the wxPython binding to the importing thread and not the thread that
  will use wxPython.

    Barry

···

-----Original Message-----
From: wxpython-users-admin@lists.wxwindows.org
[mailto:wxpython-users-admin@lists.wxwindows.org]On Behalf Of eric jones
Sent: 08 May 2001 09:11
To: wxpython-users@lists.wxwindows.org
Subject: [wxPython] Package for using wxPython in secondary thread

Hello,

Here's a package ready for wider use and testing.
The gui_thread package runs wxPython in a secondary thread leaving, the
Python command line interpreter running in the primary thread. It allows
users to create and interact with any type of wxPython window from the
Python command line.

The event based mumbo-jumbo needed to interact between threads is handled by
creating proxy classes that wrap around wxPython classes. See the page for
more details.

It is designed to work on Windows, Linux, and hopefully other platforms.

http://www.scipy.org/Members/eric/gui_thread

Consider the code alpha, and please report an bug fixes you find --
especially you Linux gurus.

thanks,

eric

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwindows.org
http://lists.wxwindows.org/mailman/listinfo/wxpython-users

Robin,
How is your thread guy doing working on the thread safety problems?

Found out just yesterday that the SWAG I tried didn't work. I plan on
building my own SMP machine soon and so will be able to better track down
the SMP problem.

The suggestions you made a while back about being able to change which is
considered the "main thread" are still a possibility. I got some
suggestions from Vadim about it but havn't been able to try anything out
yet.

···

--
Robin Dunn
Software Craftsman
robin@AllDunn.com Java give you jitters?
http://wxPython.org Relax with wxPython!

Eric,
I suggested a possible way to fix the problem you are seeing with import
of the wxPython binding to the importing thread and not the thread that
will use wxPython.

Barry

Unfortunately this doesn't work in gui_thread (At least under MSWindows).
Windows are created just fine and even respond correctly to most interactive
clicks, but they will not respond to clicks on the Close button, and
repeated Close clicks will lead to flames. The first time that wxPython is
imported *must* occur in the secondary thread. I can't state this based on
intimate knowledge of wxPython's internals, just on good-ole fashion
trial-and-error. There could be a clever way around it that I don't know
about.

Also, for a little fun (?), try the following code snippet. It'll start up
3 or so of the standard wxPython Demo windows from the command line. You
should be able to interact with them with the mouse and probe/set things
from the command line. This works pretty well on my machine, but
occasionally gives flaky results (while the demo in the package works pretty
smoothly). I'd like to here how it goes on other machines as the Linux
support still has quite a few kinks (and I'm no expert here).

    [ej@n0 ej]$ cd wxPython2.2.5/demo
    [ej@n0 demo]$ python
    Python 2.1 (#1, Apr 23 2001, 11:25:46)
    [GCC 2.95.3 20010315 (release)] on linux2
    Type "copyright", "credits" or "license" for more information.
    >>> import gui_thread
    >>> wxPython imported
    <hit return>
    >>> import Main
    >>> q = gui_thread.register(Main.wxPythonDemo)
    >>> w1 = q(None,-1,'bob')
    >>> w2 = q(None,-1,'fred')
    >>> w3 = q(None,-1,'albert')
    >>> w1.GetTitle()
    'bob'
    >>> w1.SetTitle('jane')

regards,

eric

> Eric,
> I suggested a possible way to fix the problem you are seeing with import
> of the wxPython binding to the importing thread and not the thread that
> will use wxPython.
>
> Barry

Unfortunately this doesn't work in gui_thread (At least under MSWindows).

  That would because the suggested change to wxPython is not implemented
  in the released version. I only have a proto on my machine. I can import
  on the main thread and then start an gui up on a secondary thread.

  What I did was prevent wxPython from initialising until first use. But
  the way I did it was a bit of a hack to show the principle. It needs folks
  that understand the wxPython/wxWindows internals to develop a robust
  fix.

    Barry

OK. What are the chances it'll eventually make it into wxPython/wxWindows?
I have a patch to Python that works around the thread race condition
occuring with module locks, but it wouldn't be as good as this. It still
requires that the first import of wxPython be in the second thread. Sounds
like your patch could remove this restriction. I'm all for that.

eric

···

----- Original Message -----
From: "Barry Scott" <barry@scottb.demon.co.uk>
To: <wxpython-users@lists.wxwindows.org>
Sent: Sunday, May 13, 2001 3:10 AM
Subject: RE: [wxPython] Package for using wxPython in secondary thread

> > Eric,
> > I suggested a possible way to fix the problem you are seeing with

import

> > of the wxPython binding to the importing thread and not the thread

that

> > will use wxPython.
> >
> > Barry
>
> Unfortunately this doesn't work in gui_thread (At least under

MSWindows).

That would because the suggested change to wxPython is not implemented
in the released version. I only have a proto on my machine. I can import
on the main thread and then start an gui up on a secondary thread.

What I did was prevent wxPython from initialising until first use. But
the way I did it was a bit of a hack to show the principle. It needs folks
that understand the wxPython/wxWindows internals to develop a robust
fix.

Barry

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwindows.org
http://lists.wxwindows.org/mailman/listinfo/wxpython-users