consider the following pseudo code:
class gui():
...
def main(self):
btn = button(on_click=start_worker) #on button click call worker.start_worker()
def show_messagebox(self):
messagebox.show("event_occurred")
class worker():
...
def start_worker(self):
self.run()
def event_occurred(self):
#call gui.show_messagebox
those two classes are threads which calls each other functions, what is the best design pattern / coding approach for communicating between those two classes?
for example:
def app():
def main():
g = gui()
w = worker()
or
def gui():
def main():
w = worker()
or
def worker():
def main():
g = gui()
or something else..
please elaborate your answer.
Thanks.
My wxPython dirPickerCtrl text box is appearing over the top of its browse button.
My code is:
class chooseFolder(wx.DirPickerCtrl):
def __init__(self, *args, **kwargs):
wx.DirPickerCtrl.__init__(self, *args, **kwargs)
dataFolder = chooseFolder(self, -1, message= 'Choose Folder', pos = (55,24),
style= wx.DIRP_DEFAULT_STYLE,
size = (250, 25))
I have tried applying different sizers in that panel to see if that solves it but to no avail.
I am using wx version 4.0.3
EDIT: Below is a minimal code example to demonstrate the problem I am having, shown in the second picture.
import wx
import os
class ButtonFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
self.panel = wx.Panel(self, -1)
chooseFolder(parent=self,
pos = (10,100),
style= wx.DIRP_DEFAULT_STYLE,
size = (250, 30))
self.Centre()
self.Show()
class chooseFolder(wx.DirPickerCtrl):
def __init__(self, *args, **kwargs):
wx.DirPickerCtrl.__init__(self, *args, **kwargs)
if __name__ == "__main__":
app = wx.App()
ButtonFrame()
app.MainLoop()
picture of text box on top of button
EDIT: Picture of output from minimal code example
Edit based on code sample supplied:
I cannot test on Windows but it looks as if it may be a bug (it works on Linux).
Do you get the same result if you don't sub-class DirPickerCtrl but use it directly? Like this:
import wx
class ButtonFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
self.panel = wx.Panel(self, -1)
chooseFolder = wx.DirPickerCtrl(self.panel, -1, pos = (10,100), path = "",
style= wx.DIRP_DEFAULT_STYLE,
size = (250, 30))
# chooseFolder(parent=self,
# id = -1,
# pos = (10,100),
# path = "/home",
# style= wx.DIRP_DEFAULT_STYLE)#,
# #size = (250, 30))
self.Centre()
self.Show()
#class chooseFolder(wx.DirPickerCtrl):
# def __init__(self, *args, **kwargs):
# wx.DirPickerCtrl.__init__(self, *args, **kwargs)
if __name__ == "__main__":
app = wx.App()
ButtonFrame()
app.MainLoop()
You mention that you have tried applying sizers to the panel but in the question, there is no reference to a panel at all.
Try playing with the code below and see if it helps.
For simplicity, it relies solely on fixed positions (no sizers).
import wx
import os
class ButtonFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self,None)
self.panel = wx.Panel(self, -1)
self.BtnPressHere = wx.Button(self.panel, -1, "Press Here", pos=(10,10))
self.BtnPressHere.Bind(wx.EVT_BUTTON, self.OnPress)
self.Bind(wx.EVT_DIRPICKER_CHANGED, self.DirChange)
self.Centre()
self.Show()
print("Current Dir: ",os.getcwd())
def OnPress(self,event):
dataFolder = chooseFolder(parent=self,
id=-1,
path='/home',
message='Choose Folder',
pos = (10,100),
style= wx.DIRP_DEFAULT_STYLE|wx.DIRP_CHANGE_DIR,
size = (250, 30))
def DirChange(self,event):
print("Dir changed to: ", event.GetPath())
print("Checking Current Dir: ",os.getcwd())
class chooseFolder(wx.DirPickerCtrl):
def __init__(self, *args, **kwargs):
wx.DirPickerCtrl.__init__(self, *args, **kwargs)
if __name__ == "__main__":
app = wx.App()
ButtonFrame()
app.MainLoop()
I think the problem comes from the size given to the constructor. Try setting the height (second parameter of size) to -1 .
I never figured out how to use the style parameter. Can someone tell me how to use it to make nicer toggle buttons? Or if you can't use it directly, is there a way to do it manually?
Try something like this:
import wx
class MyForm(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Toggle")
panel = wx.Panel(self, wx.ID_ANY)
self.button = wx.ToggleButton(panel, label="Press Me")
self.button.Bind(wx.EVT_TOGGLEBUTTON, self.onToggle)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.button, 0, wx.ALL, 5)
panel.SetSizer(sizer)
def onToggle(self, event):
if self.button.GetValue() == True:
self.button.SetLabel("On")
else:
self.button.SetLabel("Off")
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()
First things first, the debugger doesn't touch my breakpoint.
It is set at the first instruction in the OnPaint method in my custom class.
import wx.aui, wx.lib.agw.aui
from wx.lib import platebtn
import wx.lib.scrolledpanel as spanel
class GuiScrolledPanel(spanel.ScrolledPanel):
def __init__(self, *args, **kwargs):
spanel.ScrolledPanel.__init__(self, *args, **kwargs)
self.SetSizer(GuiSchemaSizer())
self.SetupScrolling()
self.caption = "No active schema - Create a new schema or load one "
def OnChildFocus(self, *args, **kwargs):
self.Layout()
self.AdjustScrollbars()
return spanel.ScrolledPanel.OnChildFocus(self, *args, **kwargs)
def updateCaption(self, caption):
self.caption = caption
def OnPaint(self, *args, **kwargs):
some_result = spanel.ScrolledPanel.OnPaint(self, *args, **kwargs)
print 'OnPaint in MyDrawingArea'
dc = wx.PaintDC(self)
dc.BeginDrawing()
if self.BufferBmp != None:
print '...drawing'
dc.DrawBitmap(self.BufferBmp, 0, 0, True)
#should draw smth here, but what's the point when the method isn't even called, heh?
else:
print '...nothing to draw'
dc.EndDrawing()
return some_result
Thx a lot :)
It seems that the OnPaint method mUst be registered with the event wx.EVT_BIND.
self.Bind(wx.EVT_PAINT, self.OnPaint)
I am attempting to write a chat server with EventMachine. How do I pass a message from one EventMachine connection, to another, in a thread-safe manner?
I see a messaging protocol (Stomp) being supported but I can't figure out how to use it. Any help is appreciated.
Stomp in EventMachine - http://eventmachine.rubyforge.org/EventMachine/Protocols/Stomp.html
See http://eventmachine.rubyforge.org/EventMachine/Channel.html
you can try something in these lines:
require 'eventmachine'
class Chat < EventMachine::Connection
def initialize channel
#channel = channel
end
def post_init
send_data 'Hello'
#sid = #channel.subscribe do |msg|
send_data msg
end
end
def receive_data(msg)
#channel.push msg
end
def unbind
#channel.unsubscribe #sid
end
end
EM.run do
#channel = EventMachine::Channel.new
EventMachine.start_server '127.0.0.1', 8081, Chat, #channel
end
EDIT: also check out https://github.com/eventmachine/eventmachine/tree/master/examples/guides/getting_started - there is a nice chatroom example
Try starting out with an in memory message dispatcher.
require 'thread'
class Room
def initialize
#users = []
end
def join(user)
#users << user
end
def leave(user)
#user.delete(user)
end
def broadcast(message)
#users.each do |user|
user.enqueue(message)
end
end
end
class User
def initialize
#mutex = Mutex.new
#queued_messages = []
end
def enqueue(message)
#mutex.synchronize do
#queued_message << message
end
end
def get_new_messages
#mutex.synchronize do
output = #queued_messages
#queued_messages = []
end
return output
end
end
UPDATE
ROOM = Room.new
class Connection
def user_logged_in
# #user = ...
ROOM.join(#user)
end
def received_message(message)
ROOM.broadcast(message)
end
def receive_send_more_messages_request(req)
messages = #user.get_new_messages
# write messages
end
def connection_closed
ROOM.leave(#user)
end
end