Tabless wx.Notebook

Is it possible to create a wx.Notebook without the selection tabs?

I'd like to be able to manage multiple views, but with the tab selection management handled via separate buttons located elsewhere in my UI.

It doesn't seem possible since I believe that wx.Notebook uses the native Windows control. Any suggestions on how best to simulate wx.Notebook without selector tabs would be very interesting. I basically would like to be able to load arbitrary windows and panels into each tab.

Thanks

Malcolm Hawke wrote:

Is it possible to create a wx.Notebook without the selection tabs?

I'd like to be able to manage multiple views, but with the tab selection management handled via separate buttons located elsewhere in my UI.

It doesn't seem possible since I believe that wx.Notebook uses the native Windows control. Any suggestions on how best to simulate wx.Notebook without selector tabs would be very interesting. I basically would like to be able to load arbitrary windows and panels into each tab.

Create all the panels as you normally would for a wxNotebook, but Hide() all but one of them. When you want to switch then Hide() the current and Show() the new one, and set it's size and position as needed.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin Dunn wrote:

Malcolm Hawke wrote:
> Is it possible to create a wx.Notebook without the selection tabs?
>
> I'd like to be able to manage multiple views, but with the tab selection
> management handled via separate buttons located elsewhere in my UI.

Create all the panels as you normally would for a wxNotebook, but Hide()
all but one of them. When you want to switch then Hide() the current
and Show() the new one, and set it's size and position as needed.

Hmm. are you suggesting that he still use a wxNotebook, but only have
one page showing at a time? In any case, you can just forget wxNotebook
altogether, and just create set of wxPanels and put them in a wxSizer,
and use wxSizer.Hide() and wxSizer.Show() as needed. I've enclosed and
example: a samll unit converter I wrote, that I emulate a Notebook in
the way discribed. I did it because only GTK provides a decent
implimentation of a notebook with the tabs on the side, rather than the
top.

-Chris

Converter.py (10.7 KB)

···

--
Christopher Barker, Ph.D.
Oceanographer
                                        
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Chris Barker wrote:

Robin Dunn wrote:

Malcolm Hawke wrote:

Is it possible to create a wx.Notebook without the selection tabs?

I'd like to be able to manage multiple views, but with the tab selection
management handled via separate buttons located elsewhere in my UI.

Create all the panels as you normally would for a wxNotebook, but Hide()
all but one of them. When you want to switch then Hide() the current
and Show() the new one, and set it's size and position as needed.

Hmm. are you suggesting that he still use a wxNotebook, but only have
one page showing at a time?

No, I meant that the all the panels should be precreated just like when using a notebook, but that showing and hiding would have to be managed by his own code. (Just like you suggested, well almost.)

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Chris

Nice little app. If I added an energy entry to the dictionary
would that be useful to anybody else.

Nigel

···

On Tue, 21 Oct 2003 07:55:36 -0700 Chris Barker <Chris.Barker@noaa.gov> wrote:

Robin Dunn wrote:
> Malcolm Hawke wrote:
> > Is it possible to create a wx.Notebook without the selection tabs?
> >
> > I'd like to be able to manage multiple views, but with the tab
selection
> > management handled via separate buttons located elsewhere in my UI.

> Create all the panels as you normally would for a wxNotebook, but
Hide()
> all but one of them. When you want to switch then Hide() the current
> and Show() the new one, and set it's size and position as needed.

Hmm. are you suggesting that he still use a wxNotebook, but only have
one page showing at a time? In any case, you can just forget wxNotebook
altogether, and just create set of wxPanels and put them in a wxSizer,
and use wxSizer.Hide() and wxSizer.Show() as needed. I've enclosed and
example: a samll unit converter I wrote, that I emulate a Notebook in
the way discribed. I did it because only GTK provides a decent
implimentation of a notebook with the tabs on the side, rather than the
top.

-Chris

#!/usr/bin/env python2.2

from wxPython.wx import *

ID_ABOUT_MENU = wxNewId()
ID_EXIT_MENU = wxNewId()

