Repository navigation
[Suggestion] Python.NET/WinForms example "winformsvlc.py" (for the examples folder) #306
Copy link
Copy link
Closed
Description
As equivalent to my Windows API example, below another example for the examples folder that instead uses Python.NET and Windows Forms as GUI toolkit. It's again a 1:1 port of the existing PyQt5 example. Attached screenshot shows it running in Windows 11.
Example winformsvlc.py
"""
A simple example for VLC python bindings using Python.NET and Windows Forms.
Author: https://github.com/59de44955ebd, Berlin
Date: 26.08.2026
Python.NET (https://pypi.org/project/pythonnet/) can be installed with pip:
pip install pythonnet
"""
import clr
import System
clr.AddReference('System.Windows.Forms')
from System.Threading import Thread, ThreadStart, ApartmentState
import System.Windows.Forms as WinForms
from System.Drawing import Color, Size
import vlc
class Main(WinForms.Form):
def __init__(self):
super().__init__()
self.Text = "Media Player"
self.Size = Size(640, 480)
self.StartPosition = WinForms.FormStartPosition.CenterScreen
# Create a basic vlc instance
self.instance = vlc.Instance(["--quiet", "--no-osd"])
self.media = None
# Create an empty vlc media player
self.mediaplayer = self.instance.media_player_new()
self.initialize_component()
self.is_paused = False
# The media player has to be "connected" to our VideoFrame
self.mediaplayer.set_hwnd(self.video_frame.Handle.ToInt32())
self.timer = WinForms.Timer()
self.timer.Interval = 100
self.timer.Tick += self.update_ui
def initialize_component(self):
self.SuspendLayout()
self.Menu = WinForms.MainMenu()
m = WinForms.MenuItem('&File')
self.Menu.MenuItems.Add(m)
action_item = WinForms.MenuItem('&Load Video')
action_item.Shortcut = WinForms.Shortcut.CtrlO
action_item.Click += self.open_file
m.MenuItems.Add(action_item)
m.MenuItems.Add(WinForms.MenuItem('-'))
action_item = WinForms.MenuItem('&Close App')
action_item.Click += self.quit
m.MenuItems.Add(action_item)
self.panel1 = WinForms.Panel()
self.Controls.Add(self.panel1)
self.panel1.Dock = WinForms.DockStyle.Fill
self.video_frame = WinForms.UserControl()
self.video_frame.BackColor = Color.Black
self.video_frame.Dock = WinForms.DockStyle.Fill
self.panel1.Controls.Add(self.video_frame)
self.panel2 = WinForms.TableLayoutPanel()
self.panel2.Padding = WinForms.Padding(7, 0, 7, 0)
self.panel2.Height = 70
self.panel2.Dock = WinForms.DockStyle.Bottom
self.panel2.ColumnCount = 3
self.panel2.RowCount = 2
self.Controls.Add(self.panel2)
self.trackbar_position = WinForms.TrackBar()
self.trackbar_position.Maximum = 2000
self.trackbar_position.Dock = WinForms.DockStyle.Bottom
self.trackbar_position.AutoSize = False
self.trackbar_position.Height = 30
self.trackbar_position.TickStyle = getattr(WinForms.TickStyle, 'None')
self.trackbar_position.Anchor = WinForms.AnchorStyles.Left | WinForms.AnchorStyles.Top | WinForms.AnchorStyles.Right
self.trackbar_position.Enabled = False
self.panel2.Controls.Add(self.trackbar_position, 0, 0)
self.panel2.SetColumnSpan(self.trackbar_position, 3)
self.trackbar_position.Scroll += lambda sender, args: self.set_position(self.trackbar_position.Value)
def _on_click(sender, args):
w = self.trackbar_position.Width - 28
x = args.X - 14
pos = max(0, min(2000, int(x / w * 2000)))
self.trackbar_position.Value = pos
self.set_position(pos)
self.trackbar_position.MouseDown += _on_click
self.button_play = WinForms.Button()
self.button_play.Text = "Play"
self.button_play.Anchor = WinForms.AnchorStyles.Left | WinForms.AnchorStyles.Top
self.panel2.Controls.Add(self.button_play, 0, 1)
self.button_play.Click += self.play_pause
self.button_stop = WinForms.Button()
self.button_stop.Text = "Stop"
self.button_stop.Anchor = WinForms.AnchorStyles.Left | WinForms.AnchorStyles.Top
self.panel2.Controls.Add(self.button_stop, 1, 1)
self.button_stop.Click += self.stop
self.trackbar_volume = WinForms.TrackBar()
self.trackbar_volume.Maximum = 100
self.trackbar_volume.Anchor = WinForms.AnchorStyles.Right | WinForms.AnchorStyles.Top
self.trackbar_volume.AutoSize = False
self.trackbar_volume.Height = 20
self.trackbar_volume.TickStyle = getattr(WinForms.TickStyle, 'None')
self.trackbar_volume.Value = self.mediaplayer.audio_get_volume()
self.panel2.Controls.Add(self.trackbar_volume, 2, 1)
self.trackbar_volume.Scroll += lambda *_: self.set_volume(self.trackbar_volume.Value)
def _on_click(sender, args):
w = self.trackbar_volume.Width - 28
x = args.X - 14
pos = max(0, min(100, int(x / w * 100)))
self.trackbar_volume.Value = pos
self.set_volume(pos)
self.trackbar_volume.MouseDown += _on_click
self.ResumeLayout(False)
self.PerformLayout()
def open_file(self, *_):
ofd = WinForms.OpenFileDialog()
ofd.Filter = "All Files (*.*)|*.*"
ofd.RestoreDirectory = True
if ofd.ShowDialog() != WinForms.DialogResult.OK:
return
self.media = self.instance.media_new(ofd.FileName)
# Put the media in the media player
self.mediaplayer.set_media(self.media)
# Parse the metadata of the file
self.media.parse()
# Set the title of the track as window title
self.Text = self.media.get_meta(0)
self.play_pause()
def play_pause(self, *_):
"""Toggle play/pause status"""
if self.mediaplayer.is_playing():
self.mediaplayer.pause()
self.button_play.Text = "Play"
self.is_paused = True
self.timer.Stop()
else:
if self.mediaplayer.play() == -1:
self.open_file()
return
self.mediaplayer.play()
self.button_play.Text = "Pause"
self.is_paused = False
self.timer.Start()
self.trackbar_position.Enabled = True
def stop(self, *_):
"""Stop player"""
self.mediaplayer.stop()
self.button_play.Text = "Play"
self.trackbar_position.Enabled = False
def quit(self, *_):
WinForms.Application.Exit()
def set_volume(self, volume):
"""Set the volume"""
self.mediaplayer.audio_set_volume(volume)
def set_position(self, pos):
"""Set the movie position according to the position slider"""
# Set the media position to where the slider was dragged
self.timer.Stop()
self.mediaplayer.set_position(pos / 2000.0)
self.timer.Start()
def update_ui(self, *_):
"""Update the user interface"""
# Set the slider"s position to its corresponding media position
self.trackbar_position.Value = min(2000, max(0, int(self.mediaplayer.get_position() * 2000)))
# No need for a timer if nothing is played
if not self.mediaplayer.is_playing():
self.timer.Stop()
# After the video finished, the play button stills shows "Pause",
# which is not the desired behavior of a media player.
# This fixes that "bug".
if not self.is_paused:
self.stop()
def app_thread():
app = Main()
WinForms.Application.Run(app)
app.Dispose()
if __name__ == '__main__':
thread = Thread(ThreadStart(app_thread))
thread.SetApartmentState(ApartmentState.STA)
thread.Start()
thread.Join()Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
mrJean1 commentedon Aug 26, 2026
Another nice example! Please add comment where to get
Python.NETfrom, likepython -m pip install pythonnetif that's it.59de44955ebd commentedon Aug 27, 2026
Yes, it's
pip install pythonnetresp.python -m pip install pythonnet. I will add this to the script's header comments.mrJean1 commentedon Aug 29, 2026
One comment. Clicking the
Stopbutton results in an exception ..."Value -2000 ... should be between Minimum and Maximum".Adding
max(0, ...)in this line inupdate_uiavoids the exception (caused bymedia_player.get_positionreturning -1).59de44955ebd commentedon Aug 29, 2026
Thank you! I have no idea why I missed this, I'm sure I tested the Stop button before... . But anyway, I fixed it in the code above. Thanks again.
oaubert commentedon Sep 2, 2026
Thanks for the contribution. I could add the files myself, but can you rather do a pull request creating this file in the examples directory, so that the git history properly keeps reference of authorship? You can do a single pull request for both winapivlc and winformsvlc.
oaubert commentedon Sep 10, 2026
Closed by #307