PyQT : How to activate a command link button when at least one element of treeview is checked ?
-
Hello,
I want to activate command link button if at least one element is checked in a treeview.I tried this method but it is not working well :
def activate_launch_button(self): model = self.scenarios.model() checked_indexes = model.match(model.index(0, 0), QtCore.Qt.CheckStateRole,QtCore.Qt.Checked, -1,QtCore.Qt.MatchExactly | QtCore.Qt.MatchRecursive) print checked_indexes if checked_indexes != []: self.launch_btn.setEnabled(True)
The problem with this method is the button is activated only after closing the window. I don't understand why. For caling this method I put it in two methods :
def show(self): self.project.load() if self.project.tranus_project: self.tranus_folder.setText(self.project.tranus_project.path) self.activate_launch_button() self.launch_options_TRANUS() super(OptionsTRANUSDialog, self).show()
def select_tranus_folder(self): folder = QtGui.QFileDialog.getExistingDirectory(self, "Select directory") if folder: self.tranus_folder.setText(folder) if not self.project.load_tranus_folder(folder): self.tranus_folder.setText('') self.reload_scenarios() self.activate_launch_button()
I really want that the command link button should be activated when at least one element of treeview is checked and to be inactive if there is no element checked.
Thanks.
-
@EJWA Connect a slot to http://doc.qt.io/qt-5/qabstractitemview.html#activated and call your function there
-
I'm awful at Python so I'll just describe what I'd do.
- add an integer private variable to the class that counts the items checked and initialise to 0 (
int countCheck=0;
). - define a role that will save previous check information (probably something like Qt::UserRole + Qt::CheckStateRole)
- connect a slot to the dataChanged signal of the model
- in the slot put something like (sorry if it's C++)
void dataChangedSlot(const QModelIndex& index){ if(index.data(Qt::CheckStateRole).toInt() != index.data(Qt::UserRole + Qt::CheckStateRole).toInt()){ if(index.data(Qt::CheckStateRole).toInt()!=Qt::Unchecked){ ++countCheck; model->setData(index,index.data(Qt::CheckStateRole),Qt::UserRole + Qt::CheckStateRole); } else{ --countCheck; model->setData(index,QVariant(),Qt::UserRole + Qt::CheckStateRole); } launch_btn->setEnabled(countCheck>0); } }
- add an integer private variable to the class that counts the items checked and initialise to 0 (
-
Finally, I found a partial solution to my problem, I used the signal itemChanged http://pyqt.sourceforge.net/Docs/PyQt4/qstandarditemmodel.html#itemChanged
def activate_launch_button(self): model = self.scenarios.model() model.itemChanged.connect(self.check_configure)
def check_configure(self): self.launch_btn.setEnabled(True)
It activates the button when there is one element is checked however when I uncheck all, the button doesn't become inactive. How can I solve this issue ?
-
Hello,
Sorry, but I dont' understand really C++. If I understand, I must redefine the method setData ??
I will try to understand.
-
Final solution, it works very well. Thanks to @SGaist and @VRonin :
def activate_launch_button(self): model = self.scenarios.model() model.itemChanged.connect(self.check_configure) def check_configure(self,item): model = self.scenarios.model() index = model.indexFromItem(item) if index.data(QtCore.Qt.CheckStateRole) != index.data(QtCore.Qt.UserRole + QtCore.Qt.CheckStateRole): if index.data(QtCore.Qt.CheckStateRole)!= QtCore.Qt.Unchecked : self.count_check+=1 model.setData(index,index.data(QtCore.Qt.CheckStateRole),QtCore.Qt.UserRole + QtCore.Qt.CheckStateRole) else : self.count_check-=1 model.setData(index,index.data(QtCore.Qt.CheckStateRole),QtCore.Qt.UserRole + QtCore.Qt.CheckStateRole) print self.count_check self.launch_btn.setEnabled(self.count_check>0)