class ConverterPanel(wxPanel):
    def __init__(self, parent, id, Unit, Data_dict):
    
        wxPanel.__init__(self, parent, id,
wxDefaultPosition,style=wxSUNKEN_BORDER)

        self.ID_FROM_BOX = wxNewId()
        self.ID_TO_BOX = wxNewId()
        self.ID_FROM_UNITS = wxNewId()
        self.ID_TO_UNITS = wxNewId()
        
        self.Unit = Unit
        self.Data_dict = Data_dict
        self.Units = Data_dict.keys()
        ##self.Units.sort()
        
        self.FromUnits = wxChoice(self, self.ID_FROM_UNITS,
wxDefaultPosition,wxDefaultSize,self.Units)
        self.ToUnits = wxChoice(self, self.ID_TO_UNITS,
wxDefaultPosition,wxDefaultSize,self.Units)
        self.ToUnits.SetSelection(0)
        self.FromUnits.SetSelection(0)
        #self.FromUnits.SetSize(self.FromUnits.GetBestSize())
        #self.ToUnits.SetSize(self.ToUnits.GetBestSize())
        
        self.InputBox = wxTextCtrl(self, self.ID_FROM_BOX, "",
wxDefaultPosition,wxDefaultSize)
        self.OutBox = wxTextCtrl(self, self.ID_TO_BOX, "",
wxDefaultPosition, wxDefaultSize,style = wxTE_READONLY)
        
        Grid = wxFlexGridSizer(6,2,5,20)

        Grid.Add(wxStaticText(self, -1, "Convert from:",
wxDefaultPosition, wxDefaultSize),0,wxALIGN_LEFT)
        Grid.Add(20,1,1)

        Grid.Add(self.InputBox, 0, wxALIGN_LEFT)
        Grid.Add(self.FromUnits,0, wxALIGN_RIGHT)

        Grid.Add(20,20,1)
        Grid.Add(20,20,1)

        Grid.Add(wxStaticText(self, -1, "Convert To:",
wxDefaultPosition, wxDefaultSize),0,wxALIGN_LEFT)
        Grid.Add(20,1,1)

        Grid.Add(self.OutBox, 0, wxALIGN_LEFT)
        Grid.Add(self.ToUnits,0, wxALIGN_RIGHT)

        Grid.Layout()
        OuterBox = wxBoxSizer(wxVERTICAL)
        OuterBox.Add(20,20,0)
        Label = wxStaticText(self, -1, Unit, wxDefaultPosition,
wxDefaultSize)
        of = Label.GetFont()
        Font = wxFont(int(of.GetPointSize() * 2), of.GetFamily(),
wxNORMAL, wxNORMAL)
        Label.SetFont(Font)

        OuterBox.Add(Label,0,wxALIGN_CENTER)
        OuterBox.Add(Grid,0,wxALIGN_CENTER|wxALL,30)
        OuterBox.Layout()

        self.SetAutoLayout(True)
        self.SetSizer(OuterBox)
        self.Fit()

        EVT_TEXT(self, self.ID_FROM_BOX, self.Recalculate)
        EVT_CHOICE(self,self.ID_TO_UNITS , self.Recalculate)
        EVT_CHOICE(self,self.ID_FROM_UNITS , self.Recalculate)
        
    def Recalculate(self,event):
        try:
            from_string = self.InputBox.GetValue()
            # this is not quite really sigfigs, as all zeros are
counted, but it looks better
            # it is set to a minimum of 4 figures
            sigfigs =
max(len(from_string.split("e")[0].replace(".","")),3)
            sigfigs = min(sigfigs,7) # there are no more than 7 digits
in the conversion factors
            from_val = float(self.InputBox.GetValue())
            from_unit = self.FromUnits.GetStringSelection()
            to_unit = self.ToUnits.GetStringSelection()
            
            if self.Unit == "Temperature": # Special Case
                A1 = self.Data_dict[from_unit][0]
                B1 = self.Data_dict[from_unit][1]
                A2 = self.Data_dict[to_unit][0]
                B2 = self.Data_dict[to_unit][1]
                
                #to_val = (round((from_val * A1 + B1),13) -
round(B2,13))*A2 # rounding to get rid of cancelation error
                to_val = ((from_val + B1)*A1/A2)-B2
                sigfigs += 2 # temp adds and subtracts, so it looks
better to have a couple of extra digits.
            else:
                if from_unit == "API": # another Special case (could I
do this the same as temp?)
                    from_val = 141.5/(from_val + 131.5)
                    from_unit = "Specific Gravity"
                    sigfigs += 2 # API is also weird, so it looks better
to have a couple of extra digits.
                if to_unit == "API":
                    to_val = 141.5/(from_val *
self.Data_dict[from_unit]) - 131.5
                    sigfigs += 2 # API is also wierd, so it looks better
to have a couple of extra digits.
                else:
                    to_val = from_val * self.Data_dict[from_unit] /
self.Data_dict[to_unit]
            format_string = "%%.%ig"%sigfigs
            self.OutBox.SetValue(format_string%(to_val,))# this displays
only 6 sigfigs...
        except ValueError:
            self.OutBox.SetValue("")

