Checkbuttons in Tabelle auslesen

Fragen zu Tkinter.
Antworten
DMD-OL
User
Beiträge: 315
Registriert: Samstag 26. Dezember 2015, 16:21

hi
hab einen kleinen code zum auslesen von Checkboxes in einer Tabelle verfasst (DACHTE ICH).
das auslesen funktioniert aber nicht.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import Tkinter
from Tkinter import *

zus_fenster = Tkinter.Tk()
zus_fenster.title('DMD-DATA.soft')
zus_fenster.geometry('1090x675+180+25')


def myfunction(event):
    canvas.configure(scrollregion=canvas.bbox("all"),width=1016,height=250)
def mouse_wheel(event):
     dir = 0
     if event.num == 5 or event.delta == -120:
         dir = 1
     if event.num == 4 or event.delta == 120:
         dir = -1
     canvas.yview_scroll(dir, "units")

myframe=Frame(zus_fenster,relief=GROOVE,width=60,height=50,bd=1)
myframe.place(relx=.02, rely=.6, anchor="w")
canvas=Canvas(myframe)
frame=Frame(canvas)
myscrollbar=Scrollbar(myframe,orient="vertical",command=canvas.yview)
canvas.configure(yscrollcommand=myscrollbar.set)
myscrollbar.pack(side="right",fill="y")
canvas.pack(side="left")
canvas.create_window((50,50),window=frame,anchor='nw')
frame.bind("<Configure>",myfunction)
zus_fenster.bind("<MouseWheel>", mouse_wheel)

cols = []

for i in range(5):
    for j in range(7):
        if j == 0:
            check = Tkinter.StringVar()
            e = Tkinter.Checkbutton(frame, variable=check, relief=RIDGE,width=3,justify="center").grid(row=i, column=j, sticky=NSEW)
            cols.append(e)


def auslesen():

    zskje = []
    for psese in cols:
        zskje.append(check.get())
    print zskje

