python学习之tkinter 从一个错误说起

开宗明义,最近几天在学习tkinter,开发界面,中间参考过很多代码,在借鉴别人代码时,遇到了这样的错误:
_tkinter.TclError: cannot use geometry manager pack inside . which already has slaves managed by grid
这个错误的意思是:不能在内部使用pack进行布局,因为这个‘子控件’已经通过grid管理了
这是一个比较常见的错误,如果混用grid和pack进行布局的话就会报错,
在我的代码中出现的错误不是这个提示的错误,毕竟提示就是提示,不是完全准确。
在我的代码中使用到了Frame,这是一个容器,可以用来承载放置其他GUI元素:
在构建tkinter界面过程中,首先需要实例化Tk
root=tkinter.TK()
在我的代码中也用到了Frame
在构建一个Frame时需要引入其父控件root,通过:

class TestFrame(Frame):  # 继承Frame类
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.root = master  # 定义内部变量root
        self.itemName = StringVar()
        self.createPage()

其中的master在实例化时传入的参数即为以上定义的主窗口root
然后我在该Frame中生成了一个Label控件

    def createPage(self):
        #Label(self, text='4G测试').pack()
        #如果self改成self.root就不可以,因为label是frame的内容,不是root的内容
        netLabel = Label(self.root, text='显示框', font=('Arial', 12)).grid(row=0, column=0, padx=2, pady=2, sticky='w')
        self.shellSpace = Text(self, wrap=WORD, width=70, height=15)

此时就报出了文章开头所说的错误:
因为这个Label是在Frame下建的,是该Frame的子控件,不是root的子控件,需要使用self,这个self指的是这个继承了Frame的类的实例。

然后就涉及到一个写法失误造成的错误:

以下贴出了整个类:

class TcpFrame(Frame):  # 继承Frame类
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.root = master  # 定义内部变量root
        self.createPage()

    def createPage(self):
        frameConfig = Frame(self)
        frameConfig.grid(row=1, column=0)
        labelConfig = Label(frameConfig, text='网络配置', font=('Arial', 12), bg='green').grid(row=1, column=1, padx=2,pady=2, sticky='w')
        labelProtocol = Label(frameConfig, text='(1)协议类型', font=('Arial', 12), bg='red').grid(row=2, column=1, padx=2,pady=2, sticky='w')
        protocol = StringVar(value='TCP')
        entryConfig = Entry(frameConfig, textvariable=protocol).grid(row=3, column=1, padx=2, pady=2, sticky='w')
        labelAddress = Label(frameConfig, text='(2)IP地址', font=('Arial', 12), bg='red').grid(row=4, column=1, padx=2,pady=2, sticky='w')
        ip = StringVar(value='192.168.1.100')
        entryAddress = Entry(frameConfig, textvariable=ip).grid(row=5, column=1, padx=2, pady=2, sticky='w')
        labelPort = Label(frameConfig, text='(3)端口号', font=('Arial', 12), bg='red').grid(row=6, column=1, padx=2,pady=2, sticky='w')
        port = StringVar(value=8080)
        entryPort = Entry(frameConfig, textvariable=port).grid(row=7, column=1, padx=2, pady=2, sticky='w')
        buttonOpen = Button(frameConfig, text='打开', command=self.start).grid(row=8, column=1, padx=2, pady=2, sticky='e')
        spaceBlank = Text(frameConfig, wrap=WORD, width=20, height=15).grid(row=9, column=1, padx=2, pady=2, sticky='w')

        frameData = Frame(self)
        frameData.grid(row=1, column=1)
        labelLog = Label(frameData, text='数据日志', font=('Arial', 12)).grid(row=1, column=1, padx=2, pady=2, sticky='w')
        logText = Text(frameData, wrap=WORD, width=60, height=20).grid(row=2, column=1, padx=2, pady=2, sticky='w')
        labelTran = Label(frameData, text='发送数据', font=('Arial', 12)).grid(row=3, column=1, padx=2, pady=2, sticky='w')
        tranText = Text(frameData, wrap=WORD, width=60, height=5).grid(row=4, column=1, padx=2, pady=2, sticky='w')

    def start(self):
        pass

class NetworkFrame(Frame):  # 继承Frame类
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.root = master  # 定义内部变量root
        self.createPage()

    def createPage(self):
        #Label(self, text='4G测试').pack()
        #如果self改成self.root就不可以,因为label是frame的内容,不是root的内容
        netLabel = Label(self, text='显示框', font=('Arial', 12)).grid(row=0, column=0, padx=2, pady=2, sticky='w')
        self.shellSpace = Text(self, wrap=WORD, width=70, height=15)
        self.shellSpace.grid(row=1, column=0, padx=2, pady=2, sticky='w')
        sendButton = Button(self, text='发送', font=('Arial', 12), command=self.printCommand).grid(row=2, column=0, padx=2,pady=2, sticky='e')

        shellCommand = StringVar()
        shellCommand.set(('ping www.baidu.com', '/my-demo/gcc-linaro-5.3-arm/quectel-CM &'))
        self.shellList = Listbox(self, listvariable=shellCommand, width=70, height=15)
        self.shellList.grid(row=3, column=0, padx=2, pady=2, sticky='w')
    def printCommand(self):
        print(type(self.shellList))
        value = self.shellList.get(self.shellList.curselection())
        self.shellSpace.insert(END, value)
        self.shellSpace.insert(END, '\n')

以上代码为正确写法,此时的‘self.shellList’的类型是
<class ‘tkinter.Listbox’>
<class ‘tkinter.Listbox’>
然而当时为了图方便,也是对知识一知半解的,就图省事,将

self.shellList = Listbox(self, listvariable=shellCommand, width=70, height=15)
self.shellList.grid(row=3, column=0, padx=2, pady=2, sticky='w')
写成了
self.shellList = Listbox(self, listvariable=shellCommand, width=70, height=15).grid(row=3, column=0, padx=2, pady=2, sticky='w')
        

这样在布局时是没有问题的,但是这样操作并未把 Listbox(self, listvariable=shellCommand, width=70, height=15)类赋值给self.shellList,所以在方法:printCommand中调用的时候就会报错:

value = self.shellList.get(self.shellList.curselection())
AttributeError: 'NoneType' object has no attribute 'get'

此时打印self.shellList的类型也会是NoneType,
完毕。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值