Aoeso 2023-03-04 14:35 采纳率: 21.1%
浏览 107
已结题

tkinter的复选框在限定高度内通过滚动条查看

img


如上图所示

现有的源代码,请问如何修改成我需要的样子


import threading
import tkinter as tk
from datetime import datetime
from tkinter import ttk

from 根据系统单号打印单个标签v2 import print_label_v2

root = tk.Tk()
root.title('小助手 v0.0.2')
root.geometry('650x500+100+100')
"""左边布局"""
left_frame = tk.Frame(root)
left_frame.pack(side=tk.LEFT, anchor=tk.N, padx=5, pady=5)

"""左边布局 标签打印"""
net_frame = tk.LabelFrame(left_frame, text='标签打印', padx=5, pady=5)
net_frame.pack()

tk.Label(net_frame, text='(1)订单状态').pack(anchor=tk.W)
socket_type = ttk.Combobox(net_frame)
socket_type['values'] = ['打单配货', '批量称重']
socket_type.current(0)
socket_type.pack(anchor=tk.W)

tk.Label(net_frame, text='(2)查询范围').pack(anchor=tk.W)
socket_host = ttk.Combobox(net_frame)
socket_host['values'] = ['7日内', '30日内']
socket_host.current(0)
socket_host.pack(anchor=tk.W)

tk.Label(net_frame, text='(3)打印数量').pack(anchor=tk.W)
socket_host = ttk.Combobox(net_frame)
socket_host['values'] = ['1', '2', '3', '4', '5', '6']
socket_host.current(1)
socket_host.pack(anchor=tk.W)

tk.Label(net_frame, text='(4)系统单号').pack(anchor=tk.W)
entry_port = ttk.Entry(net_frame)
entry_port.pack(fill=tk.X)


# 获取文本框输入
def getTextInput():
    result = entry_port.get()  # 获取文本输入框的内容
    print(result)  # 输出结果


# 获取打印标签数量
def getPrintNum():
    print_num = socket_host.get()
    return print_num


def thread_it(func, *args, on_finished=None):
    """将函数打包进线程"""

    def wrapped_func():
        # 调用函数并获取返回值
        result = func(*args)
        # 如果提供了on_finished回调函数,则调用它并将返回值传递给它
        if on_finished:
            on_finished(result)

    # 创建线程
    t = threading.Thread(target=wrapped_func)
    # 设置守护线程
    t.daemon = True
    # 启动线程
    t.start()


# 当按钮被点击的时候执行click_button()函数
def click_button(print_num):
    result = entry_port.get().strip('\n').strip()  # 获取文本输入框的内容
    print(result, type(result))  # 输出结果

    # 限制按钮在程序运行中不能重复点击
    global print_button
    print_button.config(state=tk.DISABLED)
    close_button.config(state=tk.DISABLED)
    global send_area
    if result.find('XD') != -1:
        print_label_v2(trade_no=result, print_num=print_num)
        send_area.insert(tk.END,
                         f'>>>{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}\t系统单号:{result}已打印\n')
        entry_port.delete(0, 999)
    else:
        send_area.insert(tk.END, f'请输入正确的系统单号!\n')
    print_button.config(state=tk.NORMAL)
    close_button.config(state=tk.NORMAL)


# 按钮
button_frame = tk.Frame(net_frame)
button_frame.pack()

print_button = tk.Button(button_frame, text='打印', bg='#7CCD7C',
                         command=lambda: thread_it(click_button, getPrintNum()))
close_button = tk.Button(button_frame, text='忽略')
print_button.pack(side=tk.LEFT)
close_button.pack(side=tk.RIGHT)

"""左边布局 使用说明"""
recv_frame = tk.LabelFrame(left_frame, text='使用说明', padx=5, pady=5)
recv_frame.pack(side=tk.TOP, anchor=tk.N, fill=tk.X)
tk.Radiobutton(recv_frame, text='方式1:勾选待打单>打印').pack(anchor=tk.W)
tk.Radiobutton(recv_frame, text='方式2:输入单号>打印').pack(anchor=tk.W)

"""右边布局"""
right_frame = tk.Frame(root)
right_frame.pack(side=tk.TOP, padx=5, pady=5)

