2013-09-25 71 views
1

我有一个简单PyQt4计划在3资料(姓名,性别&地址)每当我点击确定按钮,并保存为一个二进制文件需要(3个细节在程序的硬编码的测试目的) 。然后稍后将加载该信息并将其显示在QTableWidget中。PyQt的自定义数据结构

这是我的布局方案:

它有2个脚本:DContainer.pyData_Main.py

enter image description here

Dcontainer.py

import bisect 
from PyQt4 import QtCore 

class Person(object): 

    def __init__(self, Name = None, Gender = None , Address = None): 
     self.Name = Name 
     self.Gender = Gender 
     self.Address = Address 

class PersonContainer(object): 

    def __init__(self): 
     self.__fname = QtCore.QString("mydatabase.mqb") 
     self.__persons = [] 
     self.__personFromId = {} 

    def __iter__(self): 
     for pair in iter(self.__persons): 
      yield pair[1] 

    def __len__(self): 
     return len(self.__persons) 

    def Clear(self): 
     self.__persons = [] 
     self.__personFromId ={} 

    def add(self,person): 
     if id(person)in self.__personFromId: 
      return False 
     key = person.Name 
     bisect.insort_left(self.__persons, [key,person]) 
     self.__personFromId[id(person)] = person 
     return True 

    def save(self): 
     fh = QtCore.QFile(self.__fname) 
     if not fh.open(QtCore.QIODevice.WriteOnly): 
      raise IOError , unicode(fh.errorString()) 
     stream = QtCore.QDataStream(fh) 
     for key, person in self.__persons: 
      stream << person.Name << person.Gender << person.Address 

    def load(self): 
     fh = QtCore.QFile(self.__fname) 
     if not fh.open(QtCore.QIODevice.ReadOnly): 
      raise IOError , unicode(fh.errorString()) 
     stream = QtCore.QDataStream(fh) 
     while not stream.atEnd(): 
      Name = QtCore.QString() 
      Gender = QtCore.QString() 
      Address = QtCore.QString() 
      stream >> Name >> Gender >> Address 
     self.add(Person(Name,Gender,Address)) 

Data_Main.py

import sys 
from PyQt4 import QtCore,QtGui 
import DContainer 

class MainDialog(QtGui.QDialog): 

    def __init__(self, parent = None): 
     super(MainDialog,self).__init__(parent) 
     self.InitGui() 
     self.persons = DContainer.PersonContainer() 
     self.Update() 


    def InitGui(self): 
     buttonbox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok|QtGui.QDialogButtonBox.Cancel) 
     self.table = QtGui.QTableWidget() 
     layout = QtGui.QVBoxLayout() 
     layout.addWidget(self.table) 
     layout.addWidget(buttonbox) 
     self.setLayout(layout) 
     self.connect(buttonbox.button(buttonbox.Ok), QtCore.SIGNAL("clicked()"),self.OK) 

    def OK(self): 
     NewPerson = DContainer.Person(QtCore.QString('This is another test'),QtCore.QString('Male'),QtCore.QString('Strand Road')) 
     self.persons.add(NewPerson) 
     self.persons.save() 
     self.Update() 

    def Update(self): 
     self.table.clear() 
     self.persons.load() 
     self.table.setRowCount(len(self.persons)) 
     self.table.setColumnCount(3) 

     for row,person in enumerate(self.persons): 
      item = QtGui.QTableWidgetItem(person.Name) 
      self.table.setItem(row,0,item) 


def Main(): 
    app = QtGui.QApplication(sys.argv) 
    dialog = MainDialog() 
    dialog.show() 
    app.exec_() 

if __name__ == "__main__": 
    Main() 

我的问题是每当我OK按钮点击后,它创建多个表项

第二次点击

after 2nd click

它不应该创建后多个表格条目,因为我已经使用

if id(person)in self.__personFromId: 
      return False 

在Dcontainer.py中的Add方法中。

合理的,它应该只显示表中的一个项目,除非我给新的人员对象使用不同的名称。

是什么导致了这个问题?

+0

的对象可能具有唯一的ID,因为它们实际上不是同一个对象。在评论中对垃圾格式的理解:>>> a = {'Hi':1} >>> b = {'Hi':1} >>> print id(a),id(b) 249688688 249688832 –

回答

1

PersonContainer.add方法被调用两次当您单击确定按钮:

    MainDialog.OK方法从 MainDialog.Update方法
  1. 间接
  2. 直接与self.persons.load()

您可以添加一个可选参数Update方法来触发load的呼叫:

def Update(self, load=False): 
    self.table.clear() 
    if load: 
     self.persons.load() 

而且调用此方法load设置为True__init__方法:

def __init__(self, parent = None): 
    super(MainDialog,self).__init__(parent) 
    self.InitGui() 
    self.persons = DContainer.PersonContainer() 
    self.Update(True) 

顺便说一句,老式信号/槽不再与PyQt5支持。这是如何在新的风格写:

buttonbox.accepted.connect(self.OK) 
    buttonbox.rejected.connect(self.reject)