I am using VLC in Python to open a video stream (UDP stream).
How can I set the dimensions of the video window and its position on the screen
This is the code
import vlc
i = vlc.Instance()
p = i.media_player_new()
p.set_mrl('udp://#224.1.1.1:1234')
p.play()
In short I don't think that you can, unless your provide it with a window to play in, that you control.
This involves wrapping it within a gui, many people use Tkinter, wxPython or Qt for this. Below are samples written on Linux.
Here is a wxPython sample:
import vlc
import wx
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Video Frame WxPython", size=(500,400))
self.panel = wx.Panel(self, id= -1, pos=(10,10), size=(470,300))
self.play_button = wx.Button(self, -1, "Play", pos=(10,320))
self.stop_button = wx.Button(self, -1, "Pause", pos=(100,320))
self.Bind(wx.EVT_BUTTON, self.play, self.play_button)
self.Bind(wx.EVT_BUTTON, self.stop, self.stop_button)
self.panel.SetBackgroundColour(wx.BLACK)
self.Show()
def play(self,event):
vlc_options = '--no-xlib --quiet'
inst = vlc.Instance(vlc_options)
self.player = inst.media_player_new()
self.player.set_mrl('file:///home/rolf/BBB.ogv')
xid = self.panel.GetHandle()
self.player.set_xwindow(xid)
self.player.play()
def stop(self,event):
try:
self.player.pause()
except:
pass
app = wx.App()
frame = MyFrame()
app.MainLoop()
This is a Tkinter version (forgive any quirks, I don't use Tkinter myself):
import tkinter as tk
import vlc
class myframe(tk.Frame):
def __init__(self, root, width=500, height=400, bd=5):
super(myframe, self).__init__(root)
self.grid()
self.frame = tk.Frame(self, width=450, height=350, bd=5)
self.frame.configure(bg="black")
self.frame.grid(row=0, column=0, columnspan=2, padx=8)
self.play_button = tk.Button(self, text = 'Play', command = self.play)
self.play_button.grid(row=1, column=0, columnspan=1, padx=8)
self.stop_button = tk.Button(self, text = 'Pause', command = self.pause)
self.stop_button.grid(row=1, column=1, columnspan=1, padx=8)
def play(self):
i = vlc.Instance('--no-xlib --quiet')
self.player = i.media_player_new()
self.player.set_mrl('file:///home/rolf/BBB.ogv')
xid = self.frame.winfo_id()
self.player.set_xwindow(xid)
self.player.play()
def pause(self):
try:
self.player.pause()
except:
pass
if __name__ == '__main__':
root = tk.Tk()
root.title("Video Frame Tkinter")
app = myframe(root)
root.mainloop()
This is how they look on the screen:
Related
When I run the app, the run button is still responsive for a few seconds before the entire app freezes but the thread continues running. Where is the problem in my code and how do fix it?
import threading
from tkinter import *
from tkinter import ttk
class SubExtractor:
def __init__(self, root):
self.root = root
self._create_layout()
def _create_layout(self):
self.root.title("Sub Extractor")
self._menu_bar()
self.main_frame = ttk.Frame(self.root, padding=(5, 5, 5, 15))
self._video_frame()
self._progress_frame()
self._output_frame()
self.main_frame.grid()
def _menu_bar(self):
self.root.option_add('*tearOff', FALSE)
menubar = Menu(self.root)
self.root.config(menu=menubar)
menu_file = Menu(menubar)
menu_settings = Menu(menubar)
menubar.add_cascade(menu=menu_file, label="File")
menubar.add_cascade(menu=menu_settings, label="Settings")
menu_file.add_command(label="Open", command=self._open_file)
menu_file.add_command(label="Close", command=self._close_window)
menu_settings.add_command(label="Language", command=self._language_settings)
menu_settings.add_command(label="Extraction", command=self._extraction_settings)
def _video_frame(self):
video_frame = ttk.Frame(self.main_frame, borderwidth=2, relief="ridge", width=1000, height=600)
video_frame.grid()
def _progress_frame(self):
progress_frame = ttk.Frame(self.main_frame)
progress_frame.grid(row=1, sticky="W")
self.run_button = ttk.Button(progress_frame, text="Run", command=self._run)
self.run_button.grid(pady=10, padx=30)
self.progress_bar = ttk.Progressbar(progress_frame, orient=HORIZONTAL, length=800, mode='determinate')
self.progress_bar.grid(column=2, row=0)
def _output_frame(self):
output_frame = ttk.Frame(self.main_frame)
output_frame.grid(row=2)
self.text_output_widget = Text(output_frame, width=97, height=12, state="disabled")
self.text_output_widget.grid()
output_scroll = ttk.Scrollbar(output_frame, orient=VERTICAL, command=self.text_output_widget.yview)
output_scroll.grid(column=1, row=0, sticky="N,S")
self.text_output_widget.configure(yscrollcommand=output_scroll.set)
def _close_window(self):
self._stop_run()
self.root.quit()
def _stop_run(self):
self.interrupt = True
self.run_button.configure(text="Run", command=self._run)
def _text_to_output(self, text):
self.text_output_widget.configure(state="normal")
self.text_output_widget.insert("end", f"{text}\n")
self.text_output_widget.see("end")
self.text_output_widget.configure(state="disabled")
def long_running_method(self):
num = 100000
self.progress_bar.configure(maximum=num)
for i in range(0, num):
if self.interrupt:
break
self._text_to_output(f"Line {i} of {num}")
self.progress_bar['value'] += 1
self._stop_run()
def _run(self):
self.interrupt = False
self.run_button.configure(text='Stop', command=self._stop_run)
threading.Thread(target=self.long_running_method).start()
rt = Tk()
SubtitleExtractorGUI(rt)
rt.mainloop()
What I expect to accomplish is for the loop to insert texts in the text widget while I can still freely move and use other buttons on the app.
I'm doing a little "Supplementshop" with python 3.7.2 and tkinter. I want to use a "go back to the main window"-button. Because I'm creating new windows through buttons and functions, I think I can't use the .destroy method... After one full day of testing some codes I still did not managed to get this button. I guess, I need now some help. :D
Because the code is about 600 lines already, I just did a short version from it. Hope it's enough. Code:
from tkinter import *
import sys, os
class MainWindow():
def __init__(self, master, title, size):
self.master = master
self.title = title
self.size = size
self.master.title(self.title)
self.master.geometry(self.size)
self.hitext = Label(self.master,
text="some random text,\n to change the previous text lol").pack(fill=X, pady=10)
self.productButton = Button(self.master,
text="second window",
width=15,
command=self.productButtonClicked).place(x=15, y=55)
self.quitMainWindow = Button(self.master,
text="exit",
width=15,
command=mainWindow.quit).place(x=170, y=55)
def productButtonClicked(self):
productWindow = Toplevel()
productFenster = ProductMenuWindow(productWindow, "second window", "260x100")
class ProductMenuWindow():
def __init__(self, master, title, size):
self.master = master
self.title = title
self.size = size
self.master.geometry(self.size)
self.master.title(self.title)
self.text = Label(self.master, text="what do you want to buy?").pack(fill=X, pady=10)
self.gobackButton = Button(self.master,
text="go back to main window",
width=20,
command="").place(x=55, y=50) #here should be the command for the button
if __name__ == "__main__":
mainWindow = Tk()
mainFenster = MainWindow(mainWindow, "root/main/first window", "300x95")
mainWindow.mainloop()
If I put command=mainWindow.quit the mainwindow of course gets destroyed and the programm stops. So heres the point, I dont now further because .destroy is not working here... Also sorry for some english mistakes :P
I've made some changes.
Compare my version with yours.
from tkinter import *
import sys, os
class MainWindow():
def __init__(self, master, title, size):
self.master = master
self.title = title
self.size = size
self.master.title(self.title)
self.master.geometry(self.size)
self.hitext = Label(self.master,
text="some random text,\n to change the previous text lol").pack(fill=X, pady=10)
self.productButton = Button(self.master,
text="second window",
width=15,
command=self.productButtonClicked).place(x=15, y=55)
self.quitMainWindow = Button(self.master,
text="exit",
width=15,
command=self.on_cancel).place(x=170, y=55)
def productButtonClicked(self):
#productWindow = Toplevel()
obj = ProductMenuWindow(self, "second window", "260x100")
#productFenster = ProductMenuWindow(productWindow,)
def on_cancel(self):
self.master.destroy()
class ProductMenuWindow(Toplevel):
def __init__(self, parent, title, size):
super().__init__(name='product_main_menu')
self.parent = parent
self.title(title)
self.size = size
self.geometry(size)
self.text = Label(self, text="what do you want to buy?").pack(fill=X, pady=10)
self.gobackButton = Button(self,
text="go back to main window",
width=20,
command=self.on_cancel).place(x=55, y=50) #here should be the command for the button
def on_cancel(self):
self.destroy()
if __name__ == "__main__":
mainWindow = Tk()
mainFenster = MainWindow(mainWindow, "root/main/first window", "300x95")
mainWindow.mainloop()
p.s.
super().__init__(name='product_main_menu')
It's used to have singleton on your ProductMenuWindow.
If you write super().__init__() you see that you could open more then one window.
I'm working in Python 3.5 and TKinteer. Inside of a text widget, I have created a context menu that appears when the user right-clicks. However, when I try and create the commands I want (cut, copy, paste), the commands seem to have no effect.
The relevant code is as follows:
from tkinter import *
class Application:
def __init__(self,master):
self.master = master
self.initUI()
def initUI(self):
root.title("Simple Text Editor")
scrollBar = Scrollbar(root)
self.textPad = Text(root, width=100, height=100, wrap='word',
yscrollcommand=scrollBar.set,
borderwidth=0, highlightthickness=0)
scrollBar.config(command=self.textPad.yview)
scrollBar.pack(side='right', fill='y')
self.textPad.pack(side='left', fill='both', expand=True)
class PopupMenu:
def __init__(self, master, *args, **kwargs):
self.popup_menu = Menu(root, tearoff=0)
self.popup_menu.add_command(label="Cut",
command=lambda: app.textPad.event_generate('<Control-x>'))
self.popup_menu.add_command(label="Copy",
command=lambda: app.textPad.event_generate('<Control-c>'))
self.popup_menu.add_command(label="Paste",
command=lambda: app.textPad.event_generate('<Control-v>'))
app.textPad.bind("<Button-3>", self.popup)
self.popup_menu.bind("<FocusOut>",self.popupFocusOut)
def popup(self, event):
self.popup_menu.post(event.x_root, event.y_root)
self.popup_menu.focus_set()
def popupFocusOut(self, event=None):
self.popup_menu.unpost()
root = Tk()
app = Application(root)
popupMenu = PopupMenu(root)
root.mainloop()
You don't want to generate <Control-x>, etc. Instead, generate the virtual events <<Cut>>, <<Copy>> and <<Paste>>.
I want to be able to adjust the color of a ttk.Frame() widget. I know this question has been asked numerous times here. A very useful answer was given here: Change color of "tab header" in ttk.Notebook. One can do this using style.theme_create().
I want to make a similar adjustment using ttk.Style() but cannot figure out how. Could someone explain to me how I can do this?
The reason I am not using the method proposed in the above link is because there are other widgets in my code that I want to (and can) customize using ttk.Style().
import tkinter as tk
from tkinter import ttk
class Window():
def __init__(self, parent):
self.parent = parent
self.parent.minsize(width=600, height=400)
self.widgets()
def widgets(self):
s1 = ttk.Style()
s1.configure('My.TNotebook.Tab', padding=5, background='red')
s1.map('My.TNotebook.Tab', background=[('selected', 'green')])
self.nb1 = ttk.Notebook(self.parent, style='My.TNotebook.Tab')
self.tab1 = ttk.Frame(self.nb1)
self.tab2 = ttk.Frame(self.nb1)
self.tab3 = ttk.Frame(self.nb1)
self.nb1.add(self.tab1, text='Tab1')
self.nb1.add(self.tab2, text='Tab2')
self.nb1.add(self.tab3, text='Tab3')
self.nb1.place(relx=0.1, rely=0.1, width=500, height=200)
self.b1 = ttk.Button(self.parent, text='Quit', command=self.quit)
self.b1.place(relx=0.4, rely=0.7, height=70, width=150)
def quit(self):
self.parent.destroy()
root = tk.Tk()
app = Window(root)
root.mainloop()
I searched more and found an interesting and simple solution here: http://page.sourceforge.net/html/themes.html. The key to solving the problem seems to be the need to tell Python which theme to use (I am running Python on Windows). In my answer, I use classic but winnative, clam, alt, and default will do too. Using vista or xpnative makes no effect on the tabs' colors.
import tkinter as tk
from tkinter import ttk
class Window():
def __init__(self, parent):
self.parent = parent
self.parent.minsize(width=600, height=400)
self.widgets()
def widgets(self):
s1 = ttk.Style()
s1.theme_use('classic')
s1.configure('TNotebook.Tab', background='navajo white')
s1.map('TNotebook.Tab', background=[('selected', 'goldenrod'), ('active', 'goldenrod')])
self.nb1 = ttk.Notebook(self.parent)
self.nb1.place(relx=0.1, rely=0.1, width=500, height=200)
self.tab1 = ttk.Frame(self.nb1)
self.tab2 = ttk.Frame(self.nb1)
self.tab3 = ttk.Frame(self.nb1)
self.nb1.add(self.tab1, text='Tab1')
self.nb1.add(self.tab2, text='Tab2')
self.nb1.add(self.tab3, text='Tab3')
self.b1 = ttk.Button(self.parent, text='Quit', command=self.quit)
self.b1.place(relx=0.4, rely=0.7, height=70, width=150)
def quit(self):
self.parent.destroy()
root = tk.Tk()
app = Window(root)
root.mainloop()
This is the front end I developed for my application using Tkinter:
from Tkinter import *
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Simple")
self.pack(fill=BOTH, expand=1)
frame = Frame(self, relief="flat", borderwidth=1)
label=Label(frame,text="Scope:")
label.pack(side="left", fill=None, expand=False)
var = StringVar()
var.set("today")
list = OptionMenu(frame, var, "today","yesterday","this week","last week","this month","last month")
list.pack(side="left", fill=None, expand=False)
fetchButton = Button(frame, text="Fetch",command=self.handle(var))
fetchButton.pack(side="left", fill=None, expand=False)
frame.grid(row=1,column=1,pady=4,padx=5,sticky=W)
area = Text(self,height=15,width=60)
area.grid(row=2,column=1,rowspan=1,pady=4,padx=5)
scroll = Scrollbar(self)
scroll.pack(side=RIGHT, fill=Y)
area.config(yscrollcommand=scroll.set)
scroll.config(command=area.yview)
scroll.grid(row=2, column=2, sticky='nsew')
quitButton = Button(self, text="Cancel",command=self.quit)
quitButton.grid(pady=4,padx=5,sticky=W,row=3, column=1)
root = Tk()
app = Example(root)
root.mainloop()
Where exactly do I have to put the handle() method so it can write repeatedly to the text widget? When I put handle() within the Example class and use self.area.insert(), it shows an error saying
Example instance has no attribute 'area'
Please help out.
You need to pass the function object to the Button instance, not a function call. i.e.
fetchButton = Button(frame, text="Fetch",command=self.handle)
To make the handle work in the context of the rest of the code:
from Tkinter import *
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.parent.title("Simple")
self.pack(fill=BOTH, expand=1)
self.init_ui()
def init_ui(self):
self.frame = Frame(self, relief="flat", borderwidth=1)
self.frame.grid(row=1,column=1,pady=4,padx=5,sticky=W)
self.label=Label(self.frame,text="Scope:")
self.label.pack(side="left", fill=None, expand=False)
self.var = StringVar()
self.var.set("today")
self.list = OptionMenu(self.frame, self.var, "today","yesterday",
"this week","last week","this month",
"last month")
self.list.pack(side="left", fill=None, expand=False)
self.fetchButton = Button(self.frame, text="Fetch",command=self.handle)
self.fetchButton.pack(side="left", fill=None, expand=False)
self.area = Text(self,height=15,width=60)
self.area.grid(row=2,column=1,rowspan=1,pady=4,padx=5)
self.scroll = Scrollbar(self)
self.scroll.pack(side=RIGHT, fill=Y)
self.area.config(yscrollcommand=self.scroll.set)
self.scroll.config(command=self.area.yview)
self.scroll.grid(row=2, column=2, sticky='nsew')
self.quitButton = Button(self, text="Cancel",command=self.quit)
self.quitButton.grid(pady=4,padx=5,sticky=W,row=3, column=1)
def handle(self):
self.area.delete(1.0, END)
self.area.insert(CURRENT,self.var.get())
if __name__ == "__main__":
root = Tk()
app = Example(root)
root.mainloop()
Declaring your widgets as attributes will save you a lot of pain an suffering as your application expands. Also keeping references to everything in Tk can stop some unwanted garbage collection, particularly with images in Label instances.
It is also worth noting that using grid and pack interchangeably is likely to lead to bugs later on.