PySimpleGUI - can't update text fields - python

This is my first try with PySimpleGUI.
I've written a simple window with three output fields:
Text
Output
Multiline
The window paints fine, and the default values display. But I can't get any of the fields to update.
Am I doing something stupid (almost certainly!)?
Here is the code and result:
Code
Display
Thanks in advance, Chris.
I've tried multiple field types and various options to try to force update, all to no avail.

Something wrong
sg.Window(...).read() not return window, but event, values. It also block the execution until an event happened. It looks the only event is to close the window, then the GUI cannot be updated after window destroyed.
window[key].update(...) return None, None don't have method read to call. Method update won't update the GUI, but the configuration in PySimpleGUI.
Should update the GUI in the event loop where the window.read called after any actions for specific event.
time.sleep(30) will get the GUI no response for 30 seconds.

Related

How to update the layout inside a function in kivy

Problem
We have a FloatLayout that gets some widgets and loses some (using add_widget and remove_widget) inside a function.The problem is the window gets updated when the function reaches its end. Then Kivy updates the window and user only sees the last results.
How to update the window when we are inside a function so user can see results ???
What i tried
I tried do_layout and _trigger_layout (read that somewhere on SO). None of them did the job (no traceback, no warning, literally no change)
Also read Kivy documentation but nothing was helpful there
Instead of making all your changes while blocking the gui, use Clock.schedule_interval or Clock.schedule_once to let Kivy go back to rendering in between each change.
Edit: Also to be clear, your problem is not that you have failed to update the layout, but that you haven't given Kivy any opportunity to render the changes.

wxpython Event order

I have a wxPython gui with a grid. When a user clicks on certain cells, a drop-down menu will pop up.
self.window.Bind(wx.grid.EVT_GRID_SELECT_CELL, lambda event: self.on_left_click(event, self.grid, choices), self.grid)
The method on_left_click pulls up the drop-down menu and works as expected. The problem is that I want the default behavior for wx.grid.EVT_GRID_SELECT_CELL to happen first, and then for my custom method to fire. Normally, when you click on a grid cell, that cell's border gets bold. With my binding, the my drop-down menu appears first, and only once the drop-down menu is dismissed does the cell border get selected. I tried calling self.grid.SetGridCursor(row, col), but that generates a wx.grid.EVT_GRID_SELECT_CELL event, which causes a recursion max out and obviously is no good. I also tried using event.Skip() in the on_left_click code, but it doesn't seem to have an effect.
Here is the awkward, objectionable behavior (I just clicked on row 0, col 2):
Here is the desired behavior:
I am happy to provide more of the code if needed. I would like to do one of the following. One, somehow force wxPython to fully process wx.grid.EVT_GRID_SELECT_CELL before moving on to my custom drop-down menu. Two, manually duplicate the effect of "highlighting" the selected cell in my own code.
Thanks in advance for any help.
edit:
Here's what I ended up doing.
In place of wx.grid.EVT_GRID_SELECT_CELL, I used wx.grid.EVT_GRID_CELL_LEFT_CLICK which is essentially the first event to be fired when a user clicks on a grid cell, so I could fully customize the behavior following that initial click. Then, I could use this:
self.grid.SetGridCursor(row, col)
to outline the cell without creating the infinite recursion error, as well as implementing a bunch of other behavior that is now working more smoothly. I also needed to use self.grid.Refresh().
Create a separate method for showing drop down menu and call it with wx.CallAfter.
def on_left_click(self, event, grid, choices):
event.Skip()
self.grid.Refresh()
wx.CallAfter(self.showMenu, grid=grid, choices=choices)
def showMenu(self, grid=None, choices=None):
# Drop down menu code goes here

Wxpython closing windows

I have two windows in my application and one of these windows has no frame for design purposes.
The frame with the window has the usual toolbar with the minimize, restore, maximize and close buttons.
Is there a way i can close the window with no frame, with the framed windows close button?
Yes. You just need to save a reference to the 2nd frame. Something like this should suffice:
self.secondFrame = MySecondFrame()
Then in the first frame's close method, you can just do something like this:
self.secondFrame.Close()
However, I should note that creating a frame without the usual toolbar goes against most OS GUI guidelines and users will likely be irritated by that design decision.
EDIT: Yes, you can catch the event that occurs when the user presses the "X" button on the window via wx.EVT_CLOSE. When you do that, you need to call the main frame's Destroy() method instead of its Close method or you'll end up in an infinite loop since calling Close() fires EVT_CLOSE. You can still use Close() for the second frame though.

wxPython update a listbox live

I am developing a programme using python & wxPython. I have a listbox, and I need for it to be updated live to be used as a log.
I have done this simply with the Append() function, but the text added to the listbox is not shown until the end of the procedure, instead of being shown when the Append command is executed. I know this because after each insertion I print the size of the listbox.
def writeLog(self, text):
self.log.Append(text)
print self.log.GetStrings().__len__()
Right now, for checking purposes, I am calling a script that has the following code:
parent.writeLog("aaaaaa")
sleep(1)
parent.writeLog("aaaaaa")
sleep(1)
parent.writeLog("aaaaaa")
I have tried these answers but I couldn't make them work for me:
Update a ListBox in wxPython
wxPython: Update wx.ListBox list
So, How can I see the listBox updated in the screen right after the writeLog function is called? Is it possible? Thanks!
You have a few options here, the easiest perhaps is to call wx.Yield() when you want the ui to be updated, so after your Append calls
Another solution would be to to get any text that needs adding in a separate thread, and then send it back to the main thread via a custom event or pubsub which can then Append to the listbox

wxFrame not closing

I have a frame which I use as the main form (mainFrame), it inherits from mainFrameBase, which inherits from wxFrame.
It has a "close" system button. When it is pressed the app shuts down. All very much to my liking.
I inherit another frame from mainFrameBase (progScreen). When a button is pressed, the progScreen is shown. When I click its system close button, the form does not close.
What I want to achieve with this setup is that you can click a button on the main frame and a slightly different view of the main frame is shown to allow the user to "progam" certain buttons.
By the way, I'm using WXFormBuilder (excellent program) to create the screens.
What I would do is create two panels with the controls you want, one for the regular screen and one for the programming screen. Then when you want to switch, you hide one panel and show the other. That way, both screens are contained in one frame that when closed, exits the program. I actually have a tutorial that is similar to this here:
http://www.blog.pythonlibrary.org/2010/06/16/wxpython-how-to-switch-between-panels/
Hope that helps!

Categories