info_frame = tk.Frame(right_frame)
info_frame.pack()
tk.Label(info_frame, text='待打印订单').pack(anchor=tk.W)
#
# text_pad = tk.Text(info_frame, width=62)
# text_pad.pack(side=tk.LEFT, fill=tk.X)

# send_text_bar = tk.Scrollbar(info_frame)
# send_text_bar.pack(side=tk.RIGHT, fill=tk.Y)


"""待打印订单列表"""


class Checklist(tk.Frame):
    def __init__(self, master, options):
        super().__init__(master)

        self.vars = []

        for option in options:
            var = tk.BooleanVar(value=False)
            item = tk.Checkbutton(self, text=option, variable=var)
            item.pack(side="top", anchor="w")
            self.vars.append(var)

    def state(self):
        return [var.get() for var in self.vars]


class App(tk.Frame):
    def __init__(self, master):
        super().__init__(master)

        self.options = ["option 1", "option 2", "option 3", "option 4", "option 5", "option 1", "option 2", "option 3",
                        "option 4", "option 5"]

        self.checklist = Checklist(self, self.options)
        self.checklist.pack(side="left", fill="x", expand=True)

        # self.button = tk.Button(self, text="Submit", command=self.submit)
        # self.button.pack(side="bottom")

    def submit(self):
        print(self.checklist.state())


app = App(info_frame)
app.pack(side="top", fill="both", expand=True)

tk.Label(right_frame, text='信息日志').pack(anchor=tk.W)
send_frame = tk.Frame(right_frame)
send_frame.pack()

send_area = tk.Text(send_frame, width=58, height=6)
send_area.pack(side=tk.LEFT)
send_button = tk.Button(send_frame, text='清除', width=5)
send_button.pack(side=tk.RIGHT, fill=tk.Y)
root.mainloop()

  • 写回答