b_zus15 = Tkinter.Button(zus_fenster, text = 'Auslesen', width=12, relief="raised", fg="#000000000", justify='center', command=auslesen)
b_zus15.place(relx=.8, rely=.9, anchor="w")
zus_fenster.mainloop()
wie kann ich die einzelnen checkbuttons mit null oder eins auslesen?
ich kapier nicht was ich falsch mach :(
Zuletzt geändert von Anonymous am Montag 12. September 2016, 10:33, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

@DMD-OL: hättest Du alles in Funktionen gepackt, und nicht das Erzeugen der Checkbuttons auf oberster Ebene stehen, würdest Du sofort merken, dass der Fehler bei der Variable check liegt. Also alles was jetzt auf Modulebene liegt in eine main-Funktion packen und auch den *-Import entfernen und am Besten mit Objektorientierung anfangen.
DMD-OL
User
Beiträge: 315
Registriert: Samstag 26. Dezember 2015, 16:21

den check variablen eigene namen geben. das hab ich schon verstanden, nur wie?

Code: Alles auswählen

c={}
for x in range(0,2):
        c["stringVar_{0}".format(x)] = Tkinter.StringVar()
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

@DMD-OL: in Deinem Fall würde sich ja, da es sich um eine Tabelle handelt, eine Liste anbieten, in der Du die StringVar-Objekte speicherst.
DMD-OL
User
Beiträge: 315
Registriert: Samstag 26. Dezember 2015, 16:21

also erstmal Tkinter.StringVar() durch Tkinter.IntVar() ersetzen!
und dann noch äh....

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import Tkinter
from Tkinter import *

def main():

    zus_fenster = Tkinter.Tk()
    zus_fenster.title('DMD-DATA.soft')
    zus_fenster.geometry('1090x675+180+25')

    cols = []

    def rechnung_Pdf():

        c = {}

        for i in range(0,2):
            for j in range(1):

                c["stringVar_{0}".format(i)] = Tkinter.IntVar()

                check = Tkinter.StringVar()
                e = Tkinter.Checkbutton(frame, variable=check, relief=RIDGE,width=3,justify="center").grid(row=i, column=j, sticky=NSEW)
                cols.append(e)

    def myfunction(event):
        canvas.configure(scrollregion=canvas.bbox("all"),width=1016,height=250)
    def mouse_wheel(event):
         dir = 0
         if event.num == 5 or event.delta == -120:
             dir = 1
         if event.num == 4 or event.delta == 120:
             dir = -1
         canvas.yview_scroll(dir, "units")

    myframe=Tkinter.Frame(zus_fenster,relief="groove",width=60,height=50,bd=1)
    myframe.place(relx=.02, rely=.6, anchor="w")
    canvas=Tkinter.Canvas(myframe)
    frame=Tkinter.Frame(canvas)
    myscrollbar=Tkinter.Scrollbar(myframe,orient="vertical",command=canvas.yview)
    canvas.configure(yscrollcommand=myscrollbar.set)
    myscrollbar.pack(side="right",fill="y")
    canvas.pack(side="left")
    canvas.create_window((50,50),window=frame,anchor='nw')
    frame.bind("<Configure>",myfunction)
    zus_fenster.bind("<MouseWheel>", mouse_wheel)
    rechnung_Pdf()

    def rechnung_Pdf():

        zskje = []
        for psese in cols:
            print psese
            zskje.append(check.get())
        print zskje

    b_zus15 = Tkinter.Button(zus_fenster, text = 'Auslesen', width=12, relief="raised", fg="#000000000", justify='center', command=rechnung_Pdf)
    b_zus15.place(relx=.8, rely=.9, anchor="w")
    zus_fenster.mainloop()

if __name__ == '__main__':
    main()
besser ???
BlackJack

@DMD-OL: Du sollst nicht einfach *alles* in eine `main()`-Funktion stecken. Dann kannst Du Dir das auch sparen. Von der Modulebene soll nur das Hauptprogramm weg, eben in eine Funktion die deshalb `main()` heisst. Definitionen von Konstanten, Funktionen, und Klassen stehen auf Modulebene. Lokale Funktionen können manchmal vorkommen, sind aber eher selten. Die haben den Nachteil, dass man sie nicht isoliert testen kann.

Du hast immer noch den Sternchen-Import. Und wozu soll `c` gut sein? Mal davon abgesehen, dass das kein guter Name ist. `e` ist ebenfalls ein schlechter Name und ausserdem wird der Grundsätzlich an den Wert `None` gebunden. Das ist nämlich der Rückgabewert von der `grid()`-Methode. Damit wird auch `cols` sinnlos, weil das eine Liste voll mit `None`-Werten ist.

Zwei verschiedene Funktionen mit dem gleichen Namen im gleichen Namensraum zu definieren ist auch nicht wirklich übersichtlich, zumal keine der beiden Funktionen das macht was der Name vorgibt.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi DMD-OL

Hier eine Variante zum herumexperimentieren:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from functools import partial

try:
    # Tkinter for Python 2.xx
    import Tkinter as tk
except ImportError:
    # Tkinter for Python 3.xx
    import tkinter as tk

APP_TITLE = "Checkboxen auslesen"
APP_XPOS = 100
APP_YPOS = 100
APP_WIDTH = 600
APP_HEIGHT = 300

CHECKBOX_ITEMS = [
    'Item-01',
    'Item-02',
    'Item-03',
    'Item-04',
    'Item-05',
    'Item-06',
    'Item-07',
    'Item-08',
    'Item-09',
    'Item-10',
    'Item-11',
    'Item-12',
    'Item-13',
    'Item-14',
    'Item-15',
    'Item-16',
    'Item-17',
    'Item-18',
    'Item-19',
    'Item-20',
    ]

CHECKBOX_COLUMNS = 2
CHECKBOX_ROWS = 10


class Application(tk.Frame):

    def __init__(self, master):
        self.master = master
        self.master.protocol("WM_DELETE_WINDOW", self.close)
        tk.Frame.__init__(self, master)
        
        self.checkbox_states = list()
        self.item_index = 0
        
        self.scroll_plane = tk.Canvas(self, width=1, height=1)
        self.scroll_plane.pack(side='left', fill='both', expand=True)
        self.scroll_plane.bind('<Configure>', self.update_scrollbar)
        
        self.scroll_plane.config(
            scrollregion=self.scroll_plane.bbox("all"))

        vertical_scrollbar=tk.Scrollbar(self,
            orient="vertical", command=self.scroll_plane.yview)
        vertical_scrollbar.pack(side="left", fill="y")
        
        self.scroll_plane.configure(yscrollcommand=vertical_scrollbar.set)
    
        self.checkbox_container = tk.Frame(self.scroll_plane)
        self.checkbox_container.pack()
        
        self.scroll_plane.create_window(10, 10, window=self.checkbox_container,
            anchor='nw', tags='checkbox_container')
        
        for column in range(CHECKBOX_COLUMNS):
            for row in range(CHECKBOX_ROWS):
                self.checkbox_states.append(self.create_checkbox(row, column))
            if self.item_index == len(CHECKBOX_ITEMS):
                break
            
    def create_checkbox(self, row, column):
        item_name = CHECKBOX_ITEMS[self.item_index]
        state_var = tk.IntVar()
        checkbox = tk.Checkbutton(self.checkbox_container,
            text=item_name, variable=state_var)
        checkbox.grid(row=row, column=column)
        checkbox.config(command=partial(
            self.checkbox_callback, item_name, self.item_index))
        self.item_index += 1
        return state_var
    
    def checkbox_callback(self, item_name, index):
        print("Checkbox: {} State = {}".format(
            item_name, self.checkbox_states[index].get()))
    
    def show_checkbox_states(self):
        print('')
        for index, item_name in enumerate(CHECKBOX_ITEMS):
            print("Checkbox: {} State = {}".format(
                item_name, self.checkbox_states[index].get()))
        print('')
            
    def update_scrollbar(self, event):
        if self.bbox('all') != None:
            self.scroll_plane.config(
                scrollregion=self.scroll_plane.bbox('all'))

    def close(self):
        print("Application-Shutdown")
        self.master.destroy()

    
def main():
    app_win = tk.Tk()
    app_win.title(APP_TITLE)
    app_win.geometry("+{}+{}".format(APP_XPOS, APP_YPOS))
    app_win.geometry("{}x{}".format(APP_WIDTH, APP_HEIGHT))
   
    app = Application(app_win)
    app.pack(fill='both', expand=True)
    
    button_frame = tk.Frame(app_win, relief='raised', bd=1, bg='gray70')
    button_frame.pack(fill='x')
    tk.Button(button_frame,
        text="Auslesen", command=app.show_checkbox_states, highlightthickness=0
            ).pack(pady=4)
        
    app_win.mainloop()
 
 
if __name__ == '__main__':
    main()      
Gruss wuf :wink:
Take it easy Mates!
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

@wuf: die globale Variable self.item_index solltest Du entfernen. Ruf create_checkbox doch gleich mit item_name auf. Für reale Szenarien würde der Callback mehr mit row und column anfangen, als mit einem Index. Daher wäre checkbox_state besser eine Liste von Listen um die Tabellenstruktur exakt wiederzugeben. Im ursprünglichen Problem gab es auch nur eine Checkbox pro Zeile.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Sirius3
Danke für deine Hinweise und Anregungen. Habe somit mein Skript deinen Anregungen folgend abgeändert. Hoffe dich richtig verstanden zu haben.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from functools import partial

try:
    # Tkinter for Python 2.xx
    import Tkinter as tk
except ImportError:
    # Tkinter for Python 3.xx
    import tkinter as tk

APP_TITLE = "Checkboxen auslesen"
APP_XPOS = 100
APP_YPOS = 100
APP_WIDTH = 600
APP_HEIGHT = 300

CHECKBOX_ITEMS = [
    'Item-01',
    'Item-02',
    'Item-03',
    'Item-04',
    'Item-05',
    'Item-06',
    'Item-07',
    'Item-08',
    'Item-09',
    'Item-10',
    'Item-11',
    'Item-12',
    'Item-13',
    'Item-14',
    'Item-15',
    'Item-16',
    'Item-17',
    'Item-18',
    'Item-19',
    'Item-20',
    ]

CHECKBOX_COLUMNS = 2
CHECKBOX_ROWS = 10


class Application(tk.Frame):

    def __init__(self, master):
        self.master = master
        self.master.protocol("WM_DELETE_WINDOW", self.close)
        tk.Frame.__init__(self, master)
        
        self.checkbox_states = list()
        
        self.scroll_plane = tk.Canvas(self, width=1, height=1)
        self.scroll_plane.pack(side='left', fill='both', expand=True)
        self.scroll_plane.bind('<Configure>', self.update_scrollbar)
        
        self.scroll_plane.config(
            scrollregion=self.scroll_plane.bbox("all"))

        vertical_scrollbar=tk.Scrollbar(self,
            orient="vertical", command=self.scroll_plane.yview)
        vertical_scrollbar.pack(side="left", fill="y")
        
        self.scroll_plane.configure(yscrollcommand=vertical_scrollbar.set)
    
        self.checkbox_container = tk.Frame(self.scroll_plane)
        self.checkbox_container.pack()
        
        self.scroll_plane.create_window(10, 10, window=self.checkbox_container,
            anchor='nw', tags='checkbox_container')
         
        for item_name in CHECKBOX_ITEMS:
            self.checkbox_states.append(
                self.create_checkbox(item_name))
                        
    def create_checkbox(self, item_name):
        state_var = tk.IntVar()
        checkbox = tk.Checkbutton(self.checkbox_container,
            text=item_name, variable=state_var)
        checkbox.pack()
        checkbox.config(command=partial(
            self.checkbox_callback, item_name, state_var))
        return state_var
    
    def checkbox_callback(self, item_name, state_var):
        print("Checkbox: {} State = {}".format(
            item_name, state_var.get()))
    
    def show_checkbox_states(self):
        print('')
        for index, item_name in enumerate(CHECKBOX_ITEMS):
            print("Checkbox: {} State = {}".format(
                item_name, self.checkbox_states[index].get()))
        print('')
            
    def update_scrollbar(self, event):
        if self.bbox('all') != None:
            self.scroll_plane.config(
                scrollregion=self.scroll_plane.bbox('all'))

    def close(self):
        print("Application-Shutdown")
        self.master.destroy()

    
def main():
    app_win = tk.Tk()
    app_win.title(APP_TITLE)
    app_win.geometry("+{}+{}".format(APP_XPOS, APP_YPOS))
    app_win.geometry("{}x{}".format(APP_WIDTH, APP_HEIGHT))
   
    app = Application(app_win)
    app.pack(fill='both', expand=True)
    
    button_frame = tk.Frame(app_win, relief='raised', bd=1, bg='gray70')
    button_frame.pack(fill='x')
    tk.Button(button_frame,
        text="Auslesen", command=app.show_checkbox_states, highlightthickness=0
            ).pack(pady=4)
        
    app_win.mainloop()
 
 
if __name__ == '__main__':
    main()      
Gruss wuf :wink:
Take it easy Mates!
Antworten