wxPython 4.1.0 Released

“Escaping the Quarantine”

wxPython 4.1.0 is now available at PyPI, with some additional files at Extras

Starting with this release wxPython has switched to tracking the wxWidgets
master branch (version 3.1.x) for the wxWidgets source code, which wxPython is
built upon, and which is included in the wxPython source archives.

This will be the last release to include binaries for Python 2.7. The code will
likely still compile and be compatible with Python 2.7 for some time, but no
effort will be put into keeping it that way.

New and improved in this release:

  • Add a sample for wx.Font.AddPrivateFont to the demo.

  • Added wrappers for the OSXEnableAutomaticQuoteSubstitution,
    OSXEnableAutomaticDashSubstitution, and OSXDisableAllSmartSubstitutions
    methods in wx.TextCtrl. Also added OSXEnableAutomaticTabbing in wx.App.

  • Added wx.ColourDialogEvent, wx.DCTextBgColourChanger, wx.DCTextBgModeChanger,
    wx.grid.GridCellDateRenderer, wx.grid.GridCellDateEditor, wx.SystemAppearance,
    etc.

  • Many of the deprecated items in wxWidgets and wxPython are being or have
    been removed. Be sure to test your code in a recent 4.0.x release with
    warnings enabled so you can see which class, method or function calls you need
    to change.

  • Bug fixes in wx.lib.calendar: key navigation across month boundaries is now
    possible; key navigation now sets the date and fires the EVT_CALENDAR event;
    setter APIs now set the date correctly #1230.

  • Switch to using a wx.Overlay in the Widget Inspection Tool to highlight
    widgets when running on a GTK3 port.

  • Fixed issue in wx.lib.agw.customtreectrl where the label editor could remain
    stuck forever #1235.

  • Grafted on a EnableSystemTheme method to the classes which support it. This
    can be used to disable the default system theme on Windows for native widgets
    like wx.ListCtrl, wx.TreeCtrl and wx.dataview.DataViewCtrl. It has no effect
    on the other platforms.

  • The wx.WS_EX_VALIDATE_RECURSIVELY extended style flag is obsolete, as it is
    now the default (and only) behavior. The style flag has been added back into
    wxPython for compatibility, but with a zero value. You can just stop using it
    in your code with no change in behavior. #1278

  • Fix a sometimes crash when using a wx.Overlay by letting the wx.DCOverlay hold
    a reference to the DC, to ensure that the DCOverlay is destroyed first.
    PR#1301

  • Replaced the Vagrant VMs used for building wxPython for various Linux distros
    with Docker images.

  • Add some missing methods in wx.adv.BitmapComboBox #1307

  • Added the wx.svg package which contains code for parsing SVG (Scalable Vector
    Graphics) files, and also code for integrating with wxPython. It can rasterize
    the SVG to a wx.Bitmap of any size with no loss of quality, and it can also
    render the SVG directly to a wx.GraphicsContext using the GC’s drawing
    primitives. PR#1323

  • Ported the embedding sample from Classic, which shows how to use wxPython from
    a C++ wxWidgets application that embeds Python. PR#1353

  • Fixed wx.GetApp() to use wxWidgets’ global wxApp instance instead of
    maintaining its own pointer. This way, if the wxApp is created by C++ code
    wxPython will still be able to get access to it. #1126

  • Added wrappers for the wx.ActivityIndicator class.

  • Added wrappers for the wx.CollapsibleHeaderCtrl class.

  • Fixed issues in PlotCanvas around displaying and using scrollbars. #1428

  • Added wx.msw.CHMHelpController, and also a wx.HelpController factory function
    that creates an instance of the best Help Controller for the platform. #1536

  • Added wx.adv.GenericAnimationCtrl so the generic version of the animation classes
    can be used even on the platforms that have a native version. Note that due to
    internal changes to support both types of animations, some API changes in how
    the Animation objects are created. See the AnimationCtrl.py sample in the demo
    for the various usage patterns #1579

  • Added wrappers for the wx.grid.GridBlockCoords, wx.grid.GridBlocks, and
    wx.grid.GridBlockDiffResult classes, as well as associated new methods in the
    wx.grid.Grid class. These provide a new way to interact with blocks of
    selected cells, including an iterator interface in wx.grid.GridBlocks which
    should be a more efficient (time and memory) way to process large groups of
    selections.

1 Like

I realize that Ubuntu/Fedora are the go to Linux Distro’s many use. But Not everyone. I use OpenSuse and each and every time I have wait until some kind soul decides provide the wxPython latest version on some far off location. My error is always the same one:
In file included from …/…/…/…/ext/wxWidgets/include/wx/defs.h:45:0,
from …/…/…/…/ext/wxWidgets/include/wx/wx.h:14,
from …/…/…/…/wx/include/wxPython/wxpy_api.h:41,
from …/…/…/…/sip/cpp/sipAPI_core.h:20760,
from …/…/…/…/sip/cpp/sip_corewxLogTextCtrl.cpp:10:
…/…/…/…/ext/wxWidgets/include/wx/platform.h:154:10: fatal error: wx/setup.h: No such file or directory
#include “wx/setup.h”
^~~~~~~~~~~~
compilation terminated.
Johnf

@Robin, are you talking about standard Python ‘warnings’ enabling or something more than that?

