Python Forum
I want to add a help section to the electronic board game I'm writing.
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
I want to add a help section to the electronic board game I'm writing.
#1
I am in the process of writing an Othello (reversi) game for my mother. It's nearly done, but to polish it off, I want to add a help section. Currently, I've implemented this functionality using tkinter.messagebox.showinfo() but I want a more comprehensive help section, I want it to look nicer, and I don't want that annoying sound to play when the info box appears on the screen.

This is a code sample resembling what I tried before resorting to messageboxes:
from tkinter import *
from tkinter import scrolledtext
from tkinter import messagebox # This still gets used elsewhere, even if I succeed in creating a custom help window.
import time # This also gets used elsewhere.

# Globals containing the help texts in triple quoted strings:
gameRules = """Game Rules

A comprehensive explanation of the gamerules goes here.
"""
applicationHelp = """Application help

An explanation of how the app works goes here.
"""
# For encapsulation purposes, the application goes in here:
# I don't inherit from Frame or anything. You'll see. It works.
class OthelloGame:
    bgAndBoardColor = "#41A123"
    def __init__ (self, master):
        self.master = master
        self.master.geometry("697x745+128+128")
        self.master.title("tkOthello")

        # The important stuff: I put other stuff in this toolbar, but I'm trying to limit the code to stuff that's relevant to this post.
        self.toolbar = Menu(self.master)
        self.master.config(menu = self.toolbar)
        self.helpMenu = Menu(self.toolbar)
        self.toolbar.add_cascade(label = "Help", menu= self.helpMenu)
        self.helpMenu.add_command(label = "Gamerules", command = self.showGameRules)
        self.helpMenu.add_command(label = "Application Help", command = self.showApplicationHelp)

        # Other configuration code like setting up the gameboard goes here, but it's not the subject of this post.
    def showGameRules (self):
        global gameRules
        self.showHelp(gameRules)

    def showApplicationHelp (self):
        global applicationHelp
        self.showHelp(applicationHelp)

    def showHelp (self, helpText):
        # When the main application is closed before the help window, it causes an error.
        # The application is being closed anyway, so it's not a big problem. My main concern
        # is that it would be alarming to the user to see the tracebacks appear in the console
        # window, which I don't know how to hide. Any help on that would be appreciated as well.
        helpWindow = Tk()
        helpWindow.geometry("512x512+256+256")
        helpWindow.title("tkOthello " + helpText.split("\n")[0])
        helpWindow_bgFrame = Frame(helpWindow, bg = self.bgAndBoardColor)
        # This is as far as I got before I noticed the problem I described above, but I did add the obligatory helpWindow.mainloop() seen below.
        helpWindow.mainloop()

if __name__ == __main__:
    root = Tk()
    myGame = OthelloGame(root)
    root.mainloop()
Incidentally, How do I get this awesome code coloring in IDLE or pycharm (A very good IDE by the way. I wish I had it sooner.)
Reply
#2
The solution was to use a separate class for the second window. For some reason, this fixes it. New problem, though: I decided to use a Text widget and set its yscrollcommand property to a ScrollBar widget. The user can scroll through the help text with their scroll wheel, but for reasons unknown, the scrollbar itself is unresponsive.

In any case, here's a mock up of my program that shows how I was able to solve the problem:
from tkinter import *
from tkinter import scrolledtext
from tkinter import messagebox # This still gets used elsewhere, even if I succeed in creating a custom help window.
import time # This also gets used elsewhere.
 
# Globals containing the help texts in triple quoted strings:
gameRules = """Game Rules
 
A comprehensive explanation of the gamerules goes here.
"""
applicationHelp = """Application help
 
An explanation of how the app works goes here.
"""
# For encapsulation purposes, the application goes in here:
# I don't inherit from Frame or anything. You'll see. It works.
class OthelloGame:
    bgAndBoardColor = "#41A123"
    def __init__ (self, master):
        self.master = master
        self.master.geometry("697x745+128+128")
        self.master.title("tkOthello")
 
        # The important stuff: I put other stuff in this toolbar, but I'm trying to limit the code to stuff that's relevant to this post.
        self.toolbar = Menu(self.master)
        self.master.config(menu = self.toolbar)
        self.helpMenu = Menu(self.toolbar)
        self.toolbar.add_cascade(label = "Help", menu= self.helpMenu)
        self.helpMenu.add_command(label = "Gamerules", command = self.showGameRules)
        self.helpMenu.add_command(label = "Application Help", command = self.showApplicationHelp)
 
        # Other configuration code like setting up the gameboard goes here, but it's not the subject of this post.
    def showGameRules (self):
        global gameRules
        self.showHelp(gameRules)
 
    def showApplicationHelp (self):
        global applicationHelp
        self.showHelp(applicationHelp)
 
    def showHelp (self, helpText):
        helpWin = Tk()
        theHelpWindow = HelpWindow(helpWin, helpText, helpText.split("\n")[0])
        helpWin.mainloop()

