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.
Related
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.
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.
I am learning PyQt5 and I tried to create a extended widgets.
I am also learning OOP so I lack experience for this project.
My final goal is to have master widgets that can disable/enable some slave widgets.
So far I need check and radio buttons.
So I tried to create an abstract class that contains the extended behavior of the widgets (the management of the state of the slaves widgets):
class QDisablingWidget():
__metaclass__ = ABCMeta
def __init__(self):
self.slaveWidgets = []
self.slaveStateWhenMasterIsEnabled = {}
def addSlaveWidget(self, slaveWidget, isEnabledWhenMasterIsEnabled=True):
[...]
def updateSlaveStatus(self):
[...]
Then I create my extended widget classes:
class QDisablingCheckBox(QtWidgets.QCheckBox, QDisablingWidget):
def __init__(self, text=None, parent=None, isInMutexGroup=False):
super(QtWidgets.QCheckBox, self).__init__()
super(QDisablingWidget, self).__init__()
if text:
self.setText(text)
if parent:
self.setParent(parent)
self.isInMutexGroup = isInMutexGroup
# Click signal handling
self.stateChanged.connect(self.updateSlaveStatus)
class QDisablingRadioButton(QtWidgets.QRadioButton, QDisablingWidget):
def __init__(self, text=None, parent=None, isInMutexGroup=False):
super(QtWidgets.QRadioButton, self).__init__()
super(QDisablingWidget, self).__init__()
if text:
self.setText(text)
if parent:
self.setParent(parent)
self.isInMutexGroup = isInMutexGroup
# Click signal handling
self.toggled.connect(self.updateSlaveStatus)
You can already see the problem:
I need to connect my self.updateSlaveStatus to the correct signals (stateChanged and toggled) so I added it in the constructor of the derived classes.
Recently I also added the isInMutexGroup argument for some implementation reasons and I realize that I am duplicating the code in both derived classes...
It is the first time I try to use OOP "for real" (first attempt of multiple inheritance and abstract class), so even if I know I am breaking the beauty of the OOP concept, I don't know what to do to get a nice class hierarchy...
So basically, I am looking for a solution on this example. But I am also looking for guidelines, general advice, tutorials, etc. Actually anything that could help me!
Thank you for your help.
Even if I got a downvote for that question, I think some beginners could be interested by the solution I found:
I have my extension abstract class like that:
class QDisablingWidget(QtCore.QObject):
__metaclass__ = ABCMeta
def __init__(self, isInMutexGroup=False, **kwds):
[...]
Then I can derive class like that:
class QDisablingCheckBox(QtWidgets.QCheckBox, QDisablingWidget):
def __init__(self, **kwds):
super().__init__(**kwds)
# On click signal handling
self.stateChanged.connect(self.updateSlaveStatus)
and
class QDisablingRadioButton(QtWidgets.QRadioButton, QDisablingWidget):
def __init__(self, **kwds):
super().__init__(**kwds)
# On click signal handling
self.toggled.connect(self.updateSlaveStatus)
Finally, when I use the classes I need to create object like that:
disablingRadioBut = QWidgets.QDisablingRadioButton(text="My button",
parent=self,
isInMutexGroup=True)
I.e I must use keywords explicitly so that each constructors will eat the kewords the use/know.
Thanks to this approach I have maximum reusability of my extension class.
I got this solution here:
http://pyqt.sourceforge.net/Docs/PyQt5/multiinheritance.html
And more details here:
http://rhettinger.wordpress.com/2011/05/26/super-considered-super/
A very nice article!
which one of the following is considered better a design and why ?.
i have 2 classes , one for the gui components and the other is for it's events.
please put in mind that the eventClass will be implemented so many times, (sometimes to get data from an oracle databases and sometimes mysql databases )
class MainWindow:
def __init__(self):
self.myEvents = eventClass() # the class that has all the events
self.button = button # consider it a button from any gui library
self.menu = menu # menu box
def bottonEvent(self):
data = self.myEvents.buttonEvent()
self.menu.populate(data)
class eventClass:
def __init__(self):
pass
def getData(self):
return data # return data to puplate in the list
OR
class MainWindow:
def __init__(self):
self.myEvents = eventClass(self) # the class that has all the events
self.button = button # consider it a button from any gui library
self.menu = menu # menu box
def bottonEvent(self):
self.myEvents.ButtonEvent()
class eventClass:
def __init__(self,window):
pass
def ButtonEvent(self):
window.menu.populateData()
please inform me if anything was unclear
please help ,
thanks in advance
The first choice is better "decoupled": the event class needs and has no knowledge whatsoever about the window object or its menu attribute -- an excellent approach that makes the event class especially easy to unit-test in isolation without any overhead. This is especially nice if many implementations of the same interface need to exist, as you mention they do in your case.
The second choice introduces a mutual dependency -- an event object can't work without a window object, and a window object builds an event object. That may be an acceptable complication in more abstruse cases where it buys you something, but for this specific use it sounds more like an arbitrary extra difficulty without any real plus.
So, I would recommend the first form.
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.