wxPython: How to use multiple windows? - python-3.x

I am making a program that gives you a list of artists to choose from and when you click on the artist it opens a new window and gives you a selection of their paintings. However, when I try to do this nothing happens on the new window. I can't put any buttons on it and even static text doesn't work on it, it works just fine on the parent window, but not the child window. Am I missing something or do I need to do something else completely? Here's my code:
import webbrowser
import sqlite3
import wx
conn = sqlite3.connect("dbPaintings.db")
c = conn.cursor()
c.execute("CREATE TABLE IF NOT EXISTS tblPaintings(Artist TEXT, PaintingName TEXT, Link TEXT)")
path = 'Artists Paintings.txt'
def insertingPaintings():
line = ''
filePaintings=open(path,'r')
for x in range(15):
arrPaintings = filePaintings.readline().split(",")
if len(arrPaintings) == 3:
strArtist = arrPaintings[0]
strPainting = arrPaintings[1]
strLink = arrPaintings[2]
strLink = strLink.split("\\")[0]
c.execute("INSERT INTO tblPaintings(Artist, PaintingName, Link) VALUES(:ArtistName, :Painting, :Url)", {'ArtistName':strArtist,'Painting':strPainting,'Url':strLink})
conn.commit()
#insertingPaintings()
class ArtFrame(wx.Frame):
def __init__(self, keyID, title, parent):
wx.Frame.__init__(self,parent=parent,title=title,size=(800,600))
panel = wx.Panel(self)
wx.StaticText(panel,-1,"Working",(566,345))
self.SetBackgroundColour('white')
if keyID=='Auguste Renoir':
self.AugusteRenoirWork()
def AugusteRenoirWork(self):
UmbrellasButtonImage = wx.Image('The Umbrellas.jpg',wx.BITMAP_TYPE_JPEG).ConvertToBitmap()
UmbrellasButton = wx.BitmapButton(wx.Panel(self),-1,UmbrellasButtonImage,pos=(200,200),size=(200,250))
class MainFrame(wx.Frame):
def __init__(self,*args,**kwargs):
super(MainFrame, self).__init__(*args, **kwargs, size=(1280,720), style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER ^ wx.MAXIMIZE_BOX)
self.basicGUI()
self.Centre()
def basicGUI(self):
panel = wx.Panel(self)
self.SetBackgroundColour('black')
self.SetTitle('French Impressionism')
font=wx.Font(18, wx.DECORATIVE, wx.ITALIC, wx.NORMAL)
AugusteRenoirButtonImage = wx.Image('Auguste Renoir.jpg',wx.BITMAP_TYPE_JPEG).ConvertToBitmap()
AugusteRenoirText = wx.StaticText(panel,-1,"Auguste Renoir",(237,345))
AugusteRenoirText.SetForegroundColour("#e6b800")
AugusteRenoirText.SetFont(font)
AugusteRenoirButton = wx.BitmapButton(panel,-1,AugusteRenoirButtonImage,pos=(220,85),size=(200,250))
self.Bind(wx.EVT_BUTTON,self.RenoirWindow,AugusteRenoirButton)
ClaudeMonetButtonImage = wx.Image('Claude Monet.jpg',wx.BITMAP_TYPE_JPEG).ConvertToBitmap()
ClaudeMonetText = wx.StaticText(panel,-1,"Claude Monet",(566,345))
ClaudeMonetText.SetForegroundColour("#206020")
ClaudeMonetText.SetFont(font)
ClaudeMonetButton = wx.BitmapButton(panel,-1,ClaudeMonetButtonImage,pos=(540,85),size=(200,250))
self.Bind(wx.EVT_BUTTON,self.MonetWindow,ClaudeMonetButton)
VincentVanGoghButtonImage = wx.Image('Vincent Van Gogh.jpg',wx.BITMAP_TYPE_JPEG).ConvertToBitmap()
VincentVanGoghText = wx.StaticText(panel,-1,"Vincent Van Gogh",(862,345))
VincentVanGoghText.SetForegroundColour("#3385ff")
VincentVanGoghText.SetFont(font)
VincentVanGoghButton = wx.BitmapButton(panel,-1,VincentVanGoghButtonImage,pos=(860,85),size=(200,250))
self.Bind(wx.EVT_BUTTON,self.VanGoghWindow,VincentVanGoghButton)
GeorgesSeuratButtonImage = wx.Image('Georges Seurat.jpg',wx.BITMAP_TYPE_JPEG).ConvertToBitmap()
GeorgesSeuratText = wx.StaticText(panel,-1,"Georges Seurat",(393,640))
GeorgesSeuratText.SetForegroundColour("#990099")
GeorgesSeuratText.SetFont(font)
GeorgesSeuratButton = wx.BitmapButton(panel,-1,GeorgesSeuratButtonImage,pos=(380,380),size=(200,250))
self.Bind(wx.EVT_BUTTON,self.SeuratWindow,GeorgesSeuratButton)
PaulCezanneButtonImage = wx.Image('Paul Cezanne.jpg',wx.BITMAP_TYPE_JPEG).ConvertToBitmap()
PaulCezanneText = wx.StaticText(panel,-1,"Paul Cezanne",(735,640))
PaulCezanneText.SetForegroundColour("#cc2900")
PaulCezanneText.SetFont(font)
PaulCezanneButton = wx.BitmapButton(panel,-1,PaulCezanneButtonImage,pos=(710,380),size=(200,250))
self.Bind(wx.EVT_BUTTON,self.CezanneWindow,PaulCezanneButton)
self.Show(True)
def RenoirWindow(self,event):
wx.Panel(self)
title = "Auguste Renoir's Works"
keyID='Auguste Renoir'
frame = ArtFrame(parent=wx.GetTopLevelParent(self),title=title,keyID=keyID)
frame.Show(True)
def MonetWindow(self,event):
wx.Panel(self)
title = "Claude Monet's Works"
keyID='Claude Monet'
frame = ArtFrame(parent=wx.GetTopLevelParent(self),title=title,keyID=keyID)
def VanGoghWindow(self,event):
wx.Panel(self)
title = "Vincent Van Gogh's Works"
keyID='Vincent Van Gogh'
frame = ArtFrame(parent=wx.GetTopLevelParent(self),title=title,keyID=keyID)
def SeuratWindow(self,event):
wx.Panel(self)
title = "Georges Seurat's Works"
keyID='Georges Seurat'
frame = ArtFrame(parent=wx.GetTopLevelParent(self),title=title,keyID=keyID)
def CezanneWindow(self,event):
wx.Panel(self)
title = "Paul Cezanne's Works"
keyID='Paul Cezanne'
frame = ArtFrame(parent=wx.GetTopLevelParent(self),title=title,keyID=keyID)
app = wx.App()
MainFrame(None)
app.MainLoop()

