How to add a menu bar in the title bar (Phoenix)

Keywords : Menu bar, Shaped frame, Customized frame, Customized button, Transparency, Roll, Unroll, Fade in, Fade out, Shape, Region, BufferedPaintDC, BufferedDC, ClientDC, GCDC, AutoBufferedPaintDCFactory, AcceleratorTable.


Demonstrating (only Windows) :

Tested py3.x, wx4.x and Win10.

Are you ready to use some samples ? ;)

Test, modify, correct, complete, improve and share your discoveries ! (!)


Frame with resize border, buttons, menu bar and dragging :

First example

img_sample_one.png

   1 # sample_one.py
   2 
   3 import sys
   4 import os
   5 import platform
   6 import wx
   7 import wx.lib.fancytext as fancytext
   8 import wx.lib.agw.flatmenu as FM
   9 from   wx.lib.agw.artmanager import ArtManager, RendererBase, DCSaver
  10 from   wx.lib.agw.fmresources import ControlFocus, ControlPressed
  11 import wx.lib.mixins.listctrl as listmix
  12 import wx.dataview as dv
  13 import rectshapedbitmapbuttonTwo as SBBTwo
  14 import data
  15 
  16 musicdata = sorted(data.musicdata.items())
  17 musicdata = [[str(k)] + list(v) for k,v in musicdata]
  18 
  19 # def SwitchRGBtoBGR
  20 # def CreateBackgroundBitmap
  21 # class MyMenuRenderer
  22 # class MyMenuBar
  23 # class MyListCtrlPnl
  24 # class MyStatusBar
  25 # class MyTitleBar
  26 # class MyAboutDlg
  27 # class MyPopupMenu
  28 # class MyTitleBarPnl
  29 # class MyMainPnl
  30 # class MyFrame
  31 # class MyApp
  32 
  33 ID_FULLSCREEN = wx.NewIdRef()
  34 ID_MAIN_PNL = wx.NewIdRef()
  35 ID_BTN_FULLSCREEN = wx.NewIdRef()
  36 ID_BTN_ABOUT = wx.NewIdRef()
  37 ID_BTN_QUIT = wx.NewIdRef()
  38 ID_HELLO = wx.NewIdRef()
  39 
  40 #---------------------------------------------------------------------------
  41 
  42 def SwitchRGBtoBGR(colour):
  43     """
  44     ...
  45     """
  46 
  47     return wx.Colour(colour.Blue(), colour.Green(), colour.Red())
  48 
  49 #---------------------------------------------------------------------------
  50 
  51 def CreateBackgroundBitmap():
  52     """
  53     ...
  54     """
  55 
  56     mem_dc = wx.MemoryDC()
  57     bmp = wx.Bitmap(121, 300)
  58     mem_dc.SelectObject(bmp)
  59 
  60     mem_dc.Clear()
  61 
  62     # Colour the menu face with background colour.
  63     mem_dc.SetPen(wx.Pen("#a0a0a0", 0))
  64     mem_dc.SetBrush(wx.Brush("#fec54c"))
  65     mem_dc.DrawRectangle(0, 15, 122, 300)
  66     mem_dc.DrawLine(0, 0, 300, 0)
  67 
  68     mem_dc.SelectObject(wx.NullBitmap)
  69     return bmp
  70 
  71 #---------------------------------------------------------------------------
  72 
  73 class MyMenuRenderer(FM.FMRenderer):
  74     """
  75     Thanks to Andrea Gavana.
  76     A custom renderer class for FlatMenu.
  77     """
  78     def __init__(self):
  79         FM.FMRenderer.__init__(self)
  80 
  81     #-----------------------------------------------------------------------
  82 
  83     def DrawMenuButton(self, dc, rect, state):
  84         """
  85         Draws the highlight on a FlatMenu.
  86         """
  87 
  88         self.DrawButton(dc, rect, state)
  89 
  90 
  91     def DrawMenuBarButton(self, dc, rect, state):
  92         """
  93         Draws the highlight on a FlatMenuBar.
  94         """
  95 
  96         self.DrawButton(dc, rect, state)
  97 
  98 
  99     def DrawButton(self, dc, rect, state, colour=None):
 100         """
 101         ...
 102         """
 103 
 104         if state == ControlFocus:
 105             penColour = SwitchRGBtoBGR(ArtManager.Get().FrameColour())
 106             brushColour = SwitchRGBtoBGR(ArtManager.Get().BackgroundColour())
 107         elif state == ControlPressed:
 108             penColour = SwitchRGBtoBGR(ArtManager.Get().FrameColour())
 109             brushColour = SwitchRGBtoBGR(ArtManager.Get().HighlightBackgroundColour())
 110         else:   # ControlNormal, ControlDisabled, default.
 111             penColour = SwitchRGBtoBGR(ArtManager.Get().FrameColour())
 112             brushColour = SwitchRGBtoBGR(ArtManager.Get().BackgroundColour())
 113 
 114         # Draw the button borders.
 115         dc = wx.GCDC(dc)
 116         dc.SetPen(wx.Pen(penColour))
 117         dc.SetBrush(wx.Brush(brushColour))
 118         dc.DrawRoundedRectangle(rect.x, rect.y, rect.width, rect.height-3, 4)
 119 
 120 
 121     def DrawMenuBarBackground(self, dc, rect):
 122         """
 123         ...
 124         """
 125 
 126         # For office style, we simple draw a rectangle
 127         # with a gradient colouring.
 128         vertical = ArtManager.Get().GetMBVerticalGradient()
 129 
 130         dcsaver = DCSaver(dc)
 131 
 132         # Fill with gradient.
 133         startColour = self.menuBarFaceColour
 134         endColour   = ArtManager.Get().LightColour(startColour, 0)
 135 
 136         dc.SetPen(wx.Pen(endColour))
 137         dc.SetBrush(wx.Brush(endColour))
 138         dc.DrawRectangle(rect)
 139 
 140 
 141     def DrawToolBarBg(self, dc, rect):
 142         """
 143         ...
 144         """
 145 
 146         if not ArtManager.Get().GetRaiseToolbar():
 147             return
 148 
 149         # Fill with gradient.
 150         startColour = self.menuBarFaceColour()
 151         dc.SetPen(wx.Pen(startColour))
 152         dc.SetBrush(wx.Brush(startColour))
 153         dc.DrawRectangle(0, 0, rect.GetWidth(), rect.GetHeight())
 154 
 155 #---------------------------------------------------------------------------
 156 
 157 class MyMenuBar(FM.FlatMenuBar):
 158     """
 159     A custom renderer class for FlatMenu.
 160     """
 161     def __init__(self, parent):
 162         FM.FlatMenuBar.__init__(self, parent,
 163                                 id=wx.ID_ANY,
 164                                 iconSize=32,
 165                                 spacer=3,
 166                                 options=FM.FM_OPT_IS_LCD)
 167 
 168         #------------
 169 
 170         # Return bitmaps folder.
 171         self.bitmaps_dir = wx.GetApp().GetBitmapsDir()
 172 
 173         #------------
 174 
 175         self.parent = parent
 176 
 177         #------------
 178 
 179         # FM.StyleDefault or FM.Style2007
 180         # FM.StyleXP or FM.StyleVista
 181         self.newMyTheme = self.GetRendererManager().AddRenderer(MyMenuRenderer())
 182         self.GetRendererManager().SetTheme(self.newMyTheme)
 183 
 184         #------------
 185 
 186         # Set an icon to the exit/help menu item.
 187         exitImg = wx.Bitmap(os.path.join(self.bitmaps_dir,
 188                                          "item_exit.png"),
 189                             type=wx.BITMAP_TYPE_PNG)
 190 
 191         helpImg = wx.Bitmap(os.path.join(self.bitmaps_dir,
 192                                          "item_about.png"),
 193                             type=wx.BITMAP_TYPE_PNG)
 194 
 195         #------------
 196         #------------
 197 
 198         # File Menu.
 199         self.file_menu = FM.FlatMenu()
 200 
 201         # Create the menu items.
 202         item = FM.FlatMenuItem(self.file_menu,
 203                                ID_FULLSCREEN,
 204                                "&Fullscreen\tCtrl+F",
 205                                "Fullscreen",
 206                                wx.ITEM_NORMAL,
 207                                None)
 208         item.SetTextColour("black")
 209         self.file_menu.AppendItem(item)
 210         self.file_menu.AppendSeparator()
 211 
 212 
 213         item = FM.FlatMenuItem(self.file_menu,
 214                                wx.ID_EXIT,
 215                                "&Quit\tCtrl+Q",
 216                                "Quit the program",
 217                                wx.ITEM_NORMAL,
 218                                None,
 219                                exitImg)
 220         # Demonstrate how to set custom font
 221         # and text colour to a FlatMenuItem.
 222         item.SetFont(wx.Font(-1, wx.FONTFAMILY_DEFAULT,
 223                              wx.FONTSTYLE_NORMAL,
 224                              wx.FONTWEIGHT_BOLD,
 225                              False, ""))
 226         item.SetTextColour("#d34725")
 227 
 228         self.file_menu.AppendItem(item)
 229 
 230         #------------
 231 
 232         # Add Create background bitmap.
 233         self.file_menu.SetBackgroundBitmap(CreateBackgroundBitmap())
 234 
 235         #------------
 236         #------------
 237 
 238         # Help Menu.
 239         self.help_menu = FM.FlatMenu()
 240 
 241         # Create the menu items.
 242         item = FM.FlatMenuItem(self.help_menu,
 243                                wx.ID_ABOUT,
 244                                "&About\tCtrl+A",
 245                                "About",
 246                                wx.ITEM_NORMAL,
 247                                None,
 248                                helpImg)
 249         item.SetTextColour("black")
 250         self.help_menu.AppendItem(item)
 251         self.help_menu.AppendSeparator()
 252 
 253         item = FM.FlatMenuItem(self.help_menu,
 254                                ID_HELLO,
 255                                "Hello !",
 256                                "Hello !",
 257                                wx.ITEM_NORMAL,
 258                                None)
 259         item.SetTextColour("black")
 260         self.help_menu.AppendItem(item)
 261 
 262         #------------
 263 
 264         # Add Create background bitmap.
 265         self.help_menu.SetBackgroundBitmap(CreateBackgroundBitmap())
 266 
 267         #------------
 268         #------------
 269 
 270         # Menu background color.
 271         self.SetBackgroundColour(wx.Colour(wx.WHITE))
 272 
 273         # Add menu to the menu bar.
 274         self.Append(self.file_menu, "&File")
 275         self.Append(self.help_menu, "&Help")
 276 
 277         #------------
 278 
 279         # Simplified init method.
 280         self.SetProperties()
 281 
 282     #-----------------------------------------------------------------------
 283 
 284     def SetProperties(self):
 285         """
 286         ...
 287         """
 288 
 289         self.SetMaxSize((91, 20))
 290 
 291 #---------------------------------------------------------------------------
 292 
 293 class MyListCtrlPnl(wx.Panel):
 294     """
 295     Thanks to Robin Dunn.
 296     """
 297     def __init__(self, parent):
 298         wx.Panel.__init__(self, parent, -1)
 299 
 300         # Create the listctrl.
 301         self.dvlc = dv.DataViewListCtrl(self,
 302                                         style=dv.DV_ROW_LINES|
 303                                               dv.DV_HORIZ_RULES|
 304                                               dv.DV_VERT_RULES)
 305 
 306         # Give it some columns.
 307         # The ID col we'll customize a bit :
 308         self.dvlc.AppendTextColumn("Id", width=40)
 309         self.dvlc.AppendTextColumn("Artist", width=170)
 310         self.dvlc.AppendTextColumn("Title", width=260)
 311         self.dvlc.AppendTextColumn("Genre", width=80)
 312 
 313         # Load the data. Each item (row) is added as a sequence
 314         # of values whose order matches the columns.
 315         for itemvalues in musicdata:
 316             self.dvlc.AppendItem(itemvalues)
 317 
 318         self.dvlc.SetBackgroundColour("#c9f72b")
 319         self.dvlc.SetForegroundColour("black")
 320 
 321         # Set the layout so the listctrl fills the panel.
 322         self.Sizer = wx.BoxSizer()
 323         self.Sizer.Add(self.dvlc, 1, wx.EXPAND)
 324 
 325 #---------------------------------------------------------------------------
 326 
 327 class MyStatusBar(wx.StatusBar) :
 328     """
 329     Thanks to ???.
 330     Simple custom colorized StatusBar.
 331     """
 332     def __init__(self, parent, id) :
 333         wx.StatusBar.__init__(self, parent, id)
 334 
 335         #------------
 336 
 337         # Simplified init method.
 338         self.SetProperties()
 339         self.BindEvents()
 340 
 341     #-----------------------------------------------------------------------
 342 
 343     def SetProperties(self):
 344         """
 345         ...
 346         """
 347 
 348         if wx.Platform == "__WXMSW__":
 349             self.SetDoubleBuffered(True)
 350 
 351 
 352     def BindEvents(self):
 353         """
 354         Bind some events to an events handler.
 355         """
 356 
 357         self.Bind(wx.EVT_PAINT, self.OnPaint)
 358 
 359 
 360     def OnPaint(self, event) :
 361         """
 362         ...
 363         """
 364 
 365         dc = wx.BufferedPaintDC(self)
 366         self.Draw(dc)
 367 
 368 
 369     def Draw(self, dc) :
 370         """
 371         ...
 372         """
 373 
 374         dc.SetBackground(wx.Brush(wx.WHITE))
 375         dc.Clear()
 376 
 377         textVertOffset = 3      # Perfect for MSW.
 378         textHorzOffset = 5      # Arbitrary - looks nicer.
 379 
 380         dc.SetTextForeground("gray")
 381         dc.DrawText(self.GetStatusText(), textHorzOffset, textVertOffset)
 382 
 383 #---------------------------------------------------------------------------
 384 
 385 class MyTitleBar(wx.Control):
 386     """
 387     Thanks to Cody Precord.
 388     """
 389     def __init__(self, parent, label, size):
 390         style = (wx.BORDER_NONE)
 391         super(MyTitleBar, self).__init__(parent,
 392                                          style=style)
 393 
 394         #------------
 395 
 396         # Return bitmaps folder.
 397         self.bitmaps_dir = wx.GetApp().GetBitmapsDir()
 398 
 399         #------------
 400 
 401         # Attributes.
 402         self.parent = parent
 403         self.label = label
 404         self.size = size
 405 
 406         #------------
 407 
 408         # Simplified init method.
 409         self.SetBackground()
 410         self.SetProperties(label, size)
 411         self.CreateMenu()
 412         self.CreateCtrls()
 413         self.BindEvents()
 414         self.DoLayout()
 415 
 416     #-----------------------------------------------------------------------
 417 
 418     def SetBackground(self):
 419         """
 420         ...
 421         """
 422 
 423         self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
 424         self.SetBackgroundColour(wx.WHITE)
 425 
 426 
 427     def SetProperties(self, label, size):
 428         """
 429         ...
 430         """
 431 
 432         self.label = label
 433         self.size = size
 434 
 435         self.label_font = self.GetFont()
 436         self.label_font.SetFamily(wx.SWISS)
 437         self.label_font.SetPointSize(size)
 438         self.label_font.SetWeight(wx.BOLD)
 439         self.SetFont(self.label_font)
 440 
 441 
 442     def CreateMenu(self):
 443         """
 444         ...
 445         """
 446 
 447         self.menuBar = MyMenuBar(self)
 448 
 449 
 450     def CreateCtrls(self):
 451         """
 452         ...
 453         """
 454 
 455         w, h = self.GetSize()
 456         w1, h1 = self.GetClientSize()
 457 
 458         #------------
 459 
 460         # Load an icon bitmap for titlebar.
 461         # bmp = wx.Bitmap(os.path.join(self.bitmaps_dir,
 462         #                              "icon_app.png"),
 463         #                 type=wx.BITMAP_TYPE_PNG)
 464 
 465         # self.ico = wx.StaticBitmap(self, -1, bmp)
 466         # self.ico.SetBackgroundColour(wx.Colour(wx.WHITE))
 467         # self.ico.SetPosition((300, 1))
 468         # self.ico.SetToolTip("This is a customized icon.")
 469         # self.ico.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
 470 
 471         #------------
 472 
 473         # Button Exit.
 474         self.btn3 = SBBTwo.ShapedBitmapButton(self, -1,
 475             bitmap=wx.Bitmap(os.path.join(self.bitmaps_dir,
 476                                           "btn_gloss_exit_normal_1.png"),
 477                              type=wx.BITMAP_TYPE_PNG),
 478 
 479             pressedBmp=wx.Bitmap(os.path.join(self.bitmaps_dir,
 480                                               "btn_gloss_exit_selected_1.png"),
 481                                  type=wx.BITMAP_TYPE_PNG),
 482 
 483             hoverBmp=wx.Bitmap(os.path.join(self.bitmaps_dir,
 484                                             "btn_gloss_exit_normal_1.png"),
 485                                type=wx.BITMAP_TYPE_PNG),
 486 
 487             disabledBmp=wx.Bitmap(os.path.join(self.bitmaps_dir,
 488                                                "btn_gloss_exit_normal_1.png"),
 489                                   type=wx.BITMAP_TYPE_PNG),
 490 
 491             label="",
 492             labelForeColour=wx.WHITE,
 493             labelFont=wx.Font(9,
 494                               wx.FONTFAMILY_DEFAULT,
 495                               wx.FONTSTYLE_NORMAL,
 496                               wx.FONTWEIGHT_BOLD),
 497             style=wx.BORDER_NONE)
 498 
 499         #------------
 500 
 501         # Button Maximize.
 502         self.btn4 = SBBTwo.ShapedBitmapButton(self, -1,
 503             bitmap=wx.Bitmap(os.path.join(self.bitmaps_dir,
 504                                           "btn_gloss_maximize_normal_1.png"),
 505                              type=wx.BITMAP_TYPE_PNG),
 506 
 507             pressedBmp=wx.Bitmap(os.path.join(self.bitmaps_dir,
 508                                               "btn_gloss_maximize_selected_1.png"),
 509                                  type=wx.BITMAP_TYPE_PNG),
 510 
 511             hoverBmp=wx.Bitmap(os.path.join(self.bitmaps_dir,
 512                                             "btn_gloss_maximize_normal_1.png"),
 513                                type=wx.BITMAP_TYPE_PNG),
 514 
 515             disabledBmp=wx.Bitmap(os.path.join(self.bitmaps_dir,
 516                                                "btn_gloss_maximize_normal_1.png"),
 517                                   type=wx.BITMAP_TYPE_PNG),
 518 
 519             label="",
 520             labelForeColour=wx.WHITE,
 521             labelFont=wx.Font(9,
 522                               wx.FONTFAMILY_DEFAULT,
 523                               wx.FONTSTYLE_NORMAL,
 524                               wx.FONTWEIGHT_BOLD),
 525             style=wx.BORDER_NONE)
 526 
 527         #------------
 528 
 529         # Thanks to MCOW.
 530         # Button Reduce.
 531         self.btn5 = SBBTwo.ShapedBitmapButton(self, -1,
 532             bitmap=wx.Bitmap(os.path.join(self.bitmaps_dir,
 533                                           "btn_gloss_reduce_normal_1.png"),
 534                              type=wx.BITMAP_TYPE_PNG),
 535 
 536             pressedBmp=wx.Bitmap(os.path.join(self.bitmaps_dir,
 537                                               "btn_gloss_reduce_selected_1.png"),
 538                                  type=wx.BITMAP_TYPE_PNG),
 539 
 540             hoverBmp=wx.Bitmap(os.path.join(self.bitmaps_dir,
 541                                             "btn_gloss_reduce_normal_1.png"),
 542                                type=wx.BITMAP_TYPE_PNG),
 543 
 544             disabledBmp=wx.Bitmap(os.path.join(self.bitmaps_dir,
 545                                                "btn_gloss_reduce_normal_1.png"),
 546                                   type=wx.BITMAP_TYPE_PNG),
 547 
 548             label="",
 549             labelForeColour=wx.WHITE,
 550             labelFont=wx.Font(9,
 551                               wx.FONTFAMILY_DEFAULT,
 552                               wx.FONTSTYLE_NORMAL,
 553                               wx.FONTWEIGHT_BOLD),
 554             style=wx.BORDER_NONE)
 555 
 556         #------------
 557 
 558         # Button Roll.
 559         self.btn6 = SBBTwo.ShapedBitmapButton(self, -1,
 560             bitmap=wx.Bitmap(os.path.join(self.bitmaps_dir,
 561                                           "btn_gloss_roll_normal_1.png"),
 562                              type=wx.BITMAP_TYPE_PNG),
 563 
 564             pressedBmp=wx.Bitmap(os.path.join(self.bitmaps_dir,
 565                                               "btn_gloss_roll_selected_1.png"),
 566                                  type=wx.BITMAP_TYPE_PNG),
 567 
 568             hoverBmp=wx.Bitmap(os.path.join(self.bitmaps_dir,
 569                                             "btn_gloss_roll_normal_1.png"),
 570                                type=wx.BITMAP_TYPE_PNG),
 571 
 572             disabledBmp=wx.Bitmap(os.path.join(self.bitmaps_dir,
 573                                                "btn_gloss_roll_normal_1.png"),
 574                                   type=wx.BITMAP_TYPE_PNG),
 575 
 576             label="",
 577             labelForeColour=wx.WHITE,
 578             labelFont=wx.Font(9,
 579                               wx.FONTFAMILY_DEFAULT,
 580                               wx.FONTSTYLE_NORMAL,
 581                               wx.FONTWEIGHT_BOLD),
 582             style=wx.BORDER_NONE)
 583 
 584 
 585     def BindEvents(self):
 586         """
 587         Bind some events to an events handler.
 588         """
 589 
 590         # self.ico.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
 591         # self.ico.Bind(wx.EVT_LEFT_DOWN, self.OnRightDown)
 592 
 593         self.Bind(wx.EVT_PAINT, self.OnPaint)
 594         self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
 595         self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
 596 
 597         self.btn3.Bind(wx.EVT_BUTTON, self.OnBtnClose)
 598         self.btn4.Bind(wx.EVT_BUTTON, self.OnFullScreen)
 599         self.btn5.Bind(wx.EVT_BUTTON, self.OnIconfiy)
 600         self.btn6.Bind(wx.EVT_BUTTON, self.OnRoll)
 601 
 602         self.Bind(wx.EVT_MENU, self.OnFullScreen, id=ID_FULLSCREEN)
 603         self.Bind(wx.EVT_MENU, self.OnBtnClose, id=wx.ID_EXIT)
 604 
 605 
 606     def DoLayout(self):
 607         """
 608         ...
 609         """
 610 
 611 
 612         mainSizer = wx.BoxSizer(wx.HORIZONTAL)
 613 
 614         #------------
 615 
 616         mainSizer.Add(self.btn3, 0, wx.LEFT, 4)
 617         mainSizer.Add(self.btn4, 0, wx.LEFT, 4)
 618         mainSizer.Add(self.btn5, 0, wx.LEFT, 4)
 619         mainSizer.Add(self.btn6, 0, wx.LEFT, 4)
 620         mainSizer.Add((10,1), 0, wx.ALL, 0)
 621         mainSizer.Add(self.menuBar, 1)
 622         mainSizer.Add((20,1), 0, wx.EXPAND, 0)
 623 
 624         #------------
 625 
 626         self.SetSizer(mainSizer)
 627         self.Layout()
 628 
 629 
 630     def OnLeftDown(self, event):
 631         """
 632         ...
 633         """
 634 
 635         self.GetTopLevelParent().OnLeftDown(event)
 636 
 637 
 638     def OnLeftUp(self, event):
 639         """
 640         ...
 641         """
 642 
 643         self.GetTopLevelParent().OnLeftUp(event)
 644 
 645 
 646     def SetLabel(self, label):
 647         """
 648         ...
 649         """
 650 
 651         self.label = label
 652         self.Refresh()
 653 
 654 
 655     def DoGetBestSize(self):
 656         """
 657         ...
 658         """
 659 
 660         dc = wx.ClientDC(self)
 661         dc.SetFont(self.GetFont())
 662 
 663         textWidth, textHeight = dc.GetTextExtent(self.label)
 664         spacing = 10
 665         totalWidth = textWidth + (spacing)
 666         totalHeight = textHeight + (spacing)
 667 
 668         best = wx.Size(totalWidth, totalHeight)
 669         self.CacheBestSize(best)
 670 
 671         return best
 672 
 673 
 674     def GetLabel(self):
 675         """
 676         ...
 677         """
 678 
 679         return self.label
 680 
 681 
 682     def GetLabelColor(self):
 683         """
 684         ...
 685         """
 686 
 687         return self.foreground
 688 
 689 
 690     def GetLabelSize(self):
 691         """
 692         ...
 693         """
 694 
 695         return self.size
 696 
 697 
 698     def SetLabelColour(self, colour):
 699         """
 700         ...
 701         """
 702 
 703         self.labelColour = colour
 704 
 705 
 706     def OnPaint(self, event):
 707         """
 708         ...
 709         """
 710 
 711         dc = wx.BufferedPaintDC(self)
 712         gcdc = wx.GCDC(dc)
 713 
 714         gcdc.Clear()
 715 
 716         # Setup the GraphicsContext.
 717         gc = gcdc.GetGraphicsContext()
 718 
 719         # Get the working size we can draw in.
 720         width, height = self.GetSize()
 721 
 722         # Use the GCDC to draw the text.
 723         brush = wx.WHITE
 724         gcdc.SetPen(wx.Pen(brush, 1))
 725         gcdc.SetBrush(wx.Brush(brush))
 726         gcdc.DrawRectangle(0, 0, width, height)
 727 
 728         # Get the system font.
 729         gcdc.SetFont(self.GetFont())
 730 
 731         textWidth, textHeight = gcdc.GetTextExtent(self.label)
 732         tposx, tposy = ((width/2)-(textWidth/2), (height/3)-(textHeight/3))
 733 
 734         tposx += 0
 735         tposy += 0
 736 
 737         # Set position and text color.
 738         if tposx <= 100:
 739             gcdc.SetTextForeground("white")
 740             gcdc.DrawText("", int(tposx), int(tposy+1))
 741 
 742             gcdc.SetTextForeground(self.labelColour)
 743             gcdc.DrawText("", int(tposx), int(tposy))
 744 
 745         else:
 746             gcdc.SetTextForeground("white")
 747             gcdc.DrawText(self.label, int(tposx), int(tposy+1))
 748 
 749             gcdc.SetTextForeground(self.labelColour)
 750             gcdc.DrawText(self.label, int(tposx), int(tposy))
 751 
 752 
 753     def OnRoll(self, event):
 754         """
 755         ...
 756         """
 757 
 758         self.GetTopLevelParent().OnRoll(True)
 759 
 760         print("Roll/unRoll button was clicked.")
 761 
 762 
 763     def OnIconfiy(self, event):
 764         """
 765         ...
 766         """
 767 
 768         self.GetTopLevelParent().OnIconfiy(self)
 769 
 770         print("Iconfiy button was clicked.")
 771 
 772 
 773     def OnFullScreen(self, event):
 774         """
 775         ...
 776         """
 777 
 778         self.GetTopLevelParent().OnFullScreen(self)
 779 
 780         print("FullScreen button was clicked.")
 781 
 782 
 783     def OnBtnClose(self, event):
 784         """
 785         ...
 786         """
 787 
 788         self.GetTopLevelParent().OnCloseWindow(self)
 789 
 790         print("Close button was clicked.")
 791 
 792 #---------------------------------------------------------------------------
 793 
 794 class MyAboutDlg(wx.Frame):
 795     """
 796     Thanks to Robin Dunn.
 797     """
 798     def __init__(self, parent):
 799         style = (wx.FRAME_SHAPED | wx.NO_BORDER |
 800                  wx.CLIP_CHILDREN | wx.STAY_ON_TOP |
 801                  wx.SYSTEM_MENU | wx.CLOSE_BOX |
 802                  wx.NO_FULL_REPAINT_ON_RESIZE)
 803         wx.Frame.__init__(self,
 804                           parent,
 805                           id=-1,
 806                           title="About...",
 807                           style=style)
 808 
 809         #------------
 810 
 811         # Attributes.
 812         self.SetTransparent(0)
 813         self.opacity_in = 0
 814         self.opacity_out = 255
 815         self.deltaN = -70
 816         self.hasShape = False
 817         self.delta = wx.Point(0,0)
 818 
 819         #------------
 820 
 821         # Return application name.
 822         self.app_name = wx.GetApp().GetAppName()
 823         # Return bitmaps folder.
 824         self.bitmaps_dir = wx.GetApp().GetBitmapsDir()
 825         # Return icons folder.
 826         self.icons_dir = wx.GetApp().GetIconsDir()
 827 
 828         #------------
 829 
 830         # Simplified init method.
 831         self.SetProperties()
 832         self.OnTimerIn(self)
 833         self.CreateCtrls()
 834         self.BindEvents()
 835 
 836         #------------
 837 
 838         self.CenterOnParent(wx.BOTH)
 839         self.GetParent().Enable(False)
 840 
 841         #------------
 842 
 843         self.Show(True)
 844 
 845         #------------
 846 
 847         self.eventLoop = wx.GUIEventLoop()
 848         self.eventLoop.Run()
 849 
 850     #-----------------------------------------------------------------------
 851 
 852     def SetProperties(self):
 853         """
 854         Set the dialog properties (title, icon, transparency...).
 855         """
 856 
 857         frameIcon = wx.Icon(os.path.join(self.icons_dir,
 858                                          "icon_wxWidgets.ico"),
 859                             type=wx.BITMAP_TYPE_ICO)
 860         self.SetIcon(frameIcon)
 861 
 862 
 863     def OnTimerIn(self, evt):
 864         """
 865         Thanks to Pascal Faut.
 866         """
 867 
 868         self.timer1 = wx.Timer(self, -1)
 869         self.timer1.Start(1)
 870         self.Bind(wx.EVT_TIMER, self.AlphaCycle1, self.timer1)
 871 
 872         print("Fade-in was launched.")
 873 
 874 
 875     def OnTimerOut(self, evt):
 876         """
 877         Thanks to Pascal Faut.
 878         """
 879 
 880         self.timer2 = wx.Timer(self, -1)
 881         self.timer2.Start(1)
 882         self.Bind(wx.EVT_TIMER, self.AlphaCycle2, self.timer2)
 883 
 884         print("Fade-out was launched.")
 885 
 886 
 887     def AlphaCycle1(self, *args):
 888         """
 889         Thanks to Pascal Faut.
 890         """
 891 
 892         self.opacity_in += self.deltaN
 893         if self.opacity_in <= 0:
 894             self.deltaN = -self.deltaN
 895             self.opacity_in = 0
 896 
 897         if self.opacity_in >= 255:
 898             self.deltaN = -self.deltaN
 899             self.opacity_in = 255
 900 
 901             self.timer1.Stop()
 902 
 903         self.SetTransparent(self.opacity_in)
 904 
 905         print("Fade in = {}/255".format(self.opacity_in))
 906 
 907 
 908     def AlphaCycle2(self, *args):
 909         """
 910         Thanks to Pascal Faut.
 911         """
 912 
 913         self.opacity_out += self.deltaN
 914         if self.opacity_out >= 255:
 915             self.deltaN = -self.deltaN
 916             self.opacity_out = 255
 917 
 918         if self.opacity_out <= 0:
 919             self.deltaN = -self.deltaN
 920             self.opacity_out = 0
 921 
 922             self.timer2.Stop()
 923 
 924             wx.CallAfter(self.Destroy)
 925 
 926         self.SetTransparent(self.opacity_out)
 927 
 928         print("Fade out = {}/255".format(self.opacity_out))
 929 
 930 
 931     def CreateCtrls(self):
 932         """
 933         Make widgets for my dialog.
 934         """
 935 
 936         # Load a background bitmap.
 937         self.bmp = wx.Bitmap(os.path.join(self.bitmaps_dir,
 938                                           "skin_about.png"),
 939                              type=wx.BITMAP_TYPE_PNG)
 940         mask = wx.Mask(self.bmp, wx.RED)
 941         self.bmp.SetMask(mask)
 942 
 943         #------------
 944 
 945         self.SetClientSize((self.bmp.GetWidth(), self.bmp.GetHeight()))
 946 
 947         #------------
 948 
 949         if wx.Platform == "__WXGTK__":
 950             # wxGTK requires that the window be created before you can
 951             # set its shape, so delay the call to SetWindowShape until
 952             # this event.
 953             self.Bind(wx.EVT_WINDOW_CREATE, self.SetWindowShape)
 954         else:
 955             # On wxMSW and wxMac the window has already
 956             # been created, so go for it.
 957             self.SetWindowShape()
 958 
 959 
 960     def BindEvents(self):
 961         """
 962         Bind all the events related to my dialog.
 963         """
 964 
 965         # Bind some events to an events handler.
 966         self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
 967         self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
 968         self.Bind(wx.EVT_RIGHT_UP, self.OnCloseWindow)  # Panel right clic.
 969         self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
 970         self.Bind(wx.EVT_WINDOW_CREATE, self.SetWindowShape)
 971         self.Bind(wx.EVT_MOTION, self.OnMouseMove)
 972         self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
 973         self.Bind(wx.EVT_PAINT, self.OnPaint)
 974         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
 975 
 976 
 977     def SetWindowShape(self, event=None):
 978         """
 979         ...
 980         """
 981 
 982         # Use the bitmap's mask to determine the region.
 983         r = wx.Region(self.bmp)
 984         self.hasShape = self.SetShape(r)
 985 
 986 
 987     def OnEraseBackground(self, event):
 988         """
 989         ...
 990         """
 991 
 992         dc = event.GetDC()
 993         if not dc:
 994             dc = wx.ClientDC(self)
 995             rect = self.GetUpdateRegion().GetBox()
 996             dc.SetClippingRect(rect)
 997 
 998 
 999     def OnLeftDown(self, event):
