2015-05-22 2 views
-1

У меня есть функция, которая обновляет записи в списке, удаляя и повторно вставляя их с обновленным счетчиком, однако возникает сложность при попытке сохранить выделенный элемент, поскольку он был удален ничего не выделять.Сохранение выбранного элемента списка через повторную запись

Мой вопрос: как я могу заставить программу запомнить то, что было выделено?

Код:

#!/usr/bin/python 

from time   import clock, sleep 
from os    import system 
from collections  import defaultdict 
from subprocess  import PIPE, Popen 
from threading  import Thread, Lock 

import Tkinter as tk 
import Queue 
import signal 
import os, sys 

# ------------------------------------------------------------------- 
#  Global Definitions 

mydict ={} # define the dictionary 
dict_lock = Lock() 
transList = [] 
running = 0 
Counter = 0 
edit_ref= 0 
RecvQueue = Queue.Queue() 
terminate = 0 
pcanbus = "/dev/pcanusb0" 

# *************************************************************** 
# 
# ************************ PCAM Msg ************************ 
# 
# *************************************************************** 
class PCANmsg(object): 

    def __init__(self): 
    self.dlc  = 0 
    self.CANtime = 0 
    self.PCANperiod = 0 
    self.COUNT  = 0 
    self.hdata0  = 0 
    self.hdata1  = 0 
    self.hdata2  = 0 
    self.hdata3  = 0 
    self.hdata4  = 0 
    self.hdata5  = 0 
    self.hdata6  = 0 
    self.hdata7  = 0 
    self.timing  = 0 


class ThreadedTask(Thread): 

    def __init__(self, queue): 
     Thread.__init__(self) 
     self.queue = queue 

    def run(self): 
     global proc 
     payload = iter(proc.stdout.readline, "") 
     for line in payload: 
      if line[0].isdigit(): 
       splitline = line.split() 
       self.dictAdd(splitline) 


    def dictAdd(self, info): 

     global mydict 

     try: 
      can_ID = info[4] 

      p = PCANmsg() 

      p.dlc  = int(info[5]) 
      p.CANtime = float(info[0]) 
      p.hdata0  = info[6] 
      p.hdata1  = info[7] 
      p.hdata2  = info[8] 
      p.hdata3  = info[9] 
      p.hdata4  = info[10] 
      p.hdata5  = info[11] 
      p.hdata6  = info[12] 
      p.hdata7  = info[13] 
      p.timing  = 1 

      if can_ID in mydict.keys(): 
       q = mydict[can_ID] 
       p.COUNT = q.COUNT + 1 
       p.PCANperiod = p.CANtime - q.CANtime 
      else: 
       p.COUNT = 1 
       p.PCANperiod = 0.0 

      mydict[can_ID] = p 

      s = '%06X : %3d %02X %02X %02X %02X %02X %02X %02X %02X\t %8.2F %8d ' %\ 
        (int(can_ID,16), 
        p.dlc, 
        int(p.hdata0, 16), 
        int(p.hdata1, 16), 
        int(p.hdata2, 16), 
        int(p.hdata3, 16), 
        int(p.hdata4, 16), 
        int(p.hdata5, 16), 
        int(p.hdata6, 16), 
        int(p.hdata7, 16), 
        p.PCANperiod, 
        p.COUNT) 

      self.queue.put(s) 
     except IndexError: 
      pass 

# *************************************************************** 
# 
# ************************ RecvTran GUI ************************* 
# 
# *************************************************************** 

