Comments (16)
I am not sure if things have changed since a long time ago, but if my memory serves me well, on GTK wx.StaticBitmap is not a real control. GTK draws the bitmap itself on the parent widget. This is not the case on Windows.
I am not entirely clear what your code does and why it is structured that way - and why you do need a background bitmap in the first place. But @da-dada is right, there cannot be a "punch-through" in this case.
I don't have a fix out of the blue, beside removing the use of wx.StaticBitmap and draw the images yourself inside a wx.EVT_PAINT event. Something along these lines:
import wx
import wx.lib.scrolledpanel as scrolled
class Dummy(wx.Window):
def __init__(self, parent):
wx.Window.__init__(self, parent)
self.bitmap = wx.Bitmap('./test.png', wx.BITMAP_TYPE_PNG)
self.SetInitialSize(self.DoGetBestSize())
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_PAINT, self.OnPaint)
def DoGetBestSize(self):
w, h = self.bitmap.GetWidth(), self.bitmap.GetHeight()
return wx.Size(w, h)
def OnSize(self, event):
event.Skip()
self.Refresh()
def OnPaint(self, event):
w, h = self.GetClientSize()
dc = wx.AutoBufferedPaintDC(self)
dc.Clear()
dc.DrawBitmap(self.bitmap, 0, 0)
app = wx.App()
root = wx.Frame(None, -1, "wxPyMuPDF", size=(800, 600))
root.Maximize(True)
vbox = wx.BoxSizer(wx.VERTICAL)
root.SetSizer(vbox)
scrolly = scrolled.ScrolledPanel(root, size=root.GetSize())
scrolly.SetAutoLayout(0)
gap = 10
layout = 1
hbox = wx.BoxSizer(wx.HORIZONTAL)
fgs = wx.FlexGridSizer(cols=1, vgap=10, hgap=10)
gbs = wx.GridBagSizer(gap, gap)
gbs.SetEmptyCellSize((-gap,-gap))
pages = [wx.Window(scrolly), wx.Window(scrolly)]
def test_output(e):
print('AAAAAAAAAAAAAAAAAAAAAAAAAAAA')
for i in range(len(pages)):
pages[i].SetBackgroundColour('white')
test_win = Dummy(pages[i])
pages[i].SetSize(test_win.GetSize())
test_win.Bind(wx.EVT_ENTER_WINDOW, test_output)
gbs.Add(pages[i], (i,0), flag=wx.ALIGN_CENTER_HORIZONTAL)
hbox.AddStretchSpacer(1)
hbox.Add(gbs)
hbox.AddStretchSpacer(1)
scrolly.SetSizer(hbox)
scrolly.SetupScrolling()
vbox.Add(scrolly, 0, wx.ALIGN_CENTER)
def on_resize(e):
scrolly.SetSize(root.GetVirtualSize())
scrolly.Update()
scrolly.SetupScrolling(scrollToTop=False)
root.Bind(wx.EVT_SIZE, on_resize)
root.Show()
app.MainLoop()
from phoenix.
See here why unhandled mouse events do not propagate: https://docs.wxpython.org/events_overview.html#how-events-propagate-upwards
As Andrea wrote: paint yourself.
Have a look at the demo for some example code: Core Windows / Controls -> ScrolledWindow
As a general rule of thumb: use controls for controlling things. If you have something like a document viewer or editor, then you probably need to handle things yourself to be efficient. You don't want to have 1000 large StaticBitmaps for a 1000 page PDF document. Or: what happens if you want to zoom? You quickly will run out of memory.
from phoenix.
well, I can't find any problem what so ever with that event on Windows 11
from phoenix.
@da-dada, is that to say that when you hover over the page, the buttons come up? Are you able to trigger a print command?
from phoenix.
@ClayShoaf, it's a mouse event and doesn't trigger anything (I'm afraid there is some suitable coding required)
from phoenix.
In the code I posted, it is bound to self.showButtons
which is a function that makes buttons appear on a page. Maybe "trigger" has some other meaning and I'm using the word incorrectly.
What I'm getting at is that, on linux, this event is recognized and the function runs. On Windows 11, it is not recognized. Even if I just put print("test")
at the beginning of the self.showButtons
function, it does not print.
from phoenix.
@ClayShoaf I'm not sure what your code is doing but the event is working absolutely perfect, as you can easily see by running this snippet
class Win(wx.Window):
def __init__(self, parent, txt):
super().__init__(parent)
def evt_enter(_):
self.SetBackgroundColour(wx.RED)
self.Refresh()
txt.SetLabel('Over Me')
self.Bind(wx.EVT_ENTER_WINDOW, evt_enter)
def evt_leave(_):
self.SetBackgroundColour(wx.YELLOW)
self.Refresh()
txt.SetLabel('Not Over')
self.Bind(wx.EVT_LEAVE_WINDOW, evt_leave)
def evt_window(_):
self.SetBackgroundColour(None)
self.Refresh()
txt.SetLabel("yes, I'm a Window..")
self.Bind(wx.EVT_LEFT_DOWN, evt_window)
class Gui(wx.Frame):
def __init__(self, parent):
super().__init__(parent, title='enter / leave Window')
vbox = wx.BoxSizer(wx.VERTICAL)
txt = wx.StaticText(self)
vbox.Add(txt, 0, wx.LEFT|wx.TOP|wx.EXPAND, 10)
win = Win(self, txt)
vbox.Add(win, 1, wx.LEFT|wx.TOP|wx.EXPAND, 10)
self.SetSizer(vbox)
self.SetBackgroundColour(None)
def evt_text(_):
txt.Refresh()
txt.SetLabel("yes, I'm text..")
txt.Bind(wx.EVT_LEFT_DOWN, evt_text)
self.Show()
app = wx.App()
Gui(None)
app.MainLoop()
from phoenix.
You have to use three ticks ``` at the top and bottom of your code to get it to format correctly.
from phoenix.
@ClayShoaf or if you like to keep the handlers separate from the window
class WinEvh:
def __init__(self, gui):
super().__init__(gui)
self.gui = gui
def evt_enter(self, _):
self.SetBackgroundColour(wx.RED)
self.Refresh()
self.gui.txt.SetLabel('Over Me')
def evt_leave(self, _):
self.SetBackgroundColour(wx.YELLOW)
self.Refresh()
self.gui.txt.SetLabel('Not Over')
def evt_window(self, _):
self.SetBackgroundColour(None)
self.Refresh()
self.gui.txt.SetLabel("yes, I'm a Window..")
class Win(WinEvh, wx.Window):
def __init__(self, gui):
super().__init__(gui)
self.Bind(wx.EVT_ENTER_WINDOW, self.evt_enter)
self.Bind(wx.EVT_LEAVE_WINDOW, self.evt_leave)
self.Bind(wx.EVT_LEFT_DOWN, self.evt_window)
class Gui(wx.Frame):
def __init__(self, parent):
super().__init__(parent, title='enter / leave Window')
vbox = wx.BoxSizer(wx.VERTICAL)
self.txt = wx.StaticText(self)
vbox.Add(self.txt, 0, wx.LEFT|wx.TOP|wx.EXPAND, 10)
win = Win(self)
vbox.Add(win, 1, wx.LEFT|wx.TOP|wx.EXPAND, 10)
self.SetSizer(vbox)
self.SetBackgroundColour(None)
def evt_text(_):
self.txt.Refresh()
self.txt.SetLabel("yes, I'm text..")
self.txt.Bind(wx.EVT_LEFT_DOWN, evt_text)
self.Show()
app = wx.App()
Gui(None)
app.MainLoop()
from phoenix.
@ClayShoaf : please provide a small runnable sample demonstrating the problem.
from phoenix.
@DietmarSchwertberger this is as short as I can make it to reproduce the result. wx.EVT_ENTER_WINDOW
is triggered on Linux, but not on Windows:
import wx
import wx.lib.scrolledpanel as scrolled
app = wx.App()
root = wx.Frame(None, -1, "wxPyMuPDF", size=(800,600))
root.Maximize(True)
vbox = wx.BoxSizer(wx.VERTICAL)
root.SetSizer(vbox)
root.SetAutoLayout(1)
scrolly = scrolled.ScrolledPanel(root, size=root.GetSize())
scrolly.SetAutoLayout(0)
gap = 10
layout = 1
hbox = wx.BoxSizer(wx.HORIZONTAL)
fgs = wx.FlexGridSizer(cols=1, vgap=10, hgap=10)
gbs = wx.GridBagSizer(gap, gap)
gbs.SetEmptyCellSize((-gap,-gap))
pages = [wx.Window(scrolly), wx.Window(scrolly)]
def test_output(e):
print('AAAAAAAAAAAAAAAAAAAAAAAAAAAA')
for i in range(len(pages)):
pages[i].SetBackgroundColour('white')
test_img = wx.StaticBitmap(pages[i], -1, wx.Image('./test.png',wx.BITMAP_TYPE_PNG))
pages[i].SetSize(test_img.GetSize())
pages[i].Bind(wx.EVT_ENTER_WINDOW, test_output)
gbs.Add(pages[i], (i,0), flag=wx.ALIGN_CENTER_HORIZONTAL)
hbox.AddStretchSpacer(1)
hbox.Add(gbs)
hbox.AddStretchSpacer(1)
scrolly.SetSizer(hbox)
scrolly.SetupScrolling()
vbox.Add(scrolly, 0, wx.ALIGN_CENTER)
def on_resize(e):
scrolly.SetSize(root.GetVirtualSize())
scrolly.Update()
scrolly.SetupScrolling(scrollToTop=False)
root.Bind(wx.EVT_SIZE, on_resize)
root.Show()
app.MainLoop()
You should be able to use any test.png file for this.
It appears that the problem occurs when there is a wx.StaticBitmap
on the window. It's like the mouse event doesn't "punch through" to the underlying window, because the bitmap is covering it. I have tried binding the wx.StaticBitmap
to wx.EVT_ENTER_WINDOW
. This, at least, will cause the event to trigger on windows, but then I can't get the buttons, in my main program, to show up on my windows machine. I don't know if they are also behind the bitmap, or what. I haven't had time to troubleshoot any further, and I don't want to waste my time if there's something obvious that I'm missing.
My fear, in posting this, is that this anomaly will be "fixed" by making it not work on Linux either.
from phoenix.
well, there is no punch through: the mouse can only be in one window
what you could do is make the window under the bitmap a bit larger (what you may experience on your other systems) and the mouse will then go into that 'frame' of the underlying window first, trigger your handler and...
from phoenix.
@da-dada Incorrect. The reason I had to write this logic:
elif event.GetEventType() == wx.wxEVT_LEAVE_WINDOW:
pos = event.GetPosition()
rect_l = self.rot_l.GetRect()
rect_r = self.rot_r.GetRect()
rect_save = self.save_img.GetRect()
good = True
if rect_r.Contains(pos):
good = False
elif rect_l.Contains(pos):
good = False
elif rect_save.Contains(pos):
good = False
if good:
self.rot_l.Hide()
self.rot_r.Hide()
self.save_img.Hide()
self.parent.SetFocus()
is because whenever the mouse went over one of the buttons, it would trigger wx.EVT_LEAVE_WINDOW
. This means that the mouse is still being recognized as being in the window, even though it's over a wx.StaticBitmap
(on Linux).
Even if I were willing to do a work-around solution, like making the window bigger than the image it contains, it wouldn't work, because as soon as the mouse was over the image, it would trigger wx.EVT_LEAVE_WINDOW
and my buttons would disappear again (on Windows).
from phoenix.
on GTK wx.StaticBitmap is not a real control. GTK draws the bitmap itself on the parent widget. This is not the case on Windows.
Interesting.
I am not entirely clear what your code does and why it is structured that way - and why you do need a background bitmap in the first place.
Because I don't know all of the controls and features of wxPython, so I used the thing I was able to find that actually worked (or so I thought).
draw the images yourself inside a wx.EVT_PAINT event. Something along these lines:
Thank you very much for the code snippet! I haven't tested it on Windows, but I will assume it works as expected. I will work on changing my code to try implementing this way of drawing the images!
Now if I could just get the search function in the docs to work... 😅
from phoenix.
what happens if you want to zoom?
I tried writing some logic to only do a high quality zoom for the pages that are on screen. I originally tried to resize the windows without doing a wx.IMAGE_QUALITY_NEAREST
zoom on all of the pages, but I couldn't get it to work correctly, so, for now, I'm just doing the computationally cheapest zoom for all of the off screen pages and then doing a high quality zoom for the pages that are on screen.
I will look at the page you posted and explore wx.EVT_PAINT
. I still haven't been able to wrap my head around exactly how a dc
works, but I need to look into that as well.
I appreciate all of the replies!
from phoenix.
I appreciate all of the replies!
well, since your bug has run out of steam I think opening a discussion may attract more ideas
from phoenix.
Related Issues (20)
- Virtual ListCtrl does not reliably render more than about 364k rows HOT 13
- SOLVED: Demo fails because distutils package has been removed as of Python 3.12 PEP 632 HOT 4
- Incompatibility of GetColPos/GetRowPos and GetSelectionBlockTopLeft/GetSelectionBlockBottomRight functions in wxGrid HOT 3
- Incorrect updating of wxGrid when sorting rows using the SetRowPos function
- Call to wx.aui.AuiNotebook() causes segmentation fault in 4.2.1 on ARM Mac with conda's py 3.10
- Build wxpython on Debian, MX-21, Ubuntu 22.04 failed HOT 12
- Snapshot build(s) have stopped building HOT 7
- Importing wx.media on Windows HOT 5
- Unable to install wxPython on OpenSUSE 15.5 in venv - python-config not found. HOT 7
- PropertyGridManager does not handle the issue of parent property display disorder. HOT 3
- Is it possible to create wheel from actual master branch? HOT 10
- BusyCursor docs are outdated HOT 1
- 4-byte characters (emojis) in StaticText/TextCtrl/Button/ListCtrl/... labels or values cause string truncation HOT 2
- Recent sip related change to build.py breaks building from source on GTK HOT 2
- Bug on RibbonBar RecalculateTabSizes
- A Segmentation fault is caused by wxpython 4.2.1 + python 3.12.1 HOT 1
- "python setup.py bdist_wheel" Error while installing wxPython HOT 2
- SystemError: <slot wrapper '__init__' of 'sip.simplewrapper' objects> returned a result with an error set HOT 2
- Native error dialog on MacOS does not show exclamation mark icon
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from phoenix.