[vlc-commits] python: fix tkvlc.py example on macos

kimwiktoren git at videolan.org
Thu May 7 19:33:16 CEST 2020


vlc/python | branch: master | kimwiktoren <39512578+kimwiktoren at users.noreply.github.com> | Thu May  7 19:30:06 2020 +0200| [d2f435586a5e1cfaabd52c70ee55c80428cc59f9] | committer: GitHub

python: fix tkvlc.py example on macos

TopLevel window to hold the buttons panel. (#135)

* TopLevel window to hold the buttons panel.

Workaround as MacOS draws the video over the whole app including the buttons. Dividing the app into two
seperate windows makes the app work as intended even on MacOS as the buttons stays visible.

* sys.exit(0) displayed an error or warning when top level was used.

* Buttons panel width resizes w.r.t video panel width.

* Follow string format standards for 2.7 compatibility.

* Activate AnchorButtonsPanel only on MacOS.

* Buttons panel has anchor deactivated if dragged once.

> http://git.videolan.org/gitweb.cgi/vlc/python.git/?a=commit;h=d2f435586a5e1cfaabd52c70ee55c80428cc59f9
---

 examples/tkvlc.py | 61 +++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 52 insertions(+), 9 deletions(-)

diff --git a/examples/tkvlc.py b/examples/tkvlc.py
index 21a877b..9984138 100755
--- a/examples/tkvlc.py
+++ b/examples/tkvlc.py
@@ -19,9 +19,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 #
 """A simple example for VLC python bindings using tkinter.
-
 Requires Python 3.4 or later.
-
 Author: Patrick Fay
 Date: 23-09-2015
 """
@@ -90,7 +88,6 @@ else:  # *nix, Xwindows and Windows, UNTESTED
 
 class _Tk_Menu(Tk.Menu):
     '''Tk.Menu extended with .add_shortcut method.
-
        Note, this is a kludge just to get Command-key shortcuts to
        work on macOS.  Other modifiers like Ctrl-, Shift- and Option-
        are not handled in this code.
@@ -100,7 +97,6 @@ class _Tk_Menu(Tk.Menu):
 
     def add_shortcut(self, label='', key='', command=None, **kwds):
         '''Like Tk.menu.add_command extended with shortcut key.
-
            If needed use modifiers like Shift- and Alt_ or Option-
            as before the shortcut key character.  Do not include
            the Command- or Control- modifier nor the <...> brackets
@@ -200,13 +196,18 @@ class Player(Tk.Frame):
         self.muteIndex = fileMenu.index("Mute")
 
         # first, top panel shows video
+
         self.videopanel = ttk.Frame(self.parent)
         self.canvas = Tk.Canvas(self.videopanel)
         self.canvas.pack(fill=Tk.BOTH, expand=1)
         self.videopanel.pack(fill=Tk.BOTH, expand=1)
 
         # panel to hold buttons
-        buttons = ttk.Frame(self.parent)
+        self.buttons_panel = Tk.Toplevel(self.parent)
+        self.buttons_panel.title("")
+        self.is_buttons_panel_anchor_active = False
+
+        buttons = ttk.Frame(self.buttons_panel)
         self.playButton = ttk.Button(buttons, text="Play", command=self.OnPlay)
         stop            = ttk.Button(buttons, text="Stop", command=self.OnStop)
         self.muteButton = ttk.Button(buttons, text="Mute", command=self.OnMute)
@@ -219,11 +220,12 @@ class Player(Tk.Frame):
         self.volSlider = Tk.Scale(buttons, variable=self.volVar, command=self.OnVolume,
                                   from_=0, to=100, orient=Tk.HORIZONTAL, length=200,
                                   showvalue=0, label='Volume')
-        self.volSlider.pack(side=Tk.LEFT)
-        buttons.pack(side=Tk.BOTTOM)
+        self.volSlider.pack(side=Tk.RIGHT)
+        buttons.pack(side=Tk.BOTTOM, fill=Tk.X)
+
 
         # panel to hold player time slider
-        timers = ttk.Frame(self.parent)
+        timers = ttk.Frame(self.buttons_panel)
         self.timeVar = Tk.DoubleVar()
         self.timeSliderLast = 0
         self.timeSlider = Tk.Scale(timers, variable=self.timeVar, command=self.OnTime,
@@ -233,6 +235,7 @@ class Player(Tk.Frame):
         self.timeSliderUpdate = time.time()
         timers.pack(side=Tk.BOTTOM, fill=Tk.X)
 
+
         # VLC player
         args = []
         if _isLinux:
@@ -243,6 +246,26 @@ class Player(Tk.Frame):
         self.parent.bind("<Configure>", self.OnConfigure)  # catch window resize, etc.
         self.parent.update()
 
+        # After parent.update() otherwise panel is ignored.
+        self.buttons_panel.overrideredirect(True)
+
+        # Estetic, to keep our video panel at least as wide as our buttons panel.
+        self.parent.minsize(width=502, height=0)
+
+        if _isMacOS:
+            # Only tested on MacOS so far. Enable for other OS after verified tests.
+            self.is_buttons_panel_anchor_active = True
+
+            # Detect dragging of the buttons panel.
+            self.buttons_panel.bind("<Button-1>", lambda event: setattr(self, "has_clicked_on_buttons_panel", event.y < 0))
+            self.buttons_panel.bind("<B1-Motion>", self._DetectButtonsPanelDragging)
+            self.buttons_panel.bind("<ButtonRelease-1>", lambda _: setattr(self, "has_clicked_on_buttons_panel", False))
+            self.has_clicked_on_buttons_panel = False
+        else:
+            self.is_buttons_panel_anchor_active = False
+
+        self._AnchorButtonsPanel()
+
         self.OnTick()  # set the timer up
 
     def OnClose(self, *unused):
@@ -252,7 +275,24 @@ class Player(Tk.Frame):
         self.parent.quit()  # stops mainloop
         self.parent.destroy()  # this is necessary on Windows to avoid
         # ... Fatal Python Error: PyEval_RestoreThread: NULL tstate
-        sys.exit(0)
+
+    def _DetectButtonsPanelDragging(self, _):
+        """If our last click was on the boarder
+           we disable the anchor.
+        """
+        if self.has_clicked_on_buttons_panel:
+            self.is_buttons_panel_anchor_active = False
+            self.buttons_panel.unbind("<Button-1>")
+            self.buttons_panel.unbind("<B1-Motion>")
+            self.buttons_panel.unbind("<ButtonRelease-1>")
+
+    def _AnchorButtonsPanel(self):
+        video_height = self.parent.winfo_height()
+        panel_x = self.parent.winfo_x()
+        panel_y = self.parent.winfo_y() + video_height + 23 # 23 seems to put the panel just below our video.
+        panel_height = self.buttons_panel.winfo_height()
+        panel_width = self.parent.winfo_width()
+        self.buttons_panel.geometry("%sx%s+%s+%s" % (panel_width, panel_height, panel_x, panel_y))
 
     def OnConfigure(self, *unused):
         """Some widget configuration changed.
@@ -260,6 +300,9 @@ class Player(Tk.Frame):
         # <https://www.Tcl.Tk/man/tcl8.6/TkCmd/bind.htm#M12>
         self._geometry = ''  # force .OnResize in .OnTick, recursive?
 
+        if self.is_buttons_panel_anchor_active:
+            self._AnchorButtonsPanel()
+
     def OnFullScreen(self, *unused):
         """Toggle full screen, macOS only.
         """



More information about the vlc-commits mailing list