# A sub application for displaying help info
class HelpWindow:

    def __init__ (self, master, helpText, title = ""):
        self.master = master
        self.master.geometry("512x512+128+128")
        self.master.title(title)
        self.helpText = helpText
        self.exitButton = Button(self.master, text = "Exit", bg = "#000060", fg = "white", font = "Times 20", command = self.closeHelp)
        self.exitButton.place(relx = 0, rely = 0, relwidth = 1, height = 50)
        self.helpFrame = Frame(self.master, bg = "#FF00CC")
        self.helpFrame.place(relx = 0, y = 50, relwidth = 1, relheight = 0.9)
        self.scroll = Scrollbar(self.helpFrame)
        self.scroll.pack(side = "right", fill = Y)
        self.helpDisplay = Text(self.helpFrame, bg = "#C0C0C0", fg = "black", font = "times 12", wrap = "word", yscrollcommand = self.scroll)
        self.helpDisplay.pack(side = "right", fill = BOTH)

        self.helpDisplay.insert(INSERT, helpText)
        self.helpDisplay.config(state = "disabled")

    def closeHelp (self):
        self.master.destroy()
 
if __name__ == __main__:
    root = Tk()
    myGame = OthelloGame(root)
    root.mainloop()
I can only speculate as to why this solved the problem. I have some idea, but it does the job.
Reply
#3
scrollbars are weird in tkinter and require quite a bit more than you are providing
remove lines 58 and 59

replace with (after current line 61), (untested, so may contain errors):
self.scroll = Scrollbar(self.helpFrame, orient=tk.VERTICAL, command=self.hdisplay.yview)
self.scroll.pack()
self.scroll.config(command=self.hdisplay.yview)
Any problems, let me know, then I'll have to run the script.
Reply
#4
Thank you, Larz60+ for your reply. I tried your modification and several variations of it. (The scrollbar wouldn't show in your version.) The problem is still the same, and I suppose it would help if I did a better job describing it. The scrollbar displays in the window next to the Text widget, using the scroll wheel to scroll through the text works fine, but the bead in the scrollbar doesn't move. When clicking and dragging the bead in the scrollbar, moving it only about 1/4 of the way to the bottom in the game rules and 1/3 of the way to the bottom in the application help brings you all the way to the bottom of the help text and when you let go of the bead, it snaps to the top of the scrollbar while the text remains wherever you scrolled it to. Clicking anywhere below the bead scrolls to the bottom of the help text and with the help text scrolled down, clicking on the bead itself scrolls you all the way to the top. I'm actually beginning to suspect that this is a bug in tkinter itself, though it may be intended to work this way it's not at all unusable; just not very user friendly. I suppose I will need to implement my own callbacks if I want to make the scrollbar behave like a normal scrollbar. Hopefully, it doesn't come to writing my own scrollbar class.

Anyway, here is the code for the HelpWindow class as it is currently written:
class HelpWindow:

    def __init__ (self, master, helpText, title = ""):
        self.master = master
        self.master.geometry("512x512+128+128")
        self.master.title(title)
        self.helpText = helpText
        self.exitButton = Button(self.master, text = "Exit", bg = "#000060", fg = "white", font = "Times 20", command = self.closeHelp)
        self.exitButton.place(relx = 0, rely = 0, relwidth = 1, height = 50)
        self.helpFrame = Frame(self.master, bg = "#FF00CC")
        self.helpFrame.place(relx = 0, y = 50, relwidth = 1, relheight = 0.9)
        self.helpDisplay = Text(self.helpFrame, bg = "#C0C0C0", fg = "black", font = "times 12", wrap = "word")

        self.scroll = Scrollbar(self.helpFrame, orient = VERTICAL, command = self.helpDisplay.yview)
        self.scroll.pack(side = "right", fill = Y)
        self.helpDisplay.pack(side = "right", fill = BOTH, expand = 1)
        self.scroll.config(command = self.helpDisplay.yview)
        self.helpDisplay.insert(INSERT, self.helpText)
        self.helpDisplay.config(state = "disabled", yscrollcommand = self.scroll)
        self.scroll.config(command = self.helpDisplay.yview)

    def closeHelp (self):
        self.master.destroy()
Just in case this behavior in the scrollbars is a bug, Where would I go to report it?
Reply
#5
One suggestion, you may not like (until you try it) convert to wxpython phoenix (python 3)
Reply
#6
I decided to try your suggestion and found out that there is something wrong with my python install. I can't run python or pip from the command line. Everything else seems to work fine. Do you know how to fix it? I just spent hours trying to fix my python and install wxpython. I still can't get pip to work.
Reply
#7
There's only one proper way, re-install python, but follow snippsat's installation tutorials on this forum,
here: https://python-forum.io/Thread-Part-1-Py...er-Windows
and part 2 here: https://python-forum.io/Thread-Part-2-Py...nt-Windows
Reply
#8
Thank you. That was very helpful. The executable installers were behaving very strangely; I suspect that it was because there was a lot of python stuff already on the system, so I had to do a lot of stuff manually, but python and pip now both work from the command line.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020