class ConverterFrame(wxFrame):
    def __init__(self,parent, id,title,position,size):
        wxFrame.__init__(self,parent, id,title,position, size)

        ## Set up the MenuBar
        MenuBar = wxMenuBar()
        
        file_menu = wxMenu()
        file_menu.Append(ID_EXIT_MENU, "E&xit","Terminate the program")
        EVT_MENU(self, ID_EXIT_MENU,self.OnQuit)
        MenuBar.Append(file_menu, "&File")
        
        help_menu = wxMenu()
        help_menu.Append(ID_ABOUT_MENU, "&About",
                         "More information About this program")
        EVT_MENU(self, ID_ABOUT_MENU, self.OnAbout)
        MenuBar.Append(help_menu, "&Help")
        
        self.SetMenuBar(MenuBar)
        
        EVT_CLOSE(self, self.OnCloseWindow)
        
        MainSizer = wxBoxSizer(wxHORIZONTAL)
        self.MainSizer = MainSizer

        ButtonSizer = wxBoxSizer(wxVERTICAL)

        self.Panels = {}
        BiggestSize = (0,0)
        for (unit,data) in ConvertDataUnits.items():
            # create Panel
            Panel = ConverterPanel(self, -1,unit,data)
            Panel.Show(False)
            size = Panel.GetBestSize()
            BiggestSize = ( max(size[0],BiggestSize[0]),
max(size[1],BiggestSize[1]) )
            
            # create Button
            ID = wxNewId()
            ButtonSizer.Add(wxButton(self,ID,unit),0,wxEXPAND|wxALL,3)
            self.Panels[ID] = Panel

            ### set up the events:
            EVT_BUTTON(self, ID, self.OnButtonPress)

        ## Reset the sizes of all the Panels to match the biggest one
        for Panel in self.Panels.values():
            Panel.SetSize(BiggestSize)
        ButtonSizer.Layout()
        MainSizer.Add(ButtonSizer,0,wxALIGN_TOP|wxALL,6)

        ##Add all the Panels
        for ID in self.Panels:
            CurrentPanel = self.Panels[ID]
            ##self.CurrentPanel.Show(True)
            MainSizer.Add(CurrentPanel,1,wxGROW|wxALL,4)
            MainSizer.Hide(CurrentPanel)
        self.CurrentPanel = self.Panels.values()[0]
        MainSizer.Show(self.CurrentPanel)
        MainSizer.Layout()
        self.SetSizer(MainSizer)
        self.Fit()
        self.Show(True)

    def OnButtonPress(self,event):
        ID = event.GetId()
        self.MainSizer.Hide(self.CurrentPanel)
        self.CurrentPanel = self.Panels[ID]
        self.MainSizer.Show(self.CurrentPanel)
        self.MainSizer.Layout()

    def OnAbout(self, event):
        dlg = wxMessageDialog(self, "This is a small program that \n"
                              "Provides some handy conversions",
                              "About Me", wxOK | wxICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()
        
    def OnQuit(self,event):
        self.Close(True)
        
    def OnCloseWindow(self, event):
        self.Destroy()

class App(wxApp):
    def OnInit(self):
        frame = ConverterFrame(NULL,
                               -1,
                               "Unit Converter",
                               wxDefaultPosition,
                               wxDefaultSize)
        
        self.SetTopWindow(frame)
        return True

ConvertDataUnits = {
# All lengths in terms of meters
"Length" : {"Meters" : 1.0,
            "Centimeters" : 0.01,
            "Millimeters" : 0.001,
            "Kilometers" : 1000.0,
            "Feet" : 0.3048,
            "Inches" : 0.0254,
            "Yards" : 0.9144,
            "Miles" : 1609.344,
            "Nautical Miles": 1852.0,
            "Fathoms" : 1.8288,
            "Latitude Degrees": 111120.0,
            "Latitude Minutes": 1852.0
            },

# All Areas in terms of square meters
"Area" : {"Square Meters" : 1.0,
          "Square Centimeters": .0001,
          "Square Kilometers" : 1e6,
          "Acres" : 4046.8564,
          "Square Miles" : 2589988.1,
          "Square Yards" : 0.83612736,
          "Hectares" : 10000.0
          },

# All volumes in terms of cubic meters
"Volume" : {"Cubic Meters" : 1.0,
            "Cubic Centimeters" : 1e-6,
            "Barrels" : .1589873,
            "Liters" : 1e-3,
            "Gallons" : 0.0037854118,
            "Cubic Feet" : 0.028316847
            },

# All Temperature units in K (multiply by, add)
"Temperature" : {"Kelvin" : (1.0, 0.0),
                 "Centigrade" : (1.0, 273.16),
                 "Farenheight" : (0.55555555555555558, (273.16*9/5 - 32)
)
                 },

# All Mass units in Kg (weight is taken to be mass at standard g)
"Mass" : {"Kilograms" : 1.0,
          "Pounds" : 0.45359237,
          "Grams" : .001
          },
# All Time In Seconds
"Time" : {"Seconds" : 1.0,
                "Minutes" : 60.0,
                "Hours" : 3600.0,
                "Days" : 86400.0
                },
# All Velocities in meters per second
"Velocity" : {"Meters per Second" : 1.0,
              "Centimeters per Second" : .01,
              "Kilometers per Hour" : 0.277777,
              "Knots" : 0.514444,
              "Miles per Hour" : 0.44704,
              "Feet per Second" : 0.3048
              },
# All Discharges in cubic meters per second
"Discharge" : {"Cubic Meters per Second" : 1.0,
               "Cubic Feet per Second" : .02831685,
               "Gallons per Hour" : 1.0515032833333335e-06,
               "Gallons per Minute": 6.3090197000000006e-05,
               "Gallons per Second" : 0.0037854118
               },

# All Oil Thicknesses in meters
"Oil Thickness" : {"Meters" : 1.0,
                   "Millimeters" : 0.001,
                   "Barrels per Acre" : 3.92866176324e-05,
                   "Barrels per Square Meter" : .1589873,
                   "Liters per Square Kilometer" : 1e-9
                   },
"Kinematic Viscosity" : {"Stokes": 1.0,
                         "Centistokes": .01,
                         "Square centimeters per second": 1.0,
                         "Square meters per second": 10000,
                         #"Poise" : (["P"])
                         },

### Density in g/cc
"Density" : {"Specific Gravity" : 1.0,
             "Grams per Cubic Centimeter" : 1.0,
             "Kilograms per cubic Meter" : .001,
             "API" : 0}
}
        
if __name__ == "__main__":
    app = App(0)
    app.MainLoop()
    
> ---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwindows.org
For additional commands, e-mail: wxPython-users-help@lists.wxwindows.org

--
Nigel W. Moriarty
Building 4R0230
Physical Biosciences Division
Lawrence Berkeley National Laboratory
Berkeley, CA 94720-8235
Phone : 510-486-5709
Fax : 510-486-5909
Email : NWMoriarty@LBL.gov
Web : CCI.LBL.gov

Chris

Nice little app.

Thanks.

If I added an energy entry to the dictionary

would that be useful to anybody else.

Probably. If you do, please send it to me. However, I have only used
this internally, thought it could certainly enjoy a larger audience. I
wrote it for two reasons:

1) it was my first real wxPython app, and I wanted to learn and evaluate
wxPython.

