I cannot get wx.Panel to refresh correctly - python

I have an app where this module is included. The module's job is to get and load RSS feed into the app, depending on the RSS feed provider that the user chose. The module does its job perfectly when I do not try to remove the entries from the previous query.
When I add .Clear() method to the sizer, containing all the programmatically added rows in the UI from a query, they are removed from memory but remain in the UI. I tried lots of different methods to make the UI update, but it doesn't. So now each set of new query rows gets painted over the old query rows.
Here's the gist to the module. You can directly run it:
https://gist.github.com/TiMladenov/64e55cafd4200373ba1f9ab82160cc00
Steps to reproduce:
1. Select the first or second dropdown option
2. Then select the third one
This way the problem will be more obvious.
I have tried calling .Layout(), .Update(), .Fit() to their respective objects that are making this module work, but none seem to do their job. Or I failed somewhere....

You were only missing one option for the Clear() method in the wx.BoxSizer class.
Change the line (87):
self.RssPanelList.Clear()
to:
self.RssPanelList.Clear(delete_windows=True)
The problem is that the method Clear() does not destroy the widgets by default. Therefore, you were emptying the sizer but the widgets remain and were painting on top of each other.
In the future it would be better if you post a MWE. Your chances of getting an answer will be a lot better with a MWE in the question.

Related

How to tell when a QTableWidgetItem is being modified

I'm writing an app in Python with the PySide library. I have a QTableWidget that gets updated about every second. The thing is, I want to be able to change the data manually, and I thought that if I could find out whether or not the user is changing the data in the cell, then I could just prevent the program from updating this cell. Otherwise I get "kicked out" of the cell at each update.
Is this a good idea? Should I try something else and why?
How can I achieve my goal?
Many thanks
EDIT :
I know there exists an itemChanged signal, but what I'd really like to know is if there is a way to tell when the user is writing a new value in the cell, in order not to kick them out while editing.
In Qt Document:
void QTableWidget::itemChanged(QTableWidgetItem * item)
This signal is emitted whenever the data of item has changed.
Hope this will help you.
Edit:
QTableWidget uses a default itemdelegate(QItemDelegate instance) which has createEditor method and closeEditor signal.
You can reimplement createEditor which means edit starts, and connect the signal closeEditor which means the edit ends.
This may be the correct way.
Generally, you would handle this situation with the use of QItemDelegates, which allow you to control what cells are editable by the user, what types of controls they are given to edit the cells, and you can catch the data they input and validate or manipulate it before saving it to the model.
QItemDelegates only control edits being made using the view interface. If the table is being updated programmatically, the changes won't be sent to the QItemDelegate.
Here is an example of a QItemDelegate for a QTableWidget

GNAT GPS plug-in: Get selected line in Locations

