How to Split the Screen into 3 Panels and Treat Each Panel Separately

how to split the screen into 3 panels and treat each panel separately

That is because your markup is incorrect: the #piechart element should be wrapped within the .leftpane element, instead of being a sibling of it. Changing your original markup:

<div class="leftpane">
<h1>Test Page</h1>
</div>

<!-- Element is outside of the pane! -->
<div id="piechart"></div>

…to this:

<div class="leftpane">
<h1>Test Page</h1>

<!-- Element is nested properly inside the pane! -->
<div id="piechart"></div>
</div>

…will work.

Note: if you want your Google Chart to be responsive, instead of giving it a specific width and height, allow it to read the dimensions of the #piechart element. That also requires that you give the element a specific dimension in CSS:

#piechart {
width: 100%;
height: 300px;
}

And in your JS, set up the window resize event listener to redraw the chart:

function drawChart() {
var data = google.visualization.arrayToDataTable([
['Task', 'Hours per Day'],
['Work', 8],
['Eat', 2],
['TV', 4],
['Gym', 2],
['Sleep', 8]
]);

// Optional; add a title and set the width and height of the chart
var chartWrapper = document.getElementById('piechart');
var options = {
title: 'My Average Day',
width: chartWrapper.offsetWidth,
height: chartWrapper.offsetHeight
};

// Display the chart inside the <div> element with id="piechart"
var chart = new google.visualization.PieChart(chartWrapper);
chart.draw(data, options);

window.addEventListener('resize', function() {
chart.draw(data, {
width: chartWrapper.offsetWidth,
height: chartWrapper.offsetHeight
});
});
}

See proof-of-concept below:

// Load google chartsgoogle.charts.load('current', {  'packages': ['corechart']});google.charts.setOnLoadCallback(drawChart);
// Draw the chart and set the chart valuesfunction drawChart() { var data = google.visualization.arrayToDataTable([ ['Task', 'Hours per Day'], ['Work', 8], ['Eat', 2], ['TV', 4], ['Gym', 2], ['Sleep', 8] ]);
// Optional; add a title and set the width and height of the chart var chartWrapper = document.getElementById('piechart'); var options = { title: 'My Average Day', width: chartWrapper.offsetWidth, height: chartWrapper.offsetHeight };
// Display the chart inside the <div> element with id="piechart" var chart = new google.visualization.PieChart(chartWrapper); chart.draw(data, options); window.addEventListener('resize', function() { chart.draw(data, { width: chartWrapper.offsetWidth, height: chartWrapper.offsetHeight }); });}
body,html {  width: 100%;  height: 100%;  margin: 0;}
.container { width: 100%; height: 100%;}
.leftpane { width: 33%; height: 100%; float: left; background-color: rosybrown; border-collapse: collapse;}
.middlepane { width: 30%; height: 100%; float: left; background-color: royalblue; border-collapse: collapse;}
.rightpane { width: 37%; height: 100%; position: relative; float: right; background-color: yellow; border-collapse: collapse;}
#piechart { width: 100%; height: 300px;}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div class="container"> <div class="leftpane"> <h1>Test Page</h1> <div id="piechart"></div> </div> <div class="middlepane"> <h1>Test Page</h1> <b><p>This text is bold</p> <p>let's add more text</p> <p>bla bla bla</p></b>
<button><input type="file" id="myFile"></button> </div>
<div class="rightpane"> <h1>Test Page</h1> </div>

How to make 2 panels appear one after the other on wxpython

I'm not sure if I have understood your question correctly, but you have misunderstood the way that python's time function works: as you have written it, the timer is started, but python continues to process the rest of the code in the function.

Better to use wx.Python's Timer (see this tutorial from Mike Driscoll).

Therefore, in your Start function use:

def Start(self, event):
my_frame.panel_step1.FillGrid(17, 8)
my_frame.Layout()
self.timer = wx.Timer(self)
self.timer.StartOnce(3000)
self.Bind(wx.EVT_TIMER, self._display_second_panel, self.timer)

def _display_second_panel(self, event):
my_frame.panel_step2.Show()
my_frame.panel_step2.FillGridPanel2()
my_frame.Layout()

On a more general note, you have made the Frame a child of the panel

See the wxPython Panel documentation

A panel is a window on which controls are placed.
It is usually placed within a frame. Its main feature over its parent class wx.Window is code for handling child windows and TAB traversal, which is implemented natively if possible (e.g. in wxGTK) or by wxWidgets itself otherwise.

and Overview of wxPython

You should define a frame first and have all of the panels as children of the frame

This is how it might look

import wx
import wx.lib.scrolledpanel as scrolled
import wx.grid as grid


class MainFrame(wx.Frame):
def __init__(self, *args, **kwargs):
super().__init__(None, *args, **kwargs)
screen_width, screen_height = wx.GetDisplaySize()
win_width = min(screen_width, 1280)
win_height = min(screen_height, 800)
self.Size = (win_width, win_height)
self.Title = 'Wx App'
self.panel = MainPanel(self)

self.panel_choice = PanelChoice(self)
self.panel_step1 = PanelStep1(self)
self.panel_step2 = PanelStep2(self)
self.panel_step2.Hide()

sizer = wx.BoxSizer(wx.VERTICAL)

sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.panel_choice, 0, wx.ALL | wx.EXPAND)
sizer.Add(self.panel_step1, 0, wx.ALL | wx.EXPAND)
sizer.Add(self.panel_step2, 0, wx.ALL | wx.EXPAND)

sizer.Add(self.panel)
self.SetSizer(sizer)
self.Center()
self.Show()


class MainPanel(scrolled.ScrolledPanel):
def __init__(self, parent):
scrolled.ScrolledPanel.__init__(self, parent, -1)
self.SetBackgroundColour('F00FF')
font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False)
self.SetFont(font)