2) All the unit converters I've seen either don't have the obscure units
I need, or they have absolutely everything, which gets too cluttered. My
goal was to have all the units I need, and few others.

I have had it in mind to extend it so it's easy to edit the unit
dictionary, probably putting int in a separate config file. Then
individuals could create their own unit dictionaries that met their
needs. Maybe some day.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                        
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Chris

Here's the dictionary entry. I didn't fiddle with the sig figs.

Nigel

"Energy" : {"Hartree" : 1.0,
             "kcal/mol" : 1.0/627.503,
             "eV" : 1.0/27.2107,
             "cm-1" : 1.0/219474.63,
             "kJ/mol" : 1.0/2625.5,
             "degree K" : 1.0/31577.0,
             "J" : 1.0/43.60e-19,
             "Hz" : 1.0/6.57966e+15,
             },

···

On Tue, 21 Oct 2003 11:55:47 -0700 Chris Barker <Chris.Barker@noaa.gov> wrote:

> Chris
>
> Nice little app.

Thanks.

If I added an energy entry to the dictionary
> would that be useful to anybody else.

Probably. If you do, please send it to me. However, I have only used
this internally, thought it could certainly enjoy a larger audience. I
wrote it for two reasons:

1) it was my first real wxPython app, and I wanted to learn and evaluate
wxPython.

2) All the unit converters I've seen either don't have the obscure units
I need, or they have absolutely everything, which gets too cluttered. My
goal was to have all the units I need, and few others.

I have had it in mind to extend it so it's easy to edit the unit
dictionary, probably putting int in a separate config file. Then
individuals could create their own unit dictionaries that met their
needs. Maybe some day.

-Chris

--
Nigel W. Moriarty
Building 4R0230
Physical Biosciences Division
Lawrence Berkeley National Laboratory
Berkeley, CA 94720-8235
Phone : 510-486-5709
Fax : 510-486-5909
Email : NWMoriarty@LBL.gov
Web : CCI.LBL.gov

sorry about this, but it appears that I havn't been able to post to this
list lately, so I'm trying again.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                        
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov