Radiobutton in Tabelle verwenden

Fragen zu Tkinter.
Antworten
Nobuddy
User
Beiträge: 996
Registriert: Montag 30. Januar 2012, 16:38

Hallo zusammen

Ich möchte Daten in einer Listbox mit Tabellenaufbau durch Radiobutton auswählen.
Bei meinem Konstrukt, was lauffähig und Ihr somit testen könnt, stimmt zwar das Layout aber das Auswählen durch die Radiobuttons funktioniert nicht.

Ich poste hier mal meinen Code und hoffe Ihr könnt mir da weiterhelfen.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# For Python3.x

import os
import sys
import tkinter as tk


"""Hauptkonfiguration für die GUI Tkinter."""
CONFIG = {
    'button_width' : 12,
    'btxt_bground': 'darkgrey', # Buttons
    'bfont_white': 'white',
    'big_font': ('NimbusSansL', 14), # Buttons, Texteingabe
    'txt_bground': 'grey', # Texteingabe, Textfenster, Buttons
    'back_ground' : 'darkgrey'
    }


class TabelleWork(object):
    """
    Listbox mit Scrollmenü.
    Tabellarische Ausgabe der Daten.
    Auswahl von Datensätze durch Radiobutton
    """

    def __init__(self, controller, result, name, max_width):

        self.root = tk.Toplevel()
        self.controller = controller
        self.conf = CONFIG
        self.result = result
        self.label_names = name
        self.max_width = max_width

        self.frame = tk.Frame(self.root, bg='#822')
        self.frame.pack(side='top', expand=False)
        self.winLabel = tk.Label(self.frame)
        self.winLabel.pack(expand=False)

        self.button_frame = tk.Label(self.frame,
            bg=self.conf['back_ground'])
        self.button_frame.pack()


    def set_scrolled_tables(self):

        zeilen = len(self.result)
        if zeilen == 0:
            return '', self.root.destroy()

        tk.Button(self.button_frame, bg=self.conf['txt_bground'],
            width=self.conf['button_width'],
            font=(self.conf['big_font']), text="übernehmen",
            command=self.controller.end
            ).grid(row=0, column=1, sticky=tk.SW)
        tk.Button(self.button_frame, bg=self.conf['txt_bground'],
            width=self.conf['button_width'],
            font=(self.conf['big_font']), text="Schließen",
            command=self.controller.close
            ).grid(row=0, column=2, sticky=tk.SE)

        self.w_max = sum([row for i, row in enumerate(self.max_width)])
        self.names = len(self.label_names)
        h_now = zeilen * 60
        self.h_max = self.root.winfo_screenheight() - 120
        if h_now < self.h_max:
            self.h_max = h_now
        
        self.tabellenWindow = tk.Frame(self.winLabel)
        self.tabellenWindow.grid(row=0, column=0, sticky='nswe')
        self.tabellenWindow.grid_rowconfigure(0, weight=1)
        self.tabellenWindow.grid_columnconfigure(0, weight=1)

        ## scrollbar erstellen
        yscrollbar = tk.Scrollbar(self.tabellenWindow)
        yscrollbar.grid(row=0, column=1, sticky='ns')

        label_container = tk.Frame(self.tabellenWindow)
        label_container.grid(row=0, column=0, sticky=tk.NS)

        self.canvas = tk.Canvas(self.tabellenWindow, bd=0, 
            height=self.h_max, scrollregion=(0, 0, self.h_max, 500),
            yscrollcommand=yscrollbar.set)
        self.canvas.grid(row=0, column=0, sticky='nswe')
        self.label_frame = tk.Frame(self.canvas)

        self.xpos = 0
        self.ypos = 0
        self.entry_ipadx = 5 # Abstand zu Text in x
        self.entry_ipady = 2 # Abstand zu Text in y

        self.set_labels()
        self.set_entrys()

        yscrollbar = tk.Scrollbar(self.tabellenWindow)
        yscrollbar.grid(row=0, column=1, sticky='ns')
        yscrollbar.config(command=self.canvas.yview)

        self.canvas.update_idletasks()
        x, y, w, h = self.canvas.bbox(tk.ALL)
        self.canvas.config(width=w, yscrollcommand=yscrollbar.set)
        self.canvas.config(scrollregion=(x, y, w, h), width=w,
            height=self.h_max)


    def set_labels(self):
        """Benennungsspalte erstellen"""

        if self.names > 0:
            labels = list()
            for s in range(self.names):
                label = tk.Label(self.canvas, width=self.max_width[s],
                    text=self.label_names[s], font=self.conf['big_font'],
                    bg=self.conf['btxt_bground'], fg=self.conf['bfont_white'],
                    bd=1, highlightthickness=1, anchor=tk.W)
                label.grid(row=0, column=s, padx=self.entry_ipadx,
                    pady=self.entry_ipady)
                self.canvas.create_window(self.xpos, self.ypos,
                    window=label,anchor='nw')
                self.xpos += label.winfo_reqwidth()
                labels.append(label)
            self.ypos += label.winfo_reqheight()


    def set_entrys(self):
        """Tabellenspalte erstellen"""

        self.entry_vars = list()
        for i, row in enumerate(self.result):
            self.xpos = 0
            data = list()
            for s, width in enumerate(self.max_width):
                var = tk.StringVar()
                if s == 0:
                    self.radio = tk.Radiobutton(self.canvas, width=1,
                        textvariable=var, value=var,
                        command=lambda: self.nullmaker(var))
                    self.radio.grid(row=i, column=s)
                    self.radio.bind("<Button-1>", self.eventMouseClick)
                    self.canvas.create_window(self.xpos, self.ypos,
                        window=self.radio,anchor='nw')
                    self.xpos += self.radio.winfo_reqwidth()
                if s > 0:
                    self.entry = tk.Entry(self.canvas, textvariable=var,
                        width=width, font=(self.conf['big_font']),
                        bg=self.conf['txt_bground'], bd=1,
                        highlightthickness=1)
                    self.entry.grid(row=i, column=s, padx=self.entry_ipadx,
                        pady=self.entry_ipady)
                    self.canvas.create_window(self.xpos, self.ypos,
                        window=self.entry,anchor='nw')
                    self.xpos += self.entry.winfo_reqwidth()
                var.set(row[s])
                data.append(var)
            self.entry_vars.append(data)
            self.ypos += self.entry.winfo_reqheight()


    def eventMouseClick(self, event):
        print(event, self.entry.get())


    def nullmaker(self, var):
        print('Gewählt wurde: ', self.entry.get(), var)


    def run(self):
        self.set_scrolled_tables()
        self.root.mainloop()