Yes, standard warnings. Specificly, the DeprecationWarning.

1 Like

Do you follow the instructions here: https://wxpython.org/blog/2017-08-17-builds-for-linux-with-pip/index.html? Are there any errors or warnings displayed when the wxWigets configure script is run?

I’m looking into finding a wheel. But thanks.
Johnf

There is a change here that I was not aware of as an issue. I guess maybe there was at one time the ability to pass horizontal align flags to a horizontal sizer. Now that is not allowed. Is that correct or is it some sort of bug? Tested with windows 10, python 3.7.x, wxPython 4.1.x

Johnf

Yes, it is correct. The bug was that prior versions did not validate the flags given when adding an item to the sizer, and so ended up silently ignoring the improper flags.

It looks like 4.1 broke drag and drop of images for me.

This code worked in wxPython 4.0.4 on Mac Mojave. After the upgrade, I can no longer drag and drop images onto my app.

import os
import wx
from PIL import Image
from wx.lib.pubsub import pub 

PhotoMaxSize = 240

class DropTarget(wx.FileDropTarget):
    
    def __init__(self, widget):
        wx.FileDropTarget.__init__(self)
        self.widget = widget
        
    def OnDropFiles(self, x, y, filenames):
        image = Image.open(filenames[0])
        image.thumbnail((PhotoMaxSize, PhotoMaxSize))
        image.save('thumbnail.png')
        pub.sendMessage('dnd', filepath='thumbnail.png')
        return True
        
class PhotoCtrl(wx.App):
    def __init__(self, redirect=False, filename=None):
        wx.App.__init__(self, redirect, filename)
        self.frame = wx.Frame(None, title='Photo Control')
        self.panel = wx.Panel(self.frame)
        pub.subscribe(self.update_image_on_dnd, 'dnd')
        self.createWidgets()
        self.frame.Show()
        
    def createWidgets(self):
        instructions = 'Browse for an image or Drag and Drop'
        img = wx.Image(240,240)
        self.imageCtrl = wx.StaticBitmap(self.panel, wx.ID_ANY, 
                                         wx.Bitmap(img))
        filedroptarget = DropTarget(self)
        self.imageCtrl.SetDropTarget(filedroptarget)
        instructLbl = wx.StaticText(self.panel, label=instructions)
        self.photoTxt = wx.TextCtrl(self.panel, size=(200,-1))
        browseBtn = wx.Button(self.panel, label='Browse')
        browseBtn.Bind(wx.EVT_BUTTON, self.on_browse)
        self.mainSizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.mainSizer.Add(wx.StaticLine(self.panel, wx.ID_ANY),
                           0, wx.ALL|wx.EXPAND, 5)
        self.mainSizer.Add(instructLbl, 0, wx.ALL, 5)
        self.mainSizer.Add(self.imageCtrl, 0, wx.ALL, 5)
        self.sizer.Add(self.photoTxt, 0, wx.ALL, 5)
        self.sizer.Add(browseBtn, 0, wx.ALL, 5)
        self.mainSizer.Add(self.sizer, 0, wx.ALL, 5)
        self.panel.SetSizer(self.mainSizer)
        self.mainSizer.Fit(self.frame)
        self.panel.Layout()
        
    def on_browse(self, event):
        """ 
        Browse for file
        """
        wildcard = "JPEG files (*.jpg)|*.jpg"
        dialog = wx.FileDialog(None, "Choose a file",
                               wildcard=wildcard,
                               style=wx.OPEN)
        if dialog.ShowModal() == wx.ID_OK:
            self.photoTxt.SetValue(dialog.GetPath())
        dialog.Destroy() 
        self.on_view()
        
    def update_image_on_dnd(self, filepath):
        self.on_view(filepath=filepath)
    def on_view(self, filepath=None):
        if not filepath:
            filepath = self.photoTxt.GetValue()
            
        img = wx.Image(filepath, wx.BITMAP_TYPE_ANY)
        # scale the image, preserving the aspect ratio
        W = img.GetWidth()
        H = img.GetHeight()
        if W > H:
            NewW = PhotoMaxSize
            NewH = PhotoMaxSize * H / W
        else:
            NewH = PhotoMaxSize
            NewW = PhotoMaxSize * W / H
        img = img.Scale(NewW,NewH)
        self.imageCtrl.SetBitmap(wx.Bitmap(img))
        self.panel.Refresh()
        
if __name__ == '__main__':
    app = PhotoCtrl()
    app.MainLoop()
1 Like

@driscollis, you’re using a wx.StaticBitmap as the drop target. It’s unfortunate, but not very surprising that using it for the drop target would fail, since it’s a native widget, especially a native “static” widget. I suggest creating a ticket at trac.wxwidgets.org about it in case something can be done, and in the meantime, switching to the generic static bitmap in wx.lib.statbmp. Another idea would be to make a custom panel class with an EVT_PAINT handler, and then you could also encapsulate the DnD behavior there as well, giving you a better OOP design.

Is there a way to downgrade the response to this from an exception to a warning?

It’s a good idea, but unfortunately the point that those C++ assertions are caught and turned into Python exceptions is not able to differentiate between simple informational warnings and more serious issues or potentially fatal problems. So it would end up being an all or nothing deal, and potentially hiding very serious problems.