我想切换一个真正的按钮并在tkinter GUI

时间:2016-08-28 13:23:52

标签: python python-2.7 tkinter raspberry-pi raspberry-pi2

我想切换按钮并使用tkinter在标签上显示其更改。

如果我按下按钮,它会在标签上显示“on”,当我再次按下时,它会在标签上显示“off”

所以我尝试这些代码,如果我正在尝试错误的代码,请帮助我使用tkinter编写正确的代码。

我在组合此代码时遇到问题

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)
GPIO.setup(22,GPIO.IN,up_down=GPIO.PUD_UP)

while(1):
    if GPIO.input(22)==1:
        if bs == False :
            x.set("on")
            bs=True
            sleep(0.5)
        else:
            x.set("off")
            bs=False
            sleep(0.5)

这样可以,但我想将它连接到GUI标签上以打开或关闭它。

这是tkinter代码

import tkinter.*

root = tk()
x = StringVar()

s=Label(root,textvariable=x)

s.grid(column=0,row=0)

root.mainloop()

当我尝试组合它时,我就这样做了

from Tkinter import *
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)
GPIO.setup(7,GPIO.IN)

b=False
def check_button1():
    if GPIO.input(7)== 1:
        if b == False :
            labelText1.set("on")
            print"on"
            b=True
            time.sleep(0.5)
        else:
            labelText1.set("off")
            print"off"
            b=False
            time.sleep(0.5)

    mamdouh.after(10,check_button1)

mamdouh = Tk()
labelText1 = StringVar()

x1 = Label(mamdouh,textvariable=labelText1)
x1.config(font=('Helvetica',25,'bold'))
x1.grid(row=0,column=0)

mamdouh.title("mamdouh")
mamdouh.geometry('1200x700')
mamdouh.after(10,check_button1)
mamdouh.mainloop()

但它不起作用它每次按下按钮时都保持空白如果它运行良好我会放17个按钮

我认为问题在于如果将这个法则放在正确的位置并将b变量放在正确的位置,我认为这个if if statment和tkinter之间存在问题,因为我尝试了这个代码,但它的工作完美但是它不是切换按钮所以我想改变这个让我们也在这里添加这个代码:

from Tkinter import *
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BOARD)
GPIO.setup(7,GPIO.IN)

def check_button1():
    if(GPIO.input(7) == GPIO.LOW):
        labelText1.set("on")
    else:
        labelText1.set("off")
    mamdouh.after(10,check_button1)

mamdouh = Tk()
labelText1 = StringVar()

x1 = Label(mamdouh,textvariable=labelText1)
x1.config(font=('Helvetica',25,'bold'))
x1.grid(row=0,column=0)

mamdouh.title("mamdouh")
mamdouh.geometry('1200x700')
mamdouh.after(10,check_button1)
mamdouh.mainloop()

那么我如何才能在标签上设置这个切换按钮?

2 个答案:

答案 0 :(得分:0)

您的问题是识别按钮按下和按钮事件。您的OS鼠标驱动程序为您的鼠标按钮执行此操作。如果您的GPIO模块没有为您执行此操作,则必须通过将当前状态与先前状态进行比较来检测这些事件。 (我在这里忽略了任何可能需要' de-bounce'按钮。)你有点尝试使用time.sleep(.5)调用,但是不要使用time.sleep in gui code。

您的驱动程序应该是独立的,并且独立于除.after所需的root之外的任何tk小部件。对于多个按钮,您将需要自己的GPIOButton类。您的代码是一个起点。 Tkinter允许您将命令绑定到按钮事件。您的类init应该类似地使用和/或关闭事件命令(回调)。

这是一些未经测试的东西,可能会让你开始。

class GPIOButton:
    def __init__(self, master, buttons, command_down=None, command_up=None):
        self.master = master
        self.buttons = buttons
        self.command_down = command_down
        self.command_up = command_up
        GPIO.setmode(GPIO.BOARD)
        for button in buttons:
            GPIO.setup(button, GPIO.IN)
        self.state = [GPIO.HIGH] * len(buttons)  # best initial value?
        self.check_buttons()  # or call this elsewhere
    def check_buttons(self):
        for i, button in enumerate(self.buttons):
            oldstate = self.state[i]
            newstate = GPIO.input(button)
            if oldstate != newstate:
                self.state[i] = newstate
                command = (self.command_down if newstate==GPIO.LOW
                           else self.command_up)
                command(button)
        self.master.after(10, self.check_button)

答案 1 :(得分:0)

让我用免责声明作为答案的前言 - 我没有Raspberry Pi,因此无法验证这是否适用于真实的东西。为了测试,我使用了一个模拟随机按钮按下的代理类。您可能必须根据GPIO接口的工作速度调整DELAY值。

但是,我已将已注释掉的代码放在顶部,显示我认为您需要在代码中使用的代码。

try:
    import Tkinter as tk
    import tkFont
except ImportError:  # Python 3
    import tkinter as tk
    import tkinter.font as tkFont

#import RPi.GPIO as GPIO
#
#GPIO.setmode(GPIO.BOARD)
#
#class GPIOButton(object):
#    """ Encapsulates GPIO button interface. """
#    def __init__(self, pin):
#        self.pin = pin
#        self.status = 0
#        GPIO.setup(pin, GPIO.IN)
#
#    def update_status(self):
#        self.status = GPIO.input(pin) == GPIO.LOW

### Proxy class since I don't have a Rasperry Pi. ###
import random

class GPIOButton(object):
    def __init__(self, pin):
        self.pin = pin
        self.status = 0

    def update_status(self):
        if not random.randint(0, 99) % 20:  # occassionally toggle status
            self.status = not self.status

class App(tk.Frame):
    STRIDE = 8
    DELAY = 100  # delay in millsecs between button status updates

    def __init__(self, gpio_buttons, master=None):
        tk.Frame.__init__(self, master)
        self.grid()
        self.gpio_buttons = gpio_buttons
        self.create_widgets()
        self.after(self.DELAY, self.update_buttons, self.DELAY)  # start updates

    def create_widgets(self):
        self.btn_font = tkFont.Font(family="Helvetica", size=12, weight='bold')
        self.gui_buttons = []
        for i, button in enumerate(self.gpio_buttons):
            is_pressed = tk.BooleanVar()
            is_pressed.set(False)
            radiobutton = tk.Radiobutton(self,
                                         text=format(i+1, '02d'),
                                         font=self.btn_font,
                                         value=True,
                                         variable=is_pressed,
                                         relief=tk.RIDGE)
            row, col = divmod(i, self.STRIDE)
            radiobutton.grid(column=col, row=row)
            self.gui_buttons.append(is_pressed)

    def update_buttons(self, delay):
        for i, gpio_button in enumerate(self.gpio_buttons):
            previous_status = gpio_button.status
            gpio_button.update_status()
            if gpio_button.status != previous_status:
                self.gui_buttons[i].set(gpio_button.status)

        self.after(delay, self.update_buttons, delay)  # rinse and repeat


gpio_buttons = [GPIOButton(pin) for pin in range(16)]
app = App(gpio_buttons)
app.master.title('Rasberry Pi Buttons')
app.mainloop()

这是模拟在我的Windows计算机上运行的内容:

screenshot of display showing the status of all sixteen buttons