1000         """
1001         ...
1002         """
1003 
1004         self.CaptureMouse()
1005         x, y = self.ClientToScreen(event.GetPosition())
1006         originx, originy = self.GetPosition()
1007         dx = x - originx
1008         dy = y - originy
1009         self.delta = ((dx, dy))
1010 
1011 
1012     def OnLeftUp(self, evt):
1013         """
1014         ...
1015         """
1016 
1017         if self.HasCapture():
1018             self.ReleaseMouse()
1019 
1020 
1021     def OnMouseMove(self, event):
1022         """
1023         ...
1024         """
1025 
1026         if event.Dragging() and event.LeftIsDown():
1027             x, y = self.ClientToScreen(event.GetPosition())
1028             fp = (x - self.delta[0], y - self.delta[1])
1029             self.Move(fp)
1030 
1031 
1032     def OnPaint(self, event):
1033         """
1034         ...
1035         """
1036 
1037         dc = wx.AutoBufferedPaintDCFactory(self)
1038         dc.DrawBitmap(self.bmp, 0, 0, True)
1039 
1040         #------------
1041 
1042         # These are strings.
1043         py_version = sys.version.split()[0]
1044 
1045         str1 = (('<font style="normal" family="default" color="grey" size="10" weight="bold">'
1046                  'Programming : </font>'
1047                  '<font style="normal" family="default" color="black" size="10" weight="normal">'
1048                  'Python {}</font>').format(py_version))   # Python 3.7.2
1049 
1050         str2 = (('<font style="normal" family="default" color="red" size="10" weight="bold">'
1051                  'GUI toolkit : </font>'
1052                  '<font style="normal" family="default" color="black" size="10" weight="normal">'
1053                  'wxPython {}</font>').format(wx.VERSION_STRING))  # wxPython 4.0.4
1054 
1055         str3 = (('<font style="normal" family="default" color="brown" size="10" weight="bold">'
1056                  'Library : </font>'
1057                  '<font style="normal" family="default" color="black" size="10" weight="normal">'
1058                  '{}</font>').format(wx.GetLibraryVersionInfo().VersionString))   # wxWidgets 3.0.5
1059 
1060         str4 = (('<font style="normal" family="default" color="blue" size="10" weight="bold">'
1061                  'Operating system : </font>'
1062                  '<font style="normal" family="default" color="black" size="10" weight="normal">'
1063                  '{}</font>').format(platform.system()))   # Windows
1064 
1065         str5 = (('<font style="normal" family="default" color="gray" size="9" weight="normal">'
1066                  '{}</font>').format(self.app_name))   # Custom Gui 4
1067 
1068         str6 = (('<font style="normal" family="default" color="black" size="8" weight="normal">'
1069                  'Right clic or Esc for Exit</font>'))
1070 
1071         #------------
1072 
1073         # Return image size.
1074         bw, bh = self.bmp.GetWidth(), self.bmp.GetHeight()
1075 
1076         # Draw text.
1077         # Need width to calculate x position of str1.
1078         tw, th = fancytext.GetExtent(str1, dc)
1079         # Centered text.
1080         fancytext.RenderToDC(str1, dc, (bw-tw)/2, 30)
1081 
1082         #------------
1083 
1084         # Need width to calculate x position of str2.
1085         tw, th = fancytext.GetExtent(str2, dc)
1086         # Centered text.
1087         fancytext.RenderToDC(str2, dc, (bw-tw)/2, 50)
1088 
1089         #------------
1090 
1091         # Need width to calculate x position of str3.
1092         tw, th = fancytext.GetExtent(str3, dc)
1093         # Centered text.
1094         fancytext.RenderToDC(str3, dc, (bw-tw)/2, 70)
1095 
1096         #------------
1097 
1098         # Need width to calculate x position of str4.
1099         tw, th = fancytext.GetExtent(str4, dc)
1100         # Centered text.
1101         fancytext.RenderToDC(str4, dc, (bw-tw)/2, 90)
1102 
1103         #------------
1104 
1105         # Need width to calculate x position of str5.
1106         tw, th = fancytext.GetExtent(str5, dc)
1107         # Centered text.
1108         fancytext.RenderToDC(str5, dc, (bw-tw)/2, 130)
1109 
1110         #------------
1111 
1112         # Need width to calculate x position of str6.
1113         tw, th = fancytext.GetExtent(str6, dc)
1114         # Centered text.
1115         fancytext.RenderToDC(str6, dc, (bw-tw)/2, 195)
1116 
1117 
1118     def OnKeyUp(self, event):
1119         """
1120         ...
1121         """
1122 
1123         if event.GetKeyCode() == wx.WXK_ESCAPE:
1124             self.OnCloseWindow(event)
1125 
1126         event.Skip()
1127 
1128 
1129     def OnCloseWindow(self, event):
1130         """
1131         ...
1132         """
1133 
1134         self.GetParent().Enable(True)
1135         self.eventLoop.Exit()
1136         self.Destroy()
1137 
1138 #---------------------------------------------------------------------------
1139 
1140 class MyPopupMenu(wx.Menu):
1141     """
1142     Thanks to Robin Dunn.
1143     """
1144     def __init__(self, parent):
1145         wx.Menu.__init__(self)
1146 
1147         #------------
1148 
1149         # Attributes.
1150         self.parent = parent
1151 
1152         #------------
1153 
1154         # Returns bitmaps folder.
1155         self.bitmaps_dir = wx.GetApp().GetBitmapsDir()
1156 
1157         #------------
1158 
1159         # Simplified init method.
1160         self.CreatePopupMenu()
1161         self.BindEvents()
1162 
1163     #-----------------------------------------------------------------------
1164 
1165     def CreatePopupMenu(self, event=None):
1166         """
1167         This method is called by the base class when it needs to popup
1168         the menu for the default EVT_RIGHT_DOWN event.  Just create
1169         the menu how you want it and return it from this function,
1170         the base class takes care of the rest.
1171         """
1172 
1173         bmp = wx.Bitmap(os.path.join(self.bitmaps_dir,
1174                                      "item_about.png"),
1175                         type=wx.BITMAP_TYPE_PNG)
1176 
1177         item = wx.MenuItem(self, id=wx.ID_ABOUT, text=" About")
1178         item.SetBitmap(bmp)
1179         self.Append(item)
1180         self.AppendSeparator()
1181 
1182         #------------
1183 
1184         bmp = wx.Bitmap(os.path.join(self.bitmaps_dir,
1185                                      "item_exit.png"),
1186                         type=wx.BITMAP_TYPE_PNG)
1187 
1188         if True or "__WXMSW__" in wx.PlatformInfo:
1189             font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
1190             font.SetWeight(wx.BOLD)
1191 
1192         item = wx.MenuItem(self, id=wx.ID_EXIT, text=" Exit")
1193         item.SetBitmap(bmp)
1194         item.SetFont(font)
1195         self.Append(item)
1196 
1197         return self
1198 
1199 
1200     def BindEvents(self):
1201         """
1202         Bind some events to an events handler.
1203         """
1204 
1205         # Bind the menu events to an events handler.
1206         self.Bind(wx.EVT_MENU, self.OnAbout, id=wx.ID_ABOUT)
1207         self.Bind(wx.EVT_MENU, self.OnClose, id=wx.ID_EXIT)
1208 
1209 
1210     def OnAbout(self, event):
1211         """
1212         ...
1213         """
1214 
1215         self.mainFrame = wx.GetApp().GetTopWindow()
1216         self.mainFrame.OnAbout(self)
1217 
1218         print("About icon was clicked.")
1219 
1220 
1221     def OnClose(self, event):
1222         """
1223         ...
1224         """
1225 
1226         self.mainFrame = wx.GetApp().GetTopWindow()
1227         self.mainFrame.OnCloseWindow(self)
1228 
1229         print("Close icon was clicked.")
1230 
1231 #---------------------------------------------------------------------------
1232 
1233 class MyTitleBarPnl(wx.Panel):
1234     """
1235     Thanks to Cody Precord.
1236     """
1237     def __init__(self, parent, id, size):
1238         style = (wx.NO_BORDER)
1239         super(MyTitleBarPnl, self).__init__(parent,
1240                                             id,
1241                                             size=size,
1242                                             style=style)
1243 
1244         #------------
1245 
1246         # Attributes.
1247         self.parent = parent
1248 
1249         #------------
1250 
1251         # Return application name.
1252         self.app_name = wx.GetApp().GetAppName()
1253         # Return bitmaps folder.
1254         self.bitmaps_dir = wx.GetApp().GetBitmapsDir()
1255 
1256         #------------
1257 
1258         # Simplified init method.
1259         self.SetProperties()
1260         self.CreateCtrls()
1261         self.BindEvents()
1262 
1263     #-----------------------------------------------------------------------
1264 
1265     def SetProperties(self):
1266         """
1267         ...
1268         """
1269 
1270         self.SetBackgroundColour(wx.WHITE)
1271 
1272 
1273     def CreateCtrls(self):
1274         """
1275         ...
1276         """
1277 
1278         w, h = self.GetClientSize()
1279         print("MyTitleBarPnl :", self.GetClientSize())
1280 
1281         #------------
1282         #------------
1283 
1284         # Add titleBar.
1285         self.titleBar = MyTitleBar(self,
1286                                    label=self.app_name,
1287                                    size=10)
1288         self.titleBar.SetPosition((0, 0))
1289         self.titleBar.SetSize((w, 24))
1290         self.titleBar.SetLabelColour("black")
1291         self.titleBar.SetToolTip("This is a customized title bar.")
1292 
1293 
1294     def BindEvents(self):
1295         """
1296         Bind some events to an events handler.
1297         """
1298 
1299         self.Bind(wx.EVT_SIZE, self.OnResize)
1300 
1301 
1302     def OnResize(self, event):
1303         """
1304         ...
1305         """
1306 
1307         w, h = self.GetClientSize()
1308         print("MyTitleBarPnl :", self.GetClientSize())
1309 
1310         #------------
1311         #------------
1312 
1313         self.titleBar.SetSize((w, 24))
1314 
1315         #------------
1316 
1317         self.Refresh()
1318 
1319         print("On resize was clicked.")
1320 
1321 #---------------------------------------------------------------------------
1322 
1323 class MyMainPnl(wx.Panel):
1324     """
1325     ...
1326     """
1327     def __init__(self, parent, id, size):
1328         style = (wx.NO_BORDER | wx.TAB_TRAVERSAL)
1329         super(MyMainPnl, self).__init__(parent,
1330                                         id=int(ID_MAIN_PNL),
1331                                         size=size,
1332                                         style=style)
1333 
1334         #------------
1335 
1336         # Attributes.
1337         self.parent = parent
1338 
1339         #------------
1340 
1341         # Simplified init method.
1342         self.CreateCtrls()
1343         self.BindEvents()
1344         self.DoLayout()
1345 
1346     #-----------------------------------------------------------------------
1347 
1348     def CreateCtrls(self):
1349         """
1350         ...
1351         """
1352 
1353         w, h = self.GetClientSize()
1354         print("MyMainPnl :", self.GetClientSize())
1355 
1356         #------------
1357         #------------
1358 
1359         font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
1360         font.SetWeight(wx.BOLD)
1361 
1362         #------------
1363         #------------
1364 
1365         # Create data view control.
1366         self.list = MyListCtrlPnl(self)
1367 
1368         #------------
1369         #------------
1370 
1371         self.line = wx.StaticLine(self, -1,
1372                                   pos=(0, 70),
1373                                   size=(-1, -1),
1374                                   style=wx.LI_HORIZONTAL)
1375 
1376 
1377     def DoLayout(self):
1378         """
1379         ...
1380         """
1381 
1382         txtSizer = wx.BoxSizer(wx.VERTICAL)
1383 
1384         sizerList = wx.BoxSizer(wx.VERTICAL)
1385         sizerList.Add(self.list, 1,
1386                       wx.LEFT|wx.TOP|wx.BOTTOM|
1387                       wx.EXPAND|wx.ALIGN_TOP, 0)
1388 
1389         sizer = wx.BoxSizer(wx.VERTICAL)
1390         sizer.Add(txtSizer, 0, wx.BOTTOM, 15)
1391         sizer.Add(self.line, 0, wx.EXPAND|wx.ALL, 10)
1392 
1393         mainSizer = wx.BoxSizer(wx.HORIZONTAL)
1394         mainSizer.Add(sizerList, 1,
1395                       wx.LEFT|wx.TOP|wx.BOTTOM|wx.EXPAND, 0)
1396         mainSizer.Add(sizer, 0, wx.ALIGN_BOTTOM|wx.ALL, 0)
1397 
1398         self.SetSizer(mainSizer)
1399         self.Layout()
1400 
1401 
1402     def BindEvents(self):
1403         """
1404         Bind some events to an events handler.
1405         """
1406 
1407         self.Bind(wx.EVT_ENTER_WINDOW, self.OnInfo, id=ID_MAIN_PNL)
1408 
1409 
1410     def OnInfo(self, event):
1411         """
1412         ...
1413         """
1414 
1415         event_id = event.GetId()
1416 
1417         if event_id == ID_MAIN_PNL:
1418             self.GetParent().SetStatusText(text="Hello world !")
1419 
1420         else:
1421             # Tell the event system to continue
1422             # looking for an event handler, so the
1423             # default handler will get called.
1424             event.Skip()
1425 
1426 
1427     def OnAbout(self, event):
1428         """
1429         ...
1430         """
1431 
1432         self.GetParent().OnAbout(self)
1433 
1434         print("FullScreen button was clicked.")
1435 
1436 
1437     def OnFullScreen(self, event):
1438         """
1439         ...
1440         """
1441 
1442         self.GetParent().OnFullScreen(self)
1443 
1444         print("FullScreen button was clicked.")
1445 
1446 
1447     def OnBtnClose(self, event):
1448         """
1449         ...
1450         """
1451 
1452         self.GetParent().OnCloseWindow(self)
1453 
1454         print("Close button was clicked.")
1455 
1456 #---------------------------------------------------------------------------
1457 
1458 class MyFrame(wx.Frame):
1459     """
1460     Thanks to Robin Dunn.
1461     """
1462     def __init__(self):
1463         style = (wx.CLIP_CHILDREN | wx.CLOSE_BOX |
1464                  wx.MINIMIZE_BOX | wx.SYSTEM_MENU |
1465                  wx.RESIZE_BORDER | wx.NO_FULL_REPAINT_ON_RESIZE|
1466                  wx.STAY_ON_TOP)
1467         super(MyFrame, self).__init__(None,
1468                                       -1,
1469                                       title="",
1470                                       style=style)
1471 
1472         #------------
1473 
1474         wx.SystemOptions.SetOption("msw.remap", "0")
1475 
1476         #------------
1477 
1478         # Attributes.
1479         self.SetTransparent(0)
1480         self.opacity_in = 0
1481         self.opacity_out = 255
1482         self.deltaN = -70
1483         self.delta = wx.Point(0,0)
1484 
1485         #------------
1486 
1487         # Return application name.
1488         self.app_name = wx.GetApp().GetAppName()
1489         # Return bitmaps folder.
1490         self.bitmaps_dir = wx.GetApp().GetBitmapsDir()
1491         # Return icons folder.
1492         self.icons_dir = wx.GetApp().GetIconsDir()
1493 
1494         #------------
1495 
1496         # Simplified init method.
1497         self.SetProperties()
1498         self.OnTimerIn(self)
1499         self.AcceleratorTable()
1500         self.CreateStatusBar()
1501         self.CreateCtrls()
1502         self.BindEvents()
1503         self.DoLayout()
1504 
1505         #------------
1506 
1507         # Thanks to Ray Pasco.
1508         # Initialize to the current state.
1509         self.unrolledFrameClientSize_size = self.GetClientSize()
1510         self.isRolled = False
1511 
1512         #------------
1513 
1514         self.CenterOnScreen(wx.BOTH)
1515 
1516         #------------
1517 
1518         self.Show(True)
1519 
1520     #-----------------------------------------------------------------------
1521 
1522     def SetProperties(self):
1523         """
1524         ...
1525         """
1526 
1527         self.SetBackgroundColour(wx.Colour(wx.WHITE))
1528         self.SetTitle(self.app_name)
1529         self.SetClientSize((600, 380))
1530         self.SetMinSize((128, 60))
1531 
1532         #------------
1533 
1534         frameIcon = wx.Icon(os.path.join(self.icons_dir,
1535                                          "icon_wxWidgets.ico"),
1536                             type=wx.BITMAP_TYPE_ICO)
1537         self.SetIcon(frameIcon)
1538 
1539 
1540     def OnTimerIn(self, evt):
1541         """
1542         Thanks to Pascal Faut.
1543         """
1544 
1545         self.timer1 = wx.Timer(self, -1)
1546         self.timer1.Start(1)
1547         self.Bind(wx.EVT_TIMER, self.AlphaCycle1, self.timer1)
1548 
1549         print("Fade-in was launched.")
1550 
1551 
1552     def OnTimerOut(self, evt):
1553         """
1554         Thanks to Pascal Faut.
1555         """
1556 
1557         self.timer2 = wx.Timer(self, -1)
1558         self.timer2.Start(1)
1559         self.Bind(wx.EVT_TIMER, self.AlphaCycle2, self.timer2)
1560 
1561         print("Fade-out was launched.")
1562 
1563 
1564     def AlphaCycle1(self, *args):
1565         """
1566         Thanks to Pascal Faut.
1567         """
1568 
1569         self.opacity_in += self.deltaN
1570         if self.opacity_in <= 0:
1571             self.deltaN = -self.deltaN
1572             self.opacity_in = 0
1573 
1574         if self.opacity_in >= 255:
1575             self.deltaN = -self.deltaN
1576             self.opacity_in = 255
1577 
1578             self.timer1.Stop()
1579 
1580         self.SetTransparent(self.opacity_in)
1581 
1582         print("Fade in = {}/255".format(self.opacity_in))
1583 
1584 
1585     def AlphaCycle2(self, *args):
1586         """
1587         Thanks to Pascal Faut.
1588         """
1589 
1590         self.opacity_out += self.deltaN
1591         if self.opacity_out >= 255:
1592             self.deltaN = -self.deltaN
1593             self.opacity_out = 255
1594 
1595         if self.opacity_out <= 0:
1596             self.deltaN = -self.deltaN
1597             self.opacity_out = 0
1598 
1599             self.timer2.Stop()
1600             wx.CallAfter(self.Destroy)
1601             wx.Exit()
1602 
1603         self.SetTransparent(self.opacity_out)
1604 
1605         print("Fade out = {}/255".format(self.opacity_out))
1606 
1607 
1608     def AcceleratorTable(self):
1609         """
1610         ...
1611         """
1612 
1613         table = wx.AcceleratorTable([(wx.ACCEL_CTRL,  ord('F'), ID_FULLSCREEN),
1614                                      (wx.ACCEL_CTRL, ord('Q'), wx.ID_EXIT),
1615                                      (wx.ACCEL_CTRL, ord('A'), wx.ID_ABOUT),
1616                                      ])
1617         self.SetAcceleratorTable(table)
1618 
1619 
1620     def CreateStatusBar(self):
1621         """
1622         ...
1623         """
1624 
1625         self.sb = MyStatusBar(self, -1)
1626         self.sb.SetBackgroundColour(wx.Colour(wx.WHITE))
1627         self.sb.SetStatusText("Hello world !")
1628 
1629         self.SetStatusBar(self.sb)
1630 
1631 
1632     def CreateCtrls(self):
1633         """
1634         ...
1635         """
1636 
1637         w, h = self.GetClientSize()
1638         print("MyFrame :", self.GetClientSize())
1639 
1640         #------------
1641         #------------
1642 
1643         self.titleBarPnl = MyTitleBarPnl(self, -1, (w, 24))
1644         self.titleBarPnl.SetPosition((0, 0))
1645         print("self.titleBarPnl :", self.titleBarPnl.GetSize())
1646 
1647         #------------
1648 
1649         # self.line = wx.StaticLine(self, -1,
1650         #                          pos=(0, 70),
1651         #                          size=(-1, -1),
1652         #                          style=wx.LI_HORIZONTAL)
1653 
1654         #------------
1655 
1656         self.mainPnl = MyMainPnl(self, -1, (w, h-25))
1657         self.mainPnl.SetPosition((0, 25))
1658         print("self.mainPnl :", self.mainPnl.GetSize())
1659 
1660 
1661     def BindEvents(self):
1662         """
1663         ...
1664         """
1665 
1666         self.titleBarPnl.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
1667 
1668         self.Bind(wx.EVT_SIZE, self.OnResize)
1669         self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
1670         self.Bind(wx.EVT_MOTION, self.OnMouseMove)
1671         self.Bind(wx.EVT_CHAR_HOOK, self.OnKeyUp)
1672         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
1673 
1674         self.Bind(wx.EVT_MENU, self.OnFullScreen, id=ID_FULLSCREEN)
1675         self.Bind(wx.EVT_MENU, self.OnAbout, id=wx.ID_ABOUT)
1676         self.Bind(wx.EVT_MENU, self.OnCloseWindow, id=wx.ID_EXIT)
1677 
1678 
1679     def DoLayout(self):
1680         """
1681         ...
1682         """
1683 
1684         # MainSizer is the top-level one that manages everything.
1685         mainSizer = wx.BoxSizer(wx.VERTICAL)
1686 
1687         mainSizer.Add(self.titleBarPnl, 1, wx.EXPAND, 0)
1688         # mainSizer.Add(self.line, 0, wx.EXPAND, 0)
1689         mainSizer.Add(self.mainPnl, 1, wx.EXPAND, 0)
1690 
1691         # Finally, tell the panel to use the sizer for layout.
1692         self.SetSizer(mainSizer)
1693         self.Layout()
1694 
1695 
1696     def OnRoll(self, event) :
1697         """
1698         Thanks to Ray Pasco.
1699         """
1700 
1701         if not bool(self.isRolled) :
1702         # Set the flag to the state we want regardless of whether
1703         # or not it's in currently in the opposite state.
1704            self.RollUnRoll(wantToRoll=True)
1705 
1706         elif self.isRolled :   # UnRoll.
1707            # Set the flag to the state we want regardless of whether
1708            # or not it's in currently in the opposite state.
1709            self.RollUnRoll(wantToRoll=False)
1710 
1711         print("OnRoll :", self.GetClientSize())
1712 
1713 
1714     def RollUnRoll(self, wantToRoll) :
1715         """
1716         Thanks to Ray Pasco.
1717         """
1718 
1719         # Save the current size only if the Frame is not rolled up.
1720         if not bool(self.isRolled) :
1721             self.unrolledFrameClientSize_size = self.GetClientSize()
1722 
1723         if bool(wantToRoll) :   # UnRoll.
1724             # Set size (25).
1725             self.SetClientSize((self.unrolledFrameClientSize_size[0], 25))
1726             # Set to match this new state.
1727             self.isRolled = True
1728 
1729         else :   # Roll
1730             self.SetClientSize(self.unrolledFrameClientSize_size)
1731             # Set to match this new state.
1732             self.isRolled = False
1733 
1734         print("RollUnRoll :", self.GetClientSize())
1735 
1736 
1737     def OnAbout(self, event):
1738         """
1739         ...
1740         """
1741 
1742         self.dialog = MyAboutDlg(self)
1743 
1744 
1745     def OnLeftDown(self, event):
1746         """
1747         ...
1748         """
1749 
1750         self.CaptureMouse()
1751         x, y = self.ClientToScreen(event.GetPosition())
1752         originx, originy = self.GetPosition()
1753         dx = x - originx
1754         dy = y - originy
1755         self.delta = ((dx, dy))
1756 
1757 
1758     def OnLeftUp(self, evt):
1759         """
1760         ...
1761         """
1762 
1763         if self.HasCapture():
1764             self.ReleaseMouse()
1765 
1766 
1767     def OnMouseMove(self, event):
1768         """
1769         ...
1770         """
1771 
1772         if event.Dragging() and event.LeftIsDown():
1773             x, y = self.ClientToScreen(event.GetPosition())
1774             fp = (x - self.delta[0], y - self.delta[1])
1775             self.Move(fp)
1776 
1777 
1778     def OnIconfiy(self, event):
1779         """
1780         ...
1781         """
1782 
1783         self.Iconize()
1784 
1785 
1786     def OnResize(self, event):
1787         """
1788         ...
1789         """
1790 
1791         w, h = self.GetClientSize()
1792         print("self :", self.GetClientSize())
1793 
1794         #------------
1795         #------------
1796 
1797         self.titleBarPnl.SetSize((w, 24))
1798         # self.line.SetSize((w, -1))
1799         self.mainPnl.SetSize((w, h-25))   # 25
1800 
1801         #------------
1802 
1803         self.Refresh()
1804 
1805 
1806     def OnFullScreen(self, event):
1807         """
1808         ...
1809         """
1810 
1811         self.ShowFullScreen(not self.IsFullScreen(),
1812                             wx.FULLSCREEN_NOCAPTION)
1813 
1814 
1815     def OnKeyUp(self, event):
1816         """
1817         ...
1818         """
1819 
1820         if event.GetKeyCode() == wx.WXK_ESCAPE:
1821             # Close the frame, no action.
1822             self.OnCloseWindow(event)
1823             sys.exit()
1824         event.Skip()
1825 
1826 
1827     def OnBtnClose(self, event):
1828         """
1829         ...
1830         """
1831 
1832         self.Close()
1833 
1834 
1835     def OnCloseWindow(self, event):
1836         """
1837         Quit this application.
1838         """
1839 
1840         # self.Destroy()
1841         self.OnTimerOut(self)
1842 
1843         print("Exit application.")
1844 
1845 #---------------------------------------------------------------------------
1846 
1847 class MyApp(wx.App):
1848     """
1849     Thanks to Andrea Gavana.
1850     """
1851     def OnInit(self):
1852 
1853         #------------
1854 
1855         self.locale = wx.Locale(wx.LANGUAGE_ENGLISH)
1856 
1857         #------------
1858 
1859         self.SetAppName("Custom Gui 1")
1860 
1861         #------------
1862 
1863         self.installDir = os.path.split(os.path.abspath(sys.argv[0]))[0]
1864 
1865         #------------
1866 
1867         frame = MyFrame()
1868         self.SetTopWindow(frame)
1869         frame.Show(True)
1870 
1871         return True
1872 
1873     #-----------------------------------------------------------------------
1874 
1875     def GetInstallDir(self):
1876         """
1877         Returns the installation directory for my application.
1878         """
1879 
1880         return self.installDir
1881 
1882 
1883     def GetIconsDir(self):
1884         """
1885         Returns the icons directory for my application.
1886         """
1887 
1888         icons_dir = os.path.join(self.installDir, "icons")
1889         return icons_dir
1890 
1891 
1892     def GetBitmapsDir(self):
1893         """
1894         Returns the bitmaps directory for my application.
1895         """
1896 
1897         bitmaps_dir = os.path.join(self.installDir, "bitmaps")
1898         return bitmaps_dir
1899 
1900 #---------------------------------------------------------------------------
1901 
1902 def main():
1903     app = MyApp(False)
1904     app.MainLoop()
1905 
1906 #---------------------------------------------------------------------------
1907 
1908 if __name__ == "__main__" :
1909     main()


