根据从列表中选择的项目过滤出框架

时间:2019-10-11 05:33:11

标签: python python-3.x tkinter

我有一个名为Bone的类,其属性为(与在此问题中如何实现无关):

  • id
  • 名称
  • w(w是职位)
  • x(x是头寸)
  • y(y是头寸)
  • z(z是位置)

称为BoneFrame的类实际上创建了一个这样的框架(我也不认为如何实现):

how frame looks

在主脚本中,我有一个名为categories的变量,它具有2级类别。主要类别,然后是子类别。例如,二头肌是主类别Upper body的一部分,并且是子类别Arms的一部分。

我想知道如何根据所选的主要类别/子类别过滤出帧。因此,仅显示相关的帧。在下面的图片中,选择了主要类别Upper body。然后子类别会更新(并显示上半身子类别的列表),在这种情况下,将选择Arms子类别。

mock up


Main.py

from tkinter import *
from tkinter import ttk
from Bone import *
from BoneFrame import *

root = Tk()
root.geometry('500x500')
boneFrame = Frame(root, bg="cyan")
boneFrame.grid(row=0, column=0, sticky=W)

# Dictonary of bone objects
skeleton = {
    1: Bone(1, "Bicep", 0, 0, 0, 1),
    2: Bone(2, "Mid Chest", -0.705721, 0.0035173, 0.0442479, 0.707098),
    3: Bone(3, "Forarm", -0.0029335, -0.0260022, 0.6981489, 0.7154743),
    4: Bone(4, "Feet", 0.0189131, -0.0307881, -0.0195522, 0.9991557),
    5: Bone(5, "Toes", 0.0222693, 0.396756, 0.0086796, 0.9176129),
    6: Bone(6, "Thigh", 0.0089054, 0.3955458, 0.0229391, 0.9181166)
}

# Dictionary of Tkinter frames with a reference to the
# Bone object
boneFrames = {}
for bone_id, bone in skeleton.items():
    boneFrames[bone_id] = BoneFrame(boneFrame, bone)
    # If you uncomment the line below, you'll see it makes
    # 6 frames for the 6 bones
    boneFrames[bone_id].pack()


people = {
    "Upper Body": {
        "Arms": [boneFrames[1], boneFrames[3]],
        "Chest": [boneFrames[2]]
        },
    "Lower Body": {
        "Legs": [boneFrames[6]],
        "Foot": [boneFrames[4], boneFrames[5]]
    }
}

root.wm_attributes("-topmost", 1)
root.mainloop()

BoneFrame.py

from tkinter import *
from tkinter import ttk
from Bone import *

ID_WIDTH = 5
ID_PADDING = 15
VAL_PADDING = 2
PLUS_PADDING = 10

class BoneFrame(Frame):
    def __init__(self, parent, bone):
        super().__init__(parent)
        self.bone = bone

        self.name = Label(self, text=self.bone.get_name(), width=10)
        self.name.grid(row=0, column=0, sticky=W)

        # W Positon
        self.w_var = StringVar()
        self.w_var.set(self.bone.w)
        self.w_val = Label(self, textvariable=self.w_var, width=7)
        self.w_plus_btn = Button(self, text="+", command= lambda: self.incr_w())
        self.w_minus_btn = Button(self, text="-", command= lambda: self.decr_w())

        self.w_plus_btn.grid(row=0, column=1)
        self.w_val.grid(row=0, column=2, sticky=W, padx=(VAL_PADDING, VAL_PADDING))
        self.w_minus_btn.grid(row=0, column=3)

        # X Position
        self.x_var = StringVar()
        self.x_var.set(self.bone.x)
        self.x_val = Label(self, textvariable=self.x_var, width=7)
        self.x_plus_btn = Button(self, text="+", command= lambda: self.incr_x())
        self.x_minus_btn = Button(self, text="-", command= lambda: self.decr_x())

        self.x_plus_btn.grid(row=0, column=4, padx=(PLUS_PADDING, 0))
        self.x_val.grid(row=0, column=5, sticky=W, padx=(VAL_PADDING, VAL_PADDING))
        self.x_minus_btn.grid(row=0, column=6)

        # Y Positon
        self.y_var = StringVar()
        self.y_var.set(self.bone.y)
        self.y_val = Label(self, textvariable=self.y_var, width=7)
        self.y_plus_btn = Button(self, text="+", command= lambda: self.incr_y())
        self.y_minus_btn = Button(self, text="-", command= lambda: self.decr_y())

        self.y_plus_btn.grid(row=0, column=7, padx=(PLUS_PADDING, 0))
        self.y_val.grid(row=0, column=8, sticky=W, padx=(VAL_PADDING, VAL_PADDING))
        self.y_minus_btn.grid(row=0, column=9)

        # Z Positon
        self.z_var = StringVar()
        self.z_var.set(self.bone.z)
        self.z_val = Label(self, textvariable=self.z_var, width=7)
        self.z_plus_btn = Button(self, text="+", command= lambda: self.incr_z())
        self.z_minus_btn = Button(self, text="-", command= lambda: self.decr_z())

        self.z_plus_btn.grid(row=0, column=10, padx=(PLUS_PADDING, 0))
        self.z_val.grid(row=0, column=11, sticky=W, padx=(VAL_PADDING, VAL_PADDING))
        self.z_minus_btn.grid(row=0, column=12)


    def incr_w(self):
        self.bone.incr_w()
        self.w_var.set(self.bone.w)

    def decr_w(self):
        self.bone.decr_w()
        self.w_var.set(self.bone.w)

    def incr_x(self):
        self.bone.incr_x()
        self.x_var.set(self.bone.x)

    def decr_x(self):
        self.bone.decr_x()
        self.x_var.set(self.bone.x)

    def incr_y(self):
        self.bone.incr_y()
        self.y_var.set(self.bone.y)

    def decr_y(self):
        self.bone.decr_y()
        self.y_var.set(self.bone.y)

    def incr_z(self):
        self.bone.incr_z()
        self.z_var.set(self.bone.z)

    def decr_z(self):
        self.bone.decr_z()
        self.z_var.set(self.bone.z)

