如何让 tkinter 与 Blender v2.90 一起工作?

Posted

技术标签:

【中文标题】如何让 tkinter 与 Blender v2.90 一起工作?【英文标题】:How do I get tkinter to work with Blender v2.90? 【发布时间】:2021-12-07 17:11:40 【问题描述】:

我正在尝试获取一个使用 tkinter 运行的 Blender python 脚本。它应该打开一个 3d 面部对象,以允许用户改变鼻子以进行鼻整形手术。但是,它在很大程度上依赖于 tkinter 提供 GUI 以允许用户选择必要的文件的能力;并且代码不会超过它的导入语句。

代码如下:

import bpy
import openpyxl
from pathlib import Path
import os
import tkinter as tk
from tkinter import filedialog
from tkinter import *
activate = 0


#select original data points xlsx file
def selectDataPointsFile():
    global dataPointsFile_path
    global activate
    dataPointsFile_path = filedialog.askopenfilename(filetypes=[("Excel files", "*.xlsx")])
    activate += 1
    
    if (activate == 3):
        addPointsAndFaceButton['state'] = tk.NORMAL

    newDataPointsButton['state'] = tk.NORMAL


#select new data points xlsx file
def selectNewDataPointsFile():
    global newDataPointsFile_path
    global activate
    newDataPointsFile_path = filedialog.askopenfilename(filetypes=[("Excel files", "*.xlsx")])
    activate += 1
    
    if (activate == 3):
        addPointsAndFaceButton['state'] = tk.NORMAL
    
    faceObjectButton['state'] = tk.NORMAL


#select patient face obj file
def selectFaceObjectFile():
    global faceObjectFile_path
    global activate
    faceObjectFile_path = filedialog.askopenfilename(filetypes=[("Object files", "*.obj")])
    activate += 1
    print("Data POint Button")
    if (activate == 3):
        meshFileExportButton['state'] = tk.NORMAL
    
    
    
    
    
#select patient face obj file
def meshFile():
    global meshFile_path
    global activate
    
    meshFile_path = filedialog.askdirectory()
    
    addPointsAndFaceButton['state'] = tk.NORMAL
    
    
    
