Use AM/PM in timectrl.TimeCtrl (Windows)

Hello community, I am trying to make a TimeCtrl have AM/PM in the field. I noticed that in Ubuntu this is added automatically and it also adjusts depending on the time that is set, I was moving the parameters fmt24hr and size but I can’t make it appear, I was reading the source code and in the comment of the size parameter it says something about locale but let’s say I didn’t find anything concrete about how to assign the locale to a WxPython application, I would like to know if it is possible to get the same effect that you have in Ubuntu. I tried to do it with the local library but no change.

import wx
import locale
from wx.lib.masked import TimeCtrl

locale.setlocale(locale.LC_ALL, 'es_VE')

class TimeFrame(wx.Frame):
    def __init__(self):
        
        wx.Frame.__init__(self, None, -1, 'TimeCtrl', wx.DefaultPosition, (200, 100))

        self.time_ctrl = TimeCtrl(self, -1,
                                  displaySeconds=False,
                                  size=wx.DefaultSize,
                                  fmt24hr=False,
                                  validator=wx.DefaultValidator,
                                  style=wx.TE_PROCESS_TAB)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.time_ctrl, 0, 0, 0)
        self.SetSizer(sizer)
        self.Layout()

class App(wx.App):
    def OnInit(self):
        frame = TimeFrame()
        frame.Show(True)
        return True
        
if __name__ == "__main__":
    app = App(0)
    app.MainLoop()
1 Like

Some time ago I had a problem with the date format in a wx.adv.DatePickerCtrl. It was using ‘MM/DD/YYYY’ instead of the preferred ‘DD/MM/YYYY’. I noticed that the example in the wxPython Demo did use the correct format and after a bit of digging in the Demo code, I found that inserting the following line in the OnInit() method fixed my problem:

self.locale = wx.Locale(wx.LANGUAGE_DEFAULT)

I don’t have access to a Windows PC to test it with your code, but might be worth you trying it, or some variation.

1 Like

Hi, thanks for the reply, I have tried what you say and there is no change in the field:

I also tried using the specific attribute for my country and no change either.

self.locale = wx.Locale(wx.LANGUAGE_SPANISH_VENEZUELA)

The OnInit would have looked like this:

class App(wx.App):
    def OnInit(self):
        frame = TimeFrame()
        # self.locale = wx.Locale(wx.LANGUAGE_DEFAULT)
        self.locale = wx.Locale(wx.LANGUAGE_SPANISH_VENEZUELA)
        frame.Show(True)
    return True

In my case I put the call before creating the Frame:

    def OnInit(self):
        """Initialise the application.

        :return: bool, True.

        """
        config_pathname = MetDataModel.getConfigFilePathname()
        AppConfig.initialiseAppConfig(APP_CONFIG_NAME, config_pathname)

        # The following statement is necessary so the date-picker
        # controls display dates as DD/MM/YYYY and not MM/DD/YYYY
        self.locale = wx.Locale(wx.LANGUAGE_DEFAULT)

        sys.excepthook = unhandledExceptionHook

        main_frame = MetDataMainFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(main_frame)
        main_frame.Show()

        # Start the IPC server
        self.ipc = IPCThread(HOST, PORT_NUM, DATABASE_UPDATED, pass_data=False)

        return True

1 Like

Nothing yet, just in case I changed the field size to see if the AM/PM was covered but nothing.

class App(wx.App):
    def OnInit(self):
        self.locale = wx.Locale(wx.LANGUAGE_DEFAULT)
        frame = TimeFrame()
        self.SetTopWindow(frame)
        frame.Show()
        return True

The TimeCtrl example in the wxPython Demo has several instances of 12hr clock, do they show correctly on your windows machine?

I don’t know how they should look like but this is what the demo code looks like, I had to append the run.py module by the way.

EDIT: Well, if I am not mistaken, the 12-hour one is not displayed correctly.

