Tkinter Listbox列表框的用法

2024年04月02日 Python教程 Python51

Tkinter Listbox列表框的用法

列表框(Listbox)组件用来存放一个列表数据,可以对其数据进行添加和删除操作。

下面使用该组件实现一个栈,在头部进行压栈和出栈操作。为了让例子更加有趣,规定压栈的数据只能从“1,2,3,…,10”这个队列的头部取,也就是第一次压栈的数据是1,第二次压栈的数据是2,以此类推。问仅通过压栈和出栈操作能否得到指定的输出序列,如“10,9,8,7,6,5,4,3,2,1”,也就是说第一次出栈的是10,第二次出栈的是9,以此类推。

import sys
if sys.version_info.major == 3:            # Python 3
    import tkinter as tk
elif sys.version_info.major == 2:            # Python 2
    import Tkinter as tk
import random
class DemoApplication(tk.Frame):
    def pop(self):
        element_num = self.list_box1.size()
        if element_num == 0:
            print("Error: No Element")
        else:
            # 栈中有元素
            # 得到最后一个元素的值,该类型是字符串类型的
            las_val = self.list_box1.get(tk.END)
            las_val = int(las_val)                       # 转换成整数类型
            # 将最后一个元素放入输出队列的尾部
            self.output_list.append(las_val)
            # 删除最后一个元素
            self.list_box1.delete(tk.END)
            msg = u"输出队列:%s" % self.output_list
            self.expected_label['text'] = msg
            if element_num == 1:
                self.button_pop.config(state=tk.DISABLED)
    def push(self):
        if self.next_push > 10:
            self.button_push.config(state=tk.DISABLED)
        else:
            # 在尾部添加
            self.list_box1.insert(tk.END,str(self.next_push))
            self.next_push = self.next_push + 1
            if self.next_push > 10:
                # 不让入栈了
                self.button_push.config(state=tk.DISABLED)
            # 如果刚才不让执行出栈操作,那么现在可以进行出栈操作了
            print("self.button_pop['state'] = %s" % self.button_pop
                 ['state'])
            if self.button_pop['state'] == tk.DISABLED:
                self.button_pop.config(state=tk.NORMAL)
    def createWidgets(self):
        self.expected_val = random.randint(0, 101)
        self.list_box1 = tk.Listbox(main_win)         # 创建一个列表框
        self.list_box1.pack()
        self.next_push = 1
        self.real_label = tk.Label(main_win, text="")
        self.real_label.pack()
        self.button_push = tk.Button(main_win)
        self.button_push.state = 0
        self.button_push["text"] = u"压栈"
        self.button_push["command"] = self.push
        self.button_push.pack()
        self.button_pop = tk.Button(main_win)
        self.button_pop.state = 0
        self.button_pop["text"] = u"出栈"
        self.button_pop["command"] = self.pop
        # 最开始,栈中没有元素,所以不可以出栈
        self.button_pop.config(state=tk.DISABLED)
        self.button_pop.pack()
        self.expected_label = tk.Label(main_win, text="输出队列:")
        self.expected_label.pack()
    def __init__(self, master=None):
        tk.Frame.__init__(self, master)
        self.output_list = []
        self.pack()
        self.createWidgets()
main_win = tk.Tk()                            # 创建主窗口
main_win.title(u"栈操作演示")                # 设置窗口标题
main_win.geometry("200x300")                # 设置窗口大小
app = DemoApplication(master=main_win)        # 创建应用程序
app.mainloop()                                # 进入消息循环

运行后结果如 1 所示。

图 1 压栈出栈操作

当全部压栈完成,并且所有元素都出栈时,显示如图 2 所示的界面。

图 2 全部出栈完成

列表框默认只能选中一个元素,但是可以通过设置参数 selectmode 的值为 MULTIPLE 来允许选中多个元素。为了演示这个属性,下面来玩一个游戏,就是在给定的数中挑出一些数,要求这些数的和要尽量接近指定的值 t。

这里用 Listbox 来存放数组 l,用户可以从中任意挑选元素。在挑选的过程中,显示目前挑选数的和。在用户完成挑选后单击“查看答案”按钮可以查看是否得到了正确的结果。

下面是完整的代码:

import sys
if sys.version_info.major == 3:
    import tkinter as tk
elif sys.version_info.major == 2:
    import Tkinter as tk