#add the face with new and old points    
def facePointsAdd():
    r = 1
    wb_obj = openpyxl.load_workbook(dataPointsFile_path)
    wsheet = wb_obj.active

    wb_objNew = openpyxl.load_workbook(newDataPointsFile_path)
    wsheetNew = wb_objNew.active



    #swap y and z invert old z
    #old nose points
    noseLoop = []
    namez = []
    for i in range(1, 49):
        nosePoint = (wsheet["B"+str(i)].value, -wsheet["D"+str(i)].value, wsheet["C"+str(i)].value)
        noseLoop.append(nosePoint)
        namez.append(wsheet["A"+str(i)].value)
        
        
    #new nose points    
    noseLoopNew = []
    namezNew = []
    for i in range(1, 49):
        nosePointNew = (wsheetNew["B"+str(i)].value, -wsheetNew["D"+str(i)].value, wsheetNew["C"+str(i)].value)
        noseLoopNew.append(nosePointNew)
        namezNew.append(wsheetNew["A"+str(i)].value)
   

    #list of colored points so old and new points matchup
    colorList = []
    colorList.append((0., 0., 0.,0.))
    colorList.append((0., 0., 0.,0.))
    colorList.append((1., 0., 0.,0.))
    colorList.append((20., 30., 60.,0.))
    colorList.append((1., 1., 0.,0.))
    colorList.append((0., 0., 1.,0.))
    colorList.append((1., 0., 1.,0.))
    colorList.append((0., 1., 1.,0.))
    colorList.append((1., 1., 1.,0.))
    colorList.append((50., 1., 30.,0.))
    colorList.append((0., 1., 0.,0.))
    colorList.append((40., 100., 0.,0.))
    colorList.append((0., 50., 2.,0.))
    colorList.append((.67,.907,9,1.)) #12
    colorList.append((.1,.85,69.,0.))
    colorList.append((.3,30.,0.,0.))
    colorList.append((40.,1.,0.,0.))
    colorList.append((3.,0.,40.,0.))
    colorList.append((40.,.1,.3,0.))
    colorList.append((0., 250., 40.,0.))
    colorList.append((1.3,40.5,0.,0.))
    colorList.append((40.5,0.,35.5,0.))
    colorList.append((0.,2., 40.,0.))
    colorList.append((.3,40.,.1,0.))
    colorList.append((0.,40.5,.3,0.))
    colorList.append((35.5,40.,0.,0.))
    colorList.append((0., 0., 50.,0.))
    colorList.append((255.,105.,180.,0.))
    colorList.append((.67,.907,9,1.)) #12
    colorList.append((.1,.85,69.,0.))
    colorList.append((.3,30.,0.,0.))
    colorList.append((40.,1.,0.,0.))
    colorList.append((3.,0.,40.,0.))
    colorList.append((40.,.1,.3,0.))
    colorList.append((0., 250., 40.,0.))
    colorList.append((1.3,40.5,0.,0.))
    colorList.append((40.5,0.,35.5,0.))
    colorList.append((0.,2., 40.,0.))
    colorList.append((.3,40.,.1,0.))
    colorList.append((0.,40.5,.3,0.))
    colorList.append((35.5,40.,0.,0.))
    colorList.append((0., 0., 50.,0.))
    colorList.append((255.,105.,180.,0.))
    colorList.append((.67,.907,9,1.)) #12
    colorList.append((.1,.85,69.,0.))
    colorList.append((.3,30.,0.,0.))
    colorList.append((40.,1.,0.,0.))
    colorList.append((3.,0.,40.,0.))
    colorList.append((40.,.1,.3,0.))
    colorList.append((0., 250., 40.,0.))
    colorList.append((1.3,40.5,0.,0.))
    colorList.append((40.5,0.,35.5,0.))
    colorList.append((0.,2., 40.,0.))
    colorList.append((.3,40.,.1,0.))
    colorList.append((0.,40.5,.3,0.))
    colorList.append((35.5,40.,0.,0.))
    colorList.append((0., 0., 50.,0.))
    colorList.append((255.,105.,180.,0.))




    def makeMat(num):

        mat = bpy.data.materials.new(name = namez[i])
        mat.diffuse_color = colorList[i]
        mat.specular_color = (1., 1., 1.)
        return mat

  
    
    imported_object = bpy.ops.import_scene.obj(filepath=faceObjectFile_path)


    for i in range(0, 47):
        bpy.ops.mesh.primitive_uv_sphere_add(radius= r, location=noseLoop[i])
        sphere = bpy.context.object
        sphere.name = namez[i]
        mesh = sphere.data
        mat = makeMat(i)
        mesh.materials.append(mat)
        
        
        
        bpy.ops.mesh.primitive_cube_add(size= r, location=noseLoopNew[i])
        cube = bpy.context.object
        cube.name = (namezNew[i] + ' New')
        mesh = cube.data
        mat = makeMat(i)
        mesh.materials.append(mat)



    bpy.ops.object.select_all(action='DESELECT')


    activeObj = bpy.context.window.scene.objects[0]
    
    


    
    for i in range(0, 47):
        bpy.data.objects[namez[i]].select_set(True) # Blender 2.8x

    bpy.context.view_layer.objects.active = activeObj
    bpy.ops.object.parent_set(type='VERTEX')
    bpy.ops.object.select_all(action='DESELECT')
    bpy.ops.object.mode_set(mode='SCULPT')
    
    
    
    #insert mesh 1 (old nose mesh)
    # make mesh
    vertices = noseLoopNew
    edges = []
    faces = [[14,24,23],[14,24,22],[24,18,23],[24,17,22],[24,18,29],[24,29,17],[18,23,41],[17,22,40],[18,41,29],[29,17,40],[29,41,39],[29,40,39],[1,5,23],[5,41,23],[41,39,28],[39,40,28],[5,41,3],[3,41,7],[7,41,28],[28,40,6],[6,40,2],[22,2,4],[40,22,2],[22,4,0],[3,7,35],[7,35,28],[35,34,28],[28,34,6],[6,34,2],[34,2,26],[2,4,26],[4,31,26],[4,0,31],[32,1,5],[32,5,27],[5,27,3],[32,36,27],[3,27,35],[35,36,27],[34,35,36],[36,34,26],[36,26,31]]
    newNoseMesh = bpy.data.meshes.new('newNoseMesh')
    newNoseMesh.from_pydata(vertices, edges, faces)
    newNoseMesh.update()
    # make object from mesh
    newNoseMesh_object = bpy.data.objects.new('newNoseMesh_object', newNoseMesh)
    
    # create a collection
    mesh_collection = bpy.data.collections.new('mesh_collection')
    bpy.context.scene.collection.children.link(mesh_collection)
    
    # add object to scene collection
    mesh_collection.objects.link(newNoseMesh_object)

    bpy.object = newNoseMesh
    newMeshMat = bpy.data.materials.new('New Mesh Mat')
    newMeshMat.use_nodes=True
    nodes = newMeshMat.node_tree.nodes
        

    newMeshMat.node_tree.nodes["Principled BSDF"].inputs[0].default_value = (0.8, 0, 0.704733,1)
    newMeshMat.node_tree.nodes["Principled BSDF"].inputs[18].default_value = 1


    

    newNoseMesh_object.active_material = newMeshMat

    newNoseMesh_object.active_material.blend_method = 'BLEND'
    
    
    
    
    #insert mesh 2
    vertices = noseLoop
    edges = []
    faces = [[14,24,23],[14,24,22],[24,18,23],[24,17,22],[24,18,29],[24,29,17],[18,23,41],[17,22,40],[18,41,29],[29,17,40],[29,41,39],[29,40,39],[1,5,23],[5,41,23],[41,39,28],[39,40,28],[5,41,3],[3,41,7],[7,41,28],[28,40,6],[6,40,2],[22,2,4],[40,22,2],[22,4,0],[3,7,35],[7,35,28],[35,34,28],[28,34,6],[6,34,2],[34,2,26],[2,4,26],[4,31,26],[4,0,31],[32,1,5],[32,5,27],[5,27,3],[32,36,27],[3,27,35],[35,36,27],[34,35,36],[36,34,26],[36,26,31]]
    oldNoseMesh = bpy.data.meshes.new('oldNoseMesh')
    oldNoseMesh.from_pydata(vertices, edges, faces)
    oldNoseMesh.update()
    # make object from mesh
    oldNoseMesh_object = bpy.data.objects.new('oldNoseMesh_object', oldNoseMesh)

    # add object to scene collection
    mesh_collection.objects.link(oldNoseMesh_object)

    bpy.object = oldNoseMesh
    meshMat = bpy.data.materials.new('Mesh Mat')
    meshMat.use_nodes=True
    nodes = meshMat.node_tree.nodes
        

    meshMat.node_tree.nodes["Principled BSDF"].inputs[0].default_value = (0.00205669, 0.8, 0.0157096, 1)
    meshMat.node_tree.nodes["Principled BSDF"].inputs[18].default_value = 1 #.4


    

    oldNoseMesh_object.active_material = meshMat

    oldNoseMesh_object.active_material.blend_method = 'BLEND'
    
    
    
    
    #change opcacity of face
    activeObj = bpy.context.window.scene.objects[0]
    bpy.context.object.active_material.node_tree.nodes["Principled BSDF"].inputs[18].default_value = 0
    bpy.context.object.active_material.blend_method = 'BLEND'
    bpy.context.object.active_material.use_backface_culling = False
    

    #export face
    
    
    exportFileName = activeObj.name
    if "." in activeObj.name:
        print("Yes")
        exportFileName = exportFileName[:-4]
    
    #print(exportFileName)
    #export obj to face to (patientName)MeshNose.obj
    target_file = os.path.join(meshFile_path, exportFileName + ('MeshNose.obj'))

    bpy.ops.export_scene.obj(filepath=target_file)
    
    #delete meshes
    bpy.data.objects['newNoseMesh_object'].select_set(True)
    bpy.ops.object.delete()
    bpy.data.objects['oldNoseMesh_object'].select_set(True)
    bpy.ops.object.delete()
    # solidify face
    activeObj = bpy.context.window.scene.objects[0]
    bpy.context.object.active_material.blend_method = 'OPAQUE'
    
    bpy.context.object.active_material.node_tree.nodes["Principled BSDF"].inputs[18].default_value = 1
    bpy.context.object.active_material.use_backface_culling = False
    
    
    
    
   
    bpy.ops.object.mode_set(mode='SCULPT')
    

    #closes little window
    root.destroy()