6条回答 默认 最新

  • A1358722560 2023-03-04 16:18
    关注

    根据要求,提供以下程序:

    from tkinter import *
    from tkinter import ttk
    
    
    class ListView():
        char_ct = '☑'  # 复选框选中标识符
        chat_cf = '□'  # 复选框未选中标识符
    
        def __init__(self, tk, x=0, y=0, height=400, width=600):
            self.tk = tk
            self.x = x
            self.y = y
            self.height = height
            self.width = width
            self.rows_count = 0
            self.cols_count = 0
            self.head_tags = ['index']
            self.head_widths = [50]
            self.head_texts = ['']
            self.tree = None
            self.__created = False  # 控制表格创建后,停用部分方法
            self.__check_boxes = True  # 标识是否有复选框功能
            self.__show_index = True  # 标识是否显示行号
    
        def create_listview(self):
            """
            设置好列后,执行这个函数显示出控件
            """
            if self.__created:
                print('不能再次创建!')
            else:
                self.__created = True
                self.cols_count = len(self.head_tags) - 1  # 第一列用作索引了
    
                frame1 = Frame(self.tk, relief=RAISED)
                frame1.place(height=self.height, width=self.width, x=self.x, y=self.y)
                frame1.propagate(0)  # 使组件大小不变,此时width才起作用
    
                # 定义listview
                self.tree = ttk.Treeview(frame1, columns=self.head_tags, show='headings')
                self.tree.column(self.head_tags[0], width=self.head_widths[0], anchor='center')  # stretch=YES怎么用
                for i in range(1, len(self.head_tags)):
                    self.tree.column(self.head_tags[i], width=self.head_widths[i], anchor='center')
                    self.tree.heading(self.head_tags[i], text=self.head_texts[i])
    
                # 设置垂直滚动条
                vbar = ttk.Scrollbar(frame1, orient=VERTICAL, command=self.tree.yview)
                self.tree.configure(yscrollcommand=vbar.set)
                # self.tree.grid(row=0, column=0, sticky=NSEW)
                self.tree.grid(row=0, column=0)
                vbar.grid(row=0, column=1, sticky=NS)
    
                # 设置水平滚动条
                hbar = ttk.Scrollbar(frame1, orient=HORIZONTAL, command=self.tree.xview)
                self.tree.configure(xscrollcommand=hbar.set)
                hbar.grid(row=1, column=0, sticky=EW)
    
                # 绑定事件
                self.tree.bind('<ButtonRelease-1>', self.on_click)  # 绑定行单击事件
                self.tree.bind("<Double-1>", self.on_db_click)  # 绑定双击事件
    
        def add_column(self, text='', width=100):
            """
            增加一列,应该在show()前面设定,后面就无效了
            :param text: 表头文字
            :param width: 列宽度
            """
            if self.__created:
                print('表格已经创建,在增加的列无效!')
            else:
                self.head_tags.append(len(self.head_tags))
                self.head_widths.append(width)
                self.head_texts.append(text)
    
        def add_row_char(self, check_char=char_ct, vals=''):
            """
            在最后增加一行
            """
            if self.__check_boxes:
                if check_char != ListView.char_ct:
                    check_char = ListView.chat_cf
                index = '%s%d' % (check_char, self.rows_count + 1)
            else:
                index = self.rows_count + 1
    
            values = [index]
            for v in vals:
                values.append(v)
            self.tree.insert('', 'end', values=values)
            self.rows_count += 1
    
        def add_row(self, check_bl=True, vals=''):
            """
            在最后增加一行
            """
            check_char = self.check_bl2char(check_bl)
            self.add_row_char(check_char, vals)
    
        def set_check(self, state=True):
            """
            设置是否有复选功能
            """
            if self.__created:
                print('表格创建后,不能设置复选状态!')
            else:
                self.__check_boxes = state
    
        def set_width(self, col_num, width):
            """
            设置列宽
            :param col_num: 列号
            :param width: 宽度
            """
            self.tree.column("#%d" % col_num, width=width)  # 可以动态改变列宽
    
        def get_row(self, row_num):
            """
            获取一行的对象,供tree.item调用
            :param row_num:行号
            :return: 行对象
            """
            if row_num in range(1, self.rows_count + 1):
                items = self.tree.get_children()
                for it in items:
                    index = self.get_index_by_item(it)
                    if int(index) == int(row_num):
                        return it
    
        def get_row_values_by_item(self, item):
            """
            获取一行的值内容,包含行头部信息
            :param row_num: 行号
            :return: 元组,1为头部信息,1以后为表格信息
            """
            values = self.tree.item(item, 'values')
            return values
    
        def get_row_vals_head(self, row_num):
            """
            获取一行的值内容,包含行头部信息
            :param row_num: 行号
            :return: 元组,1为头部信息,1以后为表格信息
            """
            item = self.get_row(row_num)
            return self.get_row_values_by_item(item)
    
        def get_row_vals_by_item(self, item):
            """
            获取一行的表格内容
            :param item: 对象
            :return: 列表,索引从0开始
            """
            values = self.tree.item(item, 'values')
            vals = []
            for i in range(1, len(values)):
                vals.append(values[i])
            return vals
    
        def get_row_vals(self, row_num):
            """
            获取一行的表格内容
            :param row_num: 行号
            :return: 列表,索引从0开始
            """
            item = self.get_row(row_num)
            return self.get_row_vals_by_item(item)
    
        def get_row_head(self, row_num):
            """
            获取一行的表头内容,包含复选框和索引
            :param row_num: 行号
            :return: 字符串
            """
            row_vals = self.get_row_vals_head(row_num)
            return row_vals[1]
    
        def get_index_by_values(self, values):
            """
            获取一行的索引
            :param values: 行数据(包含行头部信息)
            :return: 索引(整数)
            """
            if self.__check_boxes:
                index = values[0][1:]
            else:
                index = values[0]
            return index
    
        def get_index_by_item(self, item):
            """
            获取一行的索引
            :param by_item: 行对象
            :return: 索引(整数)
            """
            values = self.tree.item(item, 'values')
            return self.get_index_by_values(values)
    
        def get_index(self, row_num):
            """
            获取一行的索引
            :param row_num: 行号
            :return: 索引(整数)
            """
            item = self.get_row(row_num)
            return self.get_index_by_item(item)
    
        def get_index_select(self):
            """
            获取选中行的行号
            :return: 行号
            """
            try:
                item = self.tree.selection()[0]  # 获取行对象
            except Exception:
                return 1
            return self.get_index_by_item(item)
    
        def get_checkbl_by_values(self, values):
            """
            获取某一行的勾选状况
            :param values: 行数据(包含行头部信息)
            """
            if self.__check_boxes:
                check_str = values[0][0:1]
                if check_str == ListView.char_ct:
                    return True
                else:
                    return False
    
        def get_checkbl_by_item(self, item):
            """
            获取某一行的勾选状况
            :param item: 行对象
            """
            values = self.get_row_values_by_item(item)
            return self.get_checkbl_by_values(values)
    
        def get_check_bl(self, row_num):
            """
            获取某一行的勾选状况
            :param row_num: 行号
            """
            item = self.get_row(row_num)
            return self.get_checkbl_by_item(item)
    
        def get_check_char(self, row_num):
            """
            获取某一行的勾选符号
            :param item: 行对象
            """
            item = self.get_row(row_num)
            return self.get_checkchar_by_item(item)
    
        def change_check_by_item(self, item, check_bl=True):
            """
            修改一行的复选状态
            :param item: 行对象
            :param check_bl:复选状态
            """
            if self.__check_boxes:
                check_char = self.check_bl2char(check_bl)
                index = self.get_index_by_item(item)
                value = '%s%s' % (check_char, index)
                col_str = '#%d' % 1
                self.tree.set(item, column=col_str, value=value)
    
        def change_check_by_item_char(self, item, check_char=char_ct):
            """
            修改一行的复选状态
            :param item: 行对象
            :param check_char:复选字符
            """
            if self.__check_boxes:
                index = self.get_index_by_item(item)
                value = '%s%s' % (check_char, index)
                col_str = '#%d' % 1
                self.tree.set(item, column=col_str, value=value)
    
        #
        def exchange_check_by_item(self, item):
            """
            变换一行的复选状态
            """
            if self.__check_boxes:
                vals = self.get_row_values_by_item(item)
                check_str = vals[0][0:1]
                index = vals[0][1:]
                if check_str == ListView.char_ct:
                    value = ListView.chat_cf + index
                else:
                    value = ListView.char_ct + index
                col_str = '#%d' % 1
                self.tree.set(item, column=col_str, value=value)  # 修改单元格的值
    
        def change_check_on_select(self):
            """
            改变选中行的勾选状态
            """
            try:
                item = self.tree.selection()[0]  # 获取行对象
            except Exception:
                pass
            else:
                self.exchange_check_by_item(item)
    
        def check_bl2char(self, bl=True):
            """
            返回复选框符号
            :param bl: True代表已选,False未选中
            :return: 复选框
            """
            if bl:
                return ListView.char_ct
            else:
                return ListView.chat_cf
    
        def check_char2bl(self, char=char_ct):
            """
            返回复选框符号
            :param char: ☑代表已选
            :return: 复选框
            """
            if char == ListView.char_ct:
                return True
            else:
                return False
    
        def on_click(self, event):
            """
            行单击事件
            """
            self.change_check_on_select()
    
        def on_db_click(self, event):
            item = self.tree.selection()  # 获取行对象
            print(self.tree.item(item, 'values'))
    
    
    if __name__ == '__main__':
        # 定义窗口---------------------------------------
        win = Tk()
        win.title('测试窗口')
        win.geometry("%dx%d+%d+%d" % (1024, 800, 0, 0))
    
        # 定义listview---------------------------------------
        lv = ListView(win, x=100, y=100, width=800, height=500)
        lv.add_column('第一列', 100)
        lv.add_column('第二列', 100)
        lv.add_column('第三列', 100)
        lv.add_column('第四列', 100)
        lv.create_listview()
        # 添加数据
        for i in range(0, 4):
            row = ['a%d' % (i + 1), 'b%d' % (i + 1), 'c%d' % (i + 1), 'e%d' % (i + 1)]
            lv.add_row(False, row)
    
        # # 执行按钮---------------------------------------
        def do_task():
            list1 = []
            for j in range(lv.rows_count):
                if lv.get_check_bl(j + 1) is True:
                    list1.append(j + 1)
            for k in list1:
                print(lv.get_row_vals(k))
    
    
        do_button = Button(win, text='测试', command=do_task)
        do_button.place(height=22, width=160, x=100, y=600)
    
        win.mainloop()
    
    
    

    结果为:

    img

    img

    img


    如果问题得到解决的话请点 采纳~~

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(5条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 3月11日
  • 已采纳回答 3月11日
  • 修改了问题 3月4日
  • 修改了问题 3月4日
  • 展开全部

悬赏问题

  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。