class application: 

    def __init__(self,window): 

     self.window = window 
    self.window.title("PYCAN") 
     """Initialize the Application """ 

     window.grid_rowconfigure(9,weight=1) 

     self.RecvButton = tk.Button(window, 
            text = "Receive", 
            command = self.RecvBtn_Click) 
     self.RecvButton.grid(row = 9, column = 12) 

     self.TransLabel = tk.Label(window, text = "Messages Received:") 
     self.TransLabel.grid(row = 8, columnspan = 2) 

     self.RecvList = tk.Listbox(window, height = 10, width = 60, exportselection=False) 
     self.RecScrol = tk.Scrollbar(window) 
     self.RecScrol.grid(row=9, column=11, sticky=tk.NW+tk.SE) 
     self.RecvList.grid(row = 9, rowspan = 3, columnspan = 11, sticky=tk.NW+tk.SE) 
     self.RecScrol.config(command=self.RecvList.yview) 
     self.RecvList.config(yscrollcommand=self.RecScrol.set) 
     self.RecvList.bind("<Button-1>", self.KeepSelection) 

     self.QuitButton = tk.Button(window, 
            text = 'Exit', 
            command = QuitBtn_Click) 
     self.QuitButton.grid(row = 14, column = 12) 



    window.protocol("WM_DELETE_WINDOW", QuitBtn_Click) 


    def KeepSelection(self, event): 

    lb = event.widget 
    selection = lb.curselection() 
    value = lb.get(selection[0]) 
    print "%s" % value 
    selected = int(value) 
     self.lb.select_set(selected) 

    def RecvBtn_Click(self, event=None):   

     global RecvQueue, Counter 

     try: 
      info = RecvQueue.get(0) 
      info_split = info.split() 

      if self.RecvList.size() < len(mydict): 

       #for _i in mydict.keys(): 
       for _i in sorted(mydict.keys()): 
        self.RecvList.insert("end",'%06X : %3d %02X %02X %02X %02X %02X %02X %02X %02X %8.1F %8d ' %\ 
         (int(_i,16), 
         mydict[_i].dlc, 
         int(mydict[_i].hdata0, 16), 
         int(mydict[_i].hdata1, 16), 
         int(mydict[_i].hdata2, 16), 
         int(mydict[_i].hdata3, 16), 
         int(mydict[_i].hdata4, 16), 
         int(mydict[_i].hdata5, 16), 
         int(mydict[_i].hdata6, 16), 
         int(mydict[_i].hdata7, 16), 
         mydict[_i].PCANperiod, 
         mydict[_i].COUNT)) 

      else: 
       for i, listbox_entry in enumerate(self.RecvList.get(0, "end")): 
        list_split = listbox_entry.split() 
        if list_split[0] == info_split[0]: 
      pos = self.RecScrol.get() 
         self.RecvList.delete(i) 
         self.RecvList.insert(i, info) 
      self.RecvList.yview_moveto(pos[0]) 

        else: 
         continue 
        #  self.RecvList.insert("end", info) 
      self.window.after(20, self.RecvBtn_Click) 

     Counter += 1 

     if Counter > 25: 
      with RecvQueue.mutex: 
       RecvQueue.queue.clear() 
       Counter = 0 

     except Queue.Empty: 
      self.window.after(50, self.RecvBtn_Click) 


def QuitBtn_Click(event=None): 
    global terminate 
    global proc 

    terminate = 1 

    try: 
     if terminate == 1: 
      os.kill(proc.pid, 0) 
      proc.kill() 
     root.destroy()  
    except OSError, e: 
     print "terminated Gracefully" 


# *************************************************************** 
# 
# ************************ Script Start ************************ 
# 
# *************************************************************** 
if __name__ == "__main__": 

    try: 
     proc = Popen(("receivetest -f=%s" % pcanbus).split(), stdout = PIPE) 
    except OSError: 
     print "ERROR ESTABLISHING CONNECTION" 

    DataStream = ThreadedTask(RecvQueue) 
    DataStream.daemon = True 
    DataStream.start() 

    root = tk.Tk() 

    myapp = application(root) 
    root.mainloop() 

# -------------------------------------------------------------- 

Hoepfully вы можете увидеть, что я пытаюсь сделать. Мой метод выбора не работает, потому что индекс удаляется и, следовательно, не имеет ничего общего с картой.

Данные, которые можно было бы ожидать:

