Create frame class in Tkinter Gui - python

I'm working on a Gui and I'd like to know how to create a class that would implement frame.
e.g.
class WindowContent(Tkinter.?)
""" This class would create a frame for my program window """
class App(Tkinter.Tk):
""" main window constructor """
def __init__(self):
Tkinter.Tk.__init__(self)
program_window = WindowContent ?
self.config(window = window_content) ?
rgds,

I found the answer :
class WindowProgram(Tkinter.Frame)
""" This class creates a frame for my program window """
def __init__(self, parent):
Tkinter.Frame.__init__(self, parent)
class App(Tkinter.Tk):
""" application constructor """
def __init__(self):
Tkinter.Tk.__init__(self)
self.window_program = Window_Program(self)

Why do you want a class that creates several frames? Creating one class that creates multiple frames is not a very good solution. You don't need a single class for that.
Either create separate classes for each frame, or just create methods in your app to create each frame. I prefer the latter, but if you want a frame that can be used in multiple contexts it sometimes makes sense to create a class.
When I do a GUI I structure my code like this:
class App(Tkinter.Tk):
def __init__(self):
Tkinter.Tk__init__(self)
self.menubar = self.makeMenubar(...)
self.frame1 = self.makeFrame1(...)
self.frame2 = self.makeFrame2(...)
self.configure(menu=self.menubar)
self.frame1.grid(...)
self.frame2.grid(...)
In this way, each major section gets its own method to hide the details of widget creation. You could, of course, have each frame be a custom object but usually that's unnecessary.

Related

Can you transfer attributes from one class instance to another without using inheritance?

I'm building a Tkinter app and it is currently all one big class. I'm trying to split it into smaller pieces to make it easier to work on. The problem is some of the smaller pieces contain elements that are referenced elsewhere in the larger app.
editing to add more code:
OK so say I am using init_library to make a big complicated frame which then becomes self.library.
class GUI:
def __init__(self):
self.root = tk.Tk()
self.init_library()
self.root.mainloop()
return
def init_library(self):
self.library = tk.Frame(self.root)
[...]
self.library_var = tk.StringVar("HEY")
self.library_label = tk.Label(self.library, textvariable=self.library_var)
[...]
def action(self, new_text):
[...]
self.library_var.set(new_text)
[...]
So assume that init_library is large and I would like to put it in a different file to make life easier. Now instead of a class function, I just instantiate LibraryClass.
from pieces import LibraryClass
class App:
def __init__(self):
self.root = tk.Tk()
self.library = LibraryClass()
self.root.mainloop()
return
The problem is library_var is now a child of self.library instead of App. So we would have to change action.
def action(self, new_text):
[...]
self.library.library_var.set(new_text)
[...]
Is there a way to directly assign the LibraryClass functions and attributes of self.library to App?
(I know it seems like a small thing but it would really make my life easier)

how to call a function from a different class in python pyqt

Forgive me for overcomplicating this, thats just how it happened. so i have these two classes one's windowm and the other's modelm, i am trying to get it to re-start whenever newGame() is called so here are some snippets of code:
class windowm(QMainWindow):
def __init__(self):
super(windowm, self).__init__()
# a generic widget for the center of the window
widget = QWidget()
self.setCentralWidget(widget)
and the other class:
class Model:
def __init__(self):
# setup is just starting a new game, so use that method
self.newGame()
def newGame(self):
super(windowm, self).__init__()
yes i understand it is complicated and forgive me for that, that's just how the assignment is. So i understand that this has been answered before i just have this one annoying unique scenario. so as you can see in the second code snippet i am attempting to get it to jump back into the class "windowM" and into the function init(self) to re-start the game. please help and thank you!
You'll have to create a new instance of your other class and then use that to call the game function.
I think you'll want to change your game class though, so it's easier to start a new game from the other class.
class Model:
def startNewGame(self):
# setup is just starting a new game, so use that method
self.newGame()
def newGame(self):
super(windowm, self).__init__()
Then it can be used like this:
class windowm(QMainWindow):
def __init__(self):
super(windowm, self).__init__()
# a generic widget for the center of the window
widget = QWidget()
self.setCentralWidget(widget)
# create an instance of the other class
ng = Model()
# start a new game
ng.startNewGame()

PyQt5 Making a subclass widgets

so I was wondering how I could make a subclass of a widget
For example if I wanted to create a widget, that inherited methods and attributes from QtWidgets.QPushButton, however I would create extra methods and attributes on top of that.
class Coord(QtWidgets.QPushButton):
def __init__(self):
super(Coord, self).__init__()
self.coordinates = []
#basically adding attributes to the object "QPushButton"
def set_text(self,text):
self.setText(text)
chrcount = 100 / len(text)
self.setStyleSheet("font-size: {}".format(chrcount))
#This will set the text of the button, yet will resize it appropriatly
This is an example. However, it creates the "button" widget as a new window. I was wondering how I could get it to act like QPushButton would anyway, just with the extra features I'd like to add to it
Edit: Fixed-
replaced my "super" function from
def __init__(self):
super(Coord, self).__init__()
to
def __init__(self,parent):
super(Coord, self).__init__(parent)
Don't really know how that fixed it but hey ho!
you can use the qt designer to create a button and set all possible features of a button there. If that is not enough you can adjust the button in your coding like self.button.whatever.set....If that is not enough attache the button to a class in qt designer, create a module and a class and do adjust whatever you want.

