Related
I made two combo boxes (kategoriCombo and unsurCombo). I want to populate the unsurCombo using a list that i get from parsing api based on the kategoriCombo selection. I saw this post and try it https://stackoverflow.com/questions/63224359/change-combobox-item-when-another-combobox-item-is-changed-in-pyqt5 but still doesn't work.
My code doesn't get any error but when I change the kategoriCombo, the unsurCombo doesn't update automatically even when i already use currentTextChanged and connect it to a function.
FORM_CLASS, _ = uic.loadUiType(os.path.join(
os.path.dirname(__file__), 'kugi_dialog_base.ui'))
urlKategori = "https://kugi.ina-sdi.or.id:8080/kugiapi/featurecatalog"
response = request.urlopen(urlKategori)
dataKategori = json.loads(response.read())
daftarKategori = []
for kategoriList in dataKategori:
namaKategori = kategoriList.get('name')
trimmedKategori = namaKategori.strip('#en')
daftarKategori.append(trimmedKategori)
class kugiDialog(QtWidgets.QDialog, FORM_CLASS):
def __init__(self, parent=None):
"""Constructor."""
super(kugiDialog, self).__init__(parent)
self.setupUi(self)
self.kategoriCombo.addItems(daftarKategori)
self.kategoriCombo.currentTextChanged.connect(self.changeKategori)
self.outputButton.clicked.connect(self.outFolder)
def changeKategori(self):
daftarID =[]
for dataID in dataKategori:
id = dataID.get('id')
idKategori = id.strip('#en')
daftarID.append(idKategori)
zippedKategori = zip(daftarID, daftarKategori)
selectedCategory = self.kategoriCombo.currentText()
idDipilih = []
for a, b in zippedKategori:
if b == selectedCategory:
idDipilih.append(a)
inputID = (idDipilih[0])
url = "https://kugi.ina-sdi.or.id:8080/kugiapi/featuretype?fcid="
response = request.urlopen(url+inputID)
data = json.loads(response.read())
daftarUnsur= []
for listdata in data:
unsur = listdata.get('typeName')
namaUnsur = unsur.strip('#en')
daftarUnsur.append(namaUnsur)
self.unsurCombo.addItems(daftarUnsur)
I have been working on a Tkinter project. I have set the listbox as StringVar and I would like to call a list of items inside the right listbox by setting a function 'process'.
enter image description here
After I press the button process in the gui, I am supposed to return a list ['A'] in the above case.
However, it return ['(', "'", 'A', "'", ')']
If I just print app.list_var2.get() it return ('A',)
import tkinter as tk
import pandas as pd
app=tk.Tk()
app.geometry('640x480')
app.resizable(width=True, height=True)
app.title('Simulator')
# list variables
app.list_var1 = tk.StringVar()
app.list_var2 = tk.StringVar()
app.list_var1.set(value=['A','B','C'])
app.list_var2.set(value=[])
# label frame
app.label_frame= tk.Frame(app)
app.label1 = tk.Label(app.label_frame,text='PDC',justify='left')
app.label1.pack(ipadx=10,ipady=10,side='left', anchor='w')
app.label2 = tk.Label(app.label_frame,text='SDC')
app.label2.pack(ipadx=20,ipady=10, side='left',anchor='e')
# main frame
app.main_frame = tk.Frame(app)
app.listbox1 = tk.Listbox(app.main_frame, listvariable=app.list_var1, selectmode='single')
app.listbox2 = tk.Listbox(app.main_frame, listvariable=app.list_var2, selectmode='single')
def init_default_values():
app.list_var1.set(value=['A','B','C'])
app.list_var2.set(value=[])
def move_to_right(only_one_item=False):
if app.listbox1.curselection() == ():
return
# get tuple of selected indices
if only_one_item:
selection = (app.listbox1.curselection()[0],)
else:
selection = app.listbox1.curselection()
# left all/selected values
left_value_list = [line.strip(' \'') for line in app.list_var1.get()[1:-1].split(',')]
left_selected_list = [left_value_list[index] for index in selection]
# values from right side
right_value_list = [line.strip(' \'') for line in app.list_var2.get()[1:-1].split(',')]
# merge w/o duplicates
result_list = sorted(list(set(right_value_list + left_selected_list)))
for x in left_value_list:
if x in result_list:
left_value_list.remove(x)
while("" in left_value_list) :
left_value_list.remove("")
while("" in result_list) :
result_list.remove("")
app.list_var2.set(value=result_list)
app.list_var1.set(value=left_value_list)
def move_to_left(only_one_item=False):
if app.listbox2.curselection() == ():
return
# get tuple of selected indices
if only_one_item:
selection = (app.listbox2.curselection()[0],)
else:
selection = app.listbox2.curselection()
# right all/selected values
right_value_list = [line.strip(' \'') for line in app.list_var2.get()[1:-1].split(',')]
right_selected_list = [right_value_list[index] for index in selection]
# values from left side
left_value_list = [line.strip(' \'') for line in app.list_var1.get()[1:-1].split(',')]
# merge w/o duplicates
result_list = sorted(list(set(left_value_list + right_selected_list)))
for x in right_value_list:
if x in result_list:
right_value_list.remove(x)
while("" in right_value_list) :
right_value_list.remove("")
while("" in result_list) :
result_list.remove("")
app.list_var1.set(value=result_list)
app.list_var2.set(value=right_value_list)
def reset():
init_default_values()
def process():
#if len(app.list_var2.get()) == 1:
lst=app.list_var2.get()
print(len(lst))
lst = str(app.list_var2.get()).replace(',','')
lst=list(lst)
print(type(lst))
print(len(lst))
print(lst)
# little button frame
app.button_frame = tk.Frame(app.main_frame)
app.one_to_right_button = tk.Button(app.button_frame, text='>', command=lambda: move_to_right(True))
app.one_to_left_button = tk.Button(app.button_frame, text='<', command=lambda: move_to_left(True))
app.reset_button = tk.Button(app.button_frame,text='Reset',command=reset)
app.process = tk.Button(app.button_frame,text='Process',command=process)
# packing
app.one_to_right_button.pack()
app.one_to_left_button.pack()
app.reset_button.pack()
app.process.pack()
app.listbox1.pack(side='left', anchor='w')
app.button_frame.pack(side='left')
app.listbox2.pack(side='right', anchor='e')
app.label_frame.pack()
app.main_frame.pack(padx=20,pady=20)
# insert default values
init_default_values()
app.mainloop()
Since app.list_var2 is a StringVar, so app.list_var2.get() will always return a string.
Better use app.listbox2.get(0, "end") to get all the items (a tuple) in the listbox:
def process():
lst = list(app.listbox2.get(0, 'end'))
print(lst, type(lst))
Note that you can use eval() to convert the string returned by app.list_var2.get() to tuple but it is not recommended:
def process():
lst = list(eval(app.list_var2.get()))
print(lst, type(lst))
I have a GUI where user selects gas components from list and moves it to 'Chosen' and another button takes text from 'Chosen' that has columns: Gas Component, Molecular Weight, Mol%. The first two columns get information from a dictionary that i've created, and last column is user input.
When button is clicked and all values are filled in 'Chosen', it will ask user for a number, n = 1-6 , it will then take rows with n highest mol% in 'Chosen' and create n rows in Results and add Gas Component text with n highest mol% values, to first column in 'Results'
I am currently using dictionaries to keep track of information.
def calculategas(self):
#makes sure dictionaries are clear for any errors on rerunning button
self.sortedmol.clear()
self.componentDic1.clear()
self.componentDic2.clear()
self.componentDic3.clear()
self.mmDict.clear()
self.mfDict.clear()
self.mDict.clear()
self.massFracDict.clear()
self.molarmassDict.clear()
self.item_.clear()
self.lookup.clear()
root = self.chosen.invisibleRootItem()
child_count = root.childCount()
for i in range(child_count):
item = root.child(i)
#Takes text from self.chosen QTreeWidget (Top-right)
component = item.text(0)
molWeight = item.text(1)
componentMol = float(item.text(2))
#creates dictionary of items in self.chosen
self.componentDic1[component] = componentMol
self.componentDic2[molWeight] = componentMol
#Sorts dictionaries above from highest to lowest
self.sortedmol = dict(sorted(self.componentDic1.items(), key=operator.itemgetter(1),
reverse=True)) # Sorted component list - largest to smallest mol%
self.sortedmolar = dict(sorted(self.componentDic2.items(), key=operator.itemgetter(1),
reverse=True)) # Sorted molar mass list - largest to smallest mol%
# change values of self.sortedmol with keys of self.sortedmolar
self.lookup = {v:k for k, v in self.sortedmol.items()}
self.componentDic3 = {self.lookup[v]: float(k) for k, v in self.sortedmolar.items()}
##Copies so original doesn't change
self.mmDict = self.sortedmol.copy()
self.mfDict = self.mmDict.copy()
self.mDict = self.componentDic3.copy()
###Calculations
self.molarmassDict = {k: round(v * self.mmDict[k] / 100, 3) for k, v in self.mDict.items() if
k in self.mmDict}
summolmDict = round(sum(self.molarmassDict.values()), 3)
self.massFracDict = {k: round(self.molarmassDict[k] / summolmDict, 3) for k, v in self.molarmassDict.items()
if
k in self.molarmassDict}
componentNum, ok = QInputDialog.getText(None, 'Number of components', 'How many components do you wish to use?')
if (ok):
#Remove any items in result QTreeWidget
current_item = self.result.invisibleRootItem()
children = []
for child in range(current_item.childCount()):
children.append(current_item.child(child))
for child in children:
current_item.removeChild(child)
#Adds rows to self.result QTreeWidget
for i in range(int(componentNum)):
self.item_[i] = QtWidgets.QTreeWidgetItem(self.result)
self.item_[i].setFlags(
QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
if len(self.sortedmol) > int(componentNum): # takes only # of components user wants
##Adds the number of components user inputs with highest mol% to self.result
root = self.result.invisibleRootItem()
child_count = root.childCount()
for i in range(child_count):
item = root.child(i)
item.setText(0, str(list(self.massFracDict)[i])) # update first column with dictionary keys
else:
###This section will change
root = self.result.invisibleRootItem()
child_count = root.childCount()
for i in range(child_count):
item = root.child(i)
item.setText(0, str(list(self.massFracDict)[i])) # update first column with dictionary keys
Currently everything works except that when there is a duplicate value in mol% or molecular weight it will tend to skip it.
Dictionary self.sortedmol:
Keys = Gas Component text
Values = mol% text
Dictionary self.sortedmolar:
Keys = Molecular Weight text
Values = mol% text
Problems:
If two components have same molecular weight, it will ignore it
If two components have same mol%, it will ignore it
Overall goal: Add rows with n highest mol% in 'Chosen' to 'Result and keep values for later calculations.
Question: Is there any way to fix this error, or use another way to get same desired results?
Step1:
Step2:
If you want to get the n rows where the mol% are the highest then you must use a QSortFilterProxyModel to sort, and another to filter.
from PyQt5 import QtCore, QtGui, QtWidgets
ListRole = QtCore.Qt.UserRole
VisibleRole = QtCore.Qt.UserRole + 1
class TopProxyModel(QtCore.QSortFilterProxyModel):
#property
def number(self):
if not hasattr(self, "_number"):
self._number = -1
return self._number
#number.setter
def number(self, number):
self._number = number
self.invalidateFilter()
def filterAcceptsRow(self, sourceRow, sourceParent):
if self.number < 0:
ix = self.sourceModel().index(sourceRow, 2)
self.sourceModel().setData(ix, False, VisibleRole)
return True
return sourceRow < self.number
class BlankDelegate(QtWidgets.QStyledItemDelegate):
def initStyleOption(self, option, index):
super().initStyleOption(option, index)
if not index.data(VisibleRole):
option.text = ""
def setModelData(self, editor, model, index):
sm = model
ix = index
while hasattr(sm, "sourceModel"):
ix = sm.mapToSource(ix)
sm = sm.sourceModel()
sm.setData(ix, editor.value(), QtCore.Qt.DisplayRole)
if not sm.data(ix, VisibleRole):
sm.setData(ix, True, VisibleRole)
class ReadOnlyDelegate(QtWidgets.QStyledItemDelegate):
def createEditor(self, parent, option, index):
return None
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
datas = [
("IsonButane", 58.12, 13),
("IsonPentane", 75.12, 3),
("Methane", 16.04, 5),
("Nitrogen", 28.01, 5),
("Hexane", 86.17, 5),
("Hydrogen", 2.02, 13),
("Hydrogen Sulfide", 34.08, 2),
]
add_button = QtWidgets.QPushButton(">>>", clicked=self.add_row)
remove_button = QtWidgets.QPushButton("<<<", clicked=self.remove_row)
select_button = QtWidgets.QPushButton("Calculate", clicked=self.select)
sp = select_button.sizePolicy()
sp.setHorizontalPolicy(QtWidgets.QSizePolicy.Maximum)
select_button.setSizePolicy(sp)
self.listwidget = QtWidgets.QListWidget(
selectionMode=QtWidgets.QAbstractItemView.MultiSelection
)
for data in datas:
item = QtWidgets.QListWidgetItem(data[0])
item.setData(ListRole, data)
self.listwidget.addItem(item)
self.tree_widget = QtWidgets.QTreeWidget(
columnCount=3,
indentation=0,
selectionMode=QtWidgets.QAbstractItemView.MultiSelection,
)
for i, T in enumerate(
(ReadOnlyDelegate, ReadOnlyDelegate, BlankDelegate)
):
delegate = T(self.tree_widget)
self.tree_widget.setItemDelegateForColumn(2, delegate)
self.tree_widget.setHeaderLabels(
["Gas Component", "Molecular Weight", "Mol%"]
)
self.tree_view = QtWidgets.QTreeView(indentation=0)
proxy_sort = QtCore.QSortFilterProxyModel(self)
proxy_sort.setSourceModel(self.tree_widget.model())
proxy_sort.sort(2, QtCore.Qt.DescendingOrder)
self.proxy_top = TopProxyModel(self)
self.proxy_top.number = 0
self.proxy_top.setSourceModel(proxy_sort)
self.tree_view.setModel(self.proxy_top)
lay = QtWidgets.QGridLayout(self)
lay.addWidget(QtWidgets.QLabel("<b>Available Gases:</b>"), 0, 0)
lay.addWidget(self.listwidget)
vlay = QtWidgets.QVBoxLayout()
vlay.addStretch()
vlay.addWidget(add_button)
vlay.addWidget(remove_button)
vlay.addStretch()
lay.addLayout(vlay, 1, 1)
lay.addWidget(QtWidgets.QLabel("<b>Chosen Gases</b>"), 0, 2)
lay.addWidget(self.tree_widget, 1, 2)
lay.addWidget(select_button, 2, 2, alignment=QtCore.Qt.AlignCenter)
lay.addWidget(QtWidgets.QLabel("<b>Result:</b>"), 3, 2)
lay.addWidget(self.tree_view, 4, 2)
#QtCore.pyqtSlot()
def add_row(self):
for item in self.listwidget.selectedItems():
data = item.data(ListRole)
text = item.text()
if self.tree_widget.findItems(text, QtCore.Qt.MatchExactly):
continue
it = self.listwidget.takeItem(self.listwidget.row(item))
item = QtWidgets.QTreeWidgetItem()
self.tree_widget.addTopLevelItem(item)
item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable)
for i, e in enumerate(data):
item.setData(i, QtCore.Qt.DisplayRole, e)
#QtCore.pyqtSlot()
def remove_row(self):
rows = [
self.tree_widget.indexOfTopLevelItem(item)
for item in self.tree_widget.selectedItems()
]
for row in sorted(rows, reverse=True):
item = self.tree_widget.takeTopLevelItem(row)
data = []
for i in range(self.tree_widget.columnCount()):
data.append(item.data(i, QtCore.Qt.DisplayRole))
it = QtWidgets.QListWidgetItem(data[0])
it.setData(ListRole, data)
self.listwidget.addItem(it)
if item is not None:
del item
#QtCore.pyqtSlot()
def select(self):
last_number = max(self.proxy_top.number, 0)
number, ok = QtWidgets.QInputDialog.getInt(
None,
"Number of components",
"How many components do you wish to use?",
last_number,
min=-1,
max=self.tree_widget.topLevelItemCount(),
)
if ok:
self.proxy_top.number = number
for i in range(self.tree_widget.topLevelItemCount()):
it = self.tree_widget.topLevelItem(i)
it.setData(2, VisibleRole, False)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
I'm creating 3 groups of ttk.CheckButtons, using a class clsGrpCheckButton.
The problem is that I can access only the status of the last group created, and not for the previous group.
When clicking on one of the checkButtons of any group, I'm expecting to get the list of checkbuttons check in the group (by using method chkGrpGetValue with is the command parameter of each checkbutton)
However, whatever which button is clicked, the method only and always returns the status of the last group
Here is the code to recreate the issue, and in attachment a picture that shows the problems
Thks for your help.
Rgds
import tkinter as tk
from tkinter import ttk
import pandas as pd
class clsGrpCheckButton(ttk.Checkbutton):
def __init__(self,pContainer, pLstVal,pCommand,pInitValue=True):
self.grpChk=[0]*len(pLstVal)
self.grpKey=[0]*len(pLstVal)
self.grpLstVal = [0]*len(pLstVal)
self.grpVariable= [0]*len(pLstVal)
self.grpActiveKeys = [0]
for l,t in enumerate(pLstVal):
#l : index of the list of tuples
self.grpKey[l] = t[0]
self.grpLstVal[l] = t[1]
self.grpVariable[l] = tk.StringVar()
self.grpChk[l] = ttk.Checkbutton(pContainer, text=self.grpLstVal[l],
state='active' ,
onvalue= self.grpKey[l],
offvalue= '',
variable = self.grpVariable[l],
command=pCommand)
#get default value
if pInitValue :
self.grpVariable[l].set(self.grpKey[l])
self.grpActiveKeys.append(self.grpKey[l])
#get the index in the list of checkboxes
# depending on the key
def chkGrpGetIdx(self, pKey):
i=0
while i <len(self.grpKey):
if self.grpKey[i]==pKey :
return i
i=len(self.grpKey)
else:
i+=1
def chkGrpSetValue(self, pKey, pValue):
#need find correct index first
i=self.chkGrpGetIdx(pKey)
self.grpVariable[i] = pValue
#return the list of keys of the group
def chkGrpKeyLst(self):
return self.grpKey
#return the checkox element of the group of checkox
def chkGrpGetChkObj(self,pKey):
i=self.chkGrpGetIdx(pKey)
return self.grpChk[i]
#action when check/uncheck
#at list one element should be active
def chkGrpGetValue(self):
i=0
r=len(self.grpVariable)
self.grpActiveKeys.clear()
while i < len(self.grpVariable):
if self.grpVariable[i].get() =='':
r-=1
else:
self.grpActiveKeys.append(self.grpKey[i])
i+=1
if r==0:
self.grpVariable[0].set(self.grpKey[0])
self.grpActiveKeys.append(self.grpKey[0])
print(self.grpActiveKeys)
#to avoid accessing to class attribute directly
def chkGetCheckedValues(self):
return self.grpActiveKeys
class clsWindows(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
la = [1,1,1,1,1,2,2,2,2,2,2,2,3,3,3,3]
lb= [10,11,12,14,15,20,21,22,23,24,25,26,30,31,32,33]
lc=['d10','d11','d12','d14','d15','d20','d21','d22','d23','d24','d25','d26','d30','d31','d32','d33']
df = pd.DataFrame(
{'DIVISION': la,
'DEPT_CODE': lb,
'DEPT_NAME': lc
})
lW = list(zip(df['DIVISION'].astype(str) , df['DEPT_CODE'].astype(str)))
lpt = list(zip(df['DEPT_CODE'].astype(str) , df['DEPT_NAME'].astype(str)))
curHead = ""
r=0
c=-1
for head, DPT in lW:
if not curHead==head:
curHead = head
c+=1
r=0
dq=df.query('DIVISION=='+head)
lpt = list(zip(dq['DEPT_CODE'].astype(str) , dq['DEPT_NAME'].astype(str)))
t=ttk.Labelframe(self,text=head)
t.grid(column=c, row=0, sticky='nw')
self.checkGrpDept= clsGrpCheckButton(t,lpt,lambda:self.checkGrpDept.chkGrpGetValue(),True)
self.checkGrpDept.chkGrpGetChkObj(DPT).grid(column=c, row=r, sticky='nw')
t.rowconfigure(r, weight=1)
t.columnconfigure(c, weight=1)
r+=1
def wQuit(self):
self.destroy()
app = clsWindows()
app.mainloop()
Example of issue
finally, I came up with a solution by using partial when assigning the command to each checkbutton.
Here is the full code if someone faces a similar issue
import tkinter as tk
from tkinter import ttk
import pandas as pd
from functools import partial
class clsGrpCheckButton():
def __init__(self,pContainer, pLstVal,pCommand,pInitValue=True):
self.grpChk=[0]*len(pLstVal)
self.grpKey=[0]*len(pLstVal)
self.grpLstVal = [0]*len(pLstVal)
self.grpVariable= [0]*len(pLstVal)
self.grpActiveKeys = [0]
for l,t in enumerate(pLstVal):
#l : index of the list of tuples
self.grpKey[l] = t[0]
self.grpLstVal[l] = t[1]
self.grpVariable[l] = tk.StringVar()
self.grpChk[l] = ttk.Checkbutton(pContainer, text=self.grpLstVal[l],
state='active' ,
onvalue= self.grpKey[l],
offvalue= '',
variable = self.grpVariable[l],
command=partial(pCommand,self))
#get default value
if pInitValue :
self.grpVariable[l].set(self.grpKey[l])
self.grpActiveKeys.append(self.grpKey[l])
#get the index in the list of checkboxes
# depending on the key
def chkGrpGetIdx(self, pKey):
i=0
while i <len(self.grpKey):
if self.grpKey[i]==pKey :
return i
i=len(self.grpKey)
else:
i+=1
def chkGrpSetValue(self, pKey, pValue):
#need find correct index first
i=self.chkGrpGetIdx(pKey)
self.grpVariable[i] = pValue
#return the list of keys of the group
def chkGrpKeyLst(self):
return self.grpKey
#return the checkox element of the group of checkox
def chkGrpGetChkObj(self,pKey):
i=self.chkGrpGetIdx(pKey)
return self.grpChk[i]
#action when check/uncheck
#at list one element should be active
def chkGrpGetValue(self):
i=0
r=len(self.grpVariable)
self.grpActiveKeys.clear()
while i < len(self.grpVariable):
if self.grpVariable[i].get() =='':
r-=1
else:
self.grpActiveKeys.append(self.grpKey[i])
i+=1
if r==0:
self.grpVariable[0].set(self.grpKey[0])
self.grpActiveKeys.append(self.grpKey[0])
print(self.grpActiveKeys)
#to avoid accessing to class attribute directly
def chkGetCheckedValues(self):
return self.grpActiveKeys
class clsWindows(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
la = [1,1,1,1,1,2,2,2,2,2,2,2,3,3,3,3]
lb= [10,11,12,14,15,20,21,22,23,24,25,26,30,31,32,33]
lc=['d10','d11','d12','d14','d15','d20','d21','d22','d23','d24','d25','d26','d30','d31','d32','d33']
df = pd.DataFrame(
{'DIVISION': la,
'DEPT_CODE': lb,
'DEPT_NAME': lc
})
lW = list(zip(df['DIVISION'].astype(str) , df['DEPT_CODE'].astype(str)))
lpt = list(zip(df['DEPT_CODE'].astype(str) , df['DEPT_NAME'].astype(str)))
curHead = ""
r=0
c=-1
for head, DPT in lW:
if not curHead==head:
curHead = head
c+=1
r=0
dq=df.query('DIVISION=='+head)
lpt = list(zip(dq['DEPT_CODE'].astype(str) , dq['DEPT_NAME'].astype(str)))
t=ttk.Labelframe(self,text=head)
t.grid(column=c, row=0, sticky='nw')
checkGrpDept= clsGrpCheckButton(t,lpt,clsGrpCheckButton.chkGrpGetValue,True)
checkGrpDept.chkGrpGetChkObj(DPT).grid(column=c, row=r, sticky='nw')
t.rowconfigure(r, weight=1)
t.columnconfigure(c, weight=1)
r+=1
def wQuit(self):
self.destroy()
app = clsWindows()
app.mainloop()
I am new to python and recently i make dictionary using Python and Sqlite3 with tkinter.
When I run the code it returns multiple line in IDLE but in the GUI its only display the last result. I would like to display all the information in the GUI. Thanks you for any help and suggestion.
import tkinter
import sqlite3
class Dictionary:
def __init__(self,master =None):
self.main_window = tkinter.Tk()
self.main_window.title("Lai Mirang Dictionary")
self.main_window.minsize( 600,400)
self.main_window.configure(background = 'paleturquoise')
self.frame1 = tkinter.Frame()
self.frame2= tkinter.Frame(bg = 'red')
self.frame3 =tkinter.Text( foreground = 'green')
self.frame4 = tkinter.Text()
self.lai_label = tkinter.Label(self.frame1,anchor ='nw',font = 'Times:12', text = 'Lai',width =25,borderwidth ='3',fg='blue')
self.mirang_label = tkinter.Label(self.frame1,anchor ='ne',font = 'Times:12', text = 'Mirang',borderwidth ='3',fg ='blue')
self.lai_label.pack(side='left')
self.mirang_label.pack(side = 'left')
self.kawl_buttom= tkinter.Button(self.frame2 ,fg = 'red',font = 'Times:12',text ='Kawl',command=self.dic,borderwidth ='3',)
self.lai_entry = tkinter.Entry(self.frame2, width= 28, borderwidth ='3',)
self.lai_entry.focus_force()
self.lai_entry.bind('<Return>', self.dic,)
self.lai_entry.configure(background = 'khaki')
self.lai_entry.pack(side='left')
self.kawl_buttom.pack(side = 'left')
self.value = tkinter.StringVar()
self.mirang_label= tkinter.Label(self.frame3,font = 'Times:12',fg = 'blue',textvariable = self.value,justify = 'left',wraplength ='260',width = 30, height = 15,anchor = 'nw')
self.mirang_label.pack()
self.mirang_label.configure(background = 'seashell')
self.copyright_label = tkinter.Label(self.frame4,anchor ='nw',font = 'Times:12:bold',text = "copyright # cchristoe#gmail.com",width = 30,borderwidth = 3, fg = 'purple',)
self.copyright_label.pack()
self.frame1.pack()
self.frame2.pack()
self.frame3.pack()
self.frame4.pack()
tkinter.mainloop()
self.main_window.quit()
def dic(self, event = None):
conn = sqlite3.connect('C:/users/christoe/documents/sqlite/laimirangdictionary.sqlite')
c = conn.cursor()
kawl = self.lai_entry.get()
kawl = kawl + '%'
c.execute("SELECT * FROM laimirang WHERE lai LIKE ?", (kawl,))
c.fetchall
for member in c:
out = (member)
self.value.set(out)
print(out, )
dic=Dictionary()
You need to change:
c.execute("SELECT * FROM laimirang WHERE lai LIKE ?", (kawl,))
c.fetchall
for member in c:
out = (member)
self.value.set(out)
print(out, )
To:
for member in c.execute("SELECT * FROM laimirang WHERE lai LIKE ?", (kawl,)):
current_text = self.value.get()
new_text = current_text +( "\n" if current_text else "") +" ".join(member)
self.value.set(new_text)
The new version gets the current value of the StringVar value and then appends the results returned with a space inbetween for each row returned with each row on its own line. What you were doing however involved just updating the StringVar to be the current member object, and therefore it only ever had the last values.
This is how it looks with more than one line: