wxpython listctrl and fix column widths - python

I am trying to make a "table" look good within my panel. This issue I'm having is that the table fills up the panel but everything is to the left. I would like to have each column be the same size and span the entire width of the panel. I have seen the ListCtrlAutoWidthMixin but am not sure how I could utilize this. Here is what I have in code:
self.Analysis = scrolled.ScrolledPanel(self.Notebook3, -1)
# Set Up Analysis Page (Page has four panels -- I care about Top left one)
self.AnalysisUL = wx.Panel(self.Analysis,-1, style=wx.BORDER_NONE)
self.AnalysisUR = wx.Panel(self.Analysis,-1, style=wx.BORDER_NONE)
self.AnalysisLL = wx.Panel(self.Analysis,-1, style=wx.BORDER_NONE)
self.AnalysisLR = wx.Panel(self.Analysis,-1, style=wx.BORDER_NONE)
# Top Left Box (Analyze Button and Projected Points Total)
self.Picks_Left = wx.ListCtrl(self.AnalysisUL,-1,style=wx.LC_REPORT | wx.BORDER_NONE)
self.Picks_Left.InsertColumn(1,'col1')
self.Picks_Left.InsertColumn(2,'col2',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.InsertColumn(3,'col3',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.InsertColumn(4,'col4',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.SetColumnWidth(0,-2)
self.Picks_Left.SetColumnWidth(1,-2)
self.Picks_Left.SetColumnWidth(2,-2)
self.Picks_Left.SetColumnWidth(3,-2)
# Sizer
vbox_UL = wx.BoxSizer(wx.VERTICAL)
#Title for Table
fontUL = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)
self.UL_text = wx.StaticText(self.AnalysisUL, -1, 'Title')
self.UL_text.SetFont(fontUL)
vbox_UL.Add(self.UL_text, 0, wx.CENTER|wx.ALL,20)
vbox_UL.Add(self.Picks_Left,1,wx.EXPAND|wx.ALL,3)
self.AnalysisUL.SetSizer(vbox_UL)
Again, the table spans the panel, but all my columns are shifted to the left. Also, I do not want to set the column size manually (unless I can grab the panel size and then divide by the number of columns I have -- since the program will be used on computers with different resolutions). I have tried this approach but cannot seem to get the correct size of the panels. The numbers I get with GetSize() and GetClientSize() are all too small.
Thanks for any help!
EDIT: Code Added:
import wx
import wx.lib.mixins.listctrl as listmix
import wx.lib.scrolledpanel as scrolled
import wx.lib.agw.pybusyinfo as PBI
class TMainForm(wx.Frame):
def __init__(self, *args, **kwds):
kwds["style"] = wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER
wx.Frame.__init__(self, *args, **kwds)
self.Splitter1 = wx.SplitterWindow(self, -1)#, style=wx.SP_NOSASH)
self.Splitter2 = wx.SplitterWindow(self.Splitter1)
self.Panel1 = wx.Panel(self.Splitter2, -1)
self.Panel2 = wx.Panel(self.Splitter2, -1)
self.Splitter2.SplitHorizontally(self.Panel1,self.Panel2)
self.Panel3 = wx.Panel(self.Splitter1, -1)
self.Splitter1.SplitVertically(self.Splitter2,self.Panel3,400)
self.Notebook = wx.Notebook(self.Panel1, -1)
self.MyTeam = scrolled.ScrolledPanel(self.Notebook, -1)
self.TeamComparison = scrolled.ScrolledPanel(self.Notebook, -1)
self.MyTeam.SetupScrolling()
self.TeamComparison.SetupScrolling()
self.Notebook3 = wx.Notebook(self.Panel3, -1)
self.Analysis = scrolled.ScrolledPanel(self.Notebook3, -1)
self.Analysis.SetupScrolling()
self.AnalysisUL = wx.Panel(self.Analysis,-1, style=wx.BORDER_NONE)
self.AnalysisUR = wx.Panel(self.Analysis,-1, style=wx.BORDER_NONE)
self.AnalysisLL = wx.Panel(self.Analysis,-1, style=wx.BORDER_NONE)
self.AnalysisLR = wx.Panel(self.Analysis,-1, style=wx.BORDER_NONE)
# Top Left Box (To Fix!)
self.Picks_Left = wx.ListCtrl(self.AnalysisUL,-1,style=wx.LC_REPORT | wx.BORDER_NONE)
self.Picks_Left.InsertColumn(1,' ')
self.Picks_Left.InsertColumn(2,' ',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.InsertColumn(3,'H1',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.InsertColumn(4,'H2',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.InsertColumn(5,'H#',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.InsertColumn(6,'H4',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.InsertColumn(7,'H5',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.InsertColumn(8,'H6',format=wx.LIST_FORMAT_CENTRE)
self.Picks_Left.InsertColumn(9,'H7',format=wx.LIST_FORMAT_CENTRE)
## table_width = self.Picks_Left.GetSize()[0] #GetSize returns (width, height) tuple
## print table_width
## num_col = self.Picks_Left.GetColumnCount()
## col_width = table_width/num_col
## for i in range(0, num_col):
## self.Picks_Left.SetColumnWidth(i, col_width)
self.Picks_Left.SetColumnWidth(0,-2)
self.Picks_Left.SetColumnWidth(1,-2)
self.Picks_Left.SetColumnWidth(2,-2)
self.Picks_Left.SetColumnWidth(3,-2)
self.Picks_Left.SetColumnWidth(4,-2)
self.Picks_Left.SetColumnWidth(5,-2)
self.Picks_Left.SetColumnWidth(6,-2)
self.Picks_Left.SetColumnWidth(7,-2)
self.Picks_Left.SetColumnWidth(8,-2)
# Bottom Left Box (Suggested Optimal Teams)
self.Notebook_AltTeams = wx.Notebook(self.AnalysisLL, -1)
self.Alt_Team_1 = scrolled.ScrolledPanel(self.Notebook_AltTeams, -1)
self.Alt_Team_2 = scrolled.ScrolledPanel(self.Notebook_AltTeams, -1)
self.Alt_Team_3 = scrolled.ScrolledPanel(self.Notebook_AltTeams, -1)
self.Alt_Team_4 = scrolled.ScrolledPanel(self.Notebook_AltTeams, -1)
self.Alt_Team_5 = scrolled.ScrolledPanel(self.Notebook_AltTeams, -1)
self.Alt_Team_1.SetupScrolling()
self.Alt_Team_2.SetupScrolling()
self.Alt_Team_3.SetupScrolling()
self.Alt_Team_4.SetupScrolling()
self.Alt_Team_5.SetupScrolling()
# Menu Bar
self.MainMenu = wx.MenuBar()
self.FileMenu = wx.Menu()
self.FileOpenItem = wx.MenuItem(self.FileMenu, 103, "&Open\tCtrl+O", "Open a Previous Session", wx.ITEM_NORMAL)
self.FileMenu.AppendItem(self.FileOpenItem)
self.FileReloadItem = wx.MenuItem(self.FileMenu, 104, "&Reload Defaults", "Reload Default Files", wx.ITEM_NORMAL)
self.FileMenu.AppendItem(self.FileReloadItem)
self.FileSaveItem = wx.MenuItem(self.FileMenu, 102, "&Save\tCtrl+S", "Save the data", wx.ITEM_NORMAL)
self.FileMenu.AppendItem(self.FileSaveItem)
self.FileQuitItem = wx.MenuItem(self.FileMenu, wx.ID_EXIT, "&Quit\tCtrl+Q", "Quit the program", wx.ITEM_NORMAL)
self.FileMenu.AppendItem(self.FileQuitItem)
self.MainMenu.Append(self.FileMenu, "&File")
self.SetMenuBar(self.MainMenu)
# Menu Bar end
self.StatusBar = self.CreateStatusBar(2, wx.ST_SIZEGRIP)
self.__set_properties()
self.__do_layout()
self.Bind(wx.EVT_MENU, self.OnFileQuit, self.FileQuitItem)
self.Bind(wx.EVT_MENU, self.OnFileSave, self.FileSaveItem)
self.Bind(wx.EVT_MENU, self.OnFileOpen, self.FileOpenItem)
self.Bind(wx.EVT_MENU, self.OnFileReload, self.FileReloadItem)
self.OnAnalyze()
def __set_properties(self): #Set up GUI Title and Map Window
self.SetTitle("Test")
screen_x = 95 * wx.GetDisplaySize()[0]/100
screen_y = 90 * wx.GetDisplaySize()[1]/100
self.SetSize((screen_x, screen_y))
self.SetFocus()
def __do_layout(self , call_fit = True, set_sizer = True): #Create Lay-Out of GUI
# Sizer for Panel 3 (Analysis Page)
hbox = wx.BoxSizer(wx.HORIZONTAL)
vbox1 = wx.BoxSizer(wx.VERTICAL)
vbox2 = wx.BoxSizer(wx.VERTICAL)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
vbox1.Add(self.AnalysisUL, 1, wx.EXPAND | wx.ALL, 3)
vbox1.Add(self.AnalysisLL, 1, wx.EXPAND | wx.ALL, 3)
vbox2.Add(self.AnalysisUR, 1, wx.EXPAND | wx.ALL, 3)
vbox2.Add(self.AnalysisLR, 1, wx.EXPAND | wx.ALL, 3)
# Analysis Button Panel
vbox_UL = wx.BoxSizer(wx.VERTICAL)
vbox_UL3 = wx.BoxSizer(wx.HORIZONTAL)
fontUL = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)
self.UL_text = wx.StaticText(self.AnalysisUL, -1, 'Title 1')
self.UL_text.SetFont(fontUL)
Exp_Pts = ' '
fontUL = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)
self.ULText1 = wx.StaticText(self.AnalysisUL, -1, 'Title 2')
self.ULText2 = wx.StaticText(self.AnalysisUL, -1, Exp_Pts)
self.ULText1.SetFont(fontUL)
self.ULText2.SetFont(fontUL)
self.ULText2.SetForegroundColour((0,0,255))
self.ULText1.SetForegroundColour((0,0,255))
hbox2.Add(self.ULText1, 0)
hbox2.Add(self.ULText2, 0)
vbox_UL.Add(self.UL_text, 0, wx.CENTER|wx.ALL,20)
vbox_UL.Add(self.Picks_Left,1,wx.EXPAND|wx.ALL,3)
vbox_UL.Add(hbox2, 0, wx.CENTER|wx.BOTTOM,50)
self.AnalysisUL.SetSizer(vbox_UL)
# Suggested Pick Panel
vbox_LR = wx.BoxSizer(wx.HORIZONTAL)
vbox_LR2 = wx.BoxSizer(wx.VERTICAL)
font2 = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)
SuggestedSelection = ' '
self.SuggestedText1 = wx.StaticText(self.AnalysisLR, -1, ' ')
self.SuggestedText2 = wx.StaticText(self.AnalysisLR, -1, SuggestedSelection)
self.SuggestedText1.SetFont(font2)
self.SuggestedText2.SetFont(font2)
self.SuggestedText2.SetForegroundColour((0,0,255))
vbox_LR2.Add(self.SuggestedText1,0,wx.ALIGN_CENTRE)
vbox_LR2.Add(wx.StaticText(self.AnalysisLR, -1, ''),0,wx.CENTER)
vbox_LR2.Add(wx.StaticText(self.AnalysisLR, -1, ''),0,wx.CENTER)
vbox_LR2.Add(self.SuggestedText2,0,wx.ALIGN_CENTRE)
vbox_LR.Add(vbox_LR2,1,wx.CENTER)
self.AnalysisLR.SetSizer(vbox_LR)
# Projected Team Panel
sizer_LL = wx.BoxSizer(wx.VERTICAL)
self.Alt_Team_1.SetSizer(sizer_LL)
sizer_LL = wx.BoxSizer(wx.VERTICAL)
self.Alt_Team_2.SetSizer(sizer_LL)
sizer_LL = wx.BoxSizer(wx.VERTICAL)
self.Alt_Team_3.SetSizer(sizer_LL)
sizer_LL = wx.BoxSizer(wx.VERTICAL)
self.Alt_Team_4.SetSizer(sizer_LL)
sizer_LL = wx.BoxSizer(wx.VERTICAL)
self.Alt_Team_5.SetSizer(sizer_LL)
# Picks Remaining Panel
vbox_UR = wx.BoxSizer(wx.VERTICAL)
fontUR = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)
self.UR_text = wx.StaticText(self.AnalysisUR, -1, 'Title')
self.UR_text.SetFont(fontUR)
vbox_UR.Add(self.UR_text, 0, wx.CENTER)
self.AnalysisUR.SetSizer(vbox_UR)
# Finish Analysis Sizers
hbox.Add(vbox1, 1, wx.EXPAND)
hbox.Add(vbox2, 1, wx.EXPAND)
self.Analysis.SetSizer(hbox)
# Add Notebook Pages
self.Notebook.AddPage(self.MyTeam,"A")
self.Notebook.AddPage(self.TeamComparison,"B")
self.Notebook3.AddPage(self.Analysis,"CHECK ME")
self.Notebook_AltTeams.AddPage(self.Alt_Team_1,"1")
self.Notebook_AltTeams.AddPage(self.Alt_Team_2,"2")
self.Notebook_AltTeams.AddPage(self.Alt_Team_3,"3")
self.Notebook_AltTeams.AddPage(self.Alt_Team_4,"4")
self.Notebook_AltTeams.AddPage(self.Alt_Team_5,"5")
#Sizer for Panel 1
sizer_P1 = wx.BoxSizer(wx.VERTICAL)
sizer_P1.Add(self.Notebook, 1, wx.EXPAND, 0)
self.Panel1.SetSizer(sizer_P1)
#Sizer for Panel 3
sizer_P3 = wx.BoxSizer(wx.VERTICAL)
sizer_P3.Add(self.Notebook3, 1, wx.EXPAND, 0)
self.Panel3.SetSizer(sizer_P3)
#Sizer for Panel (Alt_Teams)
fontLL = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)
self.LL_text = wx.StaticText(self.AnalysisLL, -1, 'Title')
self.LL_text.SetFont(fontLL)
vbox_LL = wx.BoxSizer(wx.VERTICAL)
vbox_LL.Add(self.LL_text, 0, wx.CENTER)
#vbox_LL.Add(self.Notebook_AltTeams,1,wx.EXPAND,0)
self.AnalysisLL.SetSizer(vbox_LL)
# Split Panel Sizer
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.Splitter1,1,wx.EXPAND)
self.SetSizer(sizer)
self.Layout()
self.Centre()
# Function closes GUI
def OnFileQuit(self,event):
self.Close()
# Function reloads default parameters/lists
def OnFileReload(self,event):
self.Close()
# Function loads previously saved files
def OnFileOpen(self,event):
self.Close()
# Function saves current work
def OnFileSave(self,event):
self.Close()
# Function analyzes draft, points, adp to suggest an optimal team and the next selection
def OnAnalyze(self):
self.Picks_Left.DeleteAllItems()
self.Picks_Left.InsertStringItem(0, ' ')
self.Picks_Left.InsertStringItem(1, 'Line 1')
self.Picks_Left.InsertStringItem(2, ' ')
self.Picks_Left.InsertStringItem(3, 'Line 2')
self.Picks_Left.InsertStringItem(4, ' ')
self.Picks_Left.InsertStringItem(5, 'Line 3')
self.Picks_Left.SetStringItem(1,2, '1')
self.Picks_Left.SetStringItem(1,3, '2')
self.Picks_Left.SetStringItem(1,4, '3')
self.Picks_Left.SetStringItem(1,5, '4')
self.Picks_Left.SetStringItem(1,6, '5')
self.Picks_Left.SetStringItem(1,7, '6')
self.Picks_Left.SetStringItem(1,8, '7')
self.Picks_Left.SetStringItem(3,2, '1')
self.Picks_Left.SetStringItem(3,3, '1')
self.Picks_Left.SetStringItem(3,4, '1')
self.Picks_Left.SetStringItem(3,5, '1')
self.Picks_Left.SetStringItem(3,6, '1')
self.Picks_Left.SetStringItem(3,7, '1')
self.Picks_Left.SetStringItem(3,8, '1')
self.Picks_Left.SetStringItem(5,2, '2')
self.Picks_Left.SetStringItem(5,3, '2')
self.Picks_Left.SetStringItem(5,4, '2')
self.Picks_Left.SetStringItem(5,5, '2')
self.Picks_Left.SetStringItem(5,6, '2')
self.Picks_Left.SetStringItem(5,7, '2')
self.Picks_Left.SetStringItem(5,8, '2')
self.AnalysisUL.Layout()
app = wx.App(0)
# Code to Execute File
class TApplication(wx.App):
def OnInit(self):
wx.InitAllImageHandlers()
MainForm = TMainForm(None, -1,"")
self.SetTopWindow(MainForm)
MainForm.Show()
return 1
if __name__ == "__main__":
Application = TApplication(0)
Application.MainLoop()

I think the trouble with the GetSize() approach might have been that you were calling it before the effects of the sizer took place, so it was returning the original size of the ListCtrl before the sizer resized it to fit the panel. Try this code after the last line of your code:
table_width = self.Picks_Left.GetSize()[0] #GetSize returns (width, height) tuple
num_col = self.Picks_Left.GetColumnCount()
col_width = table_width/num_col
for i in range(0, num_col):
self.Picks_Left.SetColumnWidth(i, col_width)

You should use the RowColSizer, which is quite fit for your request. Here is a small demo how to use it:
import wx
import wx.lib.rcsizer as rcs
class TestPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, -1)
sizer = rcs.RowColSizer()
text = "This sizer lays out it's items by row and column "\
"that are specified explicitly when the item is \n"\
"added to the sizer. Grid cells with nothing in "\
"them are supported and column- or row-spanning is \n"\
"handled as well. Growable rows and columns are "\
"specified just like the wxFlexGridSizer."
sizer.Add(wx.StaticText(self, -1, text), row=1, col=1, colspan=5)
sizer.Add(wx.TextCtrl(self, -1, "(3,1)"), flag=wx.EXPAND, row=3, col=1)
sizer.Add(wx.TextCtrl(self, -1, "(3,2)"), row=3, col=2)
sizer.Add(wx.TextCtrl(self, -1, "(3,3)"), row=3, col=3)
sizer.Add(wx.TextCtrl(self, -1, "(3,4)"), row=3, col=4)
sizer.Add(
wx.TextCtrl(self, -1, "(4,2) span:(2,2)"),
flag=wx.EXPAND, row=4, col=2, rowspan=2, colspan=2
)
sizer.Add(wx.TextCtrl(self, -1, "(6,4)"), row=6, col=4)
sizer.Add(wx.TextCtrl(self, -1, "(7,2)"), row=7, col=2)
sizer.Add(wx.TextCtrl(self, -1, "(8,3)"), row=8, col=3)
sizer.Add(
wx.TextCtrl(self, -1, "(10,1) colspan: 4"),
flag=wx.EXPAND, pos=(10,1), colspan=4
)
sizer.Add(
wx.TextCtrl(self, -1, "(3,5) rowspan: 8, growable col", style=wx.TE_MULTILINE),
flag=wx.EXPAND, pos=(3,5), size=(8,1)
)
box = wx.BoxSizer(wx.VERTICAL)
box.Add(wx.Button(self, -1, "A vertical box"), flag=wx.EXPAND)
box.Add(wx.Button(self, -1, "sizer put in the"), flag=wx.EXPAND)
box.Add(wx.Button(self, -1, "RowColSizer at (12,1)"), flag=wx.EXPAND)
sizer.Add(box, pos=(12,1))
sizer.Add(
wx.TextCtrl(self, -1, "(12,2) align bottom"),
flag=wx.ALIGN_BOTTOM, pos=(12,2)
)
sizer.Add(
wx.TextCtrl(self, -1, "(12,3) align center"),
flag=wx.ALIGN_CENTER_VERTICAL, pos=(12,3)
)
sizer.Add(wx.TextCtrl(self, -1, "(12,4)"),pos=(12,4))
sizer.Add(
wx.TextCtrl(self, -1, "(12,5) full border"),
flag=wx.EXPAND|wx.ALL, border=15, pos=(12,5)
)
sizer.AddGrowableCol(5)
sizer.AddGrowableRow(9)
sizer.AddSpacer(10,10, pos=(1,6))
sizer.AddSpacer(10,10, pos=(13,1))
self.SetSizer(sizer)
self.SetAutoLayout(True)
app = wx.App()
frame = wx.Frame(None, -1)
pn = TestPanel(frame)
frame.Show()
frame.Maximize()
app.MainLoop()
The same request also could be achieved by a more fancy way use the aui
Hope it helps you out.

Related

Can't insert graph in a wxPython GUI

I am trying to make a telemetry software for a college project, that's why I'm using wxPython to make a GUI. I'm currently trying to make a function that displays a graph of brake_p and throttle in function of the time after I opened the entry file.
The code looks good to me, however it looks like there is an error inside the module that blocks me from succeeding.
Here is the error I get when I open the entry file :
> PS C:\Users\Adrie\OneDrive\Bureau\telemetry python> &
> 'C:\Users\Adrie\AppData\Local\Microsoft\WindowsApps\python3.10.exe'
> 'c:\Users\Adrie\.vscode\extensions\ms-python.python-2022.20.1\pythonFiles\lib\python\debugpy\adapter/../..\debugpy\launcher' '54993' '--' 'c:\Users\Adrie\OneDrive\Bureau\telemetry
> python\v0601.py' Traceback (most recent call last): File
> "c:\Users\Adrie\OneDrive\Bureau\telemetry python\v0601.py", line 105,
> in OnOpen self.OpenData(file) File
> "c:\Users\Adrie\OneDrive\Bureau\telemetry python\v0601.py", line 144,
> in OpenData self.canvas.Draw(self.drawBrakeThrottlePlot) File
> "C:\Users\Adrie\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\wx\lib\plot\plotcanvas.py",
> line 1750, in Drawgraphics.logScale = self.logScale AttributeError:
> 'method' object has no attribute 'logScale' PS
> C:\Users\Adrie\OneDrive\Bureau\telemetry python>
The error I can't understand is the part in bold caracters,as it is nowhere in my code :
Drawgraphics.logScale = self.logScale
AttributeError: 'method' object has no attribute 'logScale'
I 'd like to add I plan to add a bar marker on the graph that would be either automatically move at real-time, or either movable by the user so the time at the marker would be used to display in other widget data corresponding to the exact instant (like in the matlab simulink graph/scopes), which means I can't store the graph as a bitmap but really as a graph/plot.
I tried to switch to another library to import the plot into the wxFrame but I just can't make it work as they look more complicated to me, so I got back to this method.
Here is the code :
import wx
import numpy as np
import matplotlib.pyplot as plt
from wx.lib.plot import PlotCanvas, PlotGraphics, PolyLine, PolyMarker
import wxmplot.interactive as wi
# Variables initialization
time, speed, distance, brake_p, throttle, g_x, g_y, g_z, gps_x, gps_y, omega_fl, omega_fr = ([] for i in range(12))
r=1 # Wheel radius, will implement a feature to make it editable by the user later
class MainWindow(wx.Frame):
def __init__(self, *args, **kw):
super(MainWindow, self).__init__(*args, **kw)
# Create a panel and add it to the main window
panel = wx.Panel(self)
# Set the panel as the main window's sizer
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(panel, 1, wx.EXPAND)
self.SetSizer(sizer)
# Set the window's min size
self.SetMinSize((1280,720))
# create a menu bar
self.makeMenuBar()
# and a status bar
self.CreateStatusBar()
self.SetStatusText("v 0.1")
# put some text with a larger bold font on it
st = wx.StaticText(panel, label="Welcome on the EFT's Telemetry software !")
font = st.GetFont()
font.PointSize += 10
font = font.Bold()
st.SetFont(font)
# and create a sizer to manage the layout of child widgets
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(st, wx.SizerFlags().Border(wx.TOP|wx.LEFT, 25))
panel.SetSizer(sizer)
def makeMenuBar(self):
# Make a file menu with Hello and Exit items
fileMenu = wx.Menu()
# The "\t..." syntax defines an accelerator key that also triggers
# the same event
openItem = fileMenu.Append(-1, "&Open...\tCtrl-O",
"Open a data file")
fileMenu.AppendSeparator()
# When using a stock ID we don't need to specify the menu item's
# label
exitItem = fileMenu.Append(wx.ID_EXIT)
# Now a help menu for the about item
helpMenu = wx.Menu()
aboutItem = helpMenu.Append(wx.ID_ABOUT)
# Now a view menu for the view item
# viewMenu = wx.Menu()
# aboutItem = helpMenu.Append(wx.ID_VIEW)
# Make the menu bar and add the two menus to it. The '&' defines
# that the next letter is the "mnemonic" for the menu item. On the
# platforms that support it those letters are underlined and can be
# triggered from the keyboard.
menuBar = wx.MenuBar()
menuBar.Append(fileMenu, "&File")
menuBar.Append(helpMenu, "&Help")
# menuBar.Append(viewMenu, "&View")
# Give the menu bar to the frame
self.SetMenuBar(menuBar)
# Finally, associate a handler function with the EVT_MENU event for
# each of the menu items. That means that when that menu item is
# activated then the associated handler function will be called.
self.Bind(wx.EVT_MENU, self.OnOpen, openItem)
self.Bind(wx.EVT_MENU, self.OnExit, exitItem)
self.Bind(wx.EVT_MENU, self.OnAbout, aboutItem)
def OnExit(self, event):
self.Close(True)
def OnAbout(self, event):
wx.MessageBox("This is a simple Telemetry software project.",
wx.OK|wx.ICON_INFORMATION)
def drawBrakeThrottlePlot():
data1 = PolyLine([time, brake_p], legend='Brake Pressure (%)', colour='red', width='1')
data2 = PolyLine([time, throttle], legend='Throttle (%)', colour='green', width='1')
return PlotGraphics([data1, data2], "Real Time Brake Pressure and Throttle", "Time (ms)", "Relative Value (%)")
def OnOpen(self, event):
# Create the file dialog
with wx.FileDialog(self, "Open Data file", wildcard="text files (*.txt)|*.txt",
style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog:
if fileDialog.ShowModal() == wx.ID_CANCEL:
return # the user changed their mind
# Proceed loading the file chosen by the user
pathname = fileDialog.GetPath()
try:
with open(pathname, 'r') as file:
self.OpenData(file)
except IOError:
wx.LogError("Cannot open file '%s'." % pathname)
def OpenData(self, file):
data = file.readlines() # On assigne à L toutes les lignes du fichier
nb_lignes = len(data) # On assigne à nb_lignes la longueur de L
file.close()
for i in range(nb_lignes):
data[i] = data[i].strip('\n')
temp = data[i].split()
time.append(float(temp[0]))
speed.append((float(temp[8])+float(temp[9]))*r/2)
distance.append(speed[i]*1/1000) # Ici 1/1000 correspond à la fréquence d'échantillonage, modifiable en fx du capteur
brake_p.append(float(temp[1]))
throttle.append(float(temp[2]))
g_x.append(float(temp[3]))
g_y.append(float(temp[4]))
g_z.append(float(temp[5]))
gps_x.append(float(temp[6]))
gps_y.append(float(temp[7]))
omega_fl.append(float(temp[8]))
omega_fr.append(float(temp[9]))
# Remove the text on the panel
for child in self.GetChildren():
child.Destroy()
# create a panel and add it to the main window
panel = wx.Panel(self)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(panel, 1, wx.EXPAND)
self.SetSizer(self.sizer)
# Create the plot
self.canvas = PlotCanvas(panel)
self.canvas.Draw(self.drawBrakeThrottlePlot)
self.sizer.Add(self.canvas, 1, wx.EXPAND)
self.sizer.Add(self.createControls(panel), 0, wx.EXPAND)
self.sizer.Add((-1, 10))
self.sizer.Add(self.createButtonBar(panel), 0, wx.EXPAND)
self.SetSizer(self.sizer)
self.sizer.Fit(self)
def createControls(self, panel):
box = wx.StaticBox(panel, -1, 'Data')
sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
grid = wx.GridBagSizer(5, 5)
txt1 = wx.StaticText(panel, -1, 'Time (s)')
grid.Add(txt1, (1, 0))
self.tc1 = wx.TextCtrl(panel, -1, '', size=(80, -1))
grid.Add(self.tc1, (1, 1))
txt2 = wx.StaticText(panel, -1, 'Speed (km/h)')
grid.Add(txt2, (2, 0))
self.tc2 = wx.TextCtrl(panel, -1, '', size=(80, -1))
grid.Add(self.tc2, (2, 1))
txt3 = wx.StaticText(panel, -1, 'RPM')
grid.Add(txt3, (3, 0))
self.tc3 = wx.TextCtrl(panel, -1, '', size=(80, -1))
grid.Add(self.tc3, (3, 1))
txt4 = wx.StaticText(panel, -1, 'Brake pressure')
grid.Add(txt4, (4, 0))
self.tc4 = wx.TextCtrl(panel, -1, '', size=(80, -1))
grid.Add(self.tc4, (4, 1))
txt5 = wx.StaticText(panel, -1, 'Throttle position')
grid.Add(txt5, (5, 0))
self.tc5 = wx.TextCtrl(panel, -1, '', size=(80, -1))
grid.Add(self.tc5, (5, 1))
sizer.Add(grid, 0, wx.ALL, 10)
return sizer
def createButtonBar(self, panel):
"""
Create the buttons at the bottom of the panel
"""
sizer = wx.BoxSizer(wx.HORIZONTAL)
self.zoomInButton = wx.Button(panel, -1, "Zoom In")
self.Bind(wx.EVT_BUTTON, self.OnZoomIn, self.zoomInButton)
sizer.Add(self.zoomInButton, 0, wx.LEFT | wx.RIGHT, 10)
self.zoomOutButton = wx.Button(panel, -1, "Zoom Out")
self.Bind(wx.EVT_BUTTON, self.OnZoomOut, self.zoomOutButton)
sizer.Add(self.zoomOutButton, 0, wx.LEFT | wx.RIGHT, 10)
self.panLeftButton = wx.Button(panel, -1, "Pan Left")
self.Bind(wx.EVT_BUTTON, self.OnPanLeft, self.panLeftButton)
sizer.Add(self.panLeftButton, 0, wx.LEFT | wx.RIGHT, 10)
self.panRightButton = wx.Button(panel, -1, "Pan Right")
self.Bind(wx.EVT_BUTTON, self.OnPanRight, self.panRightButton)
sizer.Add(self.panRightButton, 0, wx.LEFT | wx.RIGHT, 10)
self.resetButton = wx.Button(panel, -1, "Reset")
self.Bind(wx.EVT_BUTTON, self.OnReset, self.resetButton)
sizer.Add(self.resetButton, 0, wx.LEFT | wx.RIGHT, 10)
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, self.resetButton)
return sizer
def OnZoomIn(self, event):
self.canvas.Zoom(1.2)
event.Skip()
def OnZoomOut(self, event):
self.canvas.Zoom(1/1.2)
event.Skip()
def OnPanLeft(self, event):
self.canvas.Move(-0.1, 0)
event.Skip()
def OnPanRight(self, event):
self.canvas.Move(0.1, 0)
event.Skip()
def OnReset(self, event):
self.canvas.Reset()
event.Skip()
def OnUpdateUI(self, event):
if self.canvas.CanReset():
self.resetButton.Enable(True)
else:
self.resetButton.Enable(False)
if __name__ == '__main__':
app = wx.App()
frame = MainWindow(None, title='Telemetry EFT')
frame.Show()
app.MainLoop()
And here is a link to the example data file : data file

WxPython dynamically added sizers mis-behaving

I'm trying to set-up a display to show the gamertag and avatar of users added to a text file, it most of the way there but I can't get them to position properly.
A quick mock-up of what I want: here.
Here is what I currently have on start: here
EDIT: I've switched from using a BoxSizer to using a GridSizer and that seems to have fixed the position issue, they no longer overlap, the shifting problem is still present however.
The sizer containing the users shouldn't be overlapping with the input sizer at the top, I don't know what is causing this.
And what happens when it updates to check for new users: here
Might not be that easy to see but in the second image the lowest user is shifted down, it gets further and further down as the program runs, each time it is moved down by it's own height.
The relevant code areas:
Creating the starting sizers
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
self.widget_sizer = wx.BoxSizer(wx.VERTICAL)
#Holds input for gamertags and addition
self.input_sizer = wx.BoxSizer(wx.HORIZONTAL)
#Content to be added immediately.
self.gamer_tag_textbox = wx.TextCtrl(self, -1)
self.gamer_tag_textbox.SetFocus()
self.add_gamer_tag = wx.Button(self, -1, 'Add Friend')
#Contains the displayed content
self.user_sizer = wx.BoxSizer(wx.VERTICAL)
#Add objects to sizers
self.input_sizer.Add(self.gamer_tag_textbox, 0)
self.input_sizer.Add(self.add_gamer_tag, 0)
#Set up the sizers
self.widget_sizer.Add(self.input_sizer, 0)
self.widget_sizer.Add(self.user_sizer, 0)
self.main_sizer.Add(self.widget_sizer, 0)
self.SetSizer(self.main_sizer)
Adding sizers created for each user to the main user_sizer.
def display_user_content(self, details):
self.user_sizer.Clear(True)
#This is different to the original code, it originally used boxsizers in the for each loop.
self.single_user_sizer = wx.GridSizer(cols=2)
for each in details:
#Create sizer to contain user information
#Get username
username = each[0]
#Get location of image file
location = each[-1]
#Create static text to contain username
stat = wx.StaticText(self, -1, 'username')
#Load image from location and convert to bitmap.
png = wx.Image(location, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
#Create bitmap
avatar = wx.StaticBitmap(self, -1, png)
#Add to sizer
self.single_user_sizer.Add(avatar, 1)
self.single_user_sizer.Add(stat, 1)
#Add each users sizer to main user sizer
self.user_sizer.Add(self.single_user_sizer, 1)
#Add main user sizer to widget sizer
self.widget_sizer.Add(self.user_sizer, 0)
self.frame.Fit()
Full code (minus classes): here
Maybe this is similar to what you would like to achieve?
import wx
NUMBER = 3
class MainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.panel = wx.Panel(self)
self.windowSizer = wx.BoxSizer()
self.windowSizer.Add(self.panel, 1, wx.ALL | wx.EXPAND)
self.sizer = wx.GridBagSizer(vgap=5, hgap=5)
self.text = wx.TextCtrl(self.panel, size=(0, 0))
self.button = wx.Button(self.panel)
self.sizer.Add(self.text, (0, 0), flag=wx.EXPAND)
self.sizer.Add(self.button, (0, 1))
self.icons = []
self.stats = []
for i in range(NUMBER):
icon = wx.Panel(self.panel, size=(50, 50))
icon.SetBackgroundColour(wx.RED)
stat = wx.Panel(self.panel, size=(200, -1))
stat.SetBackgroundColour(wx.BLUE)
self.sizer.Add(icon, (i+1, 0))
self.sizer.Add(stat, (i+1, 1), flag=wx.EXPAND)
self.icons.append(icon)
self.stats.append(stat)
self.sizer.AddGrowableCol(1)
self.border = wx.BoxSizer()
self.border.Add(self.sizer, 1, wx.ALL | wx.EXPAND, 5)
self.panel.SetSizerAndFit(self.border)
self.SetSizerAndFit(self.windowSizer)
self.Show()
app = wx.App(False)
win1 = MainWindow(None)
app.MainLoop()
Or maybe more like this?
import wx
NUMBER = 3
class MainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.panel = wx.Panel(self)
self.windowSizer = wx.BoxSizer()
self.windowSizer.Add(self.panel, 1, wx.ALL | wx.EXPAND)
self.sizer = wx.GridBagSizer(vgap=5, hgap=5)
self.toolbar_sizer = wx.BoxSizer()
self.text = wx.TextCtrl(self.panel)
self.button = wx.Button(self.panel)
self.toolbar_sizer.Add(self.text, 0, flag=wx.CENTER)
self.toolbar_sizer.Add(self.button, 0)
self.sizer.Add(self.toolbar_sizer, (0, 0), span=(1, 2), flag=wx.EXPAND)
self.icons = []
self.stats = []
for i in range(NUMBER):
icon = wx.Panel(self.panel, size=(50, 50))
icon.SetBackgroundColour(wx.RED)
stat = wx.Panel(self.panel, size=(200, -1))
stat.SetBackgroundColour(wx.BLUE)
self.sizer.Add(icon, (i+1, 0))
self.sizer.Add(stat, (i+1, 1), flag=wx.EXPAND)
self.icons.append(icon)
self.stats.append(stat)
self.sizer.AddGrowableCol(1)
self.border = wx.BoxSizer()
self.border.Add(self.sizer, 1, wx.ALL | wx.EXPAND, 5)
self.panel.SetSizerAndFit(self.border)
self.SetSizerAndFit(self.windowSizer)
self.Show()
app = wx.App(False)
win = MainWindow(None)
app.MainLoop()
At the end of the display_user_content function I was adding the user_sizer to the widget_sizer each time, this was unnecessary and was causing a doubling of the number of results, I have removed that line and my code now works.
The fixed code:
def display_user_content(self, details):
self.user_sizer.Clear(True)
self.single_user_sizer = wx.GridSizer(cols=2, hgap=5, vgap=5)
for each in details:
#Get username
self.username_sizer = wx.BoxSizer(wx.HORIZONTAL)
username = each[0]
#Get location of image file
location = each[-1]
#Create static text to contain username
stat = wx.StaticText(self, -1, 'username')
#Load image from location and convert to bitmap.
png = wx.Image(location, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
#Create bitmap
avatar = wx.StaticBitmap(self, -1, png)
#Add to sizer
self.single_user_sizer.Add(avatar, 0)
self.username_sizer.Add(stat, 0)
self.single_user_sizer.Add(self.username_sizer, 0)
#Add each users sizer to main user sizer
self.user_sizer.Add(self.single_user_sizer, 0)
#Add main user sizer to widget sizer
#self.widget_sizer.Add(self.user_sizer, 0)
self.Fit()

Get Position of Button in wxpython

I am trying to figure out the position of two buttons in wxpython. I have a gui with a small vertical panel on the left and large panel on the right.
wx.Frame.__init__(self, *args, **kwds)
self.Splitter = wx.SplitterWindow(self, -1)#, style=wx.SP_NOSASH)
self.Panel1 = wx.Panel(self.Splitter, -1)
self.Panel3 = wx.Panel(self.Splitter, -1)
self.Splitter.SplitVertically(self.Panel1,self.Panel3,350)
In in the right panel (a notebook) I use a Vertical Sizer to stack three panels:
self.Notebook3 = wx.Notebook(self.Panel3, -1)
self.OptPane = scrolled.ScrolledPanel(self.Notebook3, -1)
self.pane1 = wx.Panel(self.OptPane,-1, style=wx.NO_BORDER)
self.pane2 = wx.Panel(self.OptPane,-1, style=wx.RAISED_BORDER)
self.pane3= wx.Panel(self.OptPane,-1, style=wx.NO_BORDER)
My pane 3 contains three buttons that are organized using a gridsizer (one row, three columns). It all looks great. Now, I want to be able to get the screen position of the three buttons (they change based on resolution of screen, person adjusting the size of the gui, etc.).
My screen size is (1920,1080) which is derived from wx.GetDisplaySize(). I have tried self.button1.GetScreenPosition() and self.pane3.GetScreenPosition and self.button1.GetPosition(). The first returns the position (77,93), second returns (61,95) and the last one gives me (0,0). After testing with testtext = wx.StaticText(self.Notebook3, -1, 'X marks spot',pos=(240,820)), I figured out the position of the button I want returned is (240,820) -- approximately. This is the number I want to return.
Does anyone know what I am doing wrong? Thanks!
*EDIT*
My Full Code - should be runnable -- I am running this on a 1920x1080 (for the text 'x marks the spot').
import wx
import wx.lib.scrolledpanel as scrolled
class TMainForm(wx.Frame):
def __init__(self, *args, **kwds):
kwds["style"] = wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.Splitter = wx.SplitterWindow(self, -1)
self.Panel1 = wx.Panel(self.Splitter, -1)
self.Panel3 = wx.Panel(self.Splitter, -1)
self.Splitter.SplitVertically(self.Panel1,self.Panel3,350)
self.Notebook2 = wx.Notebook(self.Panel1, -1)
self.Notebook3 = wx.Notebook(self.Panel3, -1)
self.OptPane = scrolled.ScrolledPanel(self.Notebook3, -1)
self.OptPane.SetupScrolling()
self.Opt_Info = wx.Panel(self.OptPane,-1, style=wx.NO_BORDER)
self.Opt_Middle = wx.Panel(self.OptPane,-1, style=wx.RAISED_BORDER)
self.Opt_Buttons = wx.Panel(self.OptPane,-1, style=wx.NO_BORDER)
self.Button1 = wx.Button(self.Opt_Buttons,-1,'Button1',size=(-1,-1))
self.Button2 = wx.Button(self.Opt_Buttons,-1,'Button2',size=(-1,-1))
self.Button3 = wx.Button(self.Opt_Buttons,-1,'Button3',size=(-1,-1))
self.MainMenu = wx.MenuBar()
self.FileMenu = wx.Menu()
self.FileOpenItem = wx.MenuItem(self.FileMenu, 103, "&Open\tCtrl+O", "Open a Previous Session", wx.ITEM_NORMAL)
self.FileMenu.AppendItem(self.FileOpenItem)
self.FileSaveItem = wx.MenuItem(self.FileMenu, 102, "&Save\tCtrl+S", "Save the data", wx.ITEM_NORMAL)
self.FileMenu.AppendItem(self.FileSaveItem)
self.FileQuitItem = wx.MenuItem(self.FileMenu, wx.ID_EXIT, "&Quit\tCtrl+Q", "Quit the program", wx.ITEM_NORMAL)
self.FileMenu.AppendItem(self.FileQuitItem)
self.MainMenu.Append(self.FileMenu, "&File")
self.SetMenuBar(self.MainMenu)
self.__set_properties()
self.__do_layout()
print self.Button1.GetScreenPosition()
testtext = wx.StaticText(self.Notebook3, -1, 'X marks spot',pos=(240,840))
def __set_properties(self):
self.SetTitle("My Program")
screen_x = 95 * wx.GetDisplaySize()[0]/100
screen_y = 90 * wx.GetDisplaySize()[1]/100
self.SetSize((screen_x, screen_y))
self.SetFocus()
def __do_layout(self , call_fit = True, set_sizer = True):
vbox = wx.BoxSizer(wx.VERTICAL)
hbox1 = wx.BoxSizer(wx.HORIZONTAL)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
hbox3 = wx.BoxSizer(wx.HORIZONTAL)
hbox1.Add(self.Opt_Info, 1, wx.EXPAND|wx.ALL, 3)
hbox2.Add(self.Opt_Middle, 1, wx.EXPAND|wx.ALL, 3)
hbox3.Add(self.Opt_Buttons, 1, wx.EXPAND|wx.ALL, 3)
box_bot = wx.GridSizer(1,3,2,2)
box_bot.Add(self.Button1, 1, wx.ALIGN_CENTER| wx.LEFT | wx.RIGHT, 55)
box_bot.Add(self.Button2, 1, wx.ALIGN_CENTER| wx.LEFT | wx.RIGHT, 55)
box_bot.Add(self.Button3, 1, wx.ALIGN_CENTER| wx.LEFT | wx.RIGHT, 55)
self.Opt_Buttons.SetSizer(box_bot)
vbox.Add(hbox1, 0, wx.EXPAND|wx.TOP, 20)
vbox.Add(hbox2, 1, wx.EXPAND|wx.TOP, 50)
vbox.Add(hbox3, 0, wx.EXPAND|wx.ALL, 20)
self.OptPane.SetSizer(vbox)
self.Notebook3.AddPage(self.OptPane,"Page1")
#Sizer for Panel 2
sizer_P2 = wx.BoxSizer(wx.VERTICAL)
sizer_P2.Add(self.Notebook2, 1, wx.EXPAND, 0)
self.Panel1.SetSizer(sizer_P2)
#Sizer for Panel 3
sizer_P3 = wx.BoxSizer(wx.VERTICAL)
sizer_P3.Add(self.Notebook3, 1, wx.EXPAND, 0)
self.Panel3.SetSizer(sizer_P3)
# Split Panel Sizer
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.Splitter,1,wx.EXPAND)
self.SetSizer(sizer)
self.Layout()
self.Centre()
# Code to Execute File
class TApplication(wx.App):
def OnInit(self):
wx.InitAllImageHandlers()
MainForm = TMainForm(None, -1,"")
self.SetTopWindow(MainForm)
MainForm.Show()
return 1
if __name__ == "__main__":
Application = TApplication(0)
Application.MainLoop()
I think you're asking for the position too soon. You'll want to get the position after everything is rendered to the screen, so you'll probably need to use wxPython's CallAfter. Create a method that looks something like this:
def printLocation(self):
""""""
print self.Button1.GetScreenPosition()
Then at the end of your init, add the following line:
wx.CallAfter(self.printLocation)
When I ran it on my system, I got (155, 211), which is probably closer to what you're looking for. I have a rather weird resolution here.
You might also want to look at this thread which talks about the scrolled window's CalcUnscrolledPosition method.
https://groups.google.com/forum/#!topic/wxpython-users/0VlpIcBYs04

wxPython and STC Margins - Top and Bottom

Is there any way of implementing padding in the top and bottom of my program for 3 and 4?
Or is there a workaround like adding \n etc....
I feel asif the line numbers and the Styled text are too close to the top and bottom.
How about using panels of the same color nested inside the sizer as a dirty workaround?
import wx
import wx.stc as stc
class MainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.panel = wx.Panel(self)
self.text = stc.StyledTextCtrl(self.panel)
self.text.SetWindowStyle(self.text.GetWindowStyle() | wx.NO_BORDER)
self.text.StyleSetSpec(stc.STC_STYLE_DEFAULT, "size:15,face:Courier New")
self.text.SetWrapMode(stc.STC_WRAP_WORD)
self.text.SetMarginLeft(50)
self.text.StyleSetSpec(stc.STC_STYLE_LINENUMBER, "back:#FFFFFF")
self.menu = wx.Menu()
self.menu.Append(wx.ID_ABOUT, "&About", "Information about this program")
self.menu_bar = wx.MenuBar()
self.menu_bar.Append(self.menu, "&File")
self.SetMenuBar(self.menu_bar)
self.panel_top = wx.Panel(self.panel, size = (20, -1))
self.panel_top.SetBackgroundColour(wx.WHITE)
self.panel_bottom = wx.Panel(self.panel, size = (20, -1))
self.panel_bottom.SetBackgroundColour(wx.WHITE)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.panel_top, 0, wx.ALL | wx.EXPAND)
self.sizer.Add(self.text, 1, wx.ALL | wx.EXPAND)
self.sizer.Add(self.panel_bottom, 0, wx.ALL | wx.EXPAND)
self.border = wx.BoxSizer()
self.border.Add(self.sizer, 1, wx.ALL | wx.EXPAND, border=20)
self.panel.SetSizerAndFit(self.border)
self.text.Bind(stc.EVT_STC_CHANGE, self.OnChange)
self.Show()
self.text.SetText("Line!\n"*3)
def OnChange(self, e):
lines = self.text.GetLineCount()
width = self.text.TextWidth(stc.STC_STYLE_LINENUMBER, str(lines)+" ")
self.text.SetMarginWidth(0, width)
if __name__ == "__main__":
app = wx.App(False)
win = MainWindow(None)
app.MainLoop()
For your code, modify it as follows:
self.panel_top = wx.Panel(self.panel, size = (20, -1))
self.panel_top.SetBackgroundColour(wx.BLACK)
self.panel_bottom = wx.Panel(self.panel, size = (20, -1))
self.panel_bottom.SetBackgroundColour(wx.BLACK)
#### Add the STC to a Sizer. ####
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.panel_top, 0, wx.EXPAND,border=20)
sizer.Add(self.text, 1, wx.EXPAND,border=20)
sizer.Add(self.panel_bottom, 0, wx.EXPAND,border=20)
self.panel.SetSizer(sizer)
No, I don't think that Scintilla has a property that controls the size of the top and bottom margins.

