I'm trying to create a custom control based on wx.richtext.RichTextCtrl and I'm running into a problem. Whenever I attempt to add the custom control to a sizer, wxPython chokes with the error
Traceback (most recent call last):
File "pyebook.py", line 46, in <module>
frame = MainFrame(None, 'pyebook')
File "pyebook.py", line 14, in __init__
self.mainPanel.GetSizer().Add(ReaderControl(self.mainPanel), 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
File "/usr/local/lib/wxPython-unicode-2.8.11.0/lib/python2.6/site-packages/wx-2.8-mac-unicode/wx/_core.py", line 12685, in Add
return _core_.Sizer_Add(*args, **kwargs)
TypeError: wx.Window, wx.Sizer, wx.Size, or (w,h) expected for item
The custom control is at this time extremely simple and looks like this
class ReaderControl(wx.richtext.RichTextCtrl):
def __init__(self, parent, id=-1, value=''):
wx.richtext.RichTextCtrl(parent, id, value, style=wx.richtext.RE_READONLY, name='ReaderControl')
The code I'm using to add the control to the sizer is:
self.mainPanel.GetSizer().Add(ReaderControl(self.mainPanel), 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
Any ideas what I'm doing wrong here?
I think you need to call __ init __ explicitly, so you can pass in 'self'. Otherwise, you are just creating a new instance of RichTextCtrl, not initialising your subclass properly.
IOW:
class ReaderControl(wx.richtext.RichTextCtrl):
def __init__(self, parent, id=-1, value=''):
wx.richtext.RichTextCtrl.__init__(self, parent, id, value, style=wx.richtext.RE_READONLY, name='ReaderControl'
Related
I am in the process of making an OOP Countdown GUI with the letters, numbers and conundrum games.
This is a snippet of my code so far.
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title("Main")
self.configure(bg=LIGHT_BLUE)
self.title=tk.Label(master=self,bg=LIGHT_BLUE,font=("Arial",12,"bold"),text="!Countdown Games!",pady=5,padx=5)
self.title.pack()
self.frame=tk.Frame(master=self,bg=LIGHT_BLUE)
self.LettersButton=tk.Button(master=self.frame,bg=LIGHT_BLUE,font=("Arial",12,"bold"),text="Letters",command=self.start_letters)
self.LettersButton.grid(row=0,column=0,sticky="NESW",pady=10,padx=2)
self.NumbersButton=tk.Button(master=self.frame,bg=LIGHT_BLUE,font=("Arial",12,"bold"),text="Numbers",command=self.start_numbers)
self.NumbersButton.grid(row=0,column=1,sticky="NESW",pady=10,padx=2)
self.LettersButton=tk.Button(master=self.frame,bg=LIGHT_BLUE,font=("Arial",12,"bold"),text="Conundrum",command=self.start_conundrum)
self.LettersButton.grid(row=0,column=2,sticky="NESW",pady=10,padx=2)
self.frame.pack()
self.mainloop()
def start_letters(self):
self.withdraw()
self.Letters=Letters()
def start_numbers(self):
self.withdraw()
self.Numbers=Numbers()
def start_conundrum(self):
self.withdraw()
self.Conundrum=Conundrum()
class Conundrum(tk.Toplevel):
def __init__(self):
super().__init__()
self.configure(bg=LIGHT_BLUE)
self.geometry("400x150")
self.title("Conundrum")
self.frameA=tk.Frame(master=self,bg=LIGHT_BLUE)
self.letterList=[]
self.answer=r.choice(ninewords)
self.anagram=anagram(self.answer)
for x in range(9):
self.letterList.append(ConundrumDisplay(self.frameA,x))
self.frameA.pack()
self.frameB=tk.Frame(master=self,bg=LIGHT_BLUE)
self.letterEntryList=[]
for y in range(9):
self.letterEntryList.append(ConundrumEntry(self.frameB,y))
self.frameB.pack()
self.timer=tk.Label(master=self,bg=LIGHT_BLUE,font=("Arial",12,"bold"),text="31")
self.update_timer()
self.timer.pack()
self.mainloop()
m.showinfo("Startgame","The game will start when you press OK")
for x in range(9):
self.letterlist[x].add_letter(x,self.anagram)
self.bind("<Key>",self.process_key)
self.bind("Return",self.process_guess)
self.bind("BackSpace",self.process_back)
The upper bit of code is a method from an App class which inherits from tk.Tk
The error is in the super()._ _ init _ _() line in the conundrum class after you press the Conundrum button in the main wn
This conundrum class is obviously the bit of code just below which inherits from tk.Toplevel.
I have used tk.Toplevel before but it hasn't shown the error before.
I have tried to reduce the amount of code that I am posting but if any more of it is necessary to figure out the error, then I can amend the question.
Error Message:
Traceback (most recent call last):
File "/nix/store/2vm88xw7513h9pyjyafw32cps51b0ia1-python3-3.8.12/lib/python3.8/tkinter/__init__.py", line 1892, in __call__
return self.func(*args)
File "main.py", line 50, in start_conundrum
self.Conundrum=Conundrum()
File "main.py", line 55, in __init__
super().__init__()
File "/nix/store/2vm88xw7513h9pyjyafw32cps51b0ia1-python3-3.8.12/lib/python3.8/tkinter/__init__.py", line 2624, in __init__
self.title(root.title())
TypeError: 'Label' object is not callable
The error is telling you exactly what is wrong: you can't call a Label as if it was a function.
You are doing this: self.title(root.title()). root.title is an instance of Label but you are trying to call it as if it was a function. You get the same error if you do something like this:
foo = Label(...)
foo()
Since foo is a Label rather than a function, you can't call it.
If you want to call the title function of the root window, you should not name the label self.title. Name it something else so that you can use the title method of the base class.
edit : Problem solved, I was indeed a idiot and it was indeed a very silly mistake. The solution was that I forgot to give an instance of UI when creating a Joueur instance... Sorry and thanks to all who tried to help me.
I've been trying to code a chess game. I am now in the process of testing it and I got a "weird" error (from my experience I probably just messed up, but my situation is not exactly what people on every other post on this error seem to be and I have been searching my code and documentation for clues for some hours with no success : so here I am).
So to summarize the code (I won't put code I have successfully run before and will only show what should be relevant):
I have a board class which is basically my model and my controller. In the constructor I ask for arguments two players, a UI class, and a hash class. Before I implemented the last two, and added it in the constructor, the code ran just fine.
class Plateau:
def __init__(self, j1, j2, UI, Hash):
self.UI = UI
self.UI.ajoutePlateau(self)
self.Hash = Hash
self.Hash.hashPlateau(self)
# some code to deal with the rest
...
#
self.UI.initAffichage()
I then have a UI interface and a ConsolUI (UITerminal in my code) which inherit from it. It is as expected what show to the user the board and also what ask the human player (if there is one) what he wants to play.
class UI:
def __init__(self):
self.Plateau = None
def ajoutePlateau(self, Plateau):
self.Plateau = Plateau
# a bunch of method that throw an exception and are overrided by the child class
...
#
class UITerminal(UI):
def __init__(self):
#super(UITerminal, self).__init__(self)
#super().__init__(self)
#UI.__init__(self)
#super(UITerminal, self).__init__()
super().__init__()
#UI.__init__()
# the method that had to be overridden
...
#
I have also tried few version of the UITerminal constructor (which are above and put on comment).
or even just nothing since it should not even be needed (I think...).
Then there is the hash, which is build the same way as the UI : an interface, a child.
class Hash:
def __init__(self):
pass
# a bunch of method that throw an exception and are overridden by the child class
...
#
class ZombristHash(Hash):
def __init__(self):
#super(ZombristHash, self).__init__(self)
#super().__init__(self)
#Hash.__init__(self)
#super(ZombristHash, self).__init__()
super().__init__()
#Hash.__init__()
# a bunch of code to init the zombristhash
...
#
same as with the UI, I tried multiple way to call the interface constructor.
Then I have my main, which is only 1 line and is what throw the error :
p = Plateau(Humain("j1"), Humain("j2"), UITerminal(), ZombristHash())
and the error is :
Traceback (most recent call last): File "plateau.py", line 298, in <module> p = Plateau(Humain("j1"), Humain("j2"), UITerminal(), ZombristHash())
TypeError: __init__() missing 1 required positional argument: 'UI'.
From what I understand, he tells me I haven't given the board constructor a UI as argument, but I did so I do not understand what is happening.
I tried on quamran's suggestion this :
p = Plateau(None, None, None, None)
And it seems to think it was ok now...
Traceback (most recent call last):
File "plateau.py", line 298, in <module>
p = Plateau(None, None, None, None)
File "plateau.py", line 13, in __init__
self.UI.ajoutePlateau(self)
AttributeError: 'NoneType' object has no attribute 'ajoutePlateau'
As #Jacques Gaudin noticed, you need to change this :
class ZombristHash(Hash):
def __init__(self):
Hash.__init__()
to this :
class ZombristHash(Hash):
def __init__(self):
super().__init__()
and same for UI.
Finally, you get something like this :
class Plateau:
def __init__(self, j1, j2, UI, Hash):
self.UI = UI
self.UI.ajoutePlateau(self)
self.Hash = Hash
class Hash:
def __init__(self):
pass
class ZombristHash(Hash):
def __init__(self):
super().__init__()
class UI:
def __init__(self):
self.Plateau = None
def ajoutePlateau(self, Plateau):
self.Plateau = Plateau
class UITerminal(UI):
def __init__(self):
# super(UITerminal, self).__init__()
super().__init__()
class Humain():
def __init__(self, j):
pass
p = Plateau(Humain("j1"), Humain("j2"), UITerminal(), ZombristHash())
I am trying to create a subclass of the ttk.Frame object, but I noticed that I am unable to pass keyword arguments into its parent's init method. Here is a stripped down version of my class:
from tkinter import ttk
class MyFrame(ttk.Frame):
def __init__(self, parent, **kwargs):
super(MyFrame, self).__init__(parent, kwargs)
Here's an example of attempting to create an instance of my class (root is assigned to tkinter.Tk()):
my_frame = MyFrame(root, borderwidth=5)
And here's the error when I try to create an instance of my class:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\csmith\Documents\tmp\frame_test.py", line 5, in __init__
ttk.Frame.__init__(self, parent, kwargs)
TypeError: __init__() takes from 1 to 2 positional arguments but 3 were given
I know it's possible to create Frame objects while using keyword arguments, but I can't seem to figure out why I can't create a class that passes it's keyword arguments to Frame's init method. Any advice is appreciated!
When passing in kwargs to a function, use **kwargs instead. This means 'unpack as kwargs', since you have to put all kwargs in one by one. 'Unpack' means that Python will do that for you.
Change
super(MyFrame, self).__init__(parent, kwargs)
to
super(MyFrame, self).__init__(parent, **kwargs)
I can not get a method to manage clipboard with the context menu
I'm trying with version 2.8 of wxpython
import wx
import wx.lib.iewin
class main (wx.Frame):
def __init__(self, parent):
wx.Frame.__init__ (self, parent, id, title, pos, size, style)
self.html_field = HTMLWINDOW(self.p_html, -1)
class HTMLWINDOW(wx.html.HtmlWindow):
def __init__(self, parent, id):
self.ie = wx.lib.iewin.IEHtmlWindow(self, -1, style)
self.Bind(wx.EVT_CONTEXT_MENU, self.menu)
def menu(self, event):
self.copied = self.ie.GetStringSelection()
alternative method. but only I can get words, not a whole selection
def OnCellClicked(self, cell, x, y, evt):
if isinstance(cell, wx.html.HtmlWordCell):
sel = wx.html.HtmlSelection()
word = cell.ConvertToText(sel)
super(MyHtmlWindow, self).OnCellClicked(cell, x, y, evt)
importing wx.lib.iewin I get this error
Traceback (most recent call last):
ValueError: _type_ 'v' not supported
File "main.py", line 3959, in <module>
import wx.lib.iewin as iewin
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/iewin.py", line 15, in <module>
import wx.lib.activex
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/activex.py", line 35, in <module>
import ctypes.wintypes as wt
File "/usr/lib/python2.7/ctypes/wintypes.py", line 23, in <module>
class VARIANT_BOOL(_SimpleCData):
ValueError: _type_ 'v' not supported
As Werner already pointed out, you are attempting to import wx.lib.iewin in Linux. The iewin module is Windows only. I think it should give an import error that tells you it's Windows only, but the name itself implies that. You could put in a bug ticket so that it does raise an appropriate error though.
If you need a browser-like widget, then you should check out WebView. It was added in wxPython 2.9, I believe and works cross-platform. You can read more about that widget here:
https://wxpython.org/Phoenix/docs/html/wx.html2.WebView.html
I get an AttributeError I can't seem to work out.
I'm working with two classes.
The first class goes something like that.
class Partie:
def __init__(self):
# deleted lines
self.interface = Interface(jeu=self)
def evaluerProposition(self):
# computations
self.interface.afficherReponse()
Introducing second class (in a separate file).
class Interface:
def __init__(self, jeu):
self.jeu = jeu
self.root = tkinter.Tk()
# stuff
def onClick(self, event):
# talk
self.jeu.evaluerProposition()
def afficherReponse(self):
# stuff
I start the whole thing by
partie = Partie()
All manipulations on my widget work fine until some click event causes
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python33\lib\tkinter\__init__.py", line 1442, in __call__
return self.func(*args)
File "C:\Users\Canard\Documents\My Dropbox\Python\AtelierPython\Mastermind\classeInterface.py", line 197, in clic
self.jeu.evaluerProposition()
File "C:\Users\Canard\Documents\My Dropbox\Python\AtelierPython\Mastermind\classeJeu.py", line 55, in evaluerProposition
self.interface.afficherReponse()
AttributeError: 'Partie' object has no attribute 'interface'
I typed in the interpretor
>>> dir(partie)
and got a long list in return with 'interface' among the attributes.
Also typed
>>> partie.interface
<classeInterface.Interface object at 0x02C39E50>
so the attribute seems to exist.
Following the advice in some former post, I checked the instance names do not coincide with module names.
I am confused.
Most likely, in some code that you're not showing us, you're doing something like this:
self.some_button = tkinter.Button(..., command=self.interface.onClick())
Note the trailing () on onClick(). This would cause the onClick method to be called at the time the button is created, which is probably before your constructor is done constructing the instance of the Partie class.