root = Tk()

dataPointsButton = Button(root, text="Select Old Nose Data Point File For Patient(.xlsx)", command=selectDataPointsFile)
newDataPointsButton = Button(root, text="Select New Nose Data Point File For Patient(.xlsx)", command=selectNewDataPointsFile, state=tk.DISABLED)
faceObjectButton = Button(root, text="Select 3d Model Patient Face (.obj)", command=selectFaceObjectFile, state=tk.DISABLED)
meshFileExportButton = Button(root, text="Select the Folder You Want to Export meshFile in", command=meshFile, state=tk.DISABLED)
addPointsAndFaceButton = Button(root, text="Add The Patient's Face with Points", command=facePointsAdd, state=tk.DISABLED)
dataPointsButton.grid(row = 0, column = 0)
newDataPointsButton.grid(row = 1, column = 0)
faceObjectButton.grid(row = 2, column = 0)
meshFileExportButton.grid(row = 3, column = 0)
addPointsAndFaceButton.grid(row = 4, column = 0)


root.mainloop()

print(dataPointsFile_path)
print(faceObjectFile_path)








r = 1
wb_objTest = openpyxl.load_workbook(dataPointsFile_path)
wsheetTest = wb_objTest.active

wb_objNew = openpyxl.load_workbook(newDataPointsFile_path)
wsheetNew = wb_objNew.active