import random
class DemoApplication(tk.Frame):
    # 背包问题的求解方法
    def resolve_bag(self, bag_volume, goods_list):
        biggest_valid_vol = 0
        biggest_valid_selection = []
        goods_num = len(goods_list)
        candidate_num = 1 << goods_num
        for candidate in range(candidate_num):
            selection_decision = []
            for x in range(goods_num):
                if (candidate & 1) == 1:
                    selection_decision.append(True)
                else:
                    selection_decision.append(False)
                candidate = candidate >> 1
            current_vol = 0
            for x in range(goods_num):
                if selection_decision[x] == True:
                    current_vol = current_vol + goods_list[x]
            if current_vol <= bag_volume and current_vol > biggest_valid_
                 vol:
                biggest_valid_vol = current_vol
                biggest_valid_selection = selection_decision
            result = [goods_list[x] for x in range(goods_num) \
                   if biggest_valid_selection[x] == True]
            return result
    def show_answer(self):                    # 显示标准答案
        answer_list = self.resolve_bag(self.target, self.data)
        standard_answer_sum = sum(answer_list)
        if abs(self.current_sum-self.target) <= \
                 abs(standard_answer_sum-self.target):
            # 用户的也是标准答案
            user_answer_list = [self.data[x] for x in self.list_box1.
                 curselection()]
            answer_label_text = u"标准答案是: %s" % user_answer_list
        else:
            answer_label_text = u"标准答案是: %s" % answer_list
        self.answer_label['text'] = answer_label_text
    def selection_evt_handler(self, evt):    # 选中某个元素的处理函数
        seleted_index_list = self.list_box1.curselection()
        sum = 0
        for x in seleted_index_list:
            sum = sum + self.data[x]
        self.current_sum = sum
        actual_sum_label_text = u"当前的和为%d" % self.current_sum
        self.actual_label['text'] = actual_sum_label_text
    def reset(self):                            # 重新开始
        self.generate_data()
        expect_label_txt = u"期望的和为%d" % self.target
        self.expected_label['text'] = expect_label_txt
        self.answer_label['text'] = ""
    def generate_data(self):                # 产生输入数据
        # 一共是8个元素,从0到7,全部删除
        self.list_box1.delete(0, 7)
        self.data = []
        for x in range(8):
            v = random.randint(1, 20)
            self.data.append(v)
        self.target = random.randint(20, 60)
        for x in self.data:
            self.list_box1.insert(tk.END,str(x))
    def createWidgets(self):            # 画出初始界面
        self.expected_val = random.randint(0, 101)
        self.list_box1 = tk.Listbox(main_win)
        # 允许选中多个元素
        self.list_box1["selectmode"] = tk.MULTIPLE
        self.list_box1.pack()
        self.list_box1.bind("<<ListboxSelect>>", self.selection_evt_
             handler)
        self.generate_data()
        self.next_push = 1
        self.real_label = tk.Label(main_win, text="")
        self.real_label.pack()
        expect_label_txt = u"期望的和为%d" % self.target
        self.expected_label = tk.Label(main_win, text=expect_label_txt)
        self.expected_label.pack()
        self.current_sum = 0
        actual_label_txt = u"当前的和为%d" % self.current_sum
        self.actual_label = tk.Label(main_win, text=actual_label_txt)
        self.actual_label.pack()
        self.answer_label = tk.Label(main_win, text="")
        self.answer_label.pack()
        self.button_reset = tk.Button(main_win)
        self.button_reset.state = 0
        self.button_reset["text"] = u"重新开始"
        self.button_reset["command"] = self.reset
        self.button_reset.pack()
        self.button_end = tk.Button(main_win)
        self.button_end.state = 0
        self.button_end["text"] = u"查看答案"
        self.button_end["command"] = self.show_answer
        self.button_end.pack()
    def __init__(self, master=None):        # 初始化函数
        tk.Frame.__init__(self, master)
        self.output_list = []
        self.pack()
        self.createWidgets()
    main_win = tk.Tk()
    main_win.title(u"选中最接近目标的元素组合")
    main_win.geometry("250x350")
    app = DemoApplication(master=main_win)
    app.mainloop()

开始运行时的显示如图 3 所示。

图 3 初始界面

在查看答案时得到如图 4 所示的窗口。

图 4 完成后查看答案

本文链接:http://so.lmcjl.com/news/949/

展开阅读全文