Download source

source.zip


Additional Information

Link :

https://hasenj.wordpress.com/2009/04/14/making-a-fancy-window-in-wxpython/

https://fooobar.com/questions/15910813/wxpython-change-the-headers-color

https://stackoverflow.com/questions/17479254/panel-doesnt-fully-refresh-when-using-a-custom-background-in-wxpython

https://stackoverflow.com/questions/12087140/custom-window-frame-and-window-appearance-with-wxpython

https://github.com/Metallicow/MCOW

https://github.com/Eseeme/wxpython-custom-button

- - - - -

https://wiki.wxpython.org/TitleIndex

https://docs.wxpython.org/


Thanks to

Robin Dunn, Cody Precord, Andrea Gavana, Metallicow, Mike Driscoll, Ray Pasco, Pascal Faut., Vegaseat (DaniWeb), Jan Bodnar (ZetCode), Alain Delgrange, ActiveState, the wxPython community...

Thanks also to all known contributors or anonymous that I forgot.

And finally, congratulations to the many forums and blogs for all the available examples and the help which is the strength of wxPython. ;)


About this page

Date (d/m/y) Person (bot) Comments :

08/05/21 - Ecco (Created page for wxPython Phoenix).

08/08/22 - Ecco (Updated for Python 3.10.5).


Comments

- blah, blah, blah....

How to add a menu bar in the title bar (Phoenix) (last edited 2022-08-08 18:13:00 by Ecco)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.