这是它输出的错误:

我想知道问题是否可能是我没有正确地将 tkinter 安装到 Blender ./Scripts/modules 文件夹中...

感谢任何帮助,并在此先感谢。

【问题讨论】:

这能回答你的问题吗? ImportError DLL load failed importing _tkinter @RandomDavis 没有,重新安装 64 位和 32 位 python 都没有解决这个问题。即使更改 Blender 在自己的文件结构中使用的 python 版本。 Blender 允许您使用自己的 gui 创建面板、按钮、文件对话框等,因此实际上不需要使用 tkinter。只需使用搅拌机。有关 Blender 脚本的更多详细信息,建议查看 Blender Stack Exchange。 @SylvesterKruin 谢谢,我去看看。我希望我不必重写这个程序,但我想我可能不得不这样做。 @godpleasehelp:我希望它不会那么难(我自己从来没有在 Blender 中编写过脚本)。但作为奖励,使用 Blender gui 工具将使它看起来是 Blender 原生的。 :-) 【参考方案1】:

我已经使用 Blender 的内置 GUI 而不是 tkinter 重写了代码。

代码如下:

import bpy
import openpyxl
import os

global file_path

file_path = 'C:\\Users\\USERNAME\Documents\\DigitizedRhinoplasty\\DigitizedRhinoplasty-main'
 
class MyProperties(bpy.types.PropertyGroup):
    dataPointsFile_path : bpy.props.StringProperty(
        name="dataPointsFile_path",
        description="Path to Directory",
        default="",
        maxlen=1024,
        subtype='FILE_PATH')
        
    newDataPointsFile_path : bpy.props.StringProperty(
        name="newDataPointsFile_path",
        description="Path to Directory",
        default="",
        maxlen=1024,
        subtype='FILE_PATH')
        
    faceObjectFile_path : bpy.props.StringProperty(
        name="faceObjectFile_path",
        description="Path to Directory",
        default="",
        maxlen=1024,
        subtype='FILE_PATH')
    
    meshFile_path : bpy.props.StringProperty(
        name="meshFile_path",
        description="Path to Directory",
        default="",
        maxlen=1024,
        subtype='DIR_PATH')
 
 
class ADDONNAME_PT_main_panel(bpy.types.Panel):
    bl_label = "Main Panel"
    bl_idname = "ADDONNAME_PT_main_panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "New Tab"
 
    def draw(self, context):
        layout = self.layout
        scene = context.scene
        mytool = scene.my_tool
        
        layout.prop(mytool, "dataPointsFile_path")
        layout.prop(mytool, "newDataPointsFile_path")
        layout.prop(mytool, "faceObjectFile_path")
        layout.prop(mytool, "meshFile_path")
        
        row = layout.row()
        row.operator("addonname.myop_operator")
        row.operator("addonname.myop2_operator")
        row.operator("addonname.myop3_operator")
        row.operator("addonname.myop4_operator")
        row.operator("addonname.myop5_operator")
 
 
class ADDONNAME_OT_dataPointsFile(bpy.types.Operator):
    bl_label = "data points file"
    bl_idname = "addonname.myop_operator"
    
    def execute(self, context):   
        scene = context.scene
        mytool = scene.my_tool
        
        global dataPointsFile_path
        dataPointsFile_path = file_path + mytool.dataPointsFile_path[1:]
        print(dataPointsFile_path)
        
        return 'FINISHED'
    
