Tkinter treeview text not visible until client restart - python-3.x

I have a program written in python 3.5 which scans a directory and stores the info in a SQLITE3 db. This info can be displayed in a ttk.treeview in the client.
The 2 main functions are 1) "scan" which adds the information to the db and 2) viewFiles which is below (it just grabs data from the db and displays it in the treeview).
During the scan function, a second tkinter window is opened and displays information on whats been scanned. If I try to use the viewFiles fucntion without a restart, the data displayed is invisible but I know the data is there because I can copy paste it into a text document). If I restart the client, the text is displayed correctly after pressing the button linked to the viewFiles function.
I think it must be something to do with the the focus shift thanks to this 2nd window opening during the scan process but I'm not sure and can't find any similar case to learn from.
def viewFiles(self):
global dataTreeView
results = []
foldersContentsToView = yieldFoldersToView()
for dpath in foldersContentsToView:
sqlstring= "SELECT * FROM DBDATA WHERE directorypath=:dpath"
values = {"dpath": dpath}
[results.append(i) for i in databaseFunctions.getDBobject().returnSelectQueryResults(sqlstring, values)]
for e in results:
dataTreeView.insert('', 'end', values=list(e))
Does anyone have any ideas?

The issue was that the columns were being set up in the moment the treeview was created by querying the fields in the database. However before the first scan, there were no records in the db and so the columns were not being configured properly until a restart, after which data existed and could be queried on treeview creation.
To fix the issue, I moved the column configure data to the viewFiles function like so:
def viewFiles(self):
global dataTreeView
audioDataTree['columns'] = returnListTableFields()
#Configure Columns
for column in listofdbtablefields():
dataTree.column(column,width=len(column)*10)
dataTree.heading(column, text=column)
dataTree.column(column, anchor='center')
#Hide First Column (TreeLabel)
dataTree.column('#0',width=0)
results = []
foldersContentsToView = yieldFoldersToView()
for dpath in foldersContentsToView:
sqlstring= "SELECT * FROM DBDATA WHERE directorypath=:dpath"
values = {"dpath": dpath}
[results.append(i) for i in databaseFunctions.getDBobject().returnSelectQueryResults(sqlstring, values)]
for e in results:
dataTreeView.insert('', 'end', values=list(e))

Related

Adding an updatable combobox

I am trying to create a combobox in ttk that will take output from an SQL query and put it in its drop down menu. To do this I have used postcommand in my combobox as below:
self.Port_Drop_Down = ttk.Combobox(EDM_DB_frm, state="readonly", postcommand=self.upd_edm_ports)
and then have the SQL function it is calling working like below:
def upd_edm_ports(self):
portinfo_tpl = rgu.get_edm_ports("server", "database")
self.Port_Drop_Down["values"] = portinfo_tpl
The portinfo_tpl is generating a tuple looking like ("port1", "port2", ..., "portn").
But when I access the drop down nothing shows up.

How to make pre initilized text appear in Tkinter Entry widget?/ How to set limit of number of same windows open?

Q1) I have a Entry widget and I want it to be per-initilized with a value and I want the user to have the open to erase that value and type in what ever value they want.
So for example:
Year: 2016 <----- By deafult 2016 is already inputted and visible
Is there a way I can do this?
Q2) Is there a way I can set a limit to the number of a same window that can be opened? For example: If i have a drop down menu which has a "help" option. Currently the way I have it set up, if I click the help once the help window will pop up, and if I click it again (while the first window is still open) another help window will pop up. How do I set it so that only 1 help window can be opened at a time?
Any help is greatly appreciated.
1) you can use a string variable
self.example = StringVar()
self.example.set("put what you want it to say at the start here")
#note put this before you make your entry
self.example_txt = Entry(self,textvariable = self.example)
self.example_txt.place(row = 1, column = 1)
#note iv purposely missed out class declaration ectra as i am assuming you already have that)
2) there is probably a better way to do this but you could use a global variable which is set to false when the help button is clicked and set back to true when help window closed
global valid
valid = True
#not put this at start of your program
def opennewindow():
global valid
if valid == True:
valid = False
#put code for opening new window here assuming you already have that code as
#you haven't asked for code for that
def closewindow():
global valid
valid = True
self.master.destroy()
To insert something into an entry widget you can use the insert method:
e1 = tk.Entry(...)
e1.insert(0, "hello, world")
To only allow a single help window, create the help window once and hide it. Then, make your help function merely show the window rather than create it. Or, have the function check to see if the window exists; if it doesn't, create it before making it visible.

How to add data to existing XLSX file in MATLAB every time using a push button?

