我创建了一个包含三列的表格小部件。桌子在qwizard里面。它通过读取文件并将该文件的行放在其第一列中来填充。它看起来像下面的图片。基本上我希望程序以这种方式运行:
如果同时选中 remove half of item
和 remove all of item
,请取消选中remove half of item
,只留下remove all of item
行。然后将该行添加到文件中。
按OK按钮
否则,只检查remove half of item
或remove all of item
。将行添加到文件中。
按OK按钮
问题是它最终会得到我想要的输出,但只有当我多次按Ok时
处理行为的函数是def print_checked(self):
和def setChoice(self, item):
from PyQt4 import QtCore, QtGui
import sys
class TablePage(QtGui.QWizardPage):
def __init__( self, parent=None):
super(TablePage, self).__init__(parent)
self.isWrittenTo = False
self.table = QtGui.QTableWidget()
self.table.setGeometry(200, 200, 200, 200)
self.configureTable(self.table)
self.table.verticalHeader().hide()
self.buttonBox = QtGui.QDialogButtonBox(self)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel | QtGui.QDialogButtonBox.Ok)
self.horizontalLayout = QtGui.QHBoxLayout()
self.verticalLayout = QtGui.QVBoxLayout(self)
self.horizontalLayout.addWidget(self.table)
self.verticalLayout.addLayout(self.horizontalLayout)
self.verticalLayout.addWidget(self.buttonBox)
self.buttonBox.accepted.connect(self.print_checked)
self.buttonBox.rejected.connect(self.close)
self.choice = []
self.table.itemChanged.connect(self.setChoice)
def configureTable(self, table):
rowf = 0
rowx = 0
table.setColumnCount(3)
table.setHorizontalHeaderItem(0, QtGui.QTableWidgetItem("Whole items"))
table.setHorizontalHeaderItem(1, QtGui.QTableWidgetItem("remove half of item"))
table.setHorizontalHeaderItem(2, QtGui.QTableWidgetItem("remove all of item"))
header = table.horizontalHeader()
header.setResizeMode(0, QtGui.QHeaderView.ResizeToContents)
header.setResizeMode(1, QtGui.QHeaderView.ResizeToContents)
table.horizontalHeader().setStretchLastSection(True)
item_list = []
with open("/home/test1/items.txt") as in_file:
if in_file is not None:
xvar = in_file.readlines()
for line in xvar:
item_list.append(line)
rowf += 1
table.setRowCount(rowf)
for linex in item_list:
x = QtGui.QTableWidgetItem()
table.setItem(rowx, 0, x)
rowx += 1
x.setText(linex)
for column in range(3):
for row in range(rowf):
if column % 3:
self.item = QtGui.QTableWidgetItem(column)
self.item.setFlags(QtCore.Qt.ItemIsUserCheckable |
QtCore.Qt.ItemIsEnabled)
self.item.setCheckState(QtCore.Qt.Unchecked)
self.item.setTextAlignment(QtCore.Qt.AlignHCenter)
table.setItem(row, column, self.item)
def setChoice(self, item):
if item.checkState() == QtCore.Qt.Checked:
self.choice.append(item)
if item.checkState() == QtCore.Qt.Unchecked:
self.choice.remove(item)
def print_checked(self):
path = '/home/test1/items-to-mod.txt'
mode = 'a' if self.isWrittenTo else 'w'
user = self.table
if len(self.choice) > 0:
with open(path, mode) as f:
for item in self.choice:
delete = user.horizontalHeaderItem(item.column()).text()
if delete == "remove all of item" and user.item(item.row(), 1).checkState() == QtCore.Qt.Checked:
user.item(item.row(), 1).setCheckState(QtCore.Qt.Unchecked)
print ('%s' % user.item(item.row(), 0).text() + 'is marked for %s' % delete)
f.write('fully remove %s' % user.item(item.row(), 0).text())
elif delete == "remove half of item":
print ('%s' % user.item(item.row(), 0).text() + 'is marked for %s' % delete)
f.write('remove half of %s' % user.item(item.row(), 0).text())
elif delete == "remove all of item":
print ('%s' % user.item(item.row(), 0).text() + 'is marked for %s' % delete)
f.write('fully remove %s' % user.item(item.row(), 0).text())
else:
print('%s' % item.text())
print (item.row(), item.column())
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
wizard = QtGui.QWizard()
tablepage = TablePage()
wizard.addPage(tablepage)
wizard.button(QtGui.QWizard.NextButton).clicked.connect(tablepage.print_checked)
wizard.show()
sys.exit(app.exec_())
答案 0 :(得分:1)
在您的代码中,在取消选中时重复操作,使改进代码成为可能的输出:如果标记为第一次添加1 = 2 ** 0,如果标记为第二次添加2 = 2 ** 1,因此每行只有4个案例:[0,2 ** 0,2 ** 1,2 ** 0 + 2 ** 1] = [0,1,2,3]
改变:
def print_checked(self):
path = '/home/test1/items-to-mod.txt'
mode = 'a' if self.isWrittenTo else 'w'
user = self.table
d = dict([(x, 0) for x in range(self.table.rowCount())])
for item in self.choice:
d[item.row()] += 2 ** (item.column() - 1)
text = ""
for row, value in d.iteritems():
if value == 3: # They are both checked
print("fully remove %s" % user.item(row, 0).text())
user.item(row, 1).setCheckState(QtCore.Qt.Unchecked)
text += 'fully remove %s' % user.item(row, 0).text()
elif value == 2: # only second is checked
print('fully remove of %s' % user.item(row, 0).text())
text += 'fully remove %s' % user.item(row, 0).text()
elif value == 1: # only first is checked
print("remove half of %s" % user.item(row, 0).text())
text += 'remove half of %s' % user.item(row, 0).text()
with open(path, mode) as f:
f.write(text)
输出:
单击确定后:
fully remove a
fully remove of b
remove half of c
答案 1 :(得分:1)
我要改变的第一件事是setChoice:它应该更清楚地反映状态,通过存储至少有一个支票的每一行,状态:half(1),full(2)或两者(1 + 2 = 3):
def setChoice(self, item):
row = item.row()
if item.checkState() == QtCore.Qt.Checked:
self.choice.setdefault(row, 0)
self.choice[row] += item.column()
print(item, row, self.choice[row])
else:
assert item.checkState() == QtCore.Qt.Unchecked
self.choice[row] -= item.column()
print(item, row, self.choice[row])
# if checked state is now 0, remove it (could instead leave it
# but filter on checked==0 in print_checked):
if self.choice[row] == 0:
del self.choice[row]
这需要对print_checked
进行一些更改。有很多方法可以做到这一点,但我喜欢让代码反映意图:你需要“修复”或“调整”一行有2个复选标记的行;然后像往常一样处理。我还简化了一些格式字符串。结果是:
with open(path, mode) as f:
for item_row, checked in self.choice.items():
item_text = user.item(item_row, 0).text()
if checked == 3: # delete == "remove all of item" and user.item(item.row(), 1).checkState() == QtCore.Qt.Checked:
# need to fix it!
item_half = user.item(item_row, 1)
item_half.setCheckState(QtCore.Qt.Unchecked)
checked = 2
f.write('fixing %s\n' % item_text)
delete = user.horizontalHeaderItem(checked).text()
if checked == 1: # delete == "remove half of item":
f.write ('%s is marked for %s\n' % (item_text, delete))
f.write('remove half of %s\n' % item_text)
elif checked == 2: # delete == "remove all of item":
f.write ('%s is marked for %s\n' % (item_text, delete))
f.write('fully remove %s\n' % item_text)
else:
f.write('%s\n' % item_text)
f.write(item_row, checked)