Bone.py

INCREMENT = 0.01

class Bone:
    def __init__(self, boneId, name, w, x, y, z):
        self.id = boneId
        self.name = name
        self.w = w
        self.x = x
        self.y = y
        self.z = z

    def get_id(self):
        return self.id


    def positive_incr(self, num):
        newVal = round(num + INCREMENT, 2)
        if (newVal > 1):
            return 1
        return newVal

    def negative_incr(self, num):
        newVal = round(num - INCREMENT, 2)
        if (newVal < -1):
            return -1
        return newVal

    def incr_w(self):
        self.w = self.positive_incr(self.w)
        self.update_imvu_pos("inf0.33,0.324,0.23")

    def decr_w(self):
        self.w = self.negative_incr(self.w)

    def incr_x(self):
        self.x = self.positive_incr(self.x)

    def decr_x(self):
        self.x = self.negative_incr(self.x)

    def incr_y(self):
        self.y = self.positive_incr(self.y)

    def decr_y(self):
        self.y = self.negative_incr(self.y)

    def incr_z(self):
        self.z = self.positive_incr(self.z)

    def decr_z(self):
        self.z = self.negative_incr(self.z)

    def get_name(self):
        return self.name

1 个答案:

答案 0 :(得分:1)

基本上,您正在寻找两个Listbox小部件,它们会根据用户的选择做出反应。为此,您可以绑定到"<<ListboxSelect>>"事件,然后填充下一个ListboxBoneFrame。在下面,我删除了BoneBoneFrame类中的所有方法,以使代码最少:

import tkinter as tk

class Bone:
    def __init__(self, boneId, name, w, x, y, z):
        self.id = boneId
        self.name = name
        self.w = w
        self.x = x
        self.y = y
        self.z = z

skeleton = {
    1: Bone(1, "Bicep", 0, 0, 0, 1),
    2: Bone(2, "Mid Chest", -0.705721, 0.0035173, 0.0442479, 0.707098),
    3: Bone(3, "Forarm", -0.0029335, -0.0260022, 0.6981489, 0.7154743),
    4: Bone(4, "Feet", 0.0189131, -0.0307881, -0.0195522, 0.9991557),
    5: Bone(5, "Toes", 0.0222693, 0.396756, 0.0086796, 0.9176129),
    6: Bone(6, "Thigh", 0.0089054, 0.3955458, 0.0229391, 0.9181166)
}

class BoneFrame(tk.Frame):
    def __init__(self,master=None, bone=None, **kwargs):
        super().__init__(master, kwargs)
        for num, i in enumerate((bone.name, bone.w, bone.x, bone.y, bone.z)):
            tk.Label(self,text=i).grid(row=0,column=num)

class BoneGUI(tk.Tk):
    def __init__(self):
        super().__init__()
        self.categories = {
                            "Upper Body": {
                                "Arms": [BoneFrame(self,skeleton.get(1)),
                                         BoneFrame(self,skeleton.get(3))],
                                "Chest": [BoneFrame(self,skeleton.get(2))]
                                },
                            "Lower Body": {
                                "Legs": [BoneFrame(self,skeleton.get(6))],
                                "Foot": [BoneFrame(self,skeleton.get(4)),
                                         BoneFrame(self, skeleton.get(5))]
                            }
                        }
        self.current_selection = None
        self.showing = []
        self.part = None
        self.main_cat = tk.Listbox(self,height=3,exportselection=False)
        for i in list(self.categories.keys()):
            self.main_cat.insert(tk.END,i)
        self.main_cat.grid(row=0,column=0,rowspan=2)

        self.sub_cat = tk.Listbox(self,height=3,exportselection=False)
        self.sub_cat.grid(row=0,column=1,rowspan=2)

        self.main_cat.bind("<<ListboxSelect>>", self.populate_sub_cat)
        self.sub_cat.bind("<<ListboxSelect>>", self.populate_frame)

    def populate_sub_cat(self, event=None):
        self.sub_cat.delete(0, "end")
        self.current_selection = self.categories.get(self.main_cat.get(self.main_cat.curselection()))
        for x in self.current_selection:
            self.sub_cat.insert(tk.END, x)

    def populate_frame(self, event=None):
        for i in self.showing:
            i.grid_forget()
        self.part = self.sub_cat.get(self.sub_cat.curselection())
        for num, frame in enumerate(self.current_selection.get(self.part)):
            frame.grid(row=num,column=2)
            self.showing.append(frame)

root = BoneGUI()

root.mainloop()