class Controller(object):

    def __init__(self, result, name, max_width):
        data = list()
        for i, row in enumerate(result):
            line = list()
            line.append(0)
            for i in range(len(row)):
                line.append(row[i])
            data.append(line)
        result = data
        data = list()
        for i, row in enumerate([name]):
            data.append('<x>')
            for i in range(len(row)):
                data.append(row[i])
        name = data
        data = list()
        for i, row in enumerate([max_width]):
            data.append(3)
            for i in range(len(row)):
                data.append(row[i])
        max_width = data

        self.model = Model(result, name, max_width)
        self.view = TabelleWork(self, self.model.result, self.model.name,
            self.model.max_width)
    
    def end(self):
        self.view.root.quit()
        return self.view.root.destroy()

    def close(self):
        self.view.root.quit()
        self.view.root.destroy()
        return None

    def get_data(self):
        workline = list()
        for entry_var in self.view.entry_vars:
            line = list()
            for i in range(len(entry_var)):
                line.append(entry_var[i].get())
            workline.append(line)
        mylist = list()
        for i, row in enumerate(workline):
            mylist.append(row[1:])
        return mylist

    def run(self):
        self.view.run()
        #print(self.get_data())
        return self.get_data()


class Model(object):

    def __init__(self, result, name, max_width):
        self.result = result
        self.name = name
        self.max_width = max_width


def main():
    try:
        Controller(result, name, max_width).run()
    except NameError:
        result = [['001', '123456', 'Kopierpapier A4', '500'],
            ['002', '987456', 'Kunststoffordner A4, 80 mm', '20'],
            ['003', '04711X', 'Glasmalfarbe rot, 30 ml', '1'],
            ['004', '454512', 'Kunststofflineal 30 cm', '10']]
        name = ['Lieferant', 'Artikel', 'Beschreibung', 'VE']
        max_width = [15, 15, 30, 30]
        Controller(result, name, max_width).run()


if __name__ == '__main__':
    main()
Grüße Nobuddy
Nobuddy
User
Beiträge: 996
Registriert: Montag 30. Januar 2012, 16:38

Wie kann ich in einer Tabellenausgabe (canvas) einen Radiobutton mit der jeweiligen Tabellenzeile verknüpfen, daß bei Auswahl des Radiobuttons in einer Zeile, die ausgewählte Zeile ausgegeben wird?
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Nobuddy

Habe etwas in dein Skript reingewurstelt. Mit der Schaltfläche 'übernehmen' wird die mit dem Radiobutton selektierte Zeile in der Methode 'Controller.end' ausgegeben:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# For Python3.x

import os
import sys
import tkinter as tk
from functools import partial


"""Hauptkonfiguration für die GUI Tkinter."""
CONFIG = {
    'button_width' : 12,
    'btxt_bground': 'darkgrey', # Buttons
    'bfont_white': 'white',
    'big_font': ('NimbusSansL', 14), # Buttons, Texteingabe
    'txt_bground': 'grey', # Texteingabe, Textfenster, Buttons
    'back_ground' : 'darkgrey'
    }


