I have a situation in which i create a few checkboxes and a 'save' button on a frame. Clicking on the button will save the current 'check status' of the checkboxes and close the frame (the frame has another frame as it's parent). The 'check status' is stored in a list in a separate .py file.
There's another button, clicking on which would i would want to restore those same check values on the check boxes. I am not sure what approach is proper here: whether to save the checkbox objects itself and load them or to create new checkboxes every time and apply the check status values on them.
This issue has taken up quite some time of mine as i am new to the python GUI concept, any help would be much appreciated.
P.S: if any details are required to make the question more clear kindly let me know.
EDIT: here's a small representation of what i have tried:
#file that generates the checkboxes (part of a bigger code)
var_list=[] #list of the variables of the checkbox objects
load_status = savedata.load() #fetch the saved status list from another file, if it exists
if len(load_status)!=0: #if the checkboxes have already been created before
for count in range(len(var_list)):
if load_status[count] == 0:
var_list[count].set(0) #set/apply the values from the status list
else:
var_list[count].set(1)
return
def check(var_list):
check_status_list=[]
for i in range(len(var_list)):
c = var_list[i].get()
check_status_list.append(c) #the status of the checkboxes that is stored in another file
var = IntVar()
var_list.append(var)
poll_check = ttk.Checkbutton(parent,variable=rr,command=lambda:check(var_list))
poll_check.place(x=x1,y=y1)
x1=x1+15
when i click on the save button the status list (check_status_list) is stored in another file. On clicking the third button ('load') i fetch the status list first and (try to) set the values on the already exsting checkbox objects.
Kindly feel free to point out the (obviously) silly mistake that this approach has.
Related
stackoverflow!
It's my first question, I was just a reader before
I'm trying to make an app in python using PyQt5: I need to get data from DB into a table, every row has an EDIT button, when you push it, fields of the row become editable and you can change the data and the EDIT button changes to SAVE button. When you push it , data should be saved and be sent to database(I didn't made a "commit to DB" function yet) but its not saving and comes to previous amounts every time I click SAVE.
When I click EDIT button, it takes a cell text and than replace the widget in a cell by the same , but editable version(just change an option to EDITABLE = TRUE is not working), and it makes it for the whole row.
The save button should make the same, but it makes cells UNEDITABLE again...
tell me why it is so?
my function on SAVE button is
def ButtonSaveClicked(self):
s = self.sender()
roww = int((s.text().split())[1]) - 1
print('SAVE')
# replacing the existing active widgets by inactive with a same text
q = self.ui.tableWidget.item(roww, 0).text()
self.ui.btn_sell = QtWidgets.QLineEdit(q)
self.ui.btn_sell.setEnabled(False)
self.ui.tableWidget.setCellWidget(roww, 0, self.ui.btn_sell)
q = self.ui.tableWidget.item(roww, 1).text()
print(q)
self.ui.btn_sell = QtWidgets.QLineEdit(q)
self.ui.btn_sell.setEnabled(False)
self.ui.tableWidget.setCellWidget(roww, 1, self.ui.btn_sell)
q = self.ui.tableWidget.item(roww, 2).text()
print(q)
self.ui.btn_sell = QtWidgets.QLineEdit(q)
self.ui.btn_sell.setEnabled(False)
self.ui.tableWidget.setCellWidget(roww, 2, self.ui.btn_sell)
self.ui.btn_sell = QtWidgets.QPushButton("Edit " +str(roww+1))
self.ui.btn_sell.setEnabled(True)
self.ui.tableWidget.setCellWidget(roww, 3, self.ui.btn_sell)
self.ui.btn_sell.clicked.connect(self.ButtonEditClicked)
enter image description here
I will attempt to answer your question, but I think you may also want to consider the following alternative:
You can set your table to have Edit Triggers instead of you needing to keep track of the state of a QPushButton and keep replacing items and copying data back and forth between them.
My suggestion would be to use the QAbstractItemView::DoubleClicked edit trigger and you can apply that to your QTableWidget like this:
self.tableWidget.setSelectionBehavior(QAbstractItemView::SelectItems)
self.tableWidget.setSelectionMode(QAbstractItemView::SingleSelection)
self.tableWidget.setEditTriggers(QAbstractItemView::DoubleClicked)
If the user double clicks on a cell, that cell becomes editable.
setSelectionBehavior() lets you choose whether you want each cell, row or column to be selected when clicked.
setSelectionMode() determines whether one (cell,row,column) or many (cells,rows,columns) can be selected at once. I think in your case you want to select one cell at a time.
This way the user can double click the cells they wish to edit and then you can have a "Save" button at the bottom of the widget which saves all the changes.
I will try to reproduce your problem above, but I wanted to bring this functionality to your attention as it may save you a lot of headaches.
First sorry if I am missing anything.and sorry about the format, new to stackoverflow
I am trying to read the flag state from a QtreeWidget.
I have tried a lot of things and nothing seam to work.
I am dynamical creating the tree as follows
Part=str(result2[row2][0])
qty=str(offset_B)+str(result2[row2][1])
instock=str(offset_B)+str(result2[row2][2])
B = QTreeWidgetItem(A, [Part,qty,instock])
B.setForeground(0,QtGui.QBrush(QtGui.QColor(color_item)))
B.setForeground(1,QtGui.QBrush(QtGui.QColor(color_item)))
B.setForeground(2,QtGui.QBrush(QtGui.QColor(color_item)))
B.setFlags(Qt.ItemIsTristate)
B.setCheckState(0, Qt.Unchecked)
I have a button Generate Po's and when I click it I want to iterate through the items and grab the text value of the checked Items.
sample
so it should return a list of some sort with all the text field.
I can do the list I just need to understand how to grab the "State" of the button.
I hope this is clear enough.
So basically I am reading a valuefrom a text file which is displayed on the Profile frame using a label.
def view_value(self):
self.user = self.controller.user
self.view_value()
with open(self.user + '.txt', "r") as f:
value_line = 2
for i, line in enumerate(f):
if i == value_line:
self.value.set(line)
self.value.config(textvariable=line)
When I go to a different frame to calculate this value again, it will update the text file with the newly calculated value. However, when I go back to the previous page using the back button - the old value is still there. To get the new value to appear I need to reopen/re-run the program.
Is it possible to have the newly updated value displayed on the page without restarting the application? I have tried calling my view_value method to try and update the value and also tried configuring the label from the other class but wasn't able to get it working.
I also realise there are probably a million things wrong with my code, I am very new to Python so apologies!
You need to update the StringVar Profile.allowance in order to make the display in Profile page updated. The simple way is adding the following statement before self.controller.show_frame(Profile) in write_to_file() of CalculateAllowance class:
self.controller.frames[Profile].allowance.set(self.user_data[2])
Also you need to fix the following issues in your code:
Remove calling self.view_allowance() inside view_allowance() in Profile class as it will cause infinite recursion problem.
Remove self.holiday_allowance_amount.config(textvariable=line) in view_allowance() as it wrongly reassigns textvariable to a string.
I have a problem with my code. I am trying to delete a specific line from a file. I am making a To-Do List program in Tkinter, and I am using a Label as the to-do list. I have two buttons, 'Add Item' and 'Delete Item'. I also have an entry box, and the buttons take the string from the entry using the .get() method. The delete button is not working because I cannot find a way to delete a line from a file that the program is using to store the list. I have looked over many other posts about the same problem, but mine is different. Whenever I run the program, and I click delete item after I fill out the text box, it deletes ALL items from the file, but I only want it to delete one item. The problem is NOT the one that #JetMashKangaroo had in this post: How to delete a line from a file in Python.
Here is the snippet of code:
def dele():
global ItemName
global Display
global List
ToDoDel = ItemName.get()
new_f = List.readlines()
List.seek(0)
for line in new_f:
if ToDoDel not in line:
List.write(line)
List.truncate()
Display['text'] = List.readlines()
ItemName is the entry box. Display is the label that displays the To-Do list. List is the variable below:
List = open('***/***/To-Do_List.txt','r+')
The program works perfectly, but I cannot add this delete function because it deletes all the text from the file. the function dele is called when the button 'Delete Item' is pressed. Help would be greatly appreciated.
The most likely reason you're running into a problem is that you are attempting to modify the list while also iterating over it. Here's an example post of someone else who ran into a similar issue.
My suggestion is that you keep track of which indexes to modify within your loop, then remove them after the loop has completed.
In my PyGTK application I currently use 'editable' to make cells editable. But since my cell contents sometimes are really really large I want to ask the user for changes in a new window when he doubleclicks on a cell. But I could not find out how to hook on double-clicks on specific cellrenderers - I don't want to edit the whole row and I also don't want to set this callback for the whole row, only for columns where too long content can occur. How can I do this with CellRendererText() or something similar.
My currently cell-generating code is:
cols[i] = gtk.TreeViewColumn(coltitle)
cells[i] = gtk.CellRendererText()
cols[i].pack_start(cells[i])
cols[i].add_attribute(cells[i], 'text', i)
cols[i].set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
cols[i].set_fixed_width(100)
cells[i].set_property('editable', True)
cells[i].connect('edited', self.edited, (i, ls))
cols[i].set_resizable(True)
mytreeview.append_column(cols[i])
Thanks!
I believe this is not possible directly. However, you can connect to button-press-event on the gtk.TreeView. Then, when event.type equals to gtk.gdk._2BUTTON_PRESS, convert x and y to tree location using gtk.TreeView.get_path_at_pos(). This will return both a tree path indicating the row and gtk.TreeViewColumn object on which the click was made.