12106694.169 receivetest: m s 0x0000069a 8 00 00 00 00 00 0a 58 1a 
12106694.638 receivetest: m s 0x0000069e 8 00 1f be 0f ea 0a 58 1a 
12106695.107 receivetest: m s 0x00000663 8 2f 00 62 02 00 0a 58 1a 
12106695.577 receivetest: m s 0x00000690 8 00 20 06 0f ea 0a 58 1a 
12106794.137 receivetest: m s 0x0000069a 8 00 00 00 00 00 0a 58 1a 
12106794.649 receivetest: m s 0x0000069e 8 00 1f be 0f ea 0a 58 1a 
12106795.118 receivetest: m s 0x00000663 8 2f 00 62 02 00 0a 58 1a 
12106795.587 receivetest: m s 0x00000690 8 00 20 06 0f ea 0a 58 1a 
12106894.147 receivetest: m s 0x0000069a 8 00 00 00 00 00 0a 58 1a 
12106894.617 receivetest: m s 0x0000069e 8 00 1f be 0f ea 0a 58 1a 
12106895.86 receivetest: m s 0x00000663 8 2f 00 62 02 00 0a 58 1a 
12106895.598 receivetest: m s 0x00000690 8 00 20 06 0f ea 0a 58 1a 
12106994.158 receivetest: m s 0x0000069a 8 00 00 00 00 00 0a 58 1a 
12106994.627 receivetest: m s 0x0000069e 8 00 1f be 0f ea 0a 58 1a 
12106995.97 receivetest: m s 0x00000663 8 2f 00 62 02 00 0a 58 1a 
12106995.566 receivetest: m s 0x00000690 8 00 20 06 0f ea 0a 58 1a 
12107094.169 receivetest: m s 0x0000069a 8 00 00 00 00 00 0a 58 1a 
12107094.638 receivetest: m s 0x00000663 8 2f 00 62 02 00 0a 58 1a 
12107095.107 receivetest: m s 0x0000069e 8 00 1f be 0f ea 0a 58 1a 
12107095.619 receivetest: m s 0x00000690 8 00 20 06 0f ea 0a 58 1a 
12107194.179 receivetest: m s 0x0000069a 8 00 00 00 00 00 0a 58 1a 
12107194.649 receivetest: m s 0x0000069e 8 00 1f be 0f ea 0a 58 1a 
12107195.118 receivetest: m s 0x00000663 8 2f 00 62 02 00 0a 58 1a 
12107195.587 receivetest: m s 0x00000690 8 00 20 06 0f ea 0a 58 1a 
12107294.147 receivetest: m s 0x0000069a 8 00 00 00 00 00 0a 58 1a 
12107294.659 receivetest: m s 0x0000069e 8 00 1f be 0f ea 0a 58 1a 
12107295.129 receivetest: m s 0x00000663 8 2f 00 62 02 00 0a 58 1a 
12107295.598 receivetest: m s 0x00000690 8 00 20 06 0f ea 0a 58 1a 
12107394.158 receivetest: m s 0x0000069a 8 00 00 00 00 00 0a 58 1a 
12107394.627 receivetest: m s 0x0000069e 8 00 1f be 0f ea 0a 58 1a 
12107395.97 receivetest: m s 0x00000663 8 2f 00 62 02 00 0a 58 1a 
12107395.566 receivetest: m s 0x00000690 8 00 20 06 0f ea 0a 58 1a 
12107494.254 receivetest: m s 0x0000069a 8 00 00 00 00 00 0a 58 1a 
12107494.766 receivetest: m s 0x00000690 8 00 20 06 00 00 0a 58 1a 
12107495.235 receivetest: m s 0x00000691 8 01 1e 6e 4b 50 5a 06 00 
12107495.662 receivetest: m s 0x00000663 8 2f 00 62 02 00 0a 58 1a 

EDIT Создан конденсируется рабочую версию кода

+0

Пожалуйста, создать рабочий пример, который означает Например, мы можем копировать и запускать напрямую и визуализировать вашу ситуацию. – nbro

+0

@ Xenomorph Я редактировал вопрос с рабочим примером – Jim

+0

Хорошо, даже если это довольно сложно ... также, когда вы используете потоки, каждая программа может усложняться ... Я не уверен, смогу ли я помочь, но я надеюсь, что кто-то, визуализирующий ситуацию, может вам помочь;) – nbro

ответ

1

Все, что вам нужно сделать, это получить индекс подсвеченных элементов, заменить данные, а затем повторно выберите выделенные элементы. Если каждый элемент уникален, процесс чрезвычайно прост.

Если предметы не уникальны, это все еще возможно. Все, что вам нужно сделать, это сохранить индекс каждого выбранного элемента. Когда вы что-то удаляете, запомните индекс элемента, который был удален. При восстановлении выбора индексы для элементов, находящихся над удаленным элементом, будут неизменными, а индексы для элементов ниже того, который был удален, должны вычесть его (то есть: если вы удалили элементы №5 и №10, после delete вам нужно перебрать # 9)

Вот решение, когда вы знаете, что элементы в списке уникальны.

Во-первых, это экономит все, что было выбрано, по значению:

def saveSelection(lb): 
    selection = [] 
    for i in lb.curselection(): 
     selection.append(lb.get(i)) 
    return selection 

Позже, вы можете восстановить выбранные элементы с этим:

def restoreSelection(lb, selectedItems): 
    lb.selection_clear(0, "end") 
    items = lb.get(0, "end") 
    for item in selectedItems: 
     if item in items: 
      index = items.index(item) 
      lb.selection_set(index) 
+0

Привет, я думаю, что это правильный ответ, но я изо всех сил пытаюсь включить его в свою программу, где/как мне вызвать функции. любой совет будет очень благодарен - Jim – Jim

+0

@Jim: вызовите 'saveSelection' непосредственно перед изменением списка, вызовите' restoreSelection' сразу после его изменения. –

+0

Извините, что продолжал беспокоить вас об этом, я попытался добавить это, но на всю жизнь я не могу заставить его работать, я думаю, это потому, что когда я удаляю и снова вставляю строку, он увеличивает счетчик на 1 так 'if item in items' не' True', как бы это сделать, основываясь только на первых 6 символах строки, поскольку они являются идентификаторами и не подлежат изменению. – Jim

Смежные вопросы