I am new coding guis, and I want to make a chat box where the user could chat with an IA that answer questions and FAQS
This is for a personal work where you have an IA that you can chat and interact with him, I searched tutorials on StackOverflow but are to have a chat online and it was more complex
app = wx.App(False)
frame = wx.Frame(None, -1, 'Chat', size= (450, 550))
frame.Show(True)
mati = wx.StaticBitmap(frame, -1, wx.Bitmap('chat01.png', wx.BITMAP_TYPE_ANY), pos = wx.Point(0, 0), size = (450, 550))
wx.TextCtrl(mati, pos = (0, 455), size = (450, 50))
sizer = wx.BoxSizer(wx.VERTICAL)
I expect a functional chat where the user can write questions and talk to the IA
As Michael wrote in the commments, please take a look at How to ask first.
After that take a look at wxPython Tutorial! There you will find some information about Widgets you need. To start with you should use wx.TextCtrl or wx.StaticText for inputs and prints in your GUI.
wx.TextCtrl(parent, id, value, pos, size, style)
and
Wx.StaticText(parent, id, label, position, size, style)
Also this code sample should give you a good starting point:
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, size=(200,100))
self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE)
self.Show(True)
app = wx.App(False)
frame = MyFrame(None, 'Example')
app.MainLoop()
Related
I want to have an image below a slider in a wxpython GUI. The text asks "What is the value?" and I want to have a picture of a value (such as 35) below the slider, and have different images that change as you navigate through.
I have researched this issue, but only found ways to make an image the entire background, rather then appear in the panel.
import wx
class MyPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id)
self.SetBackgroundColour("white")
text1 = wx.StaticText(self, -1, "What is the value", (10,10))
self.slider1 = wx.Slider(self, -1, 50, 0, 100, (10, 40), (200, 50),
wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_LABELS)
self.Bind(wx.EVT_SLIDER, self.sliderUpdate)
def sliderUpdate(self, event):
self.pos1 = self.slider1.GetValue()
if self.pos1 == 35:
box = wx.MessageDialog(None, "BINGO!", "Title", wx.OK)
box.ShowModal()
app = wx.App()
frame = wx.Frame(None, -1, "Title", size = (400, 310))
MyPanel(frame,-1)
frame.Show(True)
app.MainLoop()
Additionally, I am unsure how to create multiple pages to switch the pictures at the bottom and have a submit button that checks if it is correct before moving on.
Any literature or videos that you can point me to to better learn wxpython would be appreciated as well.
Just add the image to the panel in the required position or start using sizers.
I've added some quick PIL code to generate an image of a number or text, so that you can generate your image on the fly if you need to, although I have left it as a single global instance. You may want to make it a function.
import wx
from PIL import Image, ImageDraw
temp_img=[]
for i in range(101):
img = Image.new('RGB', (100,30))
d = ImageDraw.Draw(img)
d.text((10,10), str(i))
width, height = img.size
temp_img.append(wx.Bitmap.FromBuffer(width, height, img.tobytes()))
class MyPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id)
self.SetBackgroundColour("white")
text1 = wx.StaticText(self, -1, "What is the value", (10,10))
self.slider1 = wx.Slider(self, -1, 50, 0, 100, (10, 40), (200, 50),
wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_LABELS)
self.bmp = wx.StaticBitmap(self, -1, bitmap=temp_img[50], pos=(10,100))
self.Bind(wx.EVT_SLIDER, self.sliderUpdate)
def sliderUpdate(self, event):
self.pos1 = self.slider1.GetValue()
self.bmp.SetBitmap(temp_img[self.pos1])
if self.pos1 == 35:
box = wx.MessageDialog(None, "BINGO 35!", "Title", wx.OK)
box.ShowModal()
app = wx.App()
frame = wx.Frame(None, -1, "Title", size = (400, 310))
MyPanel(frame,-1)
frame.Show(True)
app.MainLoop()
Edited to show multiple images based on the slider value.
I am a humanities teacher, trying to adapt a simple app to help teachers manage classroom interaction - it takes attendance, then allows for calling on random attending students in class, or breaking them into groups, or recording an excused absence, and so on. I've long had a working version in PHP / MySQL running locally on my laptop, but I want to make it a portable python / sqlite app, with an eye toward releasing into the wild for other teachers to use and improve.
But I'm totally new to wxPython, and not really strong on object-oriented programming generally. I have spent hours reading (or skimming through) a fair number of tutorials and introductions and StackOverflow questions, and I've played with wxFormBuilder, but I do not feel like I'm making progress - I'm still quite confused about panels and sizers and layouts, and which bits should belong to what parents.
I think if I could just get this minimal version working, that would go a long way toward my real app. The toolbar-like buttons along the top seem to work fine, but I'd like a "display" area below with a minimal (but expandable) vertical size, a centered text area, and a row of 2-3 buttons in the display area below that text. This display area should change and clear depending on the button pushed above. Here's what I've got:
#!/usr/bin/env python3
import wx
class MainWindow(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, size=(-1,-1))
# self.panel = wx.Panel(self, size=(-1,300))
# buttons bar
self.top_button_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.btn_left = wx.Button(self, -1, label="left")
self.btn_right = wx.Button(self, -1, label="right")
self.btn_left.Bind(wx.EVT_BUTTON, self.OnLeft)
self.btn_right.Bind(wx.EVT_BUTTON, self.OnRight)
self.top_button_sizer.Add(self.btn_left, 1, wx.EXPAND)
self.top_button_sizer.Add(self.btn_right, 1, wx.EXPAND)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.display_sizer = wx.BoxSizer(wx.VERTICAL)
self.text_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.display_text = wx.StaticText(self, label="Push a button!")
self.display_buttons_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.text_sizer.Add(self.display_text, 0, wx.ALIGN_CENTER, 5)
self.display_sizer.Add(self.text_sizer, 1, wx.ALIGN_CENTER, 5)
self.display_sizer.Add(self.display_buttons_sizer, 0, wx.EXPAND)
self.sizer.Add(self.top_button_sizer, 0, wx.TOP | wx.EXPAND)
# self.sizer.Add(self.panel)
self.sizer.Add(self.display_sizer, 1, wx.EXPAND)
self.SetSizerAndFit(self.sizer)
self.Show()
def OnLeft(self,e):
# for child in self.display_buttons_sizer.GetChildren():
# child.Destroy()
# ^ my attempt to "clear" causes a SegFault
for child in self.display_buttons_sizer.GetChildren():
child.Destroy()
self.display_text.SetLabel("Hey lefty!")
self.btn_hey = wx.Button(self, -1, label="Hey yourself lefty.")
self.btn_whoa = wx.Button(self, -1, label="Whoa there lefty.")
self.display_buttons_sizer.Add(self.btn_hey, 1, wx.EXPAND)
self.display_buttons_sizer.Add(self.btn_whoa, 1, wx.EXPAND)
self.sizer.Layout()
def OnRight(self,e):
# for child in self.display_buttons_sizer.GetChildren():
# child.Destroy()
# ^ my attempt to "clear" causes a SegFault!
self.display_text.SetLabel("Hey righty!")
self.btn_hey = wx.Button(self, -1, label="Hey yourself righty.")
self.btn_whoa = wx.Button(self, -1, label="Whoa there righty.")
self.display_buttons_sizer.Add(self.btn_hey, 1, wx.EXPAND)
self.display_buttons_sizer.Add(self.btn_whoa, 1, wx.EXPAND)
self.sizer.Layout()
app = wx.App(False)
frame = MainWindow(None, "MWE")
app.MainLoop()
(I'm sure this is abhorrent code in lots of ways.) Should I put in a panel somewhere? Where, and how? Would it be easier to learn about "notebooks" instead of using my top buttons? How do I properly clear what's in the "display" area below for the next button push?
Bonus points: the most complicated of the top buttons on my real app is for taking attendance. It would display many lines of text (the students in that class, which I get from sqlite; I've worked that part out I think) with radio buttons for present / absent next to each line, and then record in the database. Hints about this would also be appreciated.
Thanks in advance for your patience.
You could do this sort of thing several different ways. You can swap out panels when a button is pushed or you could just use a wx.Notebook which is basically the same idea. I wrote up a tutorial on panel switching here that you might find helpful:
https://www.blog.pythonlibrary.org/2010/06/16/wxpython-how-to-switch-between-panels/
It uses a menu instead of buttons, but that wouldn't be hard to change. Here's a simple example that doesn't do panel switching, but does show how to add a multiline text control that clears itself when a button is pressed:
import wx
class MainPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
left_button = wx.Button(self, label='Left')
left_button.Bind(wx.EVT_BUTTON, self.on_left)
btn_sizer.Add(left_button, 0, wx.ALL, 5)
right_button = wx.Button(self, label='Right')
right_button.Bind(wx.EVT_BUTTON, self.on_right)
btn_sizer.Add(right_button, 0, wx.ALL, 5)
self.text_ctrl = wx.TextCtrl(self, style=wx.TE_MULTILINE)
self.main_sizer.Add(btn_sizer, 0, wx.CENTER)
self.main_sizer.Add(self.text_ctrl, 1, wx.ALL|wx.EXPAND, 5)
self.SetSizer(self.main_sizer)
def on_left(self, event):
self.text_ctrl.Clear()
self.text_ctrl.SetValue('Left')
def on_right(self, event):
self.text_ctrl.Clear()
self.text_ctrl.SetValue('Right')
class MainWindow(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, size=(-1,-1))
panel = MainPanel(self)
self.Show()
app = wx.App(False)
frame = MainWindow(None, "MWE")
app.MainLoop()
This also demonstrates how to add a panel, which is recommended as panels give you the right "look" on all platforms and it also enables tabbing between controls.
You could easily add another set of buttons to the bottom by using the same concepts shown here and then just adding the second set of button's sizer to the main sizer.
If you want to do lines of text with some kind of radio or check button, I would recommend using a wx.ListCtrl or (better), ObjectListView (https://objectlistview-python-edition.readthedocs.io/en/latest/recipes.html#recipe-checkbox) (see also https://www.blog.pythonlibrary.org/2009/12/23/wxpython-using-objectlistview-instead-of-a-listctrl/)
You can tie an event to the checkbox that can then update your database appropriately.
I so far failed to create what is colloquially called an "info icon" with wxPython. An icon with some sort of 'i' image that shows a large tooltip on hover.
I can add a wx.StaticBitmap for the image but it ignores all SetToolTipString or SetToolTip(wx.ToolTip()) calls. OR I can add a large tool tip to a wx.StaticText as shown below.
Ignore that the icon doesn't have the correct size yet.
Needless to say that eventually the tooltip needs a background color that is different from the panel background color (not the focus here). I can't use wx.adv.RichToolTip because I'm on wxPython 3.0.2.0 osx-cocoa.
What is a good way to solve this?
If you create a button with an ID of wx.ID_HELP then you'll get the stock help button for the platform, if it has one. Then you can do whatever you want with it like any button. Assign a tooltip, do something in the EVT_BUTTON event, etc. See the StockButtons sample in the demo. If the stock image or label doesn't meet your needs then you can probably just use a wx.BitmapButton to show the image you want and still have the standard tooltip support.
Something else you may want to look into is the ContextHelp sample in the demo. It shows how to use a wx.ContextHelpButton which, when clicked, puts the application into context-help mode. A popup tip window will then be shown for whatever widget is clicked on next. Not quite what you are asking for, but it might be a good fit.
wxArtProvider may be able to help http://docs.wxwidgets.org/trunk/classwx_art_provider.html
import wx
class Test(wx.Frame):
def __init__(self,parent,msg,title):
wx.Frame.__init__(self, None)
self.panel = wx.Panel(self, size=(300,400))
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
staticIcon = wx.BitmapButton(self.panel, bitmap=wx.ArtProvider.GetBitmap(wx.ART_WARNING), size=(32,32))
mainSizer.Add(staticIcon, flag=wx.ALL, border=10)
ttip = "xxxxxxxxxxxxxxx\n"
ttip += "xxxxxxxxxxxxxxxxxxxxxxxxxx\n"
ttip += "xxxxxxxxxxxxxxxxxxxxxxxxxxx\n"
ttip += "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
staticIcon.SetToolTipString(ttip)
buttonText = wx.StaticText(self.panel, -1, msg, wx.DefaultPosition, wx.DefaultSize, 0)
mainSizer.Add(buttonText, flag=wx.ALL, border=10)
staticIcon.Bind(wx.EVT_BUTTON, self.OnButton)
self.SetSizer(mainSizer)
self.Show()
def OnButton(self, evt):
print "The button was pressed - display some help"
if __name__ == '__main__':
app = wx.App()
Test(None, "Dummy Exercise", "Test 123")
app.MainLoop()
If all you want to do is show a tooltip when the image is moused over, then you need to bind your instance of the wx.StaticBitmap to EVT_MOTION:
import wx
class MyPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
bmp = wx.ArtProvider.GetBitmap(wx.ART_WARNING)
self.image = wx.StaticBitmap(self, bitmap=bmp)
self.image.Bind(wx.EVT_MOTION, self.on_mouse_over)
def on_mouse_over(self, event):
self.image.SetToolTipString('BLAH BLAH BLAH')
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title='Icon Mouser')
panel = MyPanel(self)
self.Show()
if __name__ == '__main__':
app = wx.App(False)
frame = MyFrame()
app.MainLoop()
When I run this code, I get something like this:
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.
I am new in wxPython and can't solve one problem. I need to continuously update panel with clock value. I have a solution, but in this case I can't normally close window (alt+f4 not works).
Also I do not unsderstand what is the difference between .Update .Refresh and when .Destroy should be called?
Can some one reccomend a good book, how to program in wxPython?
Thanks for any help.
class TimeDatePanel(wx.Panel):
def __init__(self, parent, ID=ID_TIMEDATE, pos=wx.DefaultPosition, size=(50, 50), controller=None):
wx.Panel.__init__(self, parent, ID, pos, size, wx.RAISED_BORDER)
self.controller = controller
transCoded = controller.transCodes
layout = wx.GridSizer(5,2,0,10)
layout.Add(wx.StaticText(self, wx.ID_ANY, transCoded.get("Time & Date")))
layout.Add(wx.StaticText(self, wx.ID_ANY, ""), 0,flag=wx.ALL)
layout.Add(wx.StaticText(self, wx.ID_ANY, transCoded.get("Local time")), 0,flag=wx.ALL|wx.ALIGN_RIGHT)
self.LT = wx.StaticText(self, wx.ID_ANY, "")
layout.Add(self.LT)
layout.Add(wx.StaticText(self, wx.ID_ANY, transCoded.get("UTC")), 0,flag=wx.ALL|wx.ALIGN_RIGHT)
self.UTC = wx.StaticText(self, wx.ID_ANY, "")
layout.Add(self.UTC)
layout.Add(wx.StaticText(self, wx.ID_ANY, transCoded.get("Julian day")), 0,flag=wx.ALL|wx.ALIGN_RIGHT)
self.JD = wx.StaticText(self, wx.ID_ANY, "")
layout.Add(self.JD)
layout.Add(wx.StaticText(self, wx.ID_ANY, transCoded.get("Local sidereal time")), 0,flag=wx.ALL|wx.ALIGN_RIGHT)
self.LST = wx.StaticText(self, wx.ID_ANY, "")
layout.Add(self.LST)
self.SetSizer(layout)
self.updateTimeDate()
self.Fit()
wx.EVT_PAINT(self, self.onPaint)
def onPaint(self, event=None):
self.updateTimeDate()
def updateTimeDate(self):
mechanics = self.controller.mechanics
self.LT.SetLabel(str(mechanics.getLT()))
self.UTC.SetLabel(str(mechanics.getUTC()))
self.JD.SetLabel(str(mechanics.getYD()))
self.LST.SetLabel(str(mechanics.getLST()))
If you need the clock updated every so often, why not use the AnalogClock, LEDNumberCtrl or maybe the TimeCtrl that's updated with a wx.Timer? The following tutorial will help you with the timer part: http://www.blog.pythonlibrary.org/2009/08/25/wxpython-using-wx-timers/
The first two widgets update themselves. You should have to call Update, Refresh or Layout when you rest a value of a StaticText control or other normal widget. Just use SetValue or SetLabel instead.
Robin Dunn has an older book called "wxPython in Action" that is still great for the most part. There's also a wxPython Cookbook by Cody Precord that came out this year.