I am developing a wxpython, i am looking for button generating, for example.
In text box enter the value how many button have to generate.
While submitting that, i have to show in panel as many as button
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Background Reset Tutorial",size=wx.Size(500,500))
# Add a panel so it looks the correct on all platforms
self.panel = wx.Panel(self, wx.ID_ANY)
self.txt = wx.TextCtrl(self.panel,id=wx.ID_ANY,pos=(185,40))
txtSizer = wx.BoxSizer(wx.HORIZONTAL)
self.btn = wx.Button(self.panel,id=wx.ID_ANY,label="Submit",pos=
(190,70),size=(100,30))
self.btn.Bind(wx.EVT_BUTTON,self.onSubmit)
def onSubmit(self,event):
gettxt = self.txt.GetValue()
I got the solution
def onBtn(self,event):
self.val = self.txtstring1.GetValue()
Blue = wx.Button(self,label="Blue",pos=(30,50))
Blue.Bind(wx.EVT_BUTTON,self.onBlue)
Green = wx.Button(self,label="Green",pos=(300,50))
Green.Bind(wx.EVT_BUTTON,self.onGreen)
for self.button_name in range(self.val):
self.btn = wx.Button(self, label=str(self.button_name),pos=(50,50))
self.btn.Bind(wx.EVT_BUTTON, lambda evt, temp=self.button_name:
self.OnButton(evt, temp))
self.widgetSizer.Add(self.btn, 0, wx.ALL|wx.CENTER, 5)
Related
In my app, I want to handle allocation / deallocation of sizers inside a scrolledPanel. In my first try, I was hiding / showing the contents of the sizers, but this was causing a lot of problems. The hidden sizers would "stay there", effectively ocuppying space, it would not update propely, etc. The solution that worked better was to destroy and create them over and over again.
But this that its problems too. The scrolledPanel blinks while I'm updating it and seems to be resource heavy. In my real app, I put the references of the buttons and checkboxes in lists and it becames more dificult to handle them.
So, if anyone has a better solution, I'm all ears!
I'm up to a hiding / showing solution! Something to reset the size of the scrolledPanel to accomodate only the sizer it currently has it would be nice too.
Thanks!
import wx
import wx.lib.scrolledpanel as scrolled
class WaterDataBase(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent)
self.setupSizers()
self.setupData()
def setupSizers(self):
masterSizer = wx.BoxSizer(wx.HORIZONTAL)
itemsSizer = wx.BoxSizer(wx.VERTICAL)
itemsSizer.Add(self.addSearchControl(), flag=wx.ALL, border=7)
self.scrolledPanelSizer = wx.BoxSizer(wx.VERTICAL)
self.scrolled_panel = scrolled.ScrolledPanel(self, wx.ID_ANY, size=(200, 200))
self.scrolled_panel.SetSizer(self.scrolledPanelSizer)
itemsSizer.Add(self.scrolled_panel, flag=wx.ALL, border=7)
masterSizer.Add(itemsSizer)
self.scrolled_panel.SetupScrolling()
self.SetSizer(masterSizer)
def addSearchControl(self):
sizer = wx.BoxSizer(wx.HORIZONTAL)
self.searchField = wx.TextCtrl(self, -1)
self.searchField.Bind(wx.EVT_TEXT, self.OnSearched)
sizer.Add(self.searchField)
return sizer
def setupData(self):
self.words = "I'm trying to make this work, please. Let's keep it on! The day is beautiful today. Together we are stronger!".split()
for word in self.words:
self.addSizerToPanel(word)
def createSizer(self, word):
# Creates a sizer with a CheckBox and a StaticText to display.
sizer = wx.BoxSizer(wx.HORIZONTAL)
checkBox = wx.CheckBox(self.scrolled_panel, -1)
text = wx.StaticText(self.scrolled_panel, -1, word)
sizer.Add(checkBox, flag=wx.ALL, border=5)
sizer.Add(text, flag=wx.LEFT, border=5)
return sizer
def addSizerToPanel(self, word):
sizer = self.createSizer(word)
self.scrolledPanelSizer.Add(sizer, flag=wx.ALL, border=5)
def OnSearched(self, event):
query = self.searchField.GetValue().lower()
result = []
# If query's empty, print all words
if not query or query.isspace():
for word in self.words:
result.append(word)
else:
for word in self.words:
if word.lower().find(query) != -1:
result.append(word)
# Destroy all panel sizers and put exactly the ones we want.
self.scrolled_panel.DestroyChildren()
for word in result:
self.addSizerToPanel(word)
self.scrolled_panel.Layout()
self.scrolled_panel.Scroll(0, 0) # Using this to cause the scrollPanel get back to the top.
app = wx.App()
frame = WaterDataBase(None).Show()
app.MainLoop()
So, it seems I've made it, finally. I still wants the advice about reseting the size of the scrolledPanel. xD
import wx
import wx.lib.scrolledpanel as scrolled
class Frame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent)
self.sizerRefs = []
self.words = []
self.setupSizers()
self.setupData()
def setupSizers(self):
masterSizer = wx.BoxSizer(wx.HORIZONTAL)
itemsSizer = wx.BoxSizer(wx.VERTICAL)
itemsSizer.Add(self.addSearchControl(), flag=wx.ALL, border=7)
self.scrolledPanelSizer = wx.BoxSizer(wx.VERTICAL)
self.scrolled_panel = scrolled.ScrolledPanel(self, wx.ID_ANY, size=(200, 200))
self.scrolled_panel.SetSizer(self.scrolledPanelSizer)
itemsSizer.Add(self.scrolled_panel, flag=wx.ALL, border=7)
masterSizer.Add(itemsSizer)
self.scrolled_panel.SetupScrolling()
self.SetSizer(masterSizer)
def addSearchControl(self):
sizer = wx.BoxSizer(wx.HORIZONTAL)
self.searchField = wx.TextCtrl(self, -1)
self.searchField.Bind(wx.EVT_TEXT, self.OnSearched)
sizer.Add(self.searchField)
return sizer
def setupData(self):
self.words = "I'm trying to make this work, please. Let's keep it on! The day is beautiful today. Together we are stronger!".split()
for i in range(0, len(self.words)):
self.addSizerToPanel(i)
def createSizer(self, index):
sizer = wx.BoxSizer(wx.HORIZONTAL)
checkBox = wx.CheckBox(self.scrolled_panel, -1)
text = wx.StaticText(self.scrolled_panel, -1, self.words[index])
sizer.Add(checkBox, flag=wx.ALL, border=5)
sizer.Add(text, flag=wx.LEFT, border=5)
self.sizerRefs.append(sizer)
return sizer
def addSizerToPanel(self, index):
sizer = self.createSizer(index)
self.scrolledPanelSizer.Add(sizer, flag=wx.ALL, border=5)
def hideAllSizers(self):
for sizer in self.sizerRefs:
sizer.ShowItems(False)
def unhideSizer(self, index):
self.sizerRefs[index].ShowItems(True)
def OnSearched(self, event):
query = self.searchField.GetValue().lower()
result = [] # Storing the indexes of the words found
# If query's empty, print all words
if not query or query.isspace():
for i in range(0, len(self.words)):
result.append(i)
else:
for i in range(0, len(self.words)):
if self.words[i].lower().find(query) != -1:
result.append(i)
# Hides all panel sizers and unhide exactly the ones we want.
self.hideAllSizers()
for i in range(0, len(result)):
self.unhideSizer(result[i])
self.scrolled_panel.Layout()
self.scrolled_panel.Scroll(0, 0) # Using this to cause the scrollPanel get back to the top.
app = wx.App()
frame = Frame(None).Show()
app.MainLoop()
I want to change the color for my whole pythonwx application. I found out that the currently used colors are noted down in wx.Frame.DefaultAttributes.colBg respectively.colFg. I checked with paint that these are really the used colors.
Now there is a wx.Frame.GetDefaultAttributes() but not wx.Frame.SetDefaultAttributes() method. But I still need to change the color and I do not think that setting every control manually is a desired solution.
I tried:
frame.DefaultProperties = customProperties
and
frame.DefaultProperties.colBg = customColor
but both throw a AttributeError ("can't set attribute"). Any help is appreciated.
The default properties are probably defined within whatever theme you have set for the desktop. I do not believe that there is a way to redefine these from within wxpython.
The easiest way that I have found to set a default colour scheme, is to set the colours for each of the children in an object, such as a panel.
In the following code, keep pressing the Encrypt button to see the results.
import wx
from random import randrange
class CipherTexter(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, size=(1000, 600))
self.panel = wx.Panel(self)
cipherText = wx.StaticText(self.panel, label="Cipher Texter ", pos=(20, 30))
encryptorText = wx.StaticText(self.panel, label="Encryptor ", pos=(20, 70))
decryptorText = wx.StaticText(self.panel, label="Decryptor ", pos=(20, 100))
self.cipher = wx.TextCtrl(self.panel, -1, style=wx.TE_MULTILINE, size=(400,400), pos=(400, 30))
self.encryptor = wx.TextCtrl(self.panel, -1, size=(100,30), pos=(200, 70))
self.decryptor = wx.TextCtrl(self.panel, -1, size=(100,30), pos=(200, 100))
self.encrypt = wx.Button(self.panel, -1, "Encrypt", pos=(20, 140))
self.decrypt = wx.Button(self.panel, -1, "Decrypt", pos=(20, 180))
self.panel.SetBackgroundColour('white')
self.encrypt.Bind(wx.EVT_BUTTON, self.encryptNow)
self.decrypt.Bind(wx.EVT_BUTTON, self.decryptNow)
self.Show()
def AColour(self):
red = randrange(0,255)
green = randrange(0,255)
blue = randrange(0,255)
x = wx.Colour(red,green,blue)
return x
def encryptNow(self, event):
cfg_colour = self.AColour()
txt_colour = self.AColour()
children = self.panel.GetChildren()
for child in children:
child.SetBackgroundColour(cfg_colour)
child.SetForegroundColour(txt_colour)
print(cfg_colour)
def decryptNow(self, event):
pass
app = wx.App(False)
frame = CipherTexter(None, "The SS Cipher")
app.MainLoop()
So this is a pretty basic program but for some reason it keeps crashing wtih exit code 139. I've looked online at the error code and it has to do with memory management but a basic form with a few plaintext, buttons, and fields should not be too much for a 64 bit machine with 16GB of RAM. I have another class that is almost identical and it works fine. Where am I going wrong here?
import wx
class mainForm(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Test")
self.panel = wx.Panel(self)
vbox_main = wx.BoxSizer(wx.VERTICAL) # main vertical box
url_box = wx.BoxSizer(wx.HORIZONTAL)
url_label = wx.StaticText(self.panel, label="URL:")
self.url_entry = wx.TextCtrl(self.panel)
url_box.Add(url_box)
url_box.Add(url_label)
url_box.Add(self.url_entry)
file_box = wx.BoxSizer(wx.HORIZONTAL)
file_label = wx.StaticText(self.panel, label="File")
self.file_entry = wx.TextCtrl(self.panel)
file_button = wx.Button(self.panel, label="Search")
file_button.Bind(wx.EVT_BUTTON, self.search)
file_box.Add(file_label)
file_box.Add(self.file_entry)
file_box.Add(file_button)
mode_box=wx.BoxSizer(wx.HORIZONTAL)
mode_label=wx.StaticText(self.panel, label='Mode')
#self.mode_button = buttons.GenToggleButton(self.panel, -1, "Autonomous Mode")
mode_box.Add(mode_label)
#mode_box.Add(self.mode_button)
go_box = wx.BoxSizer(wx.HORIZONTAL)
go_button = wx.Button(self.panel, label='Go!')
go_button.Bind(wx.EVT_BUTTON, self.submit)
go_box.Add(go_button)
vbox_main.Add(url_box)
vbox_main.Add(file_box)
vbox_main.Add(mode_box)
vbox_main.Add(go_box)
self.panel.SetSizer(vbox_main)
self.Show(True)
def search(self):
pass
def submit(self):
pass
You can not add wxBoxSizer himself and you need to comment the line:
url_box.Add(url_box)
I uses a WrapSizer in order to have an automatic layout (as thumbnail gallery) like this (see screenshot on the left) :
I would like that if there are two many elements, a (vertical only)-ScrollBar is added on the panel (see right screenshot). How to add such a vertical scrollbar to a panel using a WrapSizer?
I tried by mixing WrapSizer and ScrolledPanel, but I cannot get the desired layout.
class MyPanel(scrolled.ScrolledPanel):
def __init__(self, parent):
scrolled.ScrolledPanel.__init__(self, parent)
self.SetBackgroundColour('#f8f8f8')
sizer = wx.WrapSizer()
self.SetupScrolling()
# add some widgets btn1, btn2, etc. in the WrapSizer
sizer.Add(btn1, 0, wx.ALL, 10)
sizer.Add(btn2, 0, wx.ALL, 10)
Solution:
reset the width of the scroll panel virtual size to the displayable size.
import wx
import wx.lib.scrolledpanel as scrolled
class MyPanel(scrolled.ScrolledPanel):
def __init__(self, parent):
scrolled.ScrolledPanel.__init__(self, parent, style=wx.VSCROLL)
self.SetBackgroundColour('#f8f8f8')
self.sizer = wx.WrapSizer()
self.SetupScrolling(scroll_x = False)
self.parent = parent
self.addButton(self.sizer , 10)
self.SetSizer(self.sizer )
self.Bind(wx.EVT_SIZE, self.onSize)
def onSize(self, evt):
size = self.GetSize()
vsize = self.GetVirtualSize()
self.SetVirtualSize((size[0], vsize[1]))
evt.Skip()
def addButton(self, sizer, num):
for i in range(1, num):
btn =wx.Button( self, wx.ID_ANY, "btn"+str(i), wx.DefaultPosition, wx.DefaultSize, 0 )
sizer.Add(btn, 0, wx.ALL, 10)
if __name__=='__main__':
app = wx.App(redirect=False)
frame = wx.Frame(None)
MyPanel(frame)
frame.Show()
app.MainLoop()
It looks like you just forgot to include
self.SetSizer(sizer)
Since the WrapSizer takes the whole frame, I think that will work. Also, instead of SetupScrolling, you can use
self.SetScrollRate(horiz, vert)
to specify the increment (in pixels, i think) of the scroll, and that should work.
I can't test it here right now though, and WrapSizers are a little weird - they sometimes have trouble figuring out their proper size. You may need to wrap it in a BoxSizer going the other direction.
I have created a pop up window, but the TextCtrl is not fully expanded to fill up the window. It works great if I use StaticText instead, (but if content too large then I would need the scroll bar, that is why I am using TextCtrl now). Please provide some guidance.
self.description = WindowPopup(self, wx.SIMPLE_BORDER, content)
btn = event.GetEventObject()
dw = wx.DisplaySize()[0]
width = self.description.GetSize()[0]
y = btn.ClientToScreen((0,0))[1]
height = btn.GetSize()[1]
x = dw - width - 20 - 10
self.description.Position((x, y), (0, height))
self.description.Show(True)
class WindowPopup(wx.PopupWindow):
""" Pops up a window to provide description for the selection """
def __init__(self, parent, style, content):
wx.PopupWindow.__init__(self, parent, style)
self.SetSize((700, 287))
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
st = wx.TextCtrl(self, -1, style = wx.TE_MULTILINE | wx.TE_READONLY)
st.SetValue(content)
sizer.Add(st, 0, wx.EXPAND)
panel.SetSizer(sizer)
I suspect your problem is that the panel is not as big as the popupwindow ... so even though the textfield is expanding to fill its sizer area it is not filling the popup its self.
try using something like
def __init__(...):
...
self.SetMinSize((700,287))
sizer2 = wx.BoxSizer()
sizer2.Add(panel)
self.SetSizer(sizer2)
also make sure that you are calling layout on it at some point (note this is totally untested... so it may need some tweeks, or even worse just be wrong...)
The actual answer is:
sizer = wx.BoxSizer(wx.VERTICAL)
st = wx.TextCtrl(self, -1, style = wx.TE_MULTILINE | wx.TE_READONLY, size = (500, 174))
st.SetValue(content)
self.SetSize((500, 174))
sizer.Add(st, 0, wx.EXPAND)
self.SetSizer(sizer)
self.Layout()
self.Show(True)
Credits to Joran for noticing Layout().
PopupWindow does not require an additional panel, because the window itself can have sizer set to it. This has been realized by using the wxPython Widget Inspection Tool.
Make sure TextCtrl and PopupWindow have the same size.