Please note it would be easier if you posted a smaller snippet of code that can be run by anyone without the need of your database and jpg's etc
In
class ArtFrame(wx.Frame):
def __init__(self, keyID, title, parent):
wx.Frame.__init__(self,parent=parent,title=title,size=(800,600))
panel = wx.Panel(self)
wx.StaticText(panel,-1,"Working",(566,345))
self.SetBackgroundColour('white')
if keyID=='Auguste Renoir':
self.AugusteRenoirWork()
def AugusteRenoirWork(self):
UmbrellasButtonImage = wx.Image('The Umbrellas.jpg',wx.BITMAP_TYPE_JPEG).ConvertToBitmap()
UmbrellasButton = wx.BitmapButton(wx.Panel(self),-1,UmbrellasButtonImage,pos=(200,200),size=(200,250))
when the wx.BitmapButton is created it has a new panel as its parent wx.Panel(self), instead use the panel that was created in the init
something like this
class ArtFrame(wx.Frame):
def __init__(self, keyID, title, parent):
wx.Frame.__init__(self,parent=parent,title=title,size=(800,600))
self.panel = wx.Panel(self)
wx.StaticText(self.panel,-1,"Working",(566,345))
self.SetBackgroundColour('white')
if keyID=='Auguste Renoir':
self.AugusteRenoirWork()
def AugusteRenoirWork(self):
UmbrellasButtonImage = wx.Image('The Umbrellas.jpg',wx.BITMAP_TYPE_JPEG).ConvertToBitmap()
UmbrellasButton = wx.BitmapButton(self.panel,-1,UmbrellasButtonImage,pos=(200,200),size=(200,250))

