Pergunta

I am currently trying to implement a GUI for a task at work. I have found some open source code (see below) where we make a GUI having 3 pages where one can go between the pages using next/previous buttons. If you run the code you'll see what each button and so on is indended to do.

However, when you run the code and click the "count++" button, the overall count increases by one and not the count for the individual page (e.g. being on page 1 and clicking the count++ 4 times, still makes the count for page 2 or 3, 4 as well, and not zero). The same problem occurs when I try to update the text in each of the textboxes on each page (supposed to be number of clicks), as it won't update. I am not sure how to actually get to the textframe for each individual page.

Any suggestions on where to go from here? In the long run I would like to have scroll-down menus where the selections will be put onto each individual text-frame.

Thanks,

import ttk
from Tkinter import *
import tkMessageBox

class Wizard(object, ttk.Notebook):
    def __init__(self, master=None, **kw):
        npages = kw.pop('npages', 3)
        kw['style'] = 'Wizard.TNotebook'
        ttk.Style(master).layout('Wizard.TNotebook.Tab', '')
        ttk.Notebook.__init__(self, master, **kw)

        self._children = {}

        self.click_count = 0
        self.txt_var = "Default"

        for page in range(npages):
            self.add_empty_page()

        self.current = 0
        self._wizard_buttons()

    def _wizard_buttons(self):
        """Place wizard buttons in the pages."""
        for indx, child in self._children.iteritems():
            btnframe = ttk.Frame(child)
            btnframe.pack(side='left', fill='x', padx=6, pady=4)

            txtframe = ttk.Frame(child)
            txtframe.pack(side='right', fill='x', padx=6, pady=4)

            nextbtn = ttk.Button(btnframe, text="Next", command=self.next_page)
            nextbtn.pack(side='top', padx=6)

            countbtn = ttk.Button(txtframe, text="Count++..", command=self.update_click) 
            countbtn.grid(column=0,row=0)

            txtBox = Text(txtframe,width = 50, height = 20, wrap = WORD)            
            txtBox.grid(column=1,row=0)
            txtBox.insert(0.0, self.txt_var)

            rstbtn = ttk.Button(btnframe, text="Reset count!", command=self.reset_count)
            rstbtn.pack(side='top', padx=6)

            if indx != 0:
                prevbtn = ttk.Button(btnframe, text="Previous",
                    command=self.prev_page)
                prevbtn.pack(side='right', anchor='e', padx=6)

                if indx == len(self._children) - 1:
                    nextbtn.configure(text="Finish", command=self.close)

    def next_page(self):
        self.current += 1

    def prev_page(self):
        self.current -= 1

    def close(self):
        self.master.destroy()

    def add_empty_page(self):
        child = ttk.Frame(self)
        self._children[len(self._children)] = child
        self.add(child)

    def add_page_body(self, body):
        body.pack(side='top', fill='both', padx=6, pady=12)

    def page_container(self, page_num):
        if page_num in self._children:
            return self._children[page_num]
        else:
            raise KeyError("Invalid page: %s" % page_num)

    def _get_current(self):
        return self._current

    def _set_current(self, curr):
        if curr not in self._children:
            raise KeyError("Invalid page: %s" % curr)

        self._current = curr
        self.select(self._children[self._current])

    current = property(_get_current, _set_current)

    def update_click(self):
        self.click_count += 1
        message = "You have clicked %s times now!" % str(self.click_count)
        tkMessageBox.showinfo("monkeybar", message)
        self.txt_var = "Number of clicks: %s" % str(self.click_count) #this will not change the text in the textbox!

    def reset_count(self):
        message = "Count is now 0."
        #ctypes.windll.user32.MessageBoxA(0, message, "monkeybar", 1)
        tkMessageBox.showinfo("monkeybar", message)
        self.click_count = 0

def combine_funcs(*funcs):
    def combined_func(*args, **kwargs):
        for f in funcs:
            f(*args, **kwargs)
        return combined_func

def demo():
    root = Tk()

    nbrpages = 7    

    wizard = Wizard(npages=nbrpages)
    wizard.master.minsize(400, 350)
    wizard.master.title("test of GUI")
    pages = range(nbrpages)

    for p in pages:
        pages[p] = ttk.Label(wizard.page_container(p), text='Page %s'%str(p+1))
        wizard.add_page_body(pages[p])

    wizard.pack(fill='both', expand=True)
    root.mainloop()

if __name__ == "__main__":
    demo()
Foi útil?

Solução

Your update_click method operate on the attribute click_count of your wizard. If you want different count, you could either create a class for your pages and thus, each object would manage its own count, or manage several counter, for instance in a list, the same way you handle your _children list.

For the former case, you can create a page class inheriting ttk.Frame with the body of your _wizard_buttons loop as constructor. In the later case, you could try something like this

class Wizard(object, ttk.Notebook):
    def __init__(self, master=None, **kw):
        [...]
        #replace self.click_count = 0 with
        self.click_counters = [0 for i in range(npages)]

    def update_click(self):
        self.click_counters[self.current] += 1
        # and so on...

Regarding the Text widget update, you can not handle it though a variable, it works with Entry(one line text field) but not on Text (multiline, rich text field). If you continue with Text, the usual recipe to what you seems to want is

text.delete(1.0, END)
text.insert(END, content)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top