I have a function which generates some variable, like score, right, wrong, unanswered. This function is called using a push button. The problem is how can I add/append these values generated by a function to an XLSX file every time? Or, how to create a MAT file so that it can be added? What may be a possible solution?
The challenge involved in appending to a xls file is knowing its last row, to avoid overwriting data with the xlswrite command. I'd suggest taking a look at this file exchange submission XLSAPPEND, as it takes care of this for you.
It sounds like you've got a GUI running and want to repeatedly output data to an Excel file. One option that may speed file output is to keep a COM server open for output while your GUI is active, instead of repeatedly opening and closing one for every call to xlswrite or xlsappend. Here's a sample script to illustrate how you could do this:
function excel_output_example
% Start COM server:
excel = actxserver('Excel.Application');
excelWorkbook = excel.Workbooks.Add(1);
excelSheet = excel.ActiveSheet;
fileName = 'example.xlsx';
rowIndex = 1; % Keeps track of the next row to output data to
% Create GUI:
hFigure = figure('Position', [100 100 120 70], ...
'DeleteFcn', #(~, ~) stop_excel(excelWorkbook, excel));
uicontrol(hFigure, 'Style', 'pushbutton', ...
'Position', [20 20 80 30 ], ...
'String', 'Add to Excel', ...
'Callback', #output_to_excel);
function output_to_excel(~, ~) % Adds a random value to the next row in column A
excelSheet.Range(sprintf('A%d', rowIndex)).Value = rand();
rowIndex = rowIndex+1;
end
function stop_excel(workbookObj, comObj) % Stops the COM server
workbookObj.SaveAs(fileName);
workbookObj.Close();
comObj.Quit();
comObj.delete();
end
end
This will open a small GUI window with a push button. Every time the button is pressed, a new random value will be added the the next available row in column A of the Excel file. When the GUI window is closed the Excel file is saved and the COM server stopped. For example, after pushing the button 5 times and closing the GUI you will get something like this in your Excel file:

End edition signal of a QLineEdit in a QTableView

I've been facing a problem for several days now. I'm using a QTableView to display data from a model. I activated the complete line selection when the user click on a cell, to make the interface user friendly:
self.tableau.selectRow(element.row())
But, when the user presses F2, I would like to edit only the column 1. So, the expected behavior is:
if I selected the column 4, this one is not editable
if I press F2 when column 4 is selected, the column 1 is edited
But with the complete row selection, F2 can not know which cell is selected. So, I re-implemented the event handler:
def keyPressEvent(self, e):
"""It reimplements event management in this method """
# TODO: find a way to re-select the cell after editing
# We get the name of current file
nom_courant = self.tableau.model().index(self.row_selected, 1).data()
print(nom_courant)
if e.key() == QtCore.Qt.Key_F2:
try:
# We edit the cell name of the selected line
#http://stackoverflow.com/questions/8157688/specifying-an-index-in-qtableview-with-pyqt
self.tableau.edit(self.tableau.model().index(self.row_selected, 1))
except:
print("Pas de cell sélectionnée")
pass
# It retrieves the new file name. CAN NOT do in the
# if the model is not updated yet.
nouveau_nom = self.tableau.model().index(self.row_selected, 1).data()
print(nouveau_nom)
# Call the fct renaming only if the name has changed
if nom_courant != nouveau_nom:
#liste.renameFile(self.current_video, self.tableau.model().index(self.row_selected, 1).data())
print("entropie")
The matter now is this line:
self.tableau.edit(self.tableau.model().index(self.row_selected, 1))
I have no way to detect the end of the edition of the QLineEdit generated, and I need it to perform actions on the new content of the cell edited, because nouveau_nom is not updated if no keyboard event occurs.
Do you have an idea about how to get the end edition signal ?
(Please forgive my english, I'm french...)
First, you don't need to actually intercept and change the cell selection to a row selection. You can just set the behavior on the view:
self.tableau.setSelectionBehavior(self.tableau.SelectRows)
This will automatically select rows.
When you use a custom QLineEdit widgets in your table, then you need to connect QLineEdit.editingFinished() to whatever handler you want. Most likely you want it to call dataChanged on your model.

Deleting a row from temp table

I have two grids and on a button click items move from grid 1 to grid 2. Another button removes selected items from grid 2.
The row is deleted from the screen by using:
THIS-OBJECT:ultraGrid2:ActiveRow:Delete().
However then this is saved and repoened this row still appears as it was not been removed from the temp table. The temp-table is called selectedFormula. I've tried:
DELETE FROM selectedFormula WHERE ultraGrid2 = ultraGrid2:ActiveRow.
However i get the error message "Unable to understand after "ultraGrid2 = ultraGrid2".". Does anyone one have any ideas how to remove a item from a temp-table in Progress using ABL?
Any help will be appreciated.
You will need to get the unique key from the active row in the UltraGrid2. Using that key, you find the record in the temp-table and you delete it like this.
FIND selectedFormula
WHERE selectedFormula.[key field] = [key from UltraGrid2]
NO-ERROR.
IF AVAIL selectedFormula THEN
DELETE selectedFormula.
Note: Key can be many fields, depends on your table temp-table definition and data.

Resources