How to access variables in other classes

In Functions class, I would like to access the variable of the Frame class.
Please tell me if there is any way.
class Functions():
def changeText():
...
...
I want to change the 'text' in the Frame class
ex )Frame.text.SetFont('change text')
GUI element
class Frame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, ....)
....
....
self.text = wx.StaticText(panel, .....)
You can do this by sending an instance of the class to the function:
class myClass(object):
def __init__(self, text):
self.text = text
def changeText(input):
input.text = "world"
example = myClass("hello")
changeText(example)
You will have to tell your objects what to work on. Out of thin air your Functions instance will not know (how should it?) what Frame should be. You could make Frame a global, but I do not think that is a good idea (it will break if you want to work with more than one frame instance). So you would write:
class Functors:
...
def set_text(txt_frame, the_text):
"""txt_frame has to be a :class:`my_txt_frm` instance with ``self.text`` being a ``StaticText`` instance."""
txt_frame.text.SetLabel(the_text)
class my_txt_frm(wx.Frame): # do not name the derived class Frame to make more clear it is derived!
def __init__(# ...
...
self.text = wx.StaticText(#...
So now comes the interesting part: how to tie the parts together? You have to have something like that somewhere in your code:
funct = Functors() # the class which know how to do things on our GUI elements
frm = my_txt_frm(#...
Some lines later...
funct.set_text(frm, 'thenewtext')
So for your app which has the bigger picture it is necessary to keep references to the building blocks to be able to tie them together later.
An orderly way to tie things together is called MVC (see a great example in the wxPython wiki). Even if you do not want to model your app after this paradigm, you can learn from it how to reason about separation of concerns.

Problem with Classes in Python

Ok guys, I'm really new at python (and programming itself) so sorry for my ignorance, but I really needed to ask this.
So im doing a wxPython project where I added several tabs for a notebook (each tab of the notebook = a class) and there is one tab where I added a checkbox (in a tab, lets call it for example Tab1), and what I want is that when someone checks it, a button that exists in other tab (class called for example tab2) gets hidden where previously it was being shown.
Well I see that it isn't hard to accomplish this, but my problem is the classes (tab1 and tab2, in this example). I've been trying to figure it out by searching but I guess im not searching hard enough because I just can't get it right. If they were in the same class I wouldn't have a problem, but as they are in different classes, im having a huge struggle with this.
Hope someone can help me, and sorry for my ignorance once again.
EDIT: Sorry guys wasn't being shown/hidden, but rather being enabled/disabled.
class Tab2(wx.Panel):
def __init__(self, parent):
.....
self.jaddbutton = wx.Button(self,-1, label ="Button", size = (160,24))
self.jaddbutton.Bind(wx.EVT_BUTTON, self.jaddbuttonclick, self.jaddbutton)
def jaddbuttonclick(self, event):
....
class Tab1(wx.Panel):
def __init__(self, parent):
self.jdcheck = wx.CheckBox(self, -1, 'Disable')
self.jdcheck.Bind(wx.EVT_CHECKBOX, self.checkoptions, self.jdcheck)
def checkoptions(self,event):
checkboxval = self.jdcheck.GetValue()
if checkboxval == False:
self.jaddbutton.Disable() # This is what I want to do but it is on the other class
else:
self.jaddbutton.Enable() # Same as above
class TextFrame(wx.Frame):
def __init__(self):
p = wx.Panel(self)
self.nb = wx.Notebook(p, size = (750, 332))
#Tabs
tab1 = Tab1(self.nb)
tab2 = Tab2(self.nb)
self.nb.AddPage(tab1, "ssomething")
self.nb.AddPage(tab2, "somethingr")
This sounds more like a wxpython question than a classes question. Normally, in python, tab1 would need a handle to tab2 in order to hide the button in tab2. Or it would need a handle to some shared resource, like a parent class or shared model class, that would allow tab1 to affect settings in tab2 (like the hiding of a button). PyQt provides an event system to allow communication between classes which may not necessarily contain handles to each other. What is the common "accepted" way to communicate in wxpython?
Here is a fairly abstract example of the shared parent solution.
class Parent(object):
def create_tabs():
self.tab1 = Tab1(self)
self.tab2 = Tab2(self)
def hide_tab2_button():
self.tab2.hide_button()
class Tab1(object):
def __init__(self, parent):
self.parent = parent
def on_checkbox_checked(self):
self.parent.hide_tab2_button()
class Tab2(object):
def __init__(self, parent):
self.parent = parent
def hide_button(self):
self.button.hide() # Or whatever the wxpython command is to hide a button.
In the tabs' __init__, save the parent reference (the notebook):
class Tab1(wx.Panel):
def __init__(self, parent):
self.parent = parent
...etc, etc...
Then, self.parent.GetPage(x) lets you access the x-th page (i.e., tab) of the notebook from any other page (tab). So instead of self.jaddbutton.Disable() etc, you'd be using, e.g.:
othertab = self.parent.GetPage(1)
othertab.jaddbutton.Disable()
and so forth.

Categories