class ADDONNAME_OT_newDataPointsFile(bpy.types.Operator):
    bl_label = "new data points file"
    bl_idname = "addonname.myop2_operator"
    
    def execute(self, context):   
        scene = context.scene
        mytool = scene.my_tool
        
        global newDataPointsFile_path
        newDataPointsFile_path = file_path + mytool.newDataPointsFile_path[1:]
        print(newDataPointsFile_path)
        
        return 'FINISHED'
    
class ADDONNAME_OT_faceObjectFile(bpy.types.Operator):
    bl_label = "face object file"
    bl_idname = "addonname.myop3_operator"
    
    def execute(self, context):   
        scene = context.scene
        mytool = scene.my_tool
        
        global faceObjectFile_path
        faceObjectFile_path = file_path + mytool.faceObjectFile_path[1:]
        print(faceObjectFile_path)
        
        return 'FINISHED'
    
class ADDONNAME_OT_meshFile(bpy.types.Operator):
    bl_label = "mesh folder"
    bl_idname = "addonname.myop4_operator" 
    
    def execute(self, context):   
        scene = context.scene
        mytool = scene.my_tool
        
        global meshFile_path
        meshFile_path = file_path + mytool.meshFile_path[1:]
        print(meshFile_path)
        
        return 'FINISHED'
 
