【问题标题】:Tkinter buttons don't workTkinter 按钮不起作用
【发布时间】:2015-04-16 09:45:35
【问题描述】:

我正在尝试使用 Python 和 scapy 编写数据包嗅探器,并使用 Tkinter 实现 GUI。除了“退出”按钮外,一切似乎都运行良好。我正在使用代码:

quitButton = Button(main_win,text="Quit", command=lambda:exitClick)
quitButton.pack(side="bottom")

函数exitClick()定义为:

def exitClick(main_win):
    main_win.destroy()
    main_win.quit()
    sys.exit()

但是,当我单击退出按钮时,没有任何反应。我没有按钮按下动画,也没有程序关闭。我需要改变什么?

代码的精简版如下:

import fcntl, easygui, logging
from Tkinter import *
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *

inc_txt_str = ""
out_txt_str = ""

def exitClick(main_win):
    main_win.quit()
    sys.exit()

main_win = Tk()
main_win.withdraw()
frame_incoming = Frame(main_win)
t = Text(frame_incoming, width=45, bg="black", fg="white")
t.pack(fill=BOTH, expand=YES, side="left")
s = Scrollbar(frame_incoming)
s.pack(side="right", fill="y")
s.config(command=t.yview)
t.config(yscrollcommand=s.set)
frame_incoming.pack(side="left")

frame_outgoing = Frame(main_win)
t1 = Text(frame_outgoing, width=45, bg="white", fg="black")
t1.pack(side="left", fill="both", expand=YES)
s1 = Scrollbar(frame_outgoing)
s1.pack(side="right", fill="y")
s1.config(command=t1.yview)
t1.config(yscrollcommand=s1.set)
frame_outgoing.pack(side="left")

border_buttons = Frame(main_win)
border_buttons.pack(side="bottom")

quitButton = Button(main_win,text="Quit", command=lambda:exitClick(main_win))
quitButton.pack(side="bottom")

parseButton = Button(main_win, text='Parse IP')
parseButton.pack(side="bottom")



def eth_addr(a):
    b = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" % (ord(a[0]), ord(a[1]), ord(a[2]), ord(a[3]), ord(a[4]), ord(a[5]))
    return b


class sniffPacket:

    def processIPFrame(self, pkt_type, ip_header, payload):
        fields = struct.unpack("!BBHHHBBHII", ip_header)
        dummy_hdrlen = fields[0] & 0xf
        iplen = fields[2]
        ip_src = payload[12:16]
        ip_dst = payload[16:20]
        ip_frame = payload[0:iplen]
        if pkt_type == socket.PACKET_OUTGOING:
            if self.outgoingIP is not None:
                self.outgoingIP(ip_src, ip_dst, ip_frame)
        else:
            if self.incomingIP is not None:
                self.incomingIP(ip_src, ip_dst, ip_frame)

    def __init__(self, interface_name, incomingIP, outgoingIP):

        self.interface_name = interface_name
        self.incomingIP = incomingIP
        self.outgoingIP = outgoingIP
        self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(ETH_P_ALL))
        self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2 ** 30)
        self.ins.bind((self.interface_name, ETH_P_ALL))
        pkt, sa_ll = self.ins.recvfrom(MTU)
        eth_header = struct.unpack("!6s6sH", pkt[0:14])
        dummy_eth_protocol = socket.ntohs(eth_header[2])
        ip_header = pkt[14:34]
        payload = pkt[14:]
        self.processIPFrame(sa_ll[2], ip_header, payload)

    def getPacket(self):
        pkt, sa_ll = self.ins.recvfrom(MTU)
        eth_header = struct.unpack("!6s6sH", pkt[0:14])
        dummy_eth_protocol = socket.ntohs(eth_header[2])
        ip_header = pkt[14:34]
        payload = pkt[14:]
        self.processIPFrame(sa_ll[2], ip_header, payload)
        main_win.after(500,getPacket())


    def all_interfaces():
        max_possible = 128
        bytes = max_possible * 32
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        names = array.array('B', '\0' * bytes)
        outbytes = struct.unpack('iL', fcntl.ioctl(
            s.fileno(),
            0x8912,  # SIOCGIFCONF
            struct.pack('iL', bytes, names.buffer_info()[0])))[0]
        namestr = names.tostring()
        lst = []
        for i in range(0, outbytes, 40):
            name = namestr[i:i + 16].split('\0', 1)[0]
            ip = namestr[i + 20:i + 24]
            lst.append((name, ip))
        return lst


    def format_ip(addr):
        return str(ord(addr[0])) + '.' + \
               str(ord(addr[1])) + '.' + \
               str(ord(addr[2])) + '.' + \
               str(ord(addr[3]))


    def get_ip_address(ifname):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        return socket.inet_ntoa(fcntl.ioctl(
            s.fileno(),
            0x8915,  # SIOCGIFADDR
            struct.pack('256s', ifname[:15]))[20:24])

def incoming_packet_callback(src, dst, frame_incoming):
    global inc_txt_str
    main_win.deiconify()
    inc_txt_str += "Incoming from "
    inc_txt_str += str(socket.inet_ntoa(src))
    inc_txt_str += "\n"
    t.insert(END, inc_txt_str)
    t.see(END)
    t.update_idletasks()

def outgoing_packet_callback(src, dst, frame_incoming):
    global out_txt_str
    main_win.deiconify()
    out_txt_str += "Outgoing to "
    out_txt_str += str(socket.inet_ntoa(dst))
    out_txt_str += "\n"
    t1.insert(END, out_txt_str)
    t1.see(END)
    t1.update_idletasks()

interface = "wlan0"
ip_s = sniffPacket(interface, incoming_packet_callback, outgoing_packet_callback)
#main_win.after(500,ip_s.getPacket)
main_win.mainloop()

我对 Python 很陌生,我相信我犯了一些导致此问题的重大概念错误。

【问题讨论】:

  • 你在什么平台上运行这个?
  • Linux 现在在 Ubuntu 上运行。另外我对 Python 很陌生,所以我的代码一团糟。但如果你愿意,如果你能帮我,我可以给你看。
  • 我已经添加了代码示例
  • 我认为您不需要所有代码来重现此问题。这段代码只是充满了阻止程序运行的错误,更不用说显示窗口了。如果您希望人们提供帮助,请删除与您问题中的问题无关的所有代码。

标签: python python-2.7 tkinter tk


【解决方案1】:

您使用 lambda 能够将 main_win 变量传递给您的函数,但是您只引用该函数而不是让 lambda 实际调用它。
使用:

Button(..., command=lambda: exitClick(main_win))

【讨论】:

  • 我刚试过这个。没用。我认为问题在于按钮首先不可点击。通常,当您将鼠标悬停在 Tkinter 按钮上时,它会有点沮丧。这在我的程序中没有发生。我也无法将鼠标悬停或单击它。
  • 好吧,从你的问题来看,我并没有真正明白,因为当你点击按钮时,你使用 lambda 的方式确实不会导致任何事情发生。然后您必须发布一个示例代码来演示该问题,因为从您发布的代码中没有任何东西会导致该行为。请阅读 Bryan Oakley 发布的有关如何制作正确示例的链接。
  • 所以我减少了与问题无关的额外代码,并将其归结为这一点。希望这是一个更好的例子。
猜你喜欢
  • 1970-01-01
  • 2014-05-06
  • 1970-01-01
  • 2018-01-24
  • 2019-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-14
相关资源
最近更新 更多