Συζήτηση
Γεια χαρά, Επισκέπτης
Όνομα χρήστη: Κωδικός: Να με θυμάσαι

ΘΕΜΑ: Βοήθεια με QPushButton σε for loop

Βοήθεια με QPushButton σε for loop 7 Χρόνια 7 Μήνες πριν #3842

  • Αποστόλης
  • Το Άβαταρ του/της Αποστόλης
  • Αποσυνδεμένος
  • pytho_
  • Δημοσιεύσεις: 148
  • Ληφθείσες Ευχαριστίες 24
Καλημέρα σε όλους.
Έχω ένα πρόβλημα με ένα script σε PyQt.

Το script αφού συνδεθεί σε μια βάση SQLite3 φέρνει τις εγγραφές από κάποιους πίνακες.
Μετά με ένα for loop δημιουργείται ένα QPUshButton για κάθε μια εγγραφή, το οποίο θα πρέπει να στέλνει σε άλλη function το id της εκάστοτε εγγραφής:
rows = model.rowCount()
for row in xrange(rows):
	unId = model.record(row).value("id").toInt()
	self.unId = unId[0]
	deleteButton = QtGui.QPushButton()
	tableView.setIndexWidget(model.index(row,5), deleteButton)
	deleteButton.setText(language["bulkRemove"])
	deleteButton.setGeometry(0, 0, 120, 30)
	deleteButton.show()
	deleteButton.clicked.connect(self.deleteRelatedRowsNew)
Όπου:
tableView = QTableView
και
model = QtSql.QSqlRelationalTableModel()

Το πρόβλημα είναι οτι το deleteButton φέρνει πάντα το id της τελευταίας εγγραφής κι όχι του row στο οποίο έχει δημιουργηθεί το button.
Αν κάνω print το id (self.unId) τότε όλα τυπώνονται κανονικά.
Με το button όχι.

Έχει κανείς καμμιά ιδέα για το τι μπορεί να φταίει;
Τελευταία διόρθωση: 7 Χρόνια 7 Μήνες πριν από Αποστόλης.
Πρέπει να είστε εγγεγραμμένο μέλος του Φόρουμ για να κάνετε μια δημοσίευση.

Βοήθεια με QPushButton σε for loop 7 Χρόνια 7 Μήνες πριν #3847

  • pmav99
  • Το Άβαταρ του/της pmav99
  • Αποσυνδεμένος
  • Author
  • Δημοσιεύσεις: 684
  • Ληφθείσες Ευχαριστίες 111
Εννοείς ότι κάνεις κλικ και ότι σβήνει την τελευταία γραμμή;

Για βάλε το περιεχόμενο της self.deleteRelatedRowsNew
Πρέπει να είστε εγγεγραμμένο μέλος του Φόρουμ για να κάνετε μια δημοσίευση.

Βοήθεια με QPushButton σε for loop 7 Χρόνια 7 Μήνες πριν #3848

  • Αποστόλης
  • Το Άβαταρ του/της Αποστόλης
  • Αποσυνδεμένος
  • pytho_
  • Δημοσιεύσεις: 148
  • Ληφθείσες Ευχαριστίες 24
Έχω απενεργοποιήσει το delete.
Δεν είναι τίποτα σπουδαίο. Ένα QMessageBox φέρνει όπου ανάλογα την απάντηση καλεί άλλη function.
Τώρα ένα απλό print κάνω για να δω οτι φέρνει το σωστό id.

Πάντως ναι, αυτό είναι το πρόβλημα. Φέρνει πάντα το id του τελευταίου row.

Έχω δοκιμάσει διάφορους τρόπους.
Είτε με:
deleteButton.clicked.connect(self.deleteRelatedRowsNew)
και:
deleteRelatedRowsNew(self):
print("Row Id: ", self.unId)

