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)
Related
The people who are familiar with the Live Server of VS Code, would have easily understood what is the main motive of this question.
But for others, here's the explanation:
Main motive of Live Server is to Automatically Reload Your Site on Save in web development! (Which get changed for python tkinter).
When ever I change something in my python file which contains tkinter code, the change should be reflected in the main window (the main window should not re-open to reflect the changes).
I have tried to search on web as well as on stack over flow, but all the results are for updating value in entry, label, buttons etc. But what I want is, the whole window should be updated when ever I change something in my main file, and the main window should not be reopened to do so. So in short, updating whole window without closing it, on every changes in the main file or automatically reload your program on save without reopening!
What have I tried?:
I tried to detect change in file using os.getsize which satisfied the first part of my question, but however I am not able to solve the second part i.e window should not be closed.
import os
main__tkinter_filename="myfile.py"
initial_filesize=os.path.getsize(main_tkinter_filename) # Getting size of the file for
# comparison.
while 1:
final_filesize=os.path.getsize(main_tkinter_filename)
if final_filsize<intial_filesize or final_filesize>initial_filesize:
webbrowser.open(main_tkinter_filename)
Example:
from tkinter import *
root=Tk()
root.mainloop
results in the below GUI:
If i have added a=Label(text='text')anda.pack() after root=Tk(), it should show me the label, and if i have removed the same code, it should remove them.
I will answer your question by the best of my understanding,
I have some (a few projects of my own, still way too limited) experience with flutter which has hot-reload feature (same as you described above, which you want with python, mainly tkinter), I recently switched to python for gui (Loved it!), so I would like to share my research here:
I was successfully able to set up hot-reload both with kivy (kivymd hot reload, which comes with watchdog and kaki, which works real-time), and with tkinter, while there is a hitch with the later, you will have to press Ctrl + R as to reload the tkinter window, but it works without having to re-run the python program, I will leave the link to the found resources here, hope it helps with your query!
To setup hot-reload with tkinter (requires Ctrl + R), please refer here.
To setup hot-reload with kivy/kivymd (real-time), which I personally prefer, you can find the official docs here.
To mention, I use the above on Manjaro (Arch linux) with pycharm, atom, but I have also tried and have made it run successfully on Windows 10 with vs code (worked like charm)
Hope I could be of help! If you face any problem regarding the same, please feel free to ask! Thanks!
After digging around I have finally found out a way to implement hot reload feature (which #Stange answers provides) but just updating the selected frame or code.
The basic idea is constanly reading the file and executing the selected code, and removing the object in a list which are meant to be removed.
# Live Checker.py
import keyboard
while 1:
if keyboard.is_pressed("Ctrl+r"):
with open('test.py','r') as file:
file_data=file.read()
file_data_start_index=file_data.find("'#Start#'")
file_data_end_index=file_data.find("'#End#'")
exec_command=file_data[file_data_start_index:file_data_end_index]
with open('exec_log.txt','w') as txt_file:
txt_file.write(exec_command)
Here I am constantly checking if if ctrl+r key is pressed, and if pressed
it reads the file,
writes the selected code from the file into a txt file.
I have specified the start and end of the code to be updated by #Start# and #End# respectively.
# Main.py
def check():
with open('exec_log.txt','r') as exec_c:
exec_command=exec_c.read()
if len(exec_command)==0:
pass
else:
print(exec_command)
exec('for i in root.winfo_children():i.destroy()\n'+exec_command)
print('exec')
with open('exec_log.txt','w') as exec_c:
pass
root.update()
root.after(100,check)
root.after(100,check)
And in the main file, i have added the above code which continusly check if exec_log.txt file has any changes, and if changes are there, then it executes them and all so destroys the widget specified in the remove_list.
This is just a temporary solution which in my case helps me to implement the hot reload feature in tkinter.
I'm starting to use Qt Designer.
I am trying to create a game, and the first task that I want to do is to create a window where you have to input the name of the map that you want to load. If the map exists, I then switch to the main game window, and if the name of the map doesn't exist, I want to display a popup window that tells the user that the name of the map they wrote is not valid.
I'm a bit confused with the part of showing the "not valid" pop-up window.
I realized that I have two options:
Creating 2 separated .ui files, and with the help of the .show() and .hide() commands show the correspoding window if the user input is invalid.
The other option that I'm thinking of creating both windows in the same .ui file, which seems to be a better option, but I don't really know how to work with windows that come from the same file. Should I create a separate class for each of the windows that come from the Qt Designer file? If not, how can I access both windows from the same class?
Your second option seems impossible, it would be great to share the .ui since in my years that I have worked with Qt Designer I have not been able to implement what you point out.
An .ui is an XML file that describes the elements and their properties that will be used to create a class that is used to fill a particular widget. So considering the above, your second option is impossible.
This concludes that the only viable option is its first method.
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.
Looking for help on where to start with this, not too good with Python. What I trying to do is use tkinter for a gui interface but i need to be able to process recieved data and update labels widgets as information changes. I all ready have the communication portion of my program working fine in the shell but when I try to tie it to tkinter it will stop processing as soon as the interface is generated. Anyone have a simple code for me to modify to my needs or point me to a reference example somewhere. Spent days so far trying different options and I still have yet to find something that works.
Thanks for any help
Convert your working program into functions that you can register as callbacks in the tkinter UI (say buttons, or other widgets), that is, make it event-driven, and then, for background processing register some of the functions with the after widget method. The root.mainloop() will never return (only on UI close), use it as the last instruction.
So you can't just write your logic in a top-down structure, and hope that it will work well with the UI. The mainloop will be permanently looping, and will call specific funtions in your code, as appropriate to the received events from the user, or to callbacks you registered to run after some time with after.
See here for the after part
Take a look here for structuring tkinter programs. It should have enough info and links for you to study and learn how to do it in a right way.
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