I'm doing a python plug-in to GNAT GPS IDE.
It uses the Locations window to shows a messages to the user, therefore highlighting a file line, like errors do. I use GPS.Locations.parse() to add such information, the (somewhat hazy) documentation is here.
The user then could select the line from the code or the Locations window to perform an action.
Get the line from the opened file is a piece of cake.
But one thing that still eludes me, is how I can know which line from the Locations window the user is selecting.
I tried the GPS.MDI.get("Locations") which lead me to a maze of children windows objects. I got lost.
So how can I retrieve the text from the currently selected line in Locations?
Edit
Apparently there MessageContext that would give me what I want, but I get an error message saying there's not such class, even when the window has focus. So I recon that the class wasn't instantiated.
AttributeError: 'module' object has no attribute 'MessageContext'
I only saw this thread now. You should call GPS.current_context(), which will return an instance of GPS.Context or one of its children classes. In this case, you can likely use GPS.current_context().file()
It seems like what you want is to create an entry in the contextual menu in the Locations window. Take a look at the gps_utils.interactive hook. It wraps a python function into a GPS action. This action can then be bound to a specific contextual menu, a keybinding, a menu, a toolbar button,... You can also associate a filter with it, so that the contextual menu also shows up when the action applies (and to implement this filter, you use the above GPS.current_context().file()

pygtk treeview contents update/refresh

I finally managed to write a little app that reads from a sqlite database and show the results to a treeview. Another form (in another module) gives the ability to write new or update existing records. After writing to the database it closes the window
What I'm trying to do now is to update the "main" window (containing the treeview) to show the new dataset. I have managed so far to do this but a) the initial mainwindow stays there while a new instance of it opens on top of it showing the desired (new) dataset.
How would I make this work? Can someone give me suggestions/example?
Perhaps I need to say that the __init__ function of my mainwindow module does everything upon running: creates the gui, reads from the database and show all. I suspect that this may be the problem but having tryed almost any combination of breaking it into pieces (functions), I had no success
--EDIT--
OK I have many different functions __init__ now creates the main gui while others read the data from the DB and place it on a treeview.
I tried to use a timer but also this option doesn't seem to be apropriate as gtk.TreeView doesn't have such a method.
Finally I managed to figure this out, so I post this answer to my own question in case someone finds it helpful:
All I had to do was to .clear the list_store, rebuild it and use set_model to the TreeView.
The refresh function goes as below:
liststore.clear()
create_model_checks() # re-create liststore
treeView.set_model(liststore)

Strategy for managing long GUI construction times (wxPython)

I have a wxPython application with a multi-stage GUI. First a simple form pops for selecting from one of many (> 100) options (it's a part number list with a search box). Once the user has made their selection it builds the appropriate form and shows it, hiding the initial selection dialog. Due to the nature of this project, each secondary form has several matplotlib figures in a Notebook, around 7 or 8 figures each with 2-5 axes each. Because of this, the form takes several seconds between initialization and when it can be shown on the screen.
Does wxPython have a way to build a frame in the background? I don't mind forcing the user to wait a short while before it can be shown, but as it is right now building the form hogs the event loop and everything becomes unresponsive. If I use a thread to build the form, it completes successfully but when I call .Show() nothing happens and there's no error message.
As you can imagine, such a GUI has fairly complex code so it would be difficult to show a SSCCE (and it's not open source). If needed I can try to hack together something that would approximate my problem.
I have used BusyInfo before to tell the user that something is happening. You would put that in your frame's init() BEFORE you actually start creating the matplotlib figures. You can read about it here:
http://wiki.wxpython.org/BusyInfo
Another idea would be to create a second frame with a progressbar in it and a message. The progressbar would be set to just bounce back and forth and when you got done creating the matplot stuff, you would close the second frame.
Mike's idea of using wxBusyInfo is useful when something takes a long time, but it's possible you could make it take less time instead (or at least as well).
First, when inserting many (although I wouldn't say that 100 is that many, 1000 however definitely is) items into a wxChoice, freeze it before adding them -- and thaw it afterwards. This should cut down the time needed for the insertion drastically.
Second, creating all controls of a multi-page wxNotebook (or another wxBookCtrl) can be long, even in C++. So the idea is to not do it immediately but only create the controls of the page you are going to initially show to the user. And then create the other pages controls only when the user is about to select them, i.e. in your wxEVT_BOOKCTRL_PAGE_CHANGING event handler.
If you put this in place, you might not need wxBusyInfo any longer...

Gtk.Treeview deselect row via signals and code

I'm using PyGObject but I think this is a question that could be adapted to all GTK, so if someone know how to do it using C or anything should work in python also.
I have two treeview, Active and Inactive, I load data from a Sqlite database and I can swap and drag & drop items from one to other.
This is just an aestetic thing, if I click on one item on one treeview I want that a previous selected item on the other be deselected.
It appears that nobody had to do something similar because I didn't found anything about it on the net.
At the risk of being too basic (perhaps I misunderstand the problem), to manipulate treeview selections, you use the GtkTreeSelection object returned from GtkTreeView.get_selection. You can attach to signals on this object, change the current selection,etc.
To turn off selection in the other view, you can get its selection mode property and set to GTK_SELECTION_NONE. To turn it back on upon clicking, my thought was that you could catch a grab-focus signal, set the selection mode to single in that view, and set the selection mode to none in the other view:
(connect view-1 'grab-focus
(lambda args
(set-mode (gtk-tree-view-get-selection view-1) "GTK_SELECTION_SINGLE")
(set-mode (gtk-tree-view-get-selection view-2) "GTK_SELECTION_NONE")))
(That code is using the guile-gnome wrapper but the concept should be the same in any language binding.) A problem with this approach is that now in order to make a selection you must click the tree view twice - once to grab the focus, and again to make the selection.

Categories

Resources