class TabelleWork(object):
    """
    Listbox mit Scrollmenü.
    Tabellarische Ausgabe der Daten.
    Auswahl von Datensätze durch Radiobutton
    """

    def __init__(self, controller, result, name, max_width):
        
        self.root = tk.Toplevel()
        self.controller = controller
        self.root.lift(controller.app_win)
        self.conf = CONFIG
        self.result = result
        self.label_names = name
        self.max_width = max_width

        self.frame = tk.Frame(self.root, bg='#822')
        self.frame.pack(side='top', expand=False)
        self.winLabel = tk.Label(self.frame)
        self.winLabel.pack(expand=False)
        self.radio_var = tk.IntVar() #neu
        self.button_frame = tk.Label(self.frame,
            bg=self.conf['back_ground'])
        self.button_frame.pack()


    def set_scrolled_tables(self):

        zeilen = len(self.result)
        if zeilen == 0:
            return '', self.root.destroy()

        tk.Button(self.button_frame, bg=self.conf['txt_bground'],
            width=self.conf['button_width'],
            font=(self.conf['big_font']), text="übernehmen",
            command=self.controller.end
            ).grid(row=0, column=1, sticky=tk.SW)
        tk.Button(self.button_frame, bg=self.conf['txt_bground'],
            width=self.conf['button_width'],
            font=(self.conf['big_font']), text="Schließen",
            command=self.controller.close
            ).grid(row=0, column=2, sticky=tk.SE)

        self.w_max = sum([row for i, row in enumerate(self.max_width)])
        self.names = len(self.label_names)
        h_now = zeilen * 60
        self.h_max = self.root.winfo_screenheight() - 120
        if h_now < self.h_max:
            self.h_max = h_now
       
        self.tabellenWindow = tk.Frame(self.winLabel)
        self.tabellenWindow.grid(row=0, column=0, sticky='nswe')
        self.tabellenWindow.grid_rowconfigure(0, weight=1)
        self.tabellenWindow.grid_columnconfigure(0, weight=1)

        ## scrollbar erstellen
        yscrollbar = tk.Scrollbar(self.tabellenWindow)
        yscrollbar.grid(row=0, column=1, sticky='ns')

        label_container = tk.Frame(self.tabellenWindow)
        label_container.grid(row=0, column=0, sticky=tk.NS)

        self.canvas = tk.Canvas(self.tabellenWindow, bd=0,
            height=self.h_max, scrollregion=(0, 0, self.h_max, 500),
            yscrollcommand=yscrollbar.set)
        self.canvas.grid(row=0, column=0, sticky='nswe')
        self.label_frame = tk.Frame(self.canvas)

        self.xpos = 0
        self.ypos = 0
        self.entry_ipadx = 5 # Abstand zu Text in x
        self.entry_ipady = 2 # Abstand zu Text in y

        self.set_labels()
        self.set_entrys()

        yscrollbar = tk.Scrollbar(self.tabellenWindow)
        yscrollbar.grid(row=0, column=1, sticky='ns')
        yscrollbar.config(command=self.canvas.yview)

        self.canvas.update_idletasks()
        x, y, w, h = self.canvas.bbox(tk.ALL)
        self.canvas.config(width=w, yscrollcommand=yscrollbar.set)
        self.canvas.config(scrollregion=(x, y, w, h), width=w,
            height=self.h_max)


    def set_labels(self):
        """Benennungsspalte erstellen"""

        if self.names > 0:
            labels = list()
            for s in range(self.names):
                label = tk.Label(self.canvas, width=self.max_width[s],
                    text=self.label_names[s], font=self.conf['big_font'],
                    bg=self.conf['btxt_bground'], fg=self.conf['bfont_white'],
                    bd=1, highlightthickness=1, anchor=tk.W)
                label.grid(row=0, column=s, padx=self.entry_ipadx,
                    pady=self.entry_ipady)
                self.canvas.create_window(self.xpos, self.ypos,
                    window=label,anchor='nw')
                self.xpos += label.winfo_reqwidth()
                labels.append(label)
            self.ypos += label.winfo_reqheight()
        
    def set_entrys(self):
        """Tabellenspalte erstellen"""

        self.entry_vars = list()
        #self.radio_var = tk.IntVar()
        for i, row in enumerate(self.result):
            #print('A:', i) #, row)
            self.xpos = 0
            data = list()
            for s, width in enumerate(self.max_width):
                #print('B:', s)
                var = tk.StringVar()
                if s == 0:
                    # Radio-Button
                    radio = tk.Radiobutton(self.canvas, text=i,
                        variable=self.radio_var, value=i, width=1)
                    radio.grid(row=i, column=s)
                    # Radio-Button auf Canvas platzieren
                    self.canvas.create_window(self.xpos, self.ypos,
                        window=radio,anchor='nw')
                    self.xpos += radio.winfo_reqwidth()
                    
                if s > 0:
                    self.entry = tk.Entry(self.canvas, textvariable=var,
                        width=width, font=(self.conf['big_font']),
                        bg=self.conf['txt_bground'], bd=1,
                        highlightthickness=1)
                    self.entry.grid(row=i, column=s, padx=self.entry_ipadx,
                        pady=self.entry_ipady)
                    self.canvas.create_window(self.xpos, self.ypos,
                        window=self.entry,anchor='nw')
                    self.xpos += self.entry.winfo_reqwidth()
                var.set(row[s])
                data.append(var)
            self.entry_vars.append(data)
            self.ypos += self.entry.winfo_reqheight()


    def eventMouseClick(self, event):
        print(event, self.entry.get())


    def nullmaker(self, nr):
        print('Radio:', nr)
        return
        print(var.get())
        #print('Gewählt wurde: ', self.entry.get(), var)


    def run(self):
        self.set_scrolled_tables()
        self.controller.app_win.mainloop()


