1

I have been looking at my code for a while and new to tkinter. The purpose of my code is to display text within the Canvas widget not overlay a label. But unsure how to do this:

My code is as follows:

from tkinter import *

class Example(Frame):

    def printLabel(self):
        self.hello = []
        self.hello.append('Hello')
        self.hello.append('World!')
        return(self.hello)

    def updatePanel(self):
        self.panelA.config(text="{}".format(self.printLabel()))

    def __init__(self, root):
        Frame.__init__(self, root)
        self.buttonA()
        self.viewingPanel()

    def buttonA(self):
        self.firstPage = Button(self, text="Print Text", bd=1, anchor=CENTER, height = 11, width = 13, command=lambda: self.updatePanel())
        self.firstPage.place(x=0, y=0)

    def viewingPanel(self):
        self.panelA = Label(self, bg='white', width=65, height=13, padx=3, pady=3, anchor=NW, text="")
        self.panelA.place(x=100, y=0)
        self.cl= Canvas(self.panelA,bg='WHITE',width=165,height=113,relief=SUNKEN)
        canvas_id = self.cl.create_text(15, 15, anchor="nw")

        self.xb= Scrollbar(self.panelA,orient="horizontal", command=self.cl.xview)
        self.xb.pack(side=BOTTOM,fill=X)
        self.xb.config(command=self.cl.xview)
        self.yb= Scrollbar(self.panelA,orient="vertical", command=self.cl.yview)
        self.yb.pack(side=RIGHT,fill=Y)
        self.yb.config(command=self.cl.yview)

        self.cl.itemconfig(canvas_id,font=('Consolas',9), text="{}".format(self.printLabel()))
        self.cl.configure(scrollregion = self.cl.bbox("all"))
        self.cl.config(xscrollcommand=self.xb.set, yscrollcommand=self.yb.set)
        self.cl.config(width=250,height=150)
        self.cl.pack(side=LEFT,expand=True,fill=BOTH)

def main():
    root = Tk()
    root.title("Tk")
    root.geometry('378x176')
    app = Example(root)
    app.pack(expand=True, fill=BOTH)
    root.mainloop()

if __name__ == '__main__':
    main()

The Hello World! should display without the brackets in the Canvas but the main issue is that when I click on the Button it just overlaps the canvas and prints out the append on to the Label.

The Label should be inside the Canvas.

martineau
  • 119,623
  • 25
  • 170
  • 301
  • `self.hello` is a list and is printed as a list. Change it to `" ".join(self.hello)`. But why do you build it as a list in the first place? Did you want to do `self.hello=""; self.hello += 'Hello'`? – DYZ Jan 12 '19 at 23:33
  • 1
    The brackets are printing because the `printLabel()` method is returning a `list`. You can get rid of them by changing its last line to `return(' '.join(self.hello))`. – martineau Jan 12 '19 at 23:33
  • I don't really understand what you call the "main issue". What do you want to happen when the `Button` is pressed? – martineau Jan 12 '19 at 23:37
  • pythonewbie: If you want to put a `Label` on a `Canvas`, you must first create a `Canvas` `window` object with the `Canvas.create_window()` method and put the `Label` inside **that**. Here's some [documentation](http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/create_window.html) I found. – martineau Jan 12 '19 at 23:45
  • The Append method will be used to add more line of text in further development but the main issue which is being referred to in this question is: when i click the print button i want the text to sit inside the canvas rather than display the text separately on the Label. – pythonewbie Jan 13 '19 at 00:09
  • 1
    When I execute the GUI, the text appears without clicking ButtonA, but when ButtonA is clicked the Hello World text appears as a label over the Canvas. What i am trying to achieve is a GUI which displays text in the Canvas only when the ButtonA is clicked i.e. Hello World! From my perspective i have added a Label then embedded the Label into the Canvas so when the button is clicked it would look like the text is appearing on to the Label. I was struggling to achieve this, any suggestions on this please? – pythonewbie Jan 13 '19 at 00:18
  • 1
    GUI Executed > No Text should be there > ButtonA is clicked > Hello World! > Text should appear in Canvas rather than an overlapped Label. Issue = text appears before clicking and when button is clicked appears on Label – pythonewbie Jan 13 '19 at 00:25
  • @pythonewbie: OK, that's what I needed to know. **Tip:** In the future, when responding specifically to someone's comment, please put "@their_user_id" in it so they will be notified of your reply. – martineau Jan 13 '19 at 02:56

1 Answers1

0

Here's how to fix the "main issue" along with the "brackets issue". The latter is taken care of by using the string join() method as suggested in the comments.

The updatePanel() method has been modified so it first create a Label widget with the text you want displayed in it, followed by a Canvas "window" object specifying that widget as its contents. Code for the way you were attempting to do it was also removed from the other class methods.

from tkinter import *


class Example(Frame):

    def __init__(self, root):
        Frame.__init__(self, root)
        self.buttonA()
        self.viewingPanel()

    def printLabel(self):
        text = []
        text.append('Hello')
        text.append('World!')
        return ' '.join(text)

    def updatePanel(self):
        label = Label(self, bg='white', padx=3, pady=3, anchor=NW,
                      text=self.printLabel())
        label.place(relx=0.5, rely=0.5, anchor=CENTER)
        self.cl.create_window(100, 100, window=label)  # Put Label in a Canvas "window".

    def buttonA(self):
        self.firstPage = Button(self, text="Print Text", bd=1, anchor=CENTER, height=11,
                                width=13, command=lambda: self.updatePanel())
        self.firstPage.place(x=0, y=0)

    def viewingPanel(self):
        self.panelA = Label(self, bg='white', width=65, height=13, padx=3, pady=3,
                            anchor=NW, text="")
        self.panelA.place(x=100, y=0)
        self.cl= Canvas(self.panelA, bg='WHITE', width=165, height=113, relief=SUNKEN)
        canvas_id = self.cl.create_text(15, 15, anchor="nw")

        self.xb= Scrollbar(self.panelA,orient="horizontal", command=self.cl.xview)
        self.xb.pack(side=BOTTOM, fill=X)
        self.xb.config(command=self.cl.xview)
        self.yb= Scrollbar(self.panelA, orient="vertical", command=self.cl.yview)
        self.yb.pack(side=RIGHT, fill=Y)
        self.yb.config(command=self.cl.yview)

        self.cl.itemconfig(canvas_id, font=('Consolas',9), text=self.printLabel())
        self.cl.configure(scrollregion=self.cl.bbox("all"))
        self.cl.config(xscrollcommand=self.xb.set, yscrollcommand=self.yb.set)
        self.cl.config(width=250, height=150)
        self.cl.pack(side=LEFT, expand=True, fill=BOTH)


def main():
    root = Tk()
    root.title("Tk")
    root.geometry('378x176')
    app = Example(root)
    app.pack(expand=True, fill=BOTH)
    root.mainloop()

if __name__ == '__main__':
    main()
martineau
  • 119,623
  • 25
  • 170
  • 301
  • I have noticed if i replace the Hello World! with a longer sentence the Button displays the window is still outside the canvas and has not put the Label in the Canvas. If you keep text within the viewingPanel method the output is fine but when clicking the button the text still appears outside of the Canvas, is there a reason for this or could this be changed please? – pythonewbie Jan 13 '19 at 11:51
  • 1
    Strange things will happen if you put a text obj longer than the Label is wide into a likewise too small Canvas window object. You're basically asking it to do the impossible. You need to make the `Canvas` bigger. – martineau Jan 16 '19 at 16:15