είτε με:
deleteButton.connect(deleteButton, QtCore.SIGNAL("clicked(QModelIndex)"), deleteRelatedRows

και στην function:
deleteRelatedRowsNew(self, modelId):
self.unIdToBeDeleted1 = modelId.data(QtCore.Qt.DisplayRole).toString()
print("Test 1 " + self.unIdToBeDeleted1)

Εχω δοκιμάσει διάφορες παραλλαγές αυτών των δύο αλλά τίποτα.
Βασικά το πρόβλημα είναι στο deleteButton.
Αν στείλω το id με άλλο τρόπο (π.χ. με QtCore.QObject κάνοντας κλίκ επάνω στο κελί του id) δουλεύει μια χαρά.
Αλλά το button έχει attributes που δεν τα γνωρίζω όλα και δεν ξέρω πως να του περάσω το αντίστοιχο clicked(QModelIndex).

Υ.Γ. μήν δίνεις σημασία στα self, function values κ.λ.π.
Ο κώδικας δουλεύει.
Τελευταία διόρθωση: 7 Χρόνια 7 Μήνες πριν από Αποστόλης.
Πρέπει να είστε εγγεγραμμένο μέλος του Φόρουμ για να κάνετε μια δημοσίευση.

Βοήθεια με QPushButton σε for loop 7 Χρόνια 7 Μήνες πριν #3849

  • pmav99
  • Το Άβαταρ του/της pmav99
  • Αποσυνδεμένος
  • Author
  • Δημοσιεύσεις: 684
  • Ληφθείσες Ευχαριστίες 111
Χωρίς να δούμε ένα minimum working example είναι δύσκολο να καταλάβουμε τι λες...

Όταν κάνεις print(self.unId) λογικό είναι πάντως που σου τυπώνει το τελευταίο... Δες αυτό:
class Foo(object):
    def __init__(self):
        for row in range(11):
            self.id = row
 
    def random_callback(self):
        print(self.id)
 
f = Foo()
f.random_callback()  # print(10)
Πρέπει να είστε εγγεγραμμένο μέλος του Φόρουμ για να κάνετε μια δημοσίευση.

Βοήθεια με QPushButton σε for loop 7 Χρόνια 7 Μήνες πριν #3850

  • pmav99
  • Το Άβαταρ του/της pmav99
  • Αποσυνδεμένος
  • Author
  • Δημοσιεύσεις: 684
  • Ληφθείσες Ευχαριστίες 111
Δοκίμασε πάντως και κάτι τέτοιο:
	deleteButton.clicked.connect(lambda: self.deleteRelatedRowsNew(unId[0]))

ΥΓ. Έχω πολύ καιρό να ασχοληθώ με Qt και μπορεί να μη θυμάμαι καλά τα quirks των events της βέβαια, οπότε ίσως και να μην παίζει...
Τελευταία διόρθωση: 7 Χρόνια 7 Μήνες πριν από pmav99.
Πρέπει να είστε εγγεγραμμένο μέλος του Φόρουμ για να κάνετε μια δημοσίευση.

Βοήθεια με QPushButton σε for loop 7 Χρόνια 7 Μήνες πριν #3851

  • Αποστόλης
  • Το Άβαταρ του/της Αποστόλης
  • Αποσυνδεμένος
  • pytho_
  • Δημοσιεύσεις: 148
  • Ληφθείσες Ευχαριστίες 24
- Όταν κάνω ένα απλό print, μια χαρά δουλεύει.
Όταν πάω να κάνω print το value του button είναι που δημιουργεί το πρόβλημα.

- Το είχα δοκιμάσει. Και μου έβγαζε error.
Θα το ξαναδώ όμως.
Τελευταία διόρθωση: 7 Χρόνια 7 Μήνες πριν από Αποστόλης.
Πρέπει να είστε εγγεγραμμένο μέλος του Φόρουμ για να κάνετε μια δημοσίευση.

Βοήθεια με QPushButton σε for loop 7 Χρόνια 7 Μήνες πριν #3852

  • pmav99
  • Το Άβαταρ του/της pmav99
  • Αποσυνδεμένος
  • Author
  • Δημοσιεύσεις: 684
  • Ληφθείσες Ευχαριστίες 111
Ανέβασε ένα παράδειγμα που να δείχνει την συμπεριφορά που βλέπεις. Δεν θα βγει άκρη αλλιώς.
Πρέπει να είστε εγγεγραμμένο μέλος του Φόρουμ για να κάνετε μια δημοσίευση.

Βοήθεια με QPushButton σε for loop 7 Χρόνια 7 Μήνες πριν #3854

  • Αποστόλης
  • Το Άβαταρ του/της Αποστόλης
  • Αποσυνδεμένος
  • pytho_
  • Δημοσιεύσεις: 148
  • Ληφθείσες Ευχαριστίες 24
Βασικά το πρόβλημα το έλυσα με άλλο τρόπο.
Εν πάσει περιπτώσει.

Κατ' αρχάς τα errors για τον τρόπο που μου έγραψες:

To
deleteButton.clicked.connect(lambda: self.deleteRelatedRowsNew(self.unId[0]))
δίνει το λάθος
TypeError: 'int' object has no attribute '__getitem__'

To
deleteButton.clicked.connect(lambda: self.deleteRelatedRowsNew(self.unId))
δίνει το αρχικό λάθος: Το id της τελευταίας εγραφής.
Το ίδιο και οποιαδήποτε άλλη παραλαγή.

Δυστυχώς είχα ψάξει αυτές τις παραλλαγές, απλώς μπλέκεις σε έναν κυκεώνα native errors της PyQt ή απλά επαναλαμβάνεις το αρχικό λάθος.



Πάμε τώρα στον πραγματικό κώδικα.
Το παράδειγμά σου είναι πολύ απλό και δεν μπορεί να τρέξει έτσι το script.
Στην πραγματικότητα τρέχει ως εξής:

Το main αρχείο έχει ένα κουμπί για διαγραφή εγγραφών
self.BulkRemoveButton.clicked.connect(self.deleteRecord)
 
def deleteRecord(self):
	self.clearForms()
	DbConnect.printRecordsToDelete(self)
το οποίο καλεί ένα άλλο αρχείο:
def printRecordsToDelete(self):
	connectToDb(self)
	self.db.open()
	model = QtSql.QSqlRelationalTableModel()
 
	try:
		model.setEditStrategy(model.OnManualSubmit)
		model.setTable("location")
		model.setJoinMode(QtSql.QSqlRelationalTableModel.InnerJoin)
		model.setRelation(1, QtSql.QSqlRelation("persons", "id", "lastname, firstname") )
		model.setSort(2, QtCore.Qt.AscendingOrder)
		language = self.dictLang
		model.select()
		model.insertColumn(5)
		model.setHeaderData(0, QtCore.Qt.Horizontal, language["idLabel"] )
		model.setHeaderData(1, QtCore.Qt.Horizontal, language["lastNameLabel"] )
		model.setHeaderData(2, QtCore.Qt.Horizontal, language["firstNameLabel"] )
		model.setHeaderData(3, QtCore.Qt.Horizontal, language["addressLabel"] )
		model.setHeaderData(4, QtCore.Qt.Horizontal, language["cityLabel"] )
		model.setHeaderData(5, QtCore.Qt.Horizontal, language["delete"] )
 
		tableView = self.DeleteTableView
		tableView.setGeometry(20, 70, 640, 400)
		tableView.setStyleSheet(''' QTableView {background-color:transparent; border:0px solid #000000; color:#000000; text-align:center; font-weight:none; font-size:11pt;}''')
		tableView.setModel(model)
		rows = model.rowCount()
		for row in xrange(rows):
			unId = model.record(row).value("id").toInt()
			unId = unId[0]
			self.unId = unId
			deleteButton = QtGui.QPushButton()
			tableView.setIndexWidget(model.index(row,5), deleteButton)
			deleteButton.setText(language["bulkRemove"])
			deleteButton.setGeometry(0, 0, 120, 30)
			deleteButton.show()
			deleteButton.clicked.connect(self.deleteRelatedRowsNew)
		tableView.resizeColumnsToContents()
		tableView.show()
 
	except Exception as exc:
		printException(self, exc)
	return True

όταν ο χρήστης πατήσει το αντίστοιχο deleteButton, η function θα πρέπει να στέλνει το row id σε άλλη function:
def deleteRelatedRowsNew(self):
	sender = self.sender()
	print("Row Id: ", self.unId)
Εδώ είναι που αντιμετώπιζα το πρόβλημα με το row id της τελευταίας εγγραφής.
Τελευταία διόρθωση: 7 Χρόνια 7 Μήνες πριν από Αποστόλης.
Πρέπει να είστε εγγεγραμμένο μέλος του Φόρουμ για να κάνετε μια δημοσίευση.

Βοήθεια με QPushButton σε for loop 7 Χρόνια 7 Μήνες πριν #3855

  • Αποστόλης
  • Το Άβαταρ του/της Αποστόλης
  • Αποσυνδεμένος
  • pytho_
  • Δημοσιεύσεις: 148
  • Ληφθείσες Ευχαριστίες 24
Παραθέτω τον κώδικα με τη λύση που βρήκα, μήπως τυχόν χρειαστεί σε κάποιον κάποια άλλη φορά.
Η εφαρμογή αφορά σε "Τηλεφωνική Ατζέντα" και δίνει στον χρήστη διάφορες επιλογές στο "main" αρχείο (Add new, Search, Delete κ.λ.π.).

Στο "main" αρχείο λοιπόν υπάρχει το button
self.BulkRemoveButton.clicked.connect(self.deleteRecord)
που καλεί στο ίδιο αρχείο την function deleteRecord:
def deleteRecord(self):
	self.clearForms()
	DbConnect.printRecordsToDelete(self)

Αυτή κάνει import ένα άλλο αρχείο και τρέχει την function printRecordsToDelete:
#get all records and provide
#a way to delete them
def printRecordsToDelete(self):
 
	connectToDb(self)
	self.db.open()
 
	try:
		model = QtSql.QSqlRelationalTableModel()
		model.setEditStrategy(model.OnManualSubmit)
		model.setTable("location")
		model.setJoinMode(QtSql.QSqlRelationalTableModel.InnerJoin)
		model.setRelation(1, QtSql.QSqlRelation("persons", "id", "lastname, firstname") )
		model.setSort(2, QtCore.Qt.AscendingOrder)
		language = self.dictLang
		model.select()
		model.setHeaderData(0, QtCore.Qt.Horizontal, language["idLabel"] )
		model.setHeaderData(1, QtCore.Qt.Horizontal, language["lastNameLabel"] )
		model.setHeaderData(2, QtCore.Qt.Horizontal, language["firstNameLabel"] )
		model.setHeaderData(3, QtCore.Qt.Horizontal, language["addressLabel"] )
		model.setHeaderData(4, QtCore.Qt.Horizontal, language["cityLabel"] )
		self.DeleteTableView.setGeometry(20, 70, 640, 400)
		self.DeleteTableView.setStyleSheet(''' QTableView {background-color:transparent; border:0px solid #000000; color:#000000; text-align:center; font-weight:none; font-size:11pt;}''')
		self.DeleteTableView.setModel(model)
		rows = model.rowCount()
		for row in xrange(rows):
			deleteLabel = QtGui.QLabel()
			deleteLabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
			deleteLabel.setStyleSheet("QLabel {border:0px solid #000000; border-radius: 2px; background-color:gray; padding: 0px 5px 0 5px; text-align:center; font-weight:none; font-size:11pt;}")
			self.DeleteTableView.setIndexWidget(model.index(row,0), deleteLabel)
			deleteLabel.setText(language["deleteRecord"])
			deleteLabel.show()
			self.unForeignKey = QtCore.QObject
			self.DeleteTableView.resizeColumnsToContents()
		self.DeleteTableView.connect(self.DeleteTableView, QtCore.SIGNAL("clicked(QModelIndex)"), self.cellClicked)#pass row id to delete function
		self.DeleteTableView.show()
	except Exception as exc:
		printException(self, exc)
 
	self.db.close()
	self.db.removeDatabase("phonebook.db")
	return True

Το self.DeleteTableView.connect(self.DeleteTableView, QtCore.SIGNAL("clicked(QModelIndex)"), self.cellClicked) επιστρέφει στο "main" αρχείο το row id της εγγραφής που θέλει ο χρήστης να διαγράψει:
#get record id of clicked cell
def cellClicked(self, modelId):
	self.unIdToBeDeleted = modelId.data(QtCore.Qt.DisplayRole).toInt()
	self.unIdToBeDeleted = self.unIdToBeDeleted[0]
	if self.unIdToBeDeleted != 0:
		#print warning message pop up
		language = self.dictLang
		warnMessage = QtGui.QMessageBox()
		warnMessage.addButton(QtGui.QPushButton(language["delete"]), QtGui.QMessageBox.YesRole)
		warnMessage.addButton(QtGui.QPushButton(language["cancel"]), QtGui.QMessageBox.RejectRole)
		warnMessage.addButton(QtGui.QPushButton(language["edit"]), QtGui.QMessageBox.NoRole)
		msg = warnMessage.exec_()
		if msg == 2:
			DbConnect.editRelatedRows(self)
		elif msg == 1:
			pass
		elif msg == 0:
			DbConnect.deleteRelatedRows(self)
		else:
			pass
	else:
		return False
κι απο κει και πέρα, ανάλογα με το τι θα επιλέξει ο χρήστης, το καθένα παίρνει το δρόμο του...

Υπάρχει ένα συνεχές "πέρα-δώθε" μεταξύ του main και του άλλου αρχείου το οποίο πιθανώς να μπορεί να αποφευχθεί αλλά προς το παρόν δεν έχω τον χρόνο να μπλέξω με προβλήματα μεταβλητών που πρέπει ή δεν πρέπει να είναι self, globals,locals και δεν ξέρω κι εγώ τι άλλο...
Επίσης, υπάρχουν κι άλλα λειτυργικά θέματα.
Όπως οτι οι διάφορες φόρμες πρέπει να "καθαρίζονται" ώστε να μην εμφανίζονται στην οθόνη ασυνάρτητα πεδία (που έχουν ξεμείνει από το Search για παράδειγμα).
Κι αυτό είναι πιο εύκολο να γίνεται από το "main" αρχείο, παρά να καλούν όλα τα αρχεία όλα τα άλλα για ψύλου πήδημα
Οπότε μένει ως έχει μέχρι να βρεθεί χρόνος.

Όποιος έχει κάποια ιδέα για αλλαγή/βελτιστοποίση είναι ευπρόσδεκτος να την καταθέσει.
Τελευταία διόρθωση: 7 Χρόνια 7 Μήνες πριν από Αποστόλης.
Πρέπει να είστε εγγεγραμμένο μέλος του Φόρουμ για να κάνετε μια δημοσίευση.
Συντονιστές: pmav99
Χρόνος δημιουργίας σελίδας: 0.367 δευτερόλεπτα

Μοιράσου το!

Powered by CoalaWeb

Λίστα Ταχυδρομείου