class Controller(object):

    def __init__(self, result, name, max_width):
        self.app_win = tk.Tk()
        
        data = list()
        for i, row in enumerate(result):
            line = list()
            line.append(0)
            for i in range(len(row)):
                line.append(row[i])
            data.append(line)
        result = data
        data = list()
        for i, row in enumerate([name]):
            data.append('<x>')
            for i in range(len(row)):
                data.append(row[i])
        name = data
        data = list()
        for i, row in enumerate([max_width]):
            data.append(3)
            for i in range(len(row)):
                data.append(row[i])
        max_width = data

        self.model = Model(result, name, max_width)
        self.view = TabelleWork(self, self.model.result, self.model.name,
            self.model.max_width)
        
        self.view.radio_var.set(0)
        
    def end(self):
        selected_radio_button = self.view.radio_var.get()
        print('Selected row:', selected_radio_button)
        
        selected_row_data = self.view.entry_vars[selected_radio_button]
 
        for index, entry_var in enumerate(selected_row_data):
            print("{0}: {1}".format(
                self.view.label_names[index], entry_var.get()))
 
#        self.view.root.quit()
#        return self.view.root.destroy()

    def close(self):
        self.view.root.quit()
        self.view.root.destroy()
        return None

    def get_data(self):
        workline = list()
        for entry_var in self.view.entry_vars:
            line = list()
            for i in range(len(entry_var)):
                line.append(entry_var[i].get())
            workline.append(line)
        mylist = list()
        for i, row in enumerate(workline):
            mylist.append(row[1:])
        return mylist

    def run(self):
        self.view.run()
        #print(self.get_data())
        #return self.get_data()


class Model(object):

    def __init__(self, result, name, max_width):
        self.result = result
        self.name = name
        self.max_width = max_width

def main():
    try:
        Controller(result, name, max_width).run()
    except NameError:
        result = [['001', '123456', 'Kopierpapier A4', '500'],
            ['002', '987456', 'Kunststoffordner A4, 80 mm', '20'],
            ['003', '04711X', 'Glasmalfarbe rot, 30 ml', '1'],
            ['004', '454512', 'Kunststofflineal 30 cm', '10']]
        name = ['Lieferant', 'Artikel', 'Beschreibung', 'VE']
        max_width = [15, 15, 30, 30]
        Controller(result, name, max_width).run()

if __name__ == '__main__':
    main()
Gruss wuf :wink:
Take it easy Mates!
Nobuddy
User
Beiträge: 996
Registriert: Montag 30. Januar 2012, 16:38

Hallo wuf, echt super funktioniert prima, werde Deinen Beitrag dazu studieren. :wink:

Beim Radiobutton wurde 'command' entfernt.
Besteht da trotzdem die Möglichkeit, beim Betätigen des Radiobuttons, einen Befehl mit 'command' durchzuführen?

Grüße und Danke
Nobuddy

PS: Nachtrag
Meine Frage zu command im Radiobutton, konnte ich mir selbst beantworten.

Code: Alles auswählen

radio = tk.Radiobutton(self.canvas, text=i,
                        variable=self.radio_var, value=i, width=1,
                        command=lambda: self.controller.end())
Gibt gleich die ausgewählte Position aus, so daß ich den Übernehmen-Button für eine andere Aufgabe verwenden kann.

Die Aufgabe, welche ich dadurch umsetzen möchte, ist bei Lieferantenbestellungen beim Betätigen des Radibutton, Alternativen von gleichen Produkten anderer Lieferanten ausgeben zu lassen, um die Datenzeile durch einen Alternativlieferant zu ersetzen.
Antworten