Related

pyqt5 QPushButton object not connecting, what am I doing wrong?

Pardon the use of mixed English/Finnish in the variable names.
Now, this is a work in progress, but the basically the QPushButton created does not connect to the function specified. I won't get any printouts to the console nor does it open the color selector dialog.
I have no idea `what I'm doing wrong, since otherwise my code is working just fine. Is this a slot problem?
class tyovuoroStyle:
def __init__(self, id, selite, seliteColor = "000000", entryColor1 = "FFFFFF", entryColor2 = "CCCCCC"):
self.id = id
self.teksti = selite
self.tekstiColor = seliteColor
self.riviColor1 = entryColor1
self.riviColor2 = entryColor2
self.idLabel = QLabel(id)
self.Editor = QPlainTextEdit(selite)
self.EditorColor = QLabel()
self.changeTextColor = QPushButton("Vaihda")
self.changeTextColor.clicked.connect(self.clickChangeTextColor)
print(hexToRGB(self.tekstiColor))
EditorColorRGB = hexToRGB(self.tekstiColor)
self.EditorStyleString = str("background-color:rgb({},{},{})".format(EditorColorRGB[0],EditorColorRGB[1],EditorColorRGB[2]))
print(self.EditorStyleString)
self.EditorColor.setStyleSheet(self.EditorStyleString)
def changeTextColor(self, newColor):
self.tekstiColor = newColor
EditorColorRGB = hexToRGB(self.tekstiColor)
self.EditorStyleString = str("background-color:rgb({},{},{})".format(EditorColorRGB[0],EditorColorRGB[1],EditorColorRGB[2]))
self.EditorColor.setStyleSheet(self.EditorStyleString)
def clickChangeTextColor(self):
print("I should be seen!")
newColor = getColor()
#self.changeTextColor()
def getColor(self):
color = QColorDialog.getColor()
if color.isValid():
print(color.name())
return color.name()
else:
return False
class ColorEditor(QMainWindow):
def addEntry(self, style):
procWidget = QWidget()
procLayout = QVBoxLayout()
setTextColorHolder = QWidget()
setTextColorHolderLayout = QHBoxLayout()
setTextColorHolderLayout.addWidget(style.EditorColor)
setTextColorHolderLayout.addWidget(style.changeTextColor)
setTextColorHolder.setLayout(setTextColorHolderLayout)
procLayout.addWidget(style.idLabel)
procLayout.addWidget(style.Editor)
procLayout.addWidget(setTextColorHolder)
procWidget.setLayout(procLayout)
return procWidget
def __init__(self):
super().__init__()
self.setWindowTitle("Muokkaa värejä")
layout = QVBoxLayout()
laatikko1 = tyovuoroStyle("First Entry", "Placeholder text for first entry")
layout.addWidget(self.addEntry(laatikko1))
mainWidget = QWidget()
mainWidget.setLayout(layout)
self.setCentralWidget(mainWidget)
def hexToRGB(koodi):
red = int(koodi[:2], 16)
green = int(koodi[2:4],16)
blue = int(koodi[-2:], 16)
return red, green, blue
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setStyle("Fusion")
ColEdit = ColorEditor()
ColEdit.show()
app.exec()

using pypubsub & wxpython to transfer data between windows getting TypeError:

I am trying to pass data between two wxpython windows using PyPubSub. Below I have pared the code down the the basics. What I am getting when I fill in the data in the textcntrl on the main window and hit the button to pass it to the second window (CoordFrame) I am getting the following error-
TypeError: sendMessage() takes 2 positional arguments but 3 were given
Every example I can find shows passing two parameters in the pub.sendMessage; which is what I think I'm doing. What is the 3rd parameter being passed, where does it come form and how do I stop it? I have tried various combinations of arguments, and datatypes including binary.
'''
from pubsub import pub
import wx
class MainFrame (wx.Frame):
def __init__(self, parent, title):
super(MainFrame, self).__init__(parent, title = title, size = (200,200))
self.panel = MainPanel(self)
class CoordFrame (wx.Frame):
def __init__(self, parent, title):
super(CoordFrame, self).__init__(parent, title = title, size = (200,200))
self.panel = CoordPanel(self)
class MainPanel(wx.Panel):
def __init__(self, parent):
super(MainPanel, self).__init__(parent)
vsizer = wx.BoxSizer(wx.VERTICAL)
self.tbxNewMap = wx.TextCtrl(self, id=1001, pos=(20,20), size = (50,20) ,style = wx.TE_CENTER|wx.TE_NOHIDESEL|wx.TE_PROCESS_ENTER)
vsizer.Add(self.tbxNewMap)
self.btnEnterNewMap = wx.Button(self, id=1002, label = "New Data", pos = (20,80), size = (80,40))
vsizer.Add(self.btnEnterNewMap,0,wx.EXPAND)
self.Bind(wx.EVT_BUTTON, self.onButtonNewMap, id=1002)
def onButtonNewMap(self,event):
temp = self.tbxNewMap.GetValue()
pub.sendMessage("coord_listener", temp)
coordframe = CoordFrame(None,"Entry")
coordframe.Show()
class CoordPanel(wx.Panel):
def __init__(self, parent):
super(CoordPanel, self).__init__(parent)
vsizer = wx.BoxSizer(wx.VERTICAL)
pub.subscribe(self.coord_listener, "coord_listener")
self.tbxNewMapNumber = wx.TextCtrl(self, id=1000, pos=(20,20), size = (50,20), style = wx.TE_CENTER|wx.TE_NOHIDESEL|wx.TE_PROCESS_ENTER)
vsizer.Add(self.tbxNewMapNumber)
def coord_listener(self, message):
newmapnum = message
self.tbxNewMapNumber.SetValue(newmapnum)
self.tbxNewMapNumber.Refresh()
class GMDash(wx.App):
def OnInit(self):
self.mainframe = MainFrame(parent = None, title = "Dashboard")
self.mainframe.Show()
return True
app = GMDash()
app.MainLoop()
'''
Use a named argument in the call to sendmessage and you'll need to register the listener before sending the message, not after, as you are currently doing.
See below:
from pubsub import pub
import wx
class MainFrame (wx.Frame):
def __init__(self, parent, title):
super(MainFrame, self).__init__(parent, title = title, size = (200,200))
self.panel = MainPanel(self)
class CoordFrame (wx.Frame):
def __init__(self, parent, title):
super(CoordFrame, self).__init__(parent, title = title, size = (200,200))
self.panel = CoordPanel(self)
class MainPanel(wx.Panel):
def __init__(self, parent):
super(MainPanel, self).__init__(parent)
vsizer = wx.BoxSizer(wx.VERTICAL)
self.tbxNewMap = wx.TextCtrl(self, id=1001, pos=(20,20), size = (50,20) ,style = wx.TE_CENTER|wx.TE_NOHIDESEL|wx.TE_PROCESS_ENTER)
vsizer.Add(self.tbxNewMap)
self.btnEnterNewMap = wx.Button(self, id=1002, label = "New Data", pos = (20,80), size = (80,40))
vsizer.Add(self.btnEnterNewMap,0,wx.EXPAND)
self.Bind(wx.EVT_BUTTON, self.onButtonNewMap, id=1002)
#Register the subscrption *before* sending the message
self.coordframe = CoordFrame(None,"Entry")
def onButtonNewMap(self,event):
temp = self.tbxNewMap.GetValue()
pub.sendMessage("coord_listener", message=temp)
#coordframe = CoordFrame(None,"Entry")
self.coordframe.Show()
class CoordPanel(wx.Panel):
def __init__(self, parent):
super(CoordPanel, self).__init__(parent)
vsizer = wx.BoxSizer(wx.VERTICAL)
pub.subscribe(self.coord_listener, "coord_listener")
self.tbxNewMapNumber = wx.TextCtrl(self, id=1000, pos=(20,20), size = (50,20), style = wx.TE_CENTER|wx.TE_NOHIDESEL|wx.TE_PROCESS_ENTER)
vsizer.Add(self.tbxNewMapNumber)
def coord_listener(self, message):
print(message)
newmapnum = message
self.tbxNewMapNumber.SetValue(newmapnum)
self.tbxNewMapNumber.Refresh()
class GMDash(wx.App):
def OnInit(self):
self.mainframe = MainFrame(parent = None, title = "Dashboard")
self.mainframe.Show()
return True
app = GMDash()
app.MainLoop()

How to use wxshaped window and png with transparency in Python 3?

Edit: Found out how to place a transparent wxPanel on my shaped frame, but now ı try to put a wxGridBagSizer on the wxPanel with some widgets in it but only the first widget will appear...Any ideas?
Original question :
Well I'm trying to make a wx.ShapedWindow with a png background that has transparency, the problem is that it looks like they changed the wx lib so to set the shape on the bitmap before we could use wx.RegionFromBitmap() but this is not working anymore, i tried to use wx.Region only but i can't figure out how to have the transparency ! I have a grey zone where i would like transparent region....
If anyone can help me !
Here's what i get now :
import wx
from os import getcwd
class ShapedFrame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, None, -1, "Shaped Window", style = wx.FRAME_SHAPED | wx.SIMPLE_BORDER )
self.hasShape = False
self.delta = wx.Point(0,0)
ImgDir = (getcwd()+u"\\img\\ex.png")
self.bmp = wx.Image(ImgDir, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
w,h = self.bmp.GetWidth(), self.bmp.GetHeight()
self.SetClientSize(w,h)
#self.panel = wx.Panel(self, -1,size=(100,100))
panel = Panel(self)
panel.Show()
dc = wx.ClientDC(self)
dc.DrawBitmap(self.bmp, 0,0, True)
self.SetWindowShape()
self.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick)
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
self.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.Bind(wx.EVT_RIGHT_UP, self.OnExit)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_WINDOW_CREATE, self.SetWindowShape)
################# EDIT ONLY BUTTON 0 WILL APPEAR ########################
button0 = wx.Button(panel, -1, "hello 0")
button1 = wx.Button(panel, -1, "hello 1")
button2 = wx.Button(panel, -1, "hello 2")
button3 = wx.Button(panel, -1, "hello 3")
gbox7 = wx.GridBagSizer(0,0)
gbox7.SetEmptyCellSize((10,10))
gbox7.Add(button0,(0,0))
gbox7.Add(button1,(0,1))
gbox7.Add(button2,(1,0))
gbox7.Add(button3,(1,1))
panel.SetSizer(gbox7)
#######################################################################
def SetWindowShape(self, evt=None):
r = wx.Region(self.bmp,wx.TransparentColour)
self.hasShape = self.SetShape(r)
def OnDoubleClick(self, evt):
if self.hasShape:
self.SetShape(wx.Region())
self.hasShape = False
else:
self.SetWindowShape()
def OnPaint(self, evt):
dc = wx.PaintDC(self)
dc.DrawBitmap(self.bmp, 0,0, True)
def OnExit(self, evt):
self.Close()
def OnLeftDown(self, evt):
self.CaptureMouse()
pos = self.ClientToScreen(evt.GetPosition())
origin = self.GetPosition()
self.delta = wx.Point(pos.x - origin.x, pos.y - origin.y)
def OnMouseMove(self, evt):
if evt.Dragging() and evt.LeftIsDown():
pos = self.ClientToScreen(evt.GetPosition())
newPos = (pos.x - self.delta.x, pos.y - self.delta.y)
self.Move(newPos)
def OnLeftUp(self, evt):
if self.HasCapture():
self.ReleaseMouse()
class Panel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, -1, size=(200, 200,),style=wx.TRANSPARENT_WINDOW)
self.CenterOnParent()
app = wx.App()
ShapedFrame(None,-1,None).Show()
app.MainLoop()
Okay i found out a solution, looking in wx.coulor since 2.9 they added wxTransparentColour
so i replaced :
r = wx.Region(self.bmp,"grey",30)
with:
r = wx.Region(self.bmp,wx.TransparentColour)
and it works fine ! Hope it will help other people too :)

how entrer value in new window and passing values of wx.newindow to wx.Frame wxpython

i have a panel with button Dynamic and when i click in button i have a new window opened the problem that i need zone to enter values to edit parameter of dynamic image like that :
that my code :
import wx
class MainFrame(wx.Frame):
def __init__(self,parent):
wx.Frame.__init__(self,parent,title="Myfirst",size=(800,580))
self.top = wx.Panel(self, style = wx.SUNKEN_BORDER)
self.bottom = wx.Panel(self ,style = wx.SUNKEN_BORDER)
self.left = wx.Panel(self ,style = wx.SUNKEN_BORDER, size = (250,-1))
st1 = wx.StaticText(self.bottom, -1, "show info ")
self.bottom.SetBackgroundColour('white')
dynamic=wx.Button(self.left,-1,"Dynamique",size=(110,30),pos=(50,100))
self.Bind(wx.EVT_BUTTON, self.newwindow, dynamic)
sizer1 = wx.BoxSizer(wx.VERTICAL)
sizer1.Add(self.top,1,wx.EXPAND,5)
sizer1.Add(self.bottom,1,wx.EXPAND,5)
sizer2 = wx.BoxSizer(wx.HORIZONTAL)
sizer2.Add(self.left,0,wx.EXPAND,5)
sizer2.Add(sizer1,1,wx.EXPAND,5)
self.SetSizer(sizer2)
def newwindow(self, event):
secondWindow = window2(parent=self.left)
secondWindow.Show()
class window2(wx.Frame):
title = "new Window"
def __init__(self,parent):
wx.Frame.__init__(self,parent, -1,'Dynamic of image', size=(300,100))
panel=wx.Panel(self, -1)
self.SetBackgroundColour(wx.Colour(100,100,100))
self.Centre()
self.Show()
app = wx.App()
frame=MainFrame(None).Show()
app.MainLoop()
how can i add the zone to edit parametre like picture ?
i not sure if the newwindow what i need or dialog !!
thanks for help
I guess you will be fine with a normal new window. You can get the zone to write the parameters with a wx.TextCtrl widgets. You will need a way to export the values typed into the wx.TextCtrl so I added the style wx.TE_PROCESS_ENTER. With this style when you finish typing and press Enter you can process the typed values.
Also, there is no need to use Show() two times (secondWindow.Show() and self.Show()). One of them is enough.
Code with comments:
import wx
class MainFrame(wx.Frame):
def __init__(self,parent):
wx.Frame.__init__(self,parent,title="Myfirst",size=(800,580))
self.top = wx.Panel(self, style = wx.SUNKEN_BORDER)
self.bottom = wx.Panel(self ,style = wx.SUNKEN_BORDER)
self.left = wx.Panel(self ,style = wx.SUNKEN_BORDER, size = (250,-1))
st1 = wx.StaticText(self.bottom, -1, "show info ")
self.bottom.SetBackgroundColour('white')
dynamic=wx.Button(self.left,-1,"Dynamique",size=(110,30),pos=(50,100))
self.Bind(wx.EVT_BUTTON, self.newwindow, dynamic)
sizer1 = wx.BoxSizer(wx.VERTICAL)
sizer1.Add(self.top,1,wx.EXPAND,5)
sizer1.Add(self.bottom,1,wx.EXPAND,5)
sizer2 = wx.BoxSizer(wx.HORIZONTAL)
sizer2.Add(self.left,0,wx.EXPAND,5)
sizer2.Add(sizer1,1,wx.EXPAND,5)
self.SetSizer(sizer2)
def newwindow(self, event):
secondWindow = window2(parent=self.left)
secondWindow.Show()
class window2(wx.Frame):
title = "new Window"
def __init__(self,parent):
"""
This is similar to the class MainFrame. You define a parent wx.Panel
and all other widgets are his childs.
"""
wx.Frame.__init__(self,parent, -1,'Dynamic of image', size=(300,100))
self.panel=wx.Panel(self, -1, style=wx.SUNKEN_BORDER)
self.st = wx.StaticText(self.panel, label='modifier bornes de la dynamique', style=wx.ALIGN_CENTER)
#### Notice the wx.TE_PROCESS_ENTER style to trigger processing the input when
#### Enter is pressed. Another alternative is to put a button somewhere.
self.text = wx.TextCtrl(self.panel, size=(200, 20), style=wx.SUNKEN_BORDER|wx.TE_PROCESS_ENTER)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.st, 0, wx.EXPAND|wx.ALL, 5)
self.sizer.Add(self.text, 0, wx.ALIGN_CENTER|wx.ALL, 5)
self.panel.SetSizer(self.sizer)
self.sizer.Fit(self.panel)
#self.SetBackgroundColour(wx.Colour(100,100,100))
self.Centre()
#### No need to use Show() here since you already use it in MainFrame.newwindow()
self.Show()
#### To execute self.onEnter when Enter is pressed inside self.text
self.Bind(wx.EVT_TEXT_ENTER, self.onEnter)
def onEnter(self, event):
#### Change it to fit your needs
print(self.text.GetValue())
self.Destroy()
app = wx.App()
frame=MainFrame(None).Show()
app.MainLoop()

How do I auto fit a Matplotlib figure inside a PySide QFrame?

I'm creating a simple PySide application that also uses MatPlotLib. However, when I add the figure into a QFrame, the figure doesn't automatically fit to the frame:
My graph is created using the following code:
class GraphView(gui.QWidget):
def __init__(self, name, title, graphTitle, parent = None):
super(GraphView, self).__init__(parent)
self.name = name
self.graphTitle = graphTitle
self.dpi = 100
self.fig = Figure((5.0, 3.0), dpi = self.dpi, facecolor = (1,1,1), edgecolor = (0,0,0))
self.axes = self.fig.add_subplot(111)
self.canvas = FigureCanvas(self.fig)
self.Title = gui.QLabel(self)
self.Title.setText(title)
self.layout = gui.QVBoxLayout()
self.layout.addStretch(1)
self.layout.addWidget(self.Title)
self.layout.addWidget(self.canvas)
self.setLayout(self.layout)
def UpdateGraph(self, data, title = None):
self.axes.clear()
self.axes.plot(data)
if title != None:
self.axes.set_title(title)
self.canvas.draw()
And it's added to the main Widget like so:
# Create individual Widget/Frame (fftFrame)
fftFrame = gui.QFrame(self)
fftFrame.setFrameShape(gui.QFrame.StyledPanel)
self.FFTGraph = GraphView('fftFrame', 'FFT Transform:', 'FFT Transform of Signal', fftFrame)
Here's a working code sample that shows you how to get it working. I first thought it was because of the stretch you added to the layout, which will use up the additional space around the other widgets. But when I removed it, it still wouldn't resize. The 'easy' solution is to add a resizeEvent, which lets you define the size of your GraphView widget. In this case I just set its geometry to be that of the QFrame, though you might want to add some padding and make sure you set a sensible minimum size for the QFrame.
from PySide import QtGui
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import sys
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.fft_frame = FftFrame(self)
self.layout = QtGui.QVBoxLayout()
self.layout.addWidget(self.fft_frame)
self.setLayout(self.layout)
self.setCentralWidget(self.fft_frame)
class FftFrame(QtGui.QFrame):
def __init__(self, parent=None):
super(FftFrame, self).__init__(parent)
self.setFrameShape(QtGui.QFrame.StyledPanel)
self.parent = parent
self.graph_view = GraphView('fftFrame', 'FFT Transform:', 'FFT Transform of Signal', self)
def resizeEvent(self, event):
self.graph_view.setGeometry(self.rect())
class GraphView(QtGui.QWidget):
def __init__(self, name, title, graph_title, parent = None):
super(GraphView, self).__init__(parent)
self.name = name
self.graph_title = graph_title
self.dpi = 100
self.fig = Figure((5.0, 3.0), dpi = self.dpi, facecolor = (1,1,1), edgecolor = (0,0,0))
self.axes = self.fig.add_subplot(111)
self.canvas = FigureCanvas(self.fig)
self.canvas.setParent(self)
self.Title = QtGui.QLabel(self)
self.Title.setText(title)
self.layout = QtGui.QVBoxLayout()
self.layout.addWidget(self.Title)
self.layout.addWidget(self.canvas)
self.layout.setStretchFactor(self.canvas, 1)
self.setLayout(self.layout)
self.canvas.show()
def update_graph(self, data, title = None):
self.axes.clear()
self.axes.plot(data)
if title != None:
self.axes.set_title(title)
self.canvas.draw()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()

Resources