Giter Club home page Giter Club logo

Comments (16)

infinity77 avatar infinity77 commented on June 14, 2024 1

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.

DietmarSchwertberger avatar DietmarSchwertberger commented on June 14, 2024 1

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.

da-dada avatar da-dada commented on June 14, 2024

well, I can't find any problem what so ever with that event on Windows 11

from phoenix.

ClayShoaf avatar ClayShoaf commented on June 14, 2024

@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.

da-dada avatar da-dada commented on June 14, 2024

@ClayShoaf, it's a mouse event and doesn't trigger anything (I'm afraid there is some suitable coding required)

from phoenix.

ClayShoaf avatar ClayShoaf commented on June 14, 2024

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.

da-dada avatar da-dada commented on June 14, 2024

@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.

ClayShoaf avatar ClayShoaf commented on June 14, 2024

You have to use three ticks ``` at the top and bottom of your code to get it to format correctly.

from phoenix.

da-dada avatar da-dada commented on June 14, 2024

@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.

DietmarSchwertberger avatar DietmarSchwertberger commented on June 14, 2024

@ClayShoaf : please provide a small runnable sample demonstrating the problem.

from phoenix.

ClayShoaf avatar ClayShoaf commented on June 14, 2024

@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.

da-dada avatar da-dada commented on June 14, 2024

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.

ClayShoaf avatar ClayShoaf commented on June 14, 2024

@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.

ClayShoaf avatar ClayShoaf commented on June 14, 2024

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.

ClayShoaf avatar ClayShoaf commented on June 14, 2024

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.

da-dada avatar da-dada commented on June 14, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.