Code working in UNIX but not in windows

I have written a small bit of code in wxpython in which the splitter window is used to split the dialog box and one panel has custom tree ctrl and the other has static box.
This code was working fine in Fedora and ubuntu, but in Windows the dialog box is appearing empty.
Main code:
wx.Dialog.__init__(self, None, 6, 'Filters',size = (500,600) )
self.splitter = wx.SplitterWindow(self, -1)
leftPanel = wx.Panel(self.splitter, -1)
leftBox = wx.BoxSizer(wx.VERTICAL)
self.__tree = TreeFilter(leftPanel, 1)
leftBox.Add(self.__tree, -1, wx.GROW)
self.__tree.Bind(CT.EVT_TREE_ITEM_CHECKED, self.checked)
leftPanel.SetSizer(leftBox)
rightPanel = wx.Panel(self.splitter, -1)
rightBox = wx.BoxSizer(wx.VERTICAL)
self.display = wx.StaticText(rightPanel, -1, '', style=wx.ALIGN_LEFT)
rightBox.Add(self.display, -1, wx.GROW)
btnsizer = wx.StdDialogButtonSizer()
btn = wx.Button(rightPanel, wx.ID_OK)
btn.SetDefault()
btnsizer.AddButton(btn)
btn = wx.Button(rightPanel, wx.ID_CANCEL)
btnsizer.AddButton(btn)
btnsizer.Realize()
rightBox.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
rightPanel.SetSizer(rightBox)
self.splitter.SplitVertically(leftPanel, rightPanel)
self.Centre()
where TreeFilter is a custom tree ctrl.
Please help me fixing the problem
The problem is that you don't have the splitter itself in a sizer that's set to expand. On my screen, you can see a little box all scrunched up in the left hand corner, so I knew something like that was happening.
Here's an example that works for me:
import wx
########################################################################
class MyTreeCtrl(wx.TreeCtrl):
#----------------------------------------------------------------------
def __init__(self, parent, id):
wx.TreeCtrl.__init__(self, parent, id)
########################################################################
class TestDlg(wx.Dialog):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Dialog.__init__(self, None, 6, 'Filters',size = (500,600) )
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.splitter = wx.SplitterWindow(self, -1)
leftPanel = wx.Panel(self.splitter, -1)
leftBox = wx.BoxSizer(wx.VERTICAL)
self.tree = MyTreeCtrl(leftPanel, 1)
self.root = self.tree.AddRoot("The Root Item")
self.tree.SetPyData(self.root, None)
for x in range(15):
child = self.tree.AppendItem(self.root, "Item %d" % x)
self.tree.SetPyData(child, None)
self.tree.Expand(self.root)
leftBox.Add(self.tree, -1, wx.GROW)
#self.__tree.Bind(CT.EVT_TREE_ITEM_CHECKED, self.checked)
leftPanel.SetSizer(leftBox)
rightPanel = wx.Panel(self.splitter, -1)
rightBox = wx.BoxSizer(wx.VERTICAL)
self.display = wx.StaticText(rightPanel, -1, '', style=wx.ALIGN_LEFT)
rightBox.Add(self.display, -1, wx.GROW)
btnsizer = wx.StdDialogButtonSizer()
btn = wx.Button(rightPanel, wx.ID_OK)
btn.SetDefault()
btnsizer.AddButton(btn)
btn = wx.Button(rightPanel, wx.ID_CANCEL)
btnsizer.AddButton(btn)
btnsizer.Realize()
rightBox.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
rightPanel.SetSizer(rightBox)
self.splitter.SplitVertically(leftPanel, rightPanel)
self.Centre()
mainSizer.Add(self.splitter, 1, wx.EXPAND)
self.SetSizer(mainSizer)
#----------------------------------------------------------------------
if __name__ == "__main__":
app = wx.App(False)
dlg = TestDlg()
dlg.Show()
dlg.Destroy()
app.MainLoop()

Categories