Open PendulumDreams opened 6 years ago
It looks like your widget hierarchy is a bit like this:
+-------+ +----------+ +--------------+
| Frame +--+-+Scrolled +--+--+Vis.Glitch |
+-------+ | +----------+ | +--------------+
| +--+Partial. W.A. |
| | +--------------+
| +--+Work Around |
| +--------------+
| +-----+ +--------------+
+ |Panel+-------+--+wx.Choice |
+-----+ | +--------------+
+--+Reset Filters |
+--------------+
where the Scrolled
object and Panel
(second level) are competing for space between toggles.
This behavior stems from an old wxWidgets thing wherein "The behavior of overlapping sibling widgets is undefined"
What seems to be happening is that when the ui_filter_container is re-shown the children are being drawn onto the scrolled panel first, which is then being resized with the damage to its drawable area already done. In the second case, the Reset Filters button is the one doing the damage to the ScrolledPanel.
There are two approaches to fixing this:
You can hide anything in space that is about to be consumed by the scrolled panel before resizing the scrolled panel, which is what's happening in that last case in filterToggle3
When the parent widget, ui_filter_container
is re-shown the child widgets are already hidden by the previous two lines. This is definitely tedious. Luckily the Sizer
class is to the rescue. It has the ability to recursively hide/show widgets under its control. ex:
self.ui_main_sizer.Hide(self.ui_filter_container, True)
You can call Refresh
on the ScrolledPanel to cause a paint event which will in turn repair the damaged area. I don't really recommend this though, unless you go through the extra effort clipping the DC and only repairing the damaged region, otherwise you'll get visible stutters on quick-redraws.
OnInit
instead of __init__
You should do app-level initializaiton in the App's OnInit
method, rather than overriding the initializer. Returning True
from that method tells wx that everything is fine, and False indicates a failure and will prevent the app from running.
wx.StatusBar
Also, you may want to look into:
https://wxpython.org/Phoenix/docs/html/wx.StatusBar.html
to see if its sufficient for what you have planned for ui_status_container
I figured while I'm at it, I may as well point you in the direction of some of the more fun sizers too: https://wxpython.org/Phoenix/docs/html/wx.GridBagSizer.html
This sizer allows you to create a grid and then have widgets assigned to it span across flexible rows and columns (that is, rows and columns can be permitted to grow/shrink independently of eachother)
In essence this allows the layout you have going now, which consists of several sizers, boil down to the one top level sizer in the Frame, and then whatever sizers exist in the Frame's children.
That is the widget hierarchy. Of course there are more widgets in the actual application but those were all that I noticed with glitches. And I just added the buttons to the wrapping area because I temporarily put a bunch of buttons in there to test resizing. I didn't realize I left in the ui_status_container, wasn't needed to show the issue.
As for the StatusBar widget, I'm not planning on using it and I was planning to use a ribbon but have decided not to. If you look at the style of the newer Windows 10 applications (like print 3d or paint 3d) they no longer use a ribbon or status bar. Of course they use windows 10's new acrylic system which looks really nice, but I don't need that.
Because of what the application is being designed to do I need to have a colour theme in it which can be toggled on and off and uses no blue. The application will manage and control wallpapers so that in the morning it will show wallpapers that are bright and blue to help you wake up and nearing the time you want to sleep it will shift towards wallpapers that are darker and with less and less blue. And flat colours (no gradients) will look better on Windows 10. The application uses lots of windows api calls because of the requirements to switch wallpaper but has been built in a way where mac and linux code could be added so the application would work on them.
Thanks for the pointers about the other things. I'll definitely switch to hiding the sizer instead of each widget so that the glitch goes away with less code.
As for the sizer, I've seen and used a couple but didn't notice that one yet. I'll have to take a look. By the time I get everything working the way I want and have it ready for release I'm sure I'll know more about wxPython.
There are two factors at play here. First, Windows will not redraw something if it thinks it doesn't need it, despite the fact that without native layered double buffering it is easier than it should be for something to mess with the on-screen image of something else. Second, overlapping sibling windows (the panel and scrolled panel in this case) is just the sort of thing that can cause that kind of damage.
Fortunately the fix/workaround is usually simple. Just refresh the window that is being damaged. In your example changing the filterToggle
method to look like this takes care of the problem for me:
def filterToggle(self, event):
# Visual Glitch -- NOT!
if event.IsChecked():
self.ui_filter_container.Show()
else:
self.ui_filter_container.Hide()
self.Layout()
# added this line, removed the PostSizeEvent
self.ui_wallpapers_container.Refresh()
@swt2c : it seems to me that @RobinD42 ‘s answer clears this up, I believe this can be closed
Operating system: Windows 10 Pro Version 1709 Build 16299.192 wxPython version: 4.01 Stock or custom build: Stock Python version: 3.6.3 64 bit. Stock or custom build: Stock
Description of the problem:
Attached is a test file which replicates the issue and provides a partial workaround where I found an additional visual glitch and a full workaround. The window contains a panel on the left which contains a Choice and Button widget. On the right is a wrap sizer with a ScrolledPanel which contains three toggle buttons, one to show the initial visual glitch I found, a second to show the secondary visual glitch I found while trying to fix the first one, and a third button which runs code that works around the issue. I only noticed this issue because I had coloured the background of the scrolledpanel yellow while I was trying to set up the sizers. Used wxpython only once probably about 10ish years ago, but am making an application I will be putting up on github for free and wxpython seemed like a better choice over tkinter because tkinter has issues with becoming an executable. visual_glitch.zip
To replicate the issue press the Visual Glitch toggle button twice. On first click it will hide the panel on the left and on the second click it will show the panel again. This is what I am seeing after the second click. You can tell the stray Combo is a visual glitch if you resize the window to cut off part of what looks like the widget and then resize larger.
If you restart the application and click the partial work around button twice I see the following:
And then of course if you use the work around button I don't see any visual glitches.
Not sure if other widgets have a simlar issue. If you need any more information let me know.