Here’s what it looks like on my Linux PC:

Edit: replaced screen dump with one using time ‘now’ to make the differences a bit clearer:

1 Like

Well, evidently the same code behaves differently on the two platforms. Without needing to configure anything, in the 12 hour clock the AM is shown automatically and goes up to 12, as you could see in windows it had the same value as the 24 hour field.

Is there any important difference between TimeCtrl and TimePickerCtrl? I was looking at it and the am/pm displays and adjusts correctly, I would like to know if there is a workaround for TimeCtrl, but I think I will consider using TimePickerCtrl.

It is pretty unlikely that the “self.locale =” part is necessary.

Just “wx.Locale(wx.LANGUAGE_DEFAULT)” is likely going to init “the system”
to a default locale, and the date picker will pick that up.

(not that I recommend using wx.Locale(), but there…)

Karsten

I just tried using wx.Locale() without assigning it to an instance attribute and the date controls went back to using MM/DD/YYYY.

Hi, thanks for the clarification. Just for the record, I removed the variable assignment and put it in both __init__ and OnInit and nothing.

Yes, I had tried something like that in Ubuntu, but apparently (I don’t know) Windows doesn’t listen to wx.Locale

I have used print(locale.getlocale()) and get ('es_VE', 'ISO8859-1'), So I think the locale is well assigned.

Now that is very strange – the date controls are unlikely to
pick up a random instance attribute.

The theory would be that as long as the app holds on to the
attribute the wx.Locale() won’t get __del__eted … and if the
del contains a switch back to the “previous” locale …

One might test that theory by doing for once:

self.__some_random_123456 = wx.Locale(....)

and for another run doing

self.__some_random_123456 = wx.Locale(....)
del self.__some_random_123456

and see what happens in each case.

Karsten

Tried, nothing diferent happened.

class App(wx.App):
    def OnInit(self):
        self.__some_random_123456 = wx.Locale(wx.LANGUAGE_SPANISH_VENEZUELA)
        del self.__some_random_123456
        frame = TimeFrame()
        frame.Show(True)
        return True

and

class App(wx.App):
    def OnInit(self):
        self.__some_random_123456 = wx.Locale(wx.LANGUAGE_SPANISH_VENEZUELA)
        frame = TimeFrame()
        frame.Show(True)
        return True
class App(wx.App):
    def OnInit(self):
        self.__some_random_123456 = wx.Locale(wx.LANGUAGE_SPANISH_VENEZUELA)
        del self.__some_random_123456
        frame = TimeFrame()
        frame.Show(True)
        return True

and

class App(wx.App):
    def OnInit(self):
        self.__some_random_123456 = wx.Locale(wx.LANGUAGE_SPANISH_VENEZUELA)
        frame = TimeFrame()
        frame.Show(True)
        return True

That is what I suggested but

Tried, nothing diferent happened.

this does not sufficiently describe what happened in order to
test the theory I offered.

Karsten

I understand, but I don’t know what I can show, at the graphic level the control does not change and at the code level there is no error or warning.

Well, we’ve got 3 (4 (5)) ways the code can look

1
wx.Locale(…)

2
self.locale = wx.Locale(…)

3
self.__random_something = wx.Locale(…)

4
self.__random_something = wx.Locale(…)
del self.__random_something

Version 1 does not work, which rules out the
init-the-system-for-magic-pickup-later theory (much like it
used to be with InitAllImageFormats()).

Version 2 does work but we don’t know why.

So:
Version 3 and 4 do “the same” – but what ?

And, try this:

5
self.locale = wx.Locale(…)
del self.locale

Does it still work ?

This is 2 and 4 combined to find out whether self.locale is
either a magic attribute being picked up later or else is
being passed to the picker control down the line :wink:

(the latter assumption could be checked by perusing the code,
and it might throw a NameError – unless self.locale is
being initialzed to, say, None elsewhere…)

Karsten