Opened 7 years ago

Closed 19 months ago

#4564 closed defect (fixed)

Picture rendering error when maximizing the frame

Reported by: ericyosho Owned by: vadz
Priority: normal Milestone:
Component: wxMSW Version: stable-latest
Keywords: Cc: ericyosho
Blocked By: Blocking:
Patch: no

Description

version: wxPython2.8-win32-unicode-2.8.6.0-py25.exe
platform: windowsXP SP2

A frame is created to hold a bmp pic, whose size at first is the same with the pic size.

When maximizing the frame, 2 pics appear on the screen.
One is on the topleft corner, the other in the middle of the screen.

The topleft one gone as soon as we minimize the frame and remaximize it, or put another frame over it.

I think the topleft corner is the position where the pic lies originally. As far as we minimize and remaximize, the frame refreshes, so it is gone, leaving the middle one as desired.

I wonder whether it is a tiny bug of carelessness or a feature that we users should refresh the frame manually on our own.

Lots of thanks.

Attachments (2)

rendering error.JPG download (30.3 KB) - added by ericyosho 7 years ago.
2 pics appear on the screen when maximizing the frame
test4564_minimal.diff download (852 bytes) - added by catalin 19 months ago.

Download all attachments as: .zip

Change History (9)

Changed 7 years ago by ericyosho

2 pics appear on the screen when maximizing the frame

comment:1 Changed 6 years ago by wojdyr

  • Status changed from new to infoneeded_new

could you provide a minimal program that demonstrates the issue?

comment:2 Changed 6 years ago by erickyosho

  • Status changed from infoneeded_new to new

with pleasure:

#!/usr/bin/env python
#-*- coding: utf8 -*-
"""Hello, wxPython! program."""

import wx

class Frame(wx.Frame):
    """Frame class that displays an image."""

    def __init__(self, image, parent=None, id=-1,
                 pos=wx.DefaultPosition,
                 title='Hello, wxPython!'):
        """Create a Frame instance and display image."""
        temp = image.ConvertToBitmap()
        size = temp.GetWidth(), temp.GetHeight()
        style = wx.DEFAULT_FRAME_STYLE | wx.RAISED_BORDER | wx.CLOSE_BOX
        wx.Frame.__init__(self, parent, id, title, pos, size, style)
        self.bmp = wx.StaticBitmap(parent=self, bitmap=temp)

class App(wx.App):
    """Application class."""

    def OnInit(self):
        image = wx.Image('tv.jpg', wx.BITMAP_TYPE_JPEG)
        self.frame = Frame(image)
        self.frame.Show()
        self.SetTopWindow(self.frame)
        return True


def main():
        app = App()
        app.MainLoop()


if __name__ == '__main__':
        main()



comment:3 Changed 6 years ago by wojdyr

  • Component set to wxMSW

On wxGTK the image is always in the top left corner.

Changed 19 months ago by catalin

comment:4 follow-up: Changed 19 months ago by catalin

  • Status changed from new to confirmed
  • Version set to 2.9-svn

The problem under MSW is that the wxBitmap is painted in the middle of the wxStaticBitmap (see wxStaticBitmap::DoPaintManually) and when resized it is not Refresh()-ed.
There is also a wxGenericStaticBitmap which paints the wxBitmap always at (0, 0), see wxGenericStaticBitmap::OnPaint.

Adding an OnSize handler for the MSW implementation that calls Refresh() is enough to fix this ticket.

Other questions:
1) should MSW implementation paint at (0, 0) too?
2) should implementation that paint at (0, 0) have OnSize handlers? I didn't see any artefacts with the generic one but I didn't test it very much.
3) should wxGenericStaticBitmap::OnPaint erase the background too?

Test patch attached.

comment:5 in reply to: ↑ 4 ; follow-up: Changed 19 months ago by vadz

  • Owner set to vadz
  • Status changed from confirmed to accepted

Replying to catalin:

The problem under MSW is that the wxBitmap is painted in the middle of the wxStaticBitmap (see wxStaticBitmap::DoPaintManually)

Actually it's not used under modern Windows systems (>= XP), what we see here is the default behaviour of the native static control. It's pretty strange that it doesn't update correctly when resized but it's actually consistent with MSDN as it doesn't list WM_SIZE in the list of the messages they handle.

Adding an OnSize handler for the MSW implementation that calls Refresh() is enough to fix this ticket.

OK, I'll do it, thanks for debugging!

Other questions:
1) should MSW implementation paint at (0, 0) too?

I don't think so because this would be inconsistent with the native behaviour.

2) should implementation that paint at (0, 0) have OnSize handlers? I didn't see any artefacts with the generic one but I didn't test it very much.

No, this shouldn't be necessary, resizing the control doesn't invalidate anything in this case.

3) should wxGenericStaticBitmap::OnPaint erase the background too?

Not as long as it doesn't use SetBackgroundStyle(wxBG_STYLE_PAINT). Which, surprisingly, it doesn't currently use...

Test patch attached.

FWIW I used just

  • samples/minimal/minimal.cpp

    a b bool MyApp::OnInit() 
    172172    CreateStatusBar(2); 
    173173    SetStatusText("Welcome to wxWidgets!"); 
    174174#endif // wxUSE_STATUSBAR 
     175 
     176    new wxStaticBitmap(this, wxID_ANY, wxBitmap("../image/horse.bmp", wxBITMAP_TYPE_BMP)); 
    175177} 
    176178 
    177179 

which is even more minimal (MSW can load BMPs on its own, so no need for wxImage).

comment:6 in reply to: ↑ 5 Changed 19 months ago by catalin

Replying to vadz:

+ new wxStaticBitmap(this, wxID_ANY, wxBitmap("../image/horse.bmp", wxBITMAP_TYPE_BMP));

which is even more minimal (MSW can load BMPs on its own, so no need for wxImage).

Very true; I tried something like

new wxBitmap("..
image
horse.bmp");

which didn't work because it was not found among the resources, but now I see wxBITMAP_DEFAULT_TYPE is wxBITMAP_TYPE_BMP_RESOURCE under MSW.

comment:7 Changed 19 months ago by VZ

  • Resolution set to fixed
  • Status changed from accepted to closed

(In [73485]) Refresh wxMSW wxStaticBitmap when its size changes.

As MSW native control centers the image, it must be entirely redrawn when the
area in which the image is centered changes, but it doesn't happen by default,
so do it ourselves explicitly.

Also explain that this centering behaviour is platform-specific and shouldn't
be relied upon.

Closes #4564.

Note: See TracTickets for help on using tickets.