class ADDONNAME_OT_addPointsAndFace(bpy.types.Operator):
    bl_label = "add points"
    bl_idname = "addonname.myop5_operator" 
    
    def execute(self, context):   
        scene = context.scene
        mytool = scene.my_tool
        
        r = 1
        wb_obj = openpyxl.load_workbook(dataPointsFile_path)
        wsheet = wb_obj.active

        wb_objNew = openpyxl.load_workbook(newDataPointsFile_path)
        wsheetNew = wb_objNew.active

        #swap y and z invert old z
        #old nose points
        noseLoop = []
        namez = []
        for i in range(1, 49):
            nosePoint = (wsheet["B"+str(i)].value, -wsheet["D"+str(i)].value, wsheet["C"+str(i)].value)
            noseLoop.append(nosePoint)
            namez.append(wsheet["A"+str(i)].value)
            
            
        #new nose points    
        noseLoopNew = []
        namezNew = []
        for i in range(1, 49):
            nosePointNew = (wsheetNew["B"+str(i)].value, -wsheetNew["D"+str(i)].value, wsheetNew["C"+str(i)].value)
            noseLoopNew.append(nosePointNew)
            namezNew.append(wsheetNew["A"+str(i)].value)
       

        #list of colored points so old and new points matchup
        colorList = []
        colorList.append((0., 0., 0.,0.))
        colorList.append((0., 0., 0.,0.))
        colorList.append((1., 0., 0.,0.))
        colorList.append((20., 30., 60.,0.))
        colorList.append((1., 1., 0.,0.))
        colorList.append((0., 0., 1.,0.))
        colorList.append((1., 0., 1.,0.))
        colorList.append((0., 1., 1.,0.))
        colorList.append((1., 1., 1.,0.))
        colorList.append((50., 1., 30.,0.))
        colorList.append((0., 1., 0.,0.))
        colorList.append((40., 100., 0.,0.))
        colorList.append((0., 50., 2.,0.))
        colorList.append((.67,.907,9,1.)) #12
        colorList.append((.1,.85,69.,0.))
        colorList.append((.3,30.,0.,0.))
        colorList.append((40.,1.,0.,0.))
        colorList.append((3.,0.,40.,0.))
        colorList.append((40.,.1,.3,0.))
        colorList.append((0., 250., 40.,0.))
        colorList.append((1.3,40.5,0.,0.))
        colorList.append((40.5,0.,35.5,0.))
        colorList.append((0.,2., 40.,0.))
        colorList.append((.3,40.,.1,0.))
        colorList.append((0.,40.5,.3,0.))
        colorList.append((35.5,40.,0.,0.))
        colorList.append((0., 0., 50.,0.))
        colorList.append((255.,105.,180.,0.))
        colorList.append((.67,.907,9,1.)) #12
        colorList.append((.1,.85,69.,0.))
        colorList.append((.3,30.,0.,0.))
        colorList.append((40.,1.,0.,0.))
        colorList.append((3.,0.,40.,0.))
        colorList.append((40.,.1,.3,0.))
        colorList.append((0., 250., 40.,0.))
        colorList.append((1.3,40.5,0.,0.))
        colorList.append((40.5,0.,35.5,0.))
        colorList.append((0.,2., 40.,0.))
        colorList.append((.3,40.,.1,0.))
        colorList.append((0.,40.5,.3,0.))
        colorList.append((35.5,40.,0.,0.))
        colorList.append((0., 0., 50.,0.))
        colorList.append((255.,105.,180.,0.))
        colorList.append((.67,.907,9,1.)) #12
        colorList.append((.1,.85,69.,0.))
        colorList.append((.3,30.,0.,0.))
        colorList.append((40.,1.,0.,0.))
        colorList.append((3.,0.,40.,0.))
        colorList.append((40.,.1,.3,0.))
        colorList.append((0., 250., 40.,0.))
        colorList.append((1.3,40.5,0.,0.))
        colorList.append((40.5,0.,35.5,0.))
        colorList.append((0.,2., 40.,0.))
        colorList.append((.3,40.,.1,0.))
        colorList.append((0.,40.5,.3,0.))
        colorList.append((35.5,40.,0.,0.))
        colorList.append((0., 0., 50.,0.))
        colorList.append((255.,105.,180.,0.))




        def makeMat(num):

            mat = bpy.data.materials.new(name = namez[i])
            mat.diffuse_color = colorList[i]
            mat.specular_color = (1., 1., 1.)
            return mat

      
        
        imported_object = bpy.ops.import_scene.obj(filepath=faceObjectFile_path)


        for i in range(0, 47):
            bpy.ops.mesh.primitive_uv_sphere_add(radius= r, location=noseLoop[i])
            sphere = bpy.context.object
            sphere.name = namez[i]
            mesh = sphere.data
            mat = makeMat(i)
            mesh.materials.append(mat)
            
            
            
            bpy.ops.mesh.primitive_cube_add(size= r, location=noseLoopNew[i])
            cube = bpy.context.object
            cube.name = (namezNew[i] + ' New')
            mesh = cube.data
            mat = makeMat(i)
            mesh.materials.append(mat)

        bpy.ops.object.select_all(action='DESELECT')

        activeObj = bpy.context.window.scene.objects[0]
         
        for i in range(0, 47):
            bpy.data.objects[namez[i]].select_set(True) # Blender 2.8x

        bpy.context.view_layer.objects.active = activeObj
        bpy.ops.object.parent_set(type='VERTEX')
        bpy.ops.object.select_all(action='DESELECT')
        bpy.ops.object.mode_set(mode='SCULPT')
        
        #insert mesh 1 (old nose mesh)
        # make mesh
        vertices = noseLoopNew
        edges = []
        faces = [[14,24,23],[14,24,22],[24,18,23],[24,17,22],[24,18,29],[24,29,17],[18,23,41],[17,22,40],[18,41,29],[29,17,40],[29,41,39],[29,40,39],[1,5,23],[5,41,23],[41,39,28],[39,40,28],[5,41,3],[3,41,7],[7,41,28],[28,40,6],[6,40,2],[22,2,4],[40,22,2],[22,4,0],[3,7,35],[7,35,28],[35,34,28],[28,34,6],[6,34,2],[34,2,26],[2,4,26],[4,31,26],[4,0,31],[32,1,5],[32,5,27],[5,27,3],[32,36,27],[3,27,35],[35,36,27],[34,35,36],[36,34,26],[36,26,31]]
        newNoseMesh = bpy.data.meshes.new('newNoseMesh')
        newNoseMesh.from_pydata(vertices, edges, faces)
        newNoseMesh.update()
        # make object from mesh
        newNoseMesh_object = bpy.data.objects.new('newNoseMesh_object', newNoseMesh)
        
        # create a collection
        mesh_collection = bpy.data.collections.new('mesh_collection')
        bpy.context.scene.collection.children.link(mesh_collection)
        
        # add object to scene collection
        mesh_collection.objects.link(newNoseMesh_object)

        bpy.object = newNoseMesh
        newMeshMat = bpy.data.materials.new('New Mesh Mat')
        newMeshMat.use_nodes=True
        nodes = newMeshMat.node_tree.nodes
            
        newMeshMat.node_tree.nodes["Principled BSDF"].inputs[0].default_value = (0.8, 0, 0.704733,1)
        newMeshMat.node_tree.nodes["Principled BSDF"].inputs[18].default_value = 1

        newNoseMesh_object.active_material = newMeshMat
        newNoseMesh_object.active_material.blend_method = 'BLEND'
        
        #insert mesh 2
        vertices = noseLoop
        edges = []
        faces = [[14,24,23],[14,24,22],[24,18,23],[24,17,22],[24,18,29],[24,29,17],[18,23,41],[17,22,40],[18,41,29],[29,17,40],[29,41,39],[29,40,39],[1,5,23],[5,41,23],[41,39,28],[39,40,28],[5,41,3],[3,41,7],[7,41,28],[28,40,6],[6,40,2],[22,2,4],[40,22,2],[22,4,0],[3,7,35],[7,35,28],[35,34,28],[28,34,6],[6,34,2],[34,2,26],[2,4,26],[4,31,26],[4,0,31],[32,1,5],[32,5,27],[5,27,3],[32,36,27],[3,27,35],[35,36,27],[34,35,36],[36,34,26],[36,26,31]]
        oldNoseMesh = bpy.data.meshes.new('oldNoseMesh')
        oldNoseMesh.from_pydata(vertices, edges, faces)
        oldNoseMesh.update()
        # make object from mesh
        oldNoseMesh_object = bpy.data.objects.new('oldNoseMesh_object', oldNoseMesh)

        # add object to scene collection
        mesh_collection.objects.link(oldNoseMesh_object)

        bpy.object = oldNoseMesh
        meshMat = bpy.data.materials.new('Mesh Mat')
        meshMat.use_nodes=True
        nodes = meshMat.node_tree.nodes       

        meshMat.node_tree.nodes["Principled BSDF"].inputs[0].default_value = (0.00205669, 0.8, 0.0157096, 1)
        meshMat.node_tree.nodes["Principled BSDF"].inputs[18].default_value = 1 #.4  

        oldNoseMesh_object.active_material = meshMat

        oldNoseMesh_object.active_material.blend_method = 'BLEND'
        
        #change opcacity of face
        activeObj = bpy.context.window.scene.objects[0]
        bpy.context.object.active_material.node_tree.nodes["Principled BSDF"].inputs[18].default_value = 0
        bpy.context.object.active_material.blend_method = 'BLEND'
        bpy.context.object.active_material.use_backface_culling = False
        

        #export face
        
        
        exportFileName = activeObj.name
        if "." in activeObj.name:
            print("Yes")
            exportFileName = exportFileName[:-4]
        
        #print(exportFileName)
        #export obj to face to (patientName)MeshNose.obj
        target_file = os.path.join(meshFile_path, exportFileName + ('MeshNose.obj'))

        bpy.ops.export_scene.obj(filepath=target_file)
        
        #delete meshes
        bpy.data.objects['newNoseMesh_object'].select_set(True)
        bpy.ops.object.delete()
        bpy.data.objects['oldNoseMesh_object'].select_set(True)
        bpy.ops.object.delete()
        # solidify face
        activeObj = bpy.context.window.scene.objects[0]
        bpy.context.object.active_material.blend_method = 'OPAQUE'
        
        bpy.context.object.active_material.node_tree.nodes["Principled BSDF"].inputs[18].default_value = 1
        bpy.context.object.active_material.use_backface_culling = False
        
        bpy.ops.object.mode_set(mode='SCULPT')
        
        return 'FINISHED'
 
 
classes = [MyProperties, ADDONNAME_PT_main_panel, ADDONNAME_OT_dataPointsFile, 
            ADDONNAME_OT_newDataPointsFile, ADDONNAME_OT_faceObjectFile, ADDONNAME_OT_meshFile,
            ADDONNAME_OT_addPointsAndFace]
 
def register():
    for cls in classes:
        bpy.utils.register_class(cls)
        
    bpy.types.Scene.my_tool = bpy.props.PointerProperty(type=MyProperties)
 
def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)
        
    del bpy.types.Scene.my_tool
 
 
 
if __name__ == "__main__":
    register()

希望这对某人有所帮助!

【讨论】:

以上是关于如何让 tkinter 与 Blender v2.90 一起工作?的主要内容,如果未能解决你的问题,请参考以下文章

在 Blender 脚本中测量路径长度?

如何使用 tkinter 在 python 中嵌入 python 解释器框架?

如何让 Pixate v2 实时 CSS 与 Xcode 5 一起使用

如何分析Blender的源码

让 tkinter 在带有 asdf 的 macos 上使用 python 3.x

第九节 关于blender点对齐的方法