self.SetAutoLayout(True)
self.SetupScrolling()


class PanelChoice(wx.Panel):
def __init__(self, parent):
super(PanelChoice, self).__init__(parent)
self.SetBackgroundColour('BLUE')
self.parent = parent

h_box = wx.BoxSizer(wx.HORIZONTAL)

self.label = wx.StaticText(self, label='Select data')
h_box.Add(self.label, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 12)

list_choice = [str(choice) for choice in range(1, 7)]
self.choice = wx.ComboBox(self, choices=list_choice)
self.choice.SetValue('1')
h_box.Add(self.choice, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 3)

self.btn_go = wx.Button(self, label='Go')
self.btn_go.Bind(wx.EVT_BUTTON, handler=self.Start)
h_box.Add(self.btn_go, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 12)

self.SetSizer(h_box)

def Start(self, event):
self.parent.panel_step1.FillGrid(17, 8)
self.parent.Layout()
self.timer = wx.Timer(self)
self.timer.StartOnce(3000)
self.Bind(wx.EVT_TIMER, self._display_second_panel, self.timer)

def _display_second_panel(self, event):
self.parent.panel_step2.Show()
self.parent.panel_step2.FillGridPanel2()
self.parent.Layout()


class PanelStep1(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.SetBackgroundColour('green')
self.SetAutoLayout(1)

self.sizer = wx.BoxSizer(wx.VERTICAL)
h_box_title = wx.BoxSizer(wx.HORIZONTAL)

title = wx.StaticText(self, label='Title panel 1')
h_box_title.Add(title, 0, wx.LEFT | wx.TOP | wx.ALIGN_CENTER_VERTICAL, 6)
self.sizer.Add(h_box_title, 0, wx.LEFT, 0)

self.h_box_table = wx.BoxSizer(wx.HORIZONTAL)
self.sizer.Add(self.h_box_table, wx.ALL | wx.EXPAND, 0)

self.h_box_info = wx.BoxSizer(wx.HORIZONTAL)
self.info = wx.StaticText(self, label=' number of lines : ')
self.h_box_info.Add(self.info, 0, wx.LEFT | wx.EXPAND, 12)
self.sizer.Add(self.h_box_info, 0, wx.EXPAND, 0)

self.SetSizer(self.sizer)
self.Layout()

def FillGrid(self, nb_lines, nb_columns):
self.table = grid.Grid(self)
self.h_box_table.Add(self.table, 0, wx.LEFT | wx.EXPAND, 18)
self.table.CreateGrid(nb_lines, nb_columns)

nb_lines += 1
nb_columns += 1
for line_number in range(1, nb_lines):
for c in range(1, nb_columns):
self.table.SetCellValue(line_number-1, c-1, 'data ' + str(line_number) + '-' + str(c))

self.table.AutoSize()
self.table.SetRowLabelSize(50)
self.info.SetLabel(' number of lines : '+str(nb_lines))
self.Layout()


class PanelStep2(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.SetBackgroundColour('YELLOW')
self.SetAutoLayout(1)
self.sizer = wx.BoxSizer(wx.VERTICAL)

title = wx.StaticText(self, label='Table panel 2')
self.sizer.Add(title, 0, wx.LEFT | wx.TOP, 6)

self.info = wx.StaticText(self, label='Information on data processing ...')
self.info.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False))
self.sizer.Add(self.info, 0, wx.LEFT | wx.EXPAND, 18)

self.SetSizer(self.sizer)

def FillGridPanel2(self):
nb_lines = 27
nb_columns = 8
self.table = grid.Grid(self)
self.table.CreateGrid(nb_lines, nb_columns)
for r in range(nb_lines):
self.table.SetRowLabelValue(r, str(r+1)+' ')
self.table.SetRowLabelAlignment(wx.ALIGN_RIGHT, wx.ALIGN_CENTRE)
self.table.AutoSize()
self.table.SetRowLabelSize(30)

h_box_table = wx.BoxSizer(wx.HORIZONTAL)
h_box_table.Add(self.table, 0, wx.ALL | wx.EXPAND, 6)
self.sizer.Add(h_box_table, 0, wx.ALL | wx.EXPAND, 12)

self.Layout()


if __name__ == '__main__':
wx_app = wx.App()
MainFrame()
wx_app.MainLoop()

Make stretchable split screen in Tkinter

The main problem with your code is that you're not using PanedWidnow correctly. For example, you can't pack or grid one PanedWindow inside another. To place one widget inside a PanedWindow you must use the paned window .add() method. So, to put m2 inside m1 you must do m1.add(m2). Treat a PanedWindow like a Frame, and .add() is the equivalent to .pack() or .grid().

Also, it seems like you're thinking an PanedWindow is a pane, which it is not. If you want three panes for three side-by-side windows, you only need to create a single instance of PanedWindow, and then call .add(...) three times, once for each child window. While you can put paned windows inside paned windows, it's rarely the right thing to do unless one is horizontal and the other is vertical. For most circumstances, a single instance of PanedWindow is all you need.

how to modularise code for wxpython project

After using wxPython for just a short time I learned that structure was vital to enable you to code and maintain efficiently. For small apps a single file with multiple classes will suffice, but as the controls and/or panels and dialogs increase then organising the code in separate files becomes indispensible

A similar question has been asked and answered before (Confused on how to structure the GUI (wxpython))

In one answer I show how the code can be organised into 4 files, for example

  1. the main frame for the application and the application loader;
  2. main_panel.py: the main panel for the application;
  3. menu_bar.py: the menu bar definition for the frame;
  4. tool_bar.py: the tool bar from the frame.


Related Topics



Leave a reply



Submit