从列表框和列表中删除选定的项目 [英] Removing selected items from the listbox and from the list
问题描述
由于我最近切换到Linux,所以我有一个用C#编写的应用程序,需要将其转换为Python.这是一个简单的GUI应用程序,用于在学习新语言时管理未知单词.但是,我需要 remove_item()函数,为此我还需要 find_word()函数.
I have an application written in C# that needs to be converted to Python, since I have recently switched to Linux. It's a simple GUI application to manage unknown words while learning a new language. Nevertheless, I need remove_item() function for which I also need find_word() function.
在C#中,我将创建以下两种方法:
In C#, I would create two following methods:
void Remove()
{
Word word = new Word();
try { word = FindWord(listView1.SelectedItems[0].Text); }
catch { return; }
if (listView1.SelectedItems.Count > 0)
{
try
{
foreach (ListViewItem eachItem in listView1.SelectedItems)
{
words.RemoveAll(x => x.WordOrPhrase == eachItem.Text);
listView1.Items[listView1.Items.Count - 1].Selected = true;
listView1.Items.Remove(eachItem);
}
}
catch { }
ClearAll();
ReadOnlyON();
}
else
{
MessageBox.Show("You have not selected any words!", "Notification", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
ReadOnlyOFF();
WordCount();
Sync();
}
private Word FindWord(string word)
{
return words.Find(x => x.WordOrPhrase == word);
}
...但是在Python方面,我还是一个新手,因此,我们将不胜感激.这是我到目前为止的内容:
...but I'm still a newbie when it comes to Python, so any help would be appreciated. Here is what I have so far:
涉及FindWord()方法时,可以将其重写如下:
When it comes to the FindWord() method, it could be rewritten as following:
def FindWord(word):
for x in words:
if x.WordOrPhrase == word:
return x
或
def FindWord(word):
return next((x for x in words if x.WordOrPhrase == word), None)
或
def FindWord(word):
return next(filter(lambda x: x.WordOrPhrase == word, words), None)
...但是我正在努力重写Remove()方法.这是一种方法:
...but I'm struggling to rewrite Remove() method. Here is one way:
def remove_item(self):
word = self.listBox.get(ACTIVE)
new_word_list = [] # initialize empty list
delete_idxs = []
for idx, item in enumerate(self.words):
if item.wordorphrase == word:
delete_idxs.append(idx)
else:
new_word_list.append(item)
self.words = new_word_list # overwrite the old word_list with the new one
for idx in reversed(delete_idxs):
self.listBox.delete(idx)
...我最想将C#方法转换为Python.这是我到目前为止的内容:
...what I would like most is converting my C# method to Python. Here is what I have so far:
def remove_item(self):
word = Word()
try:
word = find_word(self.listBox.curselection())
except:
return
if self.listBox.len(curselection()) > 0:
try:
for item in self.listBox.curselection():
self.words.remove(lambda x: x.wordorphrase == item.text)
# listView1.Items[listView1.Items.Count - 1].Selected = true;
self.listBox.remove(item)
except:
pass
self.clear_all()
else:
pass
# show messagebox
我不知道如何访问:
-
listView1.SelectedItems[0].Text
-
listView1.SelectedItems.Count > 0
-
listView1.SelectedItems
-
listView1.Items[listView1.Items.Count - 1].Selected
listView1.SelectedItems[0].Text
listView1.SelectedItems.Count > 0
listView1.SelectedItems
listView1.Items[listView1.Items.Count - 1].Selected
这是我到目前为止所做的:
Here is what I have done so far:
# Vocabulary.py
# GUI program to manage unknown words
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
import xml.etree.ElementTree as ET
import os
class Word:
def __init__(self, wordorphrase, explanation, translation, example):
self.wordorphrase = wordorphrase
self.explanation = explanation
self.example = example
self.translation = translation
class Vocabulary(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.master = master
self.master.resizable(width = False, height = False)
self.master.title("Vocabulary")
self.create_widgets()
self.words = []
self.load_words()
def on_closing(self):
self.save_all()
if messagebox.askokcancel("Quit", "Do you want to quit?"):
self.master.destroy()
def create_widgets(self):
self.buttons_frame = Frame(self.master)
self.buttons_frame.grid(row = 10, sticky = W)
self.search_frame = Frame(self.master)
self.search_frame.grid(row = 1, sticky = W, columnspan = 2)
self.comboBox = ttk.Combobox(self.search_frame,
width = 3)
self.comboBox.grid(row = 0, column = 14, sticky = W)
self.comboBox['values'] = ( 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' )
self.btn_Add = Button(self.buttons_frame,
text = 'Add',
command = self.add_item)
self.btn_Add.grid(row = 0, sticky = W)
self.btn_Remove = Button(self.buttons_frame,
text = 'Remove',
command = self.remove_item)
self.btn_Remove.grid(row = 0, column = 1, sticky = W)
self.btn_Edit = Button(self.buttons_frame,
text = 'Edit',
command = self.edit_item)
self.btn_Edit.grid(row = 0, column = 2, sticky = W)
self.btn_Save = Button(self.buttons_frame,
text = 'Save',
command = self.save_item)
self.btn_Save.grid(row = 0, column = 3, sticky = W)
self.btn_Refresh = Button(self.buttons_frame,
text = 'Refresh',
command = self.refresh_all)
self.btn_Refresh.grid(row = 0, column = 4, sticky = W)
self.lblSearch = Label(self.search_frame, text = 'SEARCH: ')
self.lblSearch.grid(row = 0, column = 5, sticky = W)
self.txt_Search = Text(self.search_frame,
height = 1,
width = 70)
self.txt_Search.grid(row = 0, column = 6, columnspan = 3, sticky = W)
self.lblWordsOrPhrases = Label(self.master, text = 'WORDS/PHRASES:')
self.lblWordsOrPhrases.grid(row = 2, column = 0)
self.lblWordOrPhrase = Label(self.master, text = 'Word or phrase:')
self.lblWordOrPhrase.grid(row = 2, column = 1, sticky = W)
self.listBox = Listbox(self.master,
selectmode='extended',
height = 34,
width = 38)
self.listBox.grid(row = 3, column = 0, rowspan = 7, sticky = W)
self.txt_WordOrPhrase = Text(self.master,
height = 1,
width = 40)
self.txt_WordOrPhrase.grid(row = 3, column = 1, sticky = N)
self.lblExplanation = Label(self.master, text = 'Explanation:')
self.lblExplanation.grid(row = 4, column = 1, sticky = W)
self.txt_Explanation = Text(self.master,
height = 10,
width = 40)
self.txt_Explanation.grid(row = 5, column = 1, sticky = N)
self.lblTranslation = Label(self.master, text = 'Translation:')
self.lblTranslation.grid(row = 6, column = 1, sticky = W)
self.txt_Translation = Text(self.master,
height = 10,
width = 40)
self.txt_Translation.grid(row = 7, column = 1, sticky = N)
self.lblExamples = Label(self.master, text = 'Example(s):')
self.lblExamples.grid(row = 8, column = 1, sticky = W)
self.txt_Example = Text(self.master,
height = 10,
width = 40)
self.txt_Example.grid(row = 9, column = 1, sticky = S)
def load_words(self):
self.listBox.delete(0, END)
self.words.clear()
path = os.path.expanduser('~/Desktop')
vocabulary = os.path.join(path, 'Vocabulary', 'Words.xml')
if not os.path.exists(vocabulary):
if not os.path.exists(os.path.dirname(vocabulary)):
os.mkdir(os.path.dirname(vocabulary))
doc = ET.Element('Words')
tree = ET.ElementTree(doc)
tree.write(vocabulary)
else:
tree = ET.ElementTree(file=vocabulary)
for node in tree.findall('WordOrPhrase'):
w = Word(node.find('Word').text, node.find('Explanation').text, node.find('Translation').text,
node.find('Examples').text)
self.words.append(w)
self.listBox.insert(END, w.wordorphrase)
def save_all(self):
path = os.path.expanduser('~/Desktop')
vocabulary = os.path.join(path, 'Vocabulary', 'Words.xml')
tree = ET.ElementTree(file=vocabulary)
for xNode in tree.getroot().findall('WordOrPhrase'):
tree.getroot().remove(xNode)
for w in self.words:
xTop = ET.Element('WordOrPhrase')
xWord = ET.Element('Word')
xExplanation = ET.Element('Explanation')
xTranslation = ET.Element('Translation')
xExamples = ET.Element('Examples')
xWord.text = w.wordorphrase
xExplanation.text = w.explanation
xTranslation.text = w.translation
xExamples.text = w.example
xTop.append(xWord)
xTop.append(xExplanation)
xTop.append(xTranslation)
xTop.append(xExamples)
tree.getroot().append(xTop)
tree.write(vocabulary)
def add_item(self):
w = Word(self.get_word(), self.get_explanation(), self.get_translation(), self.get_example())
self.words.append(w)
self.listBox.insert(END, w.wordorphrase)
self.clear_all()
self.save_all()
def remove_item(self):
word = Word()
try:
word = find_word(self.listBox.curselection())
except:
return
if self.listBox.len(curselection()) > 0:
try:
for item in self.listBox.curselection():
self.words.remove(lambda x: x.wordorphrase == item.text)
# listView1.Items[listView1.Items.Count - 1].Selected = true;
self.listBox.remove(item)
except:
pass
self.clear_all()
else:
pass
# show messagebox
def edit_item(self):
pass
def save_item(self):
pass
def clear_all(self):
self.txt_WordOrPhrase.delete('1.0', END)
self.txt_Explanation.delete('1.0', END)
self.txt_Translation.delete('1.0', END)
self.txt_Example.delete('1.0', END)
def refresh_all(self):
pass
def get_word(self):
return self.txt_WordOrPhrase.get('1.0', '1.0 lineend')
def get_explanation(self):
return self.txt_Explanation.get('1.0', '1.0 lineend')
def get_translation(self):
return self.txt_Translation.get('1.0', '1.0 lineend')
def get_example(self):
return self.txt_Example.get('1.0', '1.0 lineend')
def find_word(word):
for x in self.words:
if x.wordorphrase == word:
return x
def main():
root = Tk()
gui = Vocabulary(root)
root.protocol('WM_DELETE_WINDOW', gui.on_closing)
root.mainloop()
if __name__ == '__main__':
main()
推荐答案
对于我的列表框,通常将模式设置为EXTENDED
,以便用户可以选择一个或多个项目并立即将其全部删除.我是通过以下方法进行的:
For my listboxes, I generally have the mode set to EXTENDED
so that users can select one or more items and remove all at once. I do so via the following method:
# Function with Tk.Listbox passed as arg
def remove_from(list_box):
# Tuple of currently selected items in arg
selected_items = list_box.curselection()
# Initialize a 'repositioning' variable
pos = 0
for item in selected_items:
# Set index of each item selected
idx = int(item) - pos
# Deletes only that index in the listbox
list_box.delete(idx, idx)
# Increments to account for shifts
pos += 1
例如,假设我的列表框中有4个项目.然后,我选择第一项和第三项.通过致电list_box.curselection()
我收到了以下信息:
For example, lets say in my listbox I had 4 items. I then select the first item and the third item. By calling list_box.curselection()
I've received the following:
selected_items = (0, 2)
0
是列表框中第一项的位置,2
是第三项在位置中的位置.然后为元组中的每个项目建立索引.
Where 0
is the first item's position in the listbox, and 2
is the third item's position. Then for each item in my tuple, I establish its index.
详细介绍以下内容:
idx = 0 - 0
list_box.delete(0, 0)
pos = 1
所以现在我已删除位置0
处的项目(例如第一个项目),并且列表框已移动!所以第二个现在是第一个,第三个是第二个,第四个是第三个.但是,我的元组不变,因为它是原始选择项的列表框中的位置.这是关键.接下来会发生什么:
So now I have deleted the item at position 0
(e.g. the first item) and my listbox has shifted! So the second is now the first, third is the second and fourth is the third. However, my tuple has not changed as it was the positions in the listbox of the original selection. This is key. What happens next is:
idx = 2 - 1
list_box.delete(1, 1)
pos = 2
由于列表框已移动,因此位置1
现在对应于最初位于列表框第三位置的项目.对于n
职位,这可以继续.
Since the listbox shifted, position 1
now corresponds to the item that was originally in the third position of the listbox. This can continue for n
positions.
用于自删除单词
您可以尝试以下操作:
# Function with Tk.Listbox and self.words[] passed as args
def remove_from(list_box, list):
# Tuple of currently selected items in arg
selected_items = list_box.curselection()
# List of Words already constructed
word_list = list
# Initialize a 'repositioning' variable
pos = 0
for item in selected_items:
# Set index of each item selected
idx = int(item) - pos
# Deletes only that index in the listbox
list_box.delete(idx, idx)
# Gets the string value of the given index
word = list_box.get(idx, idx)
# Removes the word from the list
if any(word in x for x in word_list):
word_list.remove(word)
# Increments to account for shifts
pos += 1
这篇关于从列表框和列表中删除选定的项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!