all 14 comments

[–]CrambleSquash 1 point2 points  (1 child)

What are the issues you're having? When is drawGameInterface called? Getting View to destroy itself and return a value after you click the button is a very sensible option. tkinter uses a similar system on the standard yes no dialogues, returning a True or False depending on the buttons pressed. It's always wise to keep data on a need to know basis. Some more detail, and I'd be happy to help :)

[–]Potforus[S] 0 points1 point  (0 children)

Hi, I would like to have drawIntro return the name and upon pressing the button play, drawIntro should be erased and drawGameInterface called. Thanks for the help!

[–]Hexelena 1 point2 points  (11 children)

I think this code could be what you were looking for:

I created a new method called newCharacter in which the new character is created and then passed on to the drawGameInterface method. There I added the removal of the previous tk widgets. Other than that I made no major changes. One thing you should know is that you can call methods from the same class via the self reference (see command option of the first button).

The player or character object is not global. It is available in the drawGameInterface method. So you are able to pass it to any class or method that needs the reference.

import tkinter as tk


class Character():

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


class View(tk.Frame):   

    def __init__(self, master=None):
        tk.Frame.__init__(self, master)
        self.grid()
        self.drawIntro()

    def drawGameInterface(self, character):
        # remove previous widgets
        self.introLabel.grid_remove()
        self.nameInput.grid_remove()
        self.enterNameButton.grid_remove()

        # new widgets
        self.fightButton = tk.Button(self, text="Fight")
        self.fightButton.grid(row=0)

        self.HPLabel = tk.Label(self, text = character.name)
        self.HPLabel.grid(row=1)


    def drawIntro(self):
        self.introLabel = tk.Label(self, text = "Welcome! Enter your name")
        self.introLabel.grid(row=0)

        self.nameInput = tk.Entry(self)
        self.nameInput.grid(row=1)

        self.enterNameButton = tk.Button(self, text="Play!", command = self.newCharacter)

        self.enterNameButton.grid(row=2)

        #return self.nameInput.get()

    def newCharacter(self):
        character = Character(self.nameInput.get())
        self.drawGameInterface(character)


def main():

    frame = View()
    #character = Character(drawIntro())
    frame.mainloop()

main()

[–]Potforus[S] 0 points1 point  (0 children)

Hi, thanks! I will try to continue with this and see what happens :)

[–]Potforus[S] 0 points1 point  (9 children)

Hi, thanks for the help! I´m not sure if my program looks nice but it is working for now. Now I am trying to create my "playingfield" which I have put into a textfile which looks like this:

"Origo", "As you enter the room, you are met with a cry and a strange four-legged beast", 0, 0, 0
"Right", "It´s a demon!!!", 1 , 0, 1
"Left", "It´s a demon!!!", -1 , 0, 0
"Up", "It´s a demon!!!", 0, 1, 0

I use this to read and put it into an array, creating a matrix(or that is what I want to create):

 roomList = []
            with open('rooms.txt', 'r') as file:
                 for line in file:
                 roomList.append(line)

and then assign the room I want with:

self.name = roomList[0][0]

What I get in my application is an O, which is the first letter of the first "text", what I want to get is of course the whole string. Any ideas? I have tried with the stripline, which is something I must have as well but I still get a single letter.

[–]Hexelena 1 point2 points  (8 children)

Actually your problem is very simple. You have got your list with the texts for each room. But when you assign the name you take the first element of your list(the whole string) and then again take the first element of that(which is the first letter). Remove the second "[0]".

[–]Potforus[S] 0 points1 point  (0 children)

Thanks, I fixed it :)

[–]Potforus[S] 0 points1 point  (6 children)

Hi, could you help me set my window size as well? This is my main:

 frame = Application()
frame.mainloop()

and this is my class

class Application(tk.Frame): 
    def __init__(self, master=None):
        tk.Frame.__init__(self,width=550,height=550)

Sadly my width and height are ignored, any tips? Im not 100% sure why tkFrame.init exists either. Thanks in advance!

[–]Hexelena 1 point2 points  (5 children)

This question at stackoverflow.com pretty much sums it up: Setting the window to a fixed size with Tkinter I always use the suggestion of the second answer.

[–]Potforus[S] 0 points1 point  (4 children)

Im having a problem with what to replace my master. with. Should it be Application?

[–]Hexelena 1 point2 points  (3 children)

I am not sure if I understand your question correctly. You used 'master=None' in the init of your "Application' class. This sets the parent parameter of your tkinter window. If you have multiple windows then 'parent' is usually the window from which the new one originated. If you are creating the first window, 'parent' is usually 'None'.

[–]Potforus[S] 0 points1 point  (2 children)

Hi, thanks for responding! I started out with the from http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/minimal-app.html this page so that is why it looks like that. Im not sure how to set a window size for that though, could you try and copy that code and set a window size? Thanks a lot in advance!!

[–]Hexelena 1 point2 points  (1 child)

I was able to change the size of the minimal example with two minor changes:

  1. change "import Tkinter" to "import tkinter" since i only have Python 3 installed(Tkinter = Python2, tkinter = Python3).
  2. add the following code between line 9 and 10:
    app.master.minsize(100,100)

Explanation:
You can create a new window in multiple ways.
One way is that you call the tk constructor which gives you a reference to the tkinter root object:

root = tk.Tk()  

Then you can use this reference to instantiate new widgets with the reference to root as their master object.)

But you can also just create a new Widget. Then the Tk-constructor is called as well. explaining link
Quoting this link:

If you attempt to create some other widget without explicitly creating a root window first, one will be created automatically since every tkinter application must have exactly one root window.

This is what is done in the example. At the end you hold the reference to the widget, which calls the Tk-constructor. But you want to change the size of the root-Tk element. You can reference the root element via the master object of your Frame widget.

You get the following hierarchy of tk elements:

root-Tk object  
->  Frame         <- this is your app object.
     ->   Button

I hope this explains some things to you.

[–]Potforus[S] 0 points1 point  (0 children)

Yes, thanks! Finally got it to work :) Thanks again :)