How do I get the Checked items in a Qlistview?

2019-01-29 06:33发布

问题:

I've populated a Qlistview from a file, each line in the file becomes a row. Now, I'd like to have another function that creates another file from all the checked items in the qlistview. My listview goes as follows.

 def show_list(self, file_in):
        QListView.__init__(self)
        QListView.setWindowFlags(self, QtCore.Qt.WindowStaysOnTopHint)
        QListView.setWindowTitle(self, "ListView")
        self.buttonBox = QtGui.QDialogButtonBox(self)
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
        self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
        list_view = QListView(self)
        list_view.setMinimumSize(350,350)

        self.verticalLayout = QtGui.QVBoxLayout(self)
        self.verticalLayout.addWidget(list_view)
        self.verticalLayout.addWidget(self.buttonBox)
        self.buttonBox.accepted.connect(self.close)
        self.buttonBox.rejected.connect(self.close)
        model = QStandardItemModel(list_view)
        with open(file_in) as f:
            if f is not None:
                item = f.readlines()
            for line in item:
                item = QStandardItem(line)
                item.setCheckable(True)
                item.setCheckState(QtCore.Qt.Unchecked)
                model.appendRow(item)

        list_view.setModel(model)
        list_view.show()

This is my attempt so far to get my desired result. Unfortunately, It doesn't print my checked items. When called like this self.print_checked_items(model) I'm wondering what could be wrong?

def print_checked_items(self, model):
    path = "/home/test1/checked.txt"
    for index in range(model.rowCount()):
        item = model.item(index)
        if item.isCheckable() and item.checkState() == QtCore.Qt.Checked:
            with open(path, "a") as f_out:
                print ('%s\n' % item.text())
                f_out.write('%s\n' % item.text()

回答1:

import sys
from PyQt4 import QtGui
from PyQt4 import QtCore


class AppRemovalPage(QtGui.QWizardPage):
    def __init__(self, parent=None):
        super(AppRemovalPage, self).__init__(parent=parent)
        self.setTitle('Apps to Remove')
        self.setSubTitle('Listview')
        self.list_view = QtGui.QListView(self)
        self.list_view.setMinimumSize(465, 200)
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.list_view)
        self.setLayout(layout)
        self.items = []
        self.isWritten = False

        loo = "/home/test1/file.txt"

        self.model = QtGui.QStandardItemModel(self.list_view)

        self.model.itemChanged.connect(self.setItems)

        file = QtCore.QFile(loo)
        if file.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text):
            while not file.atEnd():
                line = bytearray(file.readLine()).decode().strip()
                item = QtGui.QStandardItem(line)
                item.setCheckable(True)
                item.setCheckState(QtCore.Qt.Unchecked)
                self.model.appendRow(item)
        self.list_view.setModel(self.model)
        self.list_view.show()

    def setItems(self, item):
        if item.checkState() == QtCore.Qt.Checked:
            self.items.append(item)
        if item.checkState() == QtCore.Qt.Unchecked:
            self.items.remove(item)

    def print_checked_items(self):
        path = "/home/test1/checked.txt"
        mode = QtCore.QFile.Append if self.isWritten else QtCore.QFile.WriteOnly
        if len(self.items) > 0:
            file = QtCore.QFile(path)
            if file.open(mode):
                for item in self.items:
                    print('%s' % item.text())
                    file.write(item.text() + "\n")
            file.close()
        print("print checked items executed")

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    wizard = QtGui.QWizard()

    appremoval = AppRemovalPage()
    wizard.addPage(appremoval)
    wizard.addPage(QtGui.QWizardPage())

    wizard.button(QtGui.QWizard.NextButton).clicked.connect(appremoval.print_checked_items)
    wizard.show()
    sys.exit(app.exec_())

Output:

a
d
e
print checked items executed


回答2:

When I run this in Python 3.5 and PyQt5, it works fine, it prints the correct modes and checkmarked items. I removed the file reading/writing lines for testing. For PyQt4 and Python 2.7, you should just have to fix a couple of imports and the print statement. Run it, checkmark a couple items, and after 5 seconds what do you see in console?

from PyQt5 import QtCore

from PyQt5 import QtGui
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication, QWizardPage, QListView


class AppRemovalPage(QWizardPage):
    def __init__( self, parent ):
        super(AppRemovalPage, self).__init__(parent)
        self.setTitle('Apps to Remove')
        self.setSubTitle('Listview')
        self.list_view = QListView(self)
        self.list_view.setMinimumSize(465, 200)
        self.isWritten = False
        loo = "/home/test1/file.txt"

        self.model = QtGui.QStandardItemModel(self.list_view)
        for line in ('a', 'b', 'c', 'd', 'e'):
            self.item = QtGui.QStandardItem(line)
            self.item.setCheckable(True)
            self.item.setCheckState(QtCore.Qt.Unchecked)
            self.model.appendRow(self.item)

        self.list_view.setModel(self.model)
        self.list_view.show()


    def print_checked_items(self):
        for index in range(self.model.rowCount()):
            item = self.model.item(index)
            if item.checkState() == QtCore.Qt.Checked:
                if self.isWritten:
                    mode = "a"
                else:
                    mode = "w"
                    self.isWritten = True
                print ('%s' % item.text())

        print("print checked items executed")


app = QApplication([])
listview = AppRemovalPage(None)
listview.show()
QTimer.singleShot(5000, listview.print_checked_items)
app.exec_()

If I checkmark a, c and d I see this:

a w
c a
d a
print checked items executed

Update to show how Python file object also works (and is in fact better code because it supports use of context management):

def print_checked_items(self):
    path = "checked.txt"
    mode = 'a' if self.isWritten else 'w'
    if len(self.items) > 0:
        with open(path, mode) as file:
            for item in self.items:
                print('%s' % item.text())
                file.write(item.text() + "\n")
        file.close()
    print("print checked items executed")

The connection can be written wizard.button(QWizard.NextButton).clicked.connect(appremoval.print_checked_items)