I am trying to add rows to a table like GUI.
These rows are to be a list of labels.
Each row that is updated has the following methods in that class:
AddRow - To add the list of strings that will be the text in that
label.
AddLabel - Adds a label to that row and appends the Label list
AddLabelRow - Creates the list Row in the actual table and
initializes the text to "empty"
ChangeLableText - Takes an input list of strings and changes the string in the label for that class.
I then have initialized a list of objects ContentList[] for this class and call the methods
But no matter which object's ChangeLabelText is called, only the text for ContentList[0] is updated.
import json
import requests
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.lang import Builder
from kivy.uix.scrollview import ScrollView
from kivy.core.window import Window
from kivy.uix.button import Button
from kivy.app import runTouchApp
class AddContent(GridLayout):
#response = requests.get("http://localhost:10010/")
# Get the response data as a python object. Verify that it's a dictionary.
#data = response.json()[3]
#Column_keys = ["country", "date", "answered_calls", "total_calls", "asr", "mou", "aou"]
RowList = []
Label_List = []
size = 0
def AddRow(self, InputList):
self.RowList = InputList
self.size = len(InputList)
def AddLabel(self,LayoutObj):
lbl = Label(size_hint_y = None, height = 30)
LayoutObj.add_widget(lbl)
return lbl
def AddLabelRow(self,LayoutObj):
for i in range(self.size):
Lbl = self.AddLabel(LayoutObj)
Lbl.text = "empty"
#self.Label_List[i].text = data[Column_keys[i]]
#Lbl.text = str(self.data[self.Column_keys[i]])
self.Label_List.append(Lbl)
def ChangeLabel_ListText(self, TextList):
for i in range(self.size):
#self.Label_List[i].text = data[Column_keys[i]] #data is fetched from Db
self.Label_List[i].text = TextList[i]
class TableView(GridLayout):
Col_Names = ["Date","Vendor","Country","MOU","ASR","AOU"]
ContentList = [AddContent(),AddContent(),AddContent()]
def __init__(self,**kwargs):
self.layout = GridLayout(cols = len(self.Col_Names), padding =5)
self.layout.bind(minimum_height=self.layout.setter('height'))
for i in range(len(self.Col_Names)):
btn = Button(text=self.Col_Names[i], size_hint_y=None, height=30)
self.layout.add_widget(btn)
self.ContentList[0].AddRow(['1sample1','1sample2','1sample3','1sample4','1sample5','1sample6'])
self.ContentList[1].AddRow(['2sample1','2sample2','2sample3','2sample4','2sample5','2sample6'])
self.ContentList[2].AddRow(['3sample1','3sample2','3sample3','3sample4','3sample5','3sample6'])
for i in range(3):
self.ContentList[i].AddLabelRow(self.layout)
self.ContentList[2].ChangeLabel_ListText(['a','b','c','d','e','f'])
if __name__ == '__main__':
Table = TableView()
runTouchApp(Table.layout)
The line self.ContentList[2].ChangeLabel_ListText(['a','b','c','d','e','f'])
updates only the first row whatever number is given for the index.
I have been breaking my head over this for the past week. I had initially done this with only one class instead of two which gave the same output.
Any help will help greatly. Thanks!
Your first problem is that RowList, Label_List, and size are class attributes in your code. But you want to set them in every instance individually. Solution: initialize these attributes inside the __init__ method like this:
def __init__(self, **kwargs):
super(AddContent, self).__init__(**kwargs)
self.RowList = []
self.Label_List = []
self.size = 0
The second problem is, that the GridLayout (which your class is subclassing) also contains an attribute called size. Solution: pick a different name for this attribute like so:
self.length = 0
If you now do
self.ContentList[i].ChangeLabel_ListText(['a','b','c','d','e','f'])
your i-th ContentList-entry will be changed.
Here is the complete solution:
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.lang import Builder
from kivy.uix.scrollview import ScrollView
from kivy.core.window import Window
from kivy.uix.button import Button
from kivy.app import runTouchApp
class AddContent(GridLayout):
#response = requests.get("http://localhost:10010/")
# Get the response data as a python object. Verify that it's a dictionary.
#data = response.json()[3]
#Column_keys = ["country", "date", "answered_calls", "total_calls", "asr", "mou", "aou"]
def __init__(self, **kwargs):
super(AddContent, self).__init__(**kwargs)
self.RowList = []
self.Label_List = []
self.length = 0
def AddRow(self, InputList):
self.RowList = InputList
self.length = len(InputList)
def AddLabel(self,LayoutObj):
lbl = Label(size_hint_y=None, height=30)
LayoutObj.add_widget(lbl)
return lbl
def AddLabelRow(self,LayoutObj):
for i in range(self.length):
Lbl = self.AddLabel(LayoutObj)
Lbl.text = "empty"
#self.Label_List[i].text = data[Column_keys[i]]
#Lbl.text = str(self.data[self.Column_keys[i]])
self.Label_List.append(Lbl)
def ChangeLabel_ListText(self, TextList):
for i in range(self.length):
#self.Label_List[i].text = data[Column_keys[i]] #data is fetched from Db
self.Label_List[i].text = TextList[i]
class TableView(GridLayout):
Col_Names = ["Date","Vendor","Country","MOU","ASR","AOU"]
ContentList = [AddContent(),AddContent(),AddContent()]
def __init__(self,**kwargs):
self.layout = GridLayout(cols = len(self.Col_Names), padding=5)
self.layout.bind(minimum_height=self.layout.setter('height'))
for i in range(len(self.Col_Names)):
btn = Button(text=self.Col_Names[i], size_hint_y=None, height=30)
self.layout.add_widget(btn)
self.ContentList[0].AddRow(['1sample1','1sample2','1sample3','1sample4','1sample5','1sample6'])
self.ContentList[1].AddRow(['2sample1','2sample2','2sample3','2sample4','2sample5','2sample6'])
self.ContentList[2].AddRow(['3sample1','3sample2','3sample3','3sample4','3sample5','3sample6'])
for i in range(3):
self.ContentList[i].AddLabelRow(self.layout)
self.ContentList[2].ChangeLabel_ListText(['a','b','c','d','e','f'])
if __name__ == '__main__':
Table = TableView()
runTouchApp(Table.layout)
Related
Here is my sample code.I am learning the list view methods,I already posted one question,but i have a small doubt in my program.In my program after "fliter" i am getting the matched items of the word in that i want to choose the selected item using the enter key but it is printing the first item after selecting..I don't want to print the first item of the matched list..can any one please help me.Thank you in advance.
given below is my code:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Dialog(QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent=parent)
vLayout = QVBoxLayout(self)
hLayout = QHBoxLayout()
self.lineEdit = QLineEdit(self)
hLayout.addWidget(self.lineEdit)
self.filter = QPushButton("filter", self)
hLayout.addWidget(self.filter)
self.filter.clicked.connect(self.filterClicked)
self.list = QListView(self)
vLayout.addLayout(hLayout)
vLayout.addWidget(self.list)
self.model = QStandardItemModel(self.list)
codes = [
'windows',
'windows xp',
'windows7',
'hai',
'habit',
'hack',
'good'
]
for code in codes:
item = QStandardItem(code)
self.model.appendRow(item)
self.list.setModel(self.model)
shorcut=QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Return), self)
shorcut.activated.connect(self.on_enter_pressed)
#QtCore.pyqtSlot()
def on_enter_pressed(self):
if len(self.lineEdit.text())>0:
self.filterClicked()
def filterClicked(self):
filter_text = str(self.lineEdit.text()).lower()
for row in range(self.model.rowCount()):
if filter_text in str(self.model.item(row).text()).lower():
self.list.setRowHidden(row, False)
self.list.setFocus()
else:
self.list.setRowHidden(row, True)
ix = self.list.selectionModel().selectedIndexes()
#here if i mentioned self.list.selectionModel().currentIndex() means it is automatically printing the first item in List_View
# i dont want to print first item ...after slecting the item in list view i will press enter key then only i want to print the selected item name
print ix.data()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
w = Dialog()
w.show()
sys.exit(app.exec_())
finally i got this answer..thq eyllanesc sir,i refer all your previous answers related to list view..Thank you so much..
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Dialog(QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent=parent)
vLayout = QVBoxLayout(self)
hLayout = QHBoxLayout()
self.lineEdit = QLineEdit(self)
hLayout.addWidget(self.lineEdit)
self.filter = QPushButton("filter", self)
hLayout.addWidget(self.filter)
self.filter.clicked.connect(self.filterClicked)
self.list = QListView(self)
vLayout.addLayout(hLayout)
vLayout.addWidget(self.list)
self.model = QStandardItemModel(self.list)
codes = [
'windows',
'windows xp',
'windows7',
'hai',
'habit',
'hack',
'good'
]
for code in codes:
item = QStandardItem(code)
self.model.appendRow(item)
self.list.setModel(self.model)
shorcut=QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Return), self)
shorcut.activated.connect(self.on_enter_pressed)
#QtCore.pyqtSlot()
def on_enter_pressed(self):
if len(self.lineEdit.text())>0:
self.filterClicked()
def filterClicked(self):
filter_text = str(self.lineEdit.text()).lower()
for row in range(self.model.rowCount()):
if filter_text in str(self.model.item(row).text()).lower():
self.list.setRowHidden(row, False)
self.list.setFocus()
else:
self.list.setRowHidden(row, True)
indexes = self.list.selectionModel().selectedIndexes()
for index in indexes:
print index.data().toString()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
w = Dialog()
w.show()
sys.exit(app.exec_())
Here is my sample code. When I click the index item in list view, I am getting the selection item,it's working fine.But I want to get the selected item using up and down arrows. Can anyone please help me. Thank you in advance.
Given below is my code:
import sys
from PyQt4 import QtCore,QtGui
class mtable(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.auto_search1 = QtGui.QWidget()
self.auto_search_vbox1 = QtGui.QVBoxLayout(self.auto_search1)
self.auto_search_vbox1.setAlignment(QtCore.Qt.AlignLeft)
hbox1=QtGui.QHBoxLayout()
self.le_search1 = QtGui.QLineEdit()
self.se_btn1 = QtGui.QPushButton("Search")
self.searchBtn = QtGui.QPushButton("Close")
self.searchBtn.clicked.connect(self.auto_search1.close)
self.se_btn1.clicked.connect(self.filterClicked1)
hbox1.addWidget(self.le_search1)
hbox1.addWidget(self.se_btn1)
hbox1.addWidget(self.searchBtn)
self.auto_search_vbox1.addLayout(hbox1)
self.total_list1 =[]
self.list1 = QtGui.QListView()
self.list1.clicked.connect(self.on_treeView_clicked)
self.model1 = QtGui.QStandardItemModel(self.list1)
self.y =['one','two', 'three']
for i in self.y:
self.total_list1.append(i)
for code in self.total_list1:
item1 = QtGui.QStandardItem(code)
self.model1.appendRow(item1)
self.list1.setModel(self.model1)
self.auto_search_vbox1.addWidget(self.list1)
self.auto_search1.show()
self.auto_search1.resize(1000,500)
#QtCore.pyqtSlot(QtCore.QModelIndex)
def on_treeView_clicked(self, index):
itms = self.list1.selectedIndexes()
for data in itms:
print index.data().toString()
self.le_search1.setText(index.data().toString())
self.filterClicked1()
def filterClicked1(self):
print "searching logic"
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
tb = mtable()
sys.exit(app.exec_())
Here I need to select the green highlighted item using arrow keys without clicking the item
You have to use the currentChanged signal of the selectionModel() of the QListView:
import sys
from PyQt4 import QtCore,QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.lineedit = QtGui.QLineEdit()
self.search_button = QtGui.QPushButton("Search")
self.close_button = QtGui.QPushButton("Close")
self.listview = QtGui.QListView()
model = QtGui.QStandardItemModel(self.listview)
for e in ('one', 'two', 'three'):
model.appendRow(QtGui.QStandardItem(e))
self.listview.setModel(model)
# signals connections
self.listview.selectionModel().currentChanged.connect(self.on_currentChanged)
QtCore.QTimer.singleShot(0, self.selectFirstItem)
# layout
central_widget = QtGui.QWidget()
self.setCentralWidget(central_widget)
vlay = QtGui.QVBoxLayout(central_widget)
hlay = QtGui.QHBoxLayout()
hlay.addWidget(self.lineedit)
hlay.addWidget(self.search_button)
hlay.addWidget(self.close_button)
vlay.addLayout(hlay)
vlay.addWidget(self.listview)
self.resize(640, 480)
def selectFirstItem(self):
self.listview.setFocus()
ix = self.listview.model().index(0, 0)
self.listview.selectionModel().setCurrentIndex(ix, QtGui.QItemSelectionModel.Select)
#QtCore.pyqtSlot(QtCore.QModelIndex)
def on_currentChanged(self, current):
self.lineedit.setText(current.data())
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
I have written the code for Undo & Redo actions for QTableView by using QUndoStack class in PyQt4.
The Undo action works fine; but when I perform Redo action, I am getting "RuntimeError: maximum recursion depth exceeded while calling a Python object."
I have used QTableView's pressed & dataChanged signals to retrieve the texts from model.
Following is the code sample.
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.QtSql import *
import os
import sys
import random
# SQL Query:---------------------------------------------------------------------------------------------
def StudentQuery():
StudentQuery = QSqlQuery()
StudentQuery.exec_("DROP TABLE STUDENTS")
StudentQuery.exec_("""CREATE TABLE STUDENTS (
s1 REAL NULL,
s2 REAL NULL,
s3 REAL NULL)""")
Students = ("STD1", "STD2", "STD3")
StudentQuery.prepare("INSERT INTO STUDENTS (s1, s2, s3) VALUES (?, ?, ?)")
for Student in Students:
s1 = random.randint(0, 25)
s2 = random.randint(0, 25)
s3 = random.randint(0, 25)
StudentQuery.addBindValue(QVariant(s1))
StudentQuery.addBindValue(QVariant(s2))
StudentQuery.addBindValue(QVariant(s3))
StudentQuery.exec_()
QApplication.processEvents()
# Ui Dialog:------------------------------------------------------------------------------------------------
class Ui_Student(QDialog):
def __init__(self, parent=None):
super(Ui_Student, self).__init__(parent)
self.setFixedSize(340, 170)
self.setWindowTitle("STUDENT")
self.model = QSqlTableModel(self)
self.model.setTable("STUDENTS")
self.model.setEditStrategy(QSqlTableModel.OnManualSubmit)
self.model.select()
self.view = QTableView(self)
self.view.setGeometry(QRect(10, 10, 320, 120))
self.view.setSelectionBehavior(QAbstractItemView.SelectItems)
self.view.setFocusPolicy(Qt.StrongFocus)
self.view.setModel(self.model)
self.view.installEventFilter(self)
QSqlDatabase.database().commit()
# Button Box:---------------------------------------------------------------------------------------------------
self.buttonBox = QDialogButtonBox(self)
self.buttonBox.setGeometry(QRect(118, 127, 100, 45))
self.buttonBox.setOrientation(Qt.Horizontal)
self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok)
# SIGNAL & SLOT: -----------------------------------------------------------------------------------------------
QObject.connect(self.buttonBox, SIGNAL("accepted()"), self.accept)
QObject.connect(self.buttonBox, SIGNAL("rejected()"), self.reject)
# Code For Undo/Redo:---------------------------------------------------------------------------------------------------
self.undoStack = QUndoStack(self)
self.undoStack.setUndoLimit(10)
self.L_Row = []
self.L_Column = []
self.L_Text0 = []
self.L_Text1 = []
self.view.pressed.connect(self.InitialText)
self.view.model().dataChanged.connect(self.FinalText)
def InitialText(self, signal):
self.Row = signal.row()
self.Column = signal.column()
Model = self.view.model()
self.Text0 = Model.data(Model.index(self.Row, self.Column), 0).toString()
self.L_Row.append(self.Row)
self.L_Column.append(self.Column)
self.L_Text0.append(self.Text0)
# print self.L_Text0
def FinalText(self):
View = self.view
Model = self.view.model()
self.Text1 = Model.data(Model.index(self.Row, self.Column), 0).toString()
self.L_Text1.append(self.Text1)
for i in range(len(self.L_Text0)):
if not (self.L_Text0[i] == self.L_Text1[i]):
command = CommandEdit(View, Model, self.L_Row[i], self.L_Column[i],
self.L_Text0[i], self.L_Text1[i], "ABC")
self.undoStack.push(command)
# ContextMenu:---------------------------------------------------------------------------------------------------
def contextMenuEvent(self, event):
menu = QMenu(self)
UndoAction = self.undoStack.createUndoAction(self)
UndoAction.setText("&Undo")
menu.addAction(UndoAction)
UndoAction.setShortcuts(QKeySequence.Undo)
self.connect(UndoAction, SIGNAL("triggered()"), self.undoStack.undo)
RedoAction = self.undoStack.createUndoAction(self)
RedoAction.setText("&Redo")
menu.addAction(RedoAction)
RedoAction.setShortcuts(QKeySequence.Redo)
self.connect(RedoAction, SIGNAL("triggered()"), self.undoStack.redo)
menu.exec_(event.globalPos())
# QUndoCommand Class:---------------------------------------------------------------------------------------------------
class CommandEdit(QUndoCommand):
def __init__(self, View, Model, RowIndex, ColumnIndex, Text0, Text1, description):
super(CommandEdit, self).__init__(description)
self.view = View
self.model = Model
self.rowIndex = RowIndex
self.columnIndex = ColumnIndex
self.text0 = Text0
self.text1 = Text1
def undo(self):
self.model.setData(self.model.index(self.rowIndex, self.columnIndex), QVariant(self.text0))
def redo(self): # Error occurred while executing this function.
self.model.setData(self.model.index(self.rowIndex, self.columnIndex), QVariant(self.text1))
# Code Execute:---------------------------------------------------------------------------------------------------
if __name__ == "__main__":
app = QApplication(sys.argv)
filename = os.path.join(os.path.dirname(__file__), "STD.db")
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName(filename)
db.open()
StudentQuery()
form = Ui_Student()
form.show()
sys.exit(app.exec_())
Am I doing something wrong while defining def InitialText & def FinalText?
I am new to kivy/python. I wanted to test my programming skills, so I modified this code off a post. It take texts as numbers from the textinput and converts them into a matrix and performs an operation. It works perfectly for positive numbers, however I want to capture negative numbers as well. But that always gives an error.
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
class Screen(GridLayout):
def __init__(self, **kwargs):
super(Screen, self).__init__(**kwargs)
self.input = TextInput(multiline=False, size_hint = (None, None))
self.add_widget(self.input)
self.input.bind(on_text_validate=self.print_input)
def print_input(self, value):
"""function to convert Textinput text into a matrix"""
ans1 = [i for i in list(value.text) if i != ',']
new = []
for i in range(len(ans1)):
if ans1[i] == "-":
n = ans1[i] + ans1[i + 1] # concatenate "-" and the next item after it
ans1.remove(ans1[i]) # delete "-"
ans1.remove(ans1[i+1]) # delete the next element after "-"
new.append(n)
new.append(ans1[i])
# the list new can now be converted into a matrix of which dimension depends on the list
class MyApp(App):
def build(self):
return Screen()
if __name__ == '__main__':
MyApp().run()
This is the error I keep getting:
if ans1[i] == "-":
IndexError: list index out of range
Hurray! I have seen the magic. The secret was string.split()
This is the modified code. Works perfectly for both positive and
negative entries.
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from sympy import *
class Screen(GridLayout):
def __init__(self, **kwargs):
super(Screen, self).__init__(**kwargs)
self.input = TextInput(multiline=False, size_hint = (None, None))
self.add_widget(self.input)
self.input.bind(on_text_validate=self.print_input)
def print_input(self, value):
"""function to convert Textinput text into a matrix. works
for only square matrices"""
m = 3; n = 3 # rows and columns
list = [float(el) for el in value.text.split(',')] # entries must be separated with ','
mat = Matrix(list)
mat1 = mat.reshape(3, 3) # can be made general
pprint(mat1)
class MyApp(App):
def build(self):
return Screen()
if __name__ == '__main__':
MyApp().run()
With my code below, you can add/select the whole row and when edit button pressed, that print the current row on the screen.
Furthermore, previously all the rows are disabled! Instead of print the current row, I'll be able to edit the row when selected.
# -*- coding: utf-8 -*-
import sqlite3 as sql
from PyQt4 import QtCore, QtGui
import sys, os
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.tabs = QtGui.QTabWidget(self)
self.general = QtGui.QWidget()
self.tabs.addTab(self.general, "General")
cWidget = QtGui.QWidget(self)
self.setCentralWidget(cWidget)
self.general_table = QtGui.QTableWidget(self.general)
self.setHeader()
add_record = QtGui.QPushButton("Add Record")
edit = QtGui.QPushButton("Edit")
layout = QtGui.QVBoxLayout(cWidget)
layout.addWidget(self.tabs)
layout.addWidget(add_record)
layout.addWidget(edit)
self.connect(add_record, QtCore.SIGNAL('clicked()'), self.addRecord)
self.connect(edit, QtCore.SIGNAL('clicked()'), self.edit)
self.general_table.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
def addRecord(self):
rcount_general = self.general_table.rowCount()
self.general_table.insertRow(rcount_general)
def edit(self):
indexes = self.general_table.selectionModel().selectedRows()
for index in sorted(indexes):
print("Row %d is selected" % index.row())
def setHeader(self):
# General
self.general_table.setRowCount(1)
self.general_table.setColumnCount(3)
self.general_table.setHorizontalHeaderLabels(["A1", "A2", "A3"])
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
You could call the setFlags function on the item.
For editable:
item = QtGui.QTableWidgetItem()
item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled )
self.your_table.setItem(row, column, item)
For not editable:
item = QtGui.QTableWidgetItem()
item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable |
QtCore.Qt.ItemIsEnabled)
self.your_table.setItem(row, column, item)