I tried another attempt with this
kivy 1.9.0
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.lang import Builder
from kivy.uix.widget import Widget
from simpleOSC import initOSCClient, initOSCServer, closeOSC, \
setOSCHandler, sendOSCMsg
class OscShowcase(BoxLayout):
pass
def __init__(self, **kwargs):
super(OscShowcase, self).__init__(**kwargs)
#self.but_Osc = Button(text='Press to show Osc')
#self.but_Osc.bind(on_release=self.send_Osc)
#self.add_widget(self.but_Osc)
def send_Osc(self, *l):
pass
#sendOSCMsg('/chaine_en_dur/', [2.0])
def sendOSCMsg( address='/print', data=[] ) :
m = OSCMessage()
m.setAddress(address)
for d in data :
m.append(d)
basic_client.send(m)
class OscWidget(GridLayout):
def __init__(self, **kwargs):
super(OscWidget, self).__init__(**kwargs)
class TestOscApp(App):
def build(self):
return OscShowcase()
if __name__ == '__main__':
host = '127.0.0.1'
sport = 9000
rport = 9001
# osc
initOSCClient(host, sport)
initOSCServer(host, rport)
TestOscApp().run()
.kv file
<OscShowcase>:
BoxLayout:
OscWidget:
Button:
text: 'OSC'
pos: (700, 500)
# on_release : sendOSCMsg('')
# sendOSCMsg: '/chaine_en_dur/', [2.0]
# on_release : self.but_Osc.bind()
group: 'OscButton'
on_press: sendOSCMsg('2')
I still get an error "NameError: name 'sendOSCMsg is not defined" when I press the button. Is anybody can help me to understand why? I would like to send osc messages out to Max MSP
Kv Lang has some scopes, you can read more about it here
There are three keywords specific to Kv language:
app: always refers to the instance of your application.
root: refers to the base widget/template in the current rule
self: always refer to the current widget
You can run a method from TestOscApp with app.method_name() and from OscShowcase with root.method_name()
So, just update your kv to call sendOSCMsg from OscShowcase:
on_press: root.sendOSCMsg('2')
Related
I'm working on a GStreamer-based program using Python and the GObject introspection bindings. I'm trying to build this pipeline:
videomixer name=mix ! autovideosink \
uridecodebin uri=v4l2:///dev/video0 ! mix.
The pipeline works perfectly using gst-launch-1.0, but my Python program gives the errors:
(minimal.py:12168): GStreamer-CRITICAL **: gst_element_link_pads_full: assertion 'GST_IS_ELEMENT (src)' failed
on_error(): (GError('Internal data flow error.',), 'gstbasesrc.c(2865): gst_base_src_loop (): /GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstV4l2Src:source:\nstreaming task paused, reason not-linked (-1)')
My code:
#!/usr/bin/python3
import gi
gi.require_version('Gst', '1.0')
from gi.repository import GObject, Gst, Gtk, GdkX11, GstVideo
GObject.threads_init()
Gst.init(None)
class Source:
def __init__(self, uri, pipeline, mixer):
self.uri = uri
self.pipeline = pipeline
self.mixer = mixer
self.src = Gst.ElementFactory.make('uridecodebin', None)
self.pipeline.add(self.src)
self.src.set_property('uri', uri)
self.src.connect('pad-added', self.on_pad_added, self.src, self.mixer)
def on_pad_added(self, element, pad, src, dest):
name = pad.query_caps(None).to_string()
print('on_pad_added:', name)
if name.startswith('video/'):
src.link(dest)
class Main:
def __init__(self):
self.window = Gtk.Window()
self.window.connect('destroy', self.quit)
self.window.set_default_size(1280, 720)
self.drawingarea = Gtk.DrawingArea()
self.window.add(self.drawingarea)
self.pipeline = Gst.Pipeline()
self.bus = self.pipeline.get_bus()
self.bus.add_signal_watch()
self.bus.connect('message::error', self.on_error)
self.bus.enable_sync_message_emission()
self.bus.connect('sync-message::element', self.on_sync_message)
self.mixer = Gst.ElementFactory.make('videomixer', None)
self.sink = Gst.ElementFactory.make('autovideosink', None)
self.pipeline.add(self.mixer)
self.pipeline.add(self.sink)
self.mixer.link(self.sink)
video = Source('v4l2:///dev/video0', self.pipeline, self.mixer)
def run(self):
self.window.show_all()
# You need to get the XID after window.show_all(). You shouldn't get it
# in the on_sync_message() handler because threading issues will cause
# segfaults there.
self.xid = self.drawingarea.get_property('window').get_xid()
self.pipeline.set_state(Gst.State.PLAYING)
Gtk.main()
def quit(self, window):
self.pipeline.set_state(Gst.State.NULL)
Gtk.main_quit()
def on_sync_message(self, bus, msg):
if msg.get_structure().get_name() == 'prepare-window-handle': msg.src.set_window_handle(self.xid)
def on_error(self, bus, msg):
print('on_error():', msg.parse_error())
main = Main()
main.run()
I figured out the problem, I was linking the dynamically-created pad incorrectly:
src.link(dest)
Should have been:
pad.link(dest.get_compatible_pad(pad, None))
If the element is not added with the pipeline, then this error will occur. Ensure that the problematic element is added with the pipeline.
from __future__ import unicode_literals
import sys
from scrapy.pipelines.images import ImagesPipeline
from scrapy.exceptions import DropItem
from scrapy.http import Request
import os
reload(sys)
sys.setdefaultencoding('utf-8')
class TetePipeline(ImagesPipeline):
def get_media_requests(self, item, info):
for image_url in item['image_urls']:
yield Request(image_url)
def item_completed(self, results, item, info):
item['image'] = []
image_paths = [x['path'] for ok, x in results if ok]
if not image_paths:
raise DropItem('Items contains no images')
item['image_paths'] = image_paths
for i in item['image_paths']:
item['image'].append(item['image_titles']+i[-8:])
item['image_paths'] = item['image']
return item
#
scrapy version :1.0
This is my code,It can download images,but the image names are the result of the image url SHA1 hash.
I want to change the image name using custom name.in ths example is :item['image_titles']+i[-8:],int the scrapy shell the item['image_titles']+i[-8:] can be normal output,where is the reason?
class TetePipeline(ImagesPipeline):
def get_media_requests(self, item, info):
for image_url in item['image_urls']:
yield Request(image_url, meta={'item': item})
def file_path(self, request, response=None, info=None):
item = request.meta['item']
image_guid = request.url.split('/')[-1]
image_name = item['image_titles']+image_guid[-8:]
return image_name
Change the file_path func, return the image_name, because the get_media_requests will download the image, item_completed has downloaded
I am essentially repeating a question that was asked (but not answered) in the comments of PyQt: Getting file name for file dropped in app .
What I'd like to be able to do, a la that post, is convert an output from a file drop event in pyqt that currently looks like this:
/.file/id=6571367.661326 into an actual file path (i.e. /.Documents/etc./etc./myProject/fileNeeded.extension)
so that I can make use of the file that made the attempted QDropEvent. how to do this. Any thoughts?
EDIT:
As mentioned below in the comments, this appears to be a platform specific problem. I am running Mac OS X El Capitan (10.11.2)
I figured out the solution after translating Obj-C code found in https://bugreports.qt.io/browse/QTBUG-40449. Note that this solution is only necessary for Macs running OS X Yosemite or later AND not running PyQt5 (i.e. running v.4.8 in my case).
import objc
import CoreFoundation as CF
def getUrlFromLocalFileID(self, localFileID):
localFileQString = QString(localFileID.toLocalFile())
relCFStringRef = CF.CFStringCreateWithCString(
CF.kCFAllocatorDefault,
localFileQString.toUtf8(),
CF.kCFStringEncodingUTF8
)
relCFURL = CF.CFURLCreateWithFileSystemPath(
CF.kCFAllocatorDefault,
relCFStringRef,
CF.kCFURLPOSIXPathStyle,
False # is directory
)
absCFURL = CF.CFURLCreateFilePathURL(
CF.kCFAllocatorDefault,
relCFURL,
objc.NULL
)
return QUrl(str(absCFURL[0])).toLocalFile()
To see this working in a drag and drop situation, see below:
import sys
import objc
import CoreFoundation as CF
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class MyListWidget(QListWidget):
def __init__(self, parent):
super(MyListWidget, self).__init__(parent)
self.setAcceptDrops(True)
self.setDragDropMode(QAbstractItemView.InternalMove)
def getUrlFromLocalFileID(self, localFileID):
localFileQString = QString(localFileID.toLocalFile())
relCFStringRef = CF.CFStringCreateWithCString(
CF.kCFAllocatorDefault,
localFileQString.toUtf8(),
CF.kCFStringEncodingUTF8
)
relCFURL = CF.CFURLCreateWithFileSystemPath(
CF.kCFAllocatorDefault,
relCFStringRef,
CF.kCFURLPOSIXPathStyle,
False # is directory
)
absCFURL = CF.CFURLCreateFilePathURL(
CF.kCFAllocatorDefault,
relCFURL,
objc.NULL
)
return QUrl(str(absCFURL[0])).toLocalFile()
def dragEnterEvent(self, event):
if event.mimeData().hasUrls():
event.acceptProposedAction()
else:
super(MyListWidget, self).dragEnterEvent(event)
def dragMoveEvent(self, event):
super(MyListWidget, self).dragMoveEvent(event)
def dropEvent(self, event):
if event.mimeData().hasUrls():
event.setDropAction(Qt.CopyAction)
event.accept()
links = []
for url in event.mimeData().urls():
if QString(url.toLocalFile()).startsWith('/.file/id='):
url = self.getUrlFromLocalFileID(url)
links.append(url)
else:
links.append(str(url.toLocalFile()))
for link in links:
self.addItem(link)
else:
super(MyListWidget,self).dropEvent(event)
class MyWindow(QWidget):
def __init__(self):
super(MyWindow,self).__init__()
self.setGeometry(100,100,300,400)
self.setWindowTitle("Filenames")
self.list = MyListWidget(self)
layout = QVBoxLayout(self)
layout.addWidget(self.list)
self.setLayout(layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyle("plastique")
window = MyWindow()
window.show()
sys.exit(app.exec_())
I'm trying to make a function that runs a ttk progressbar until a file is created. It seems that Widget.after is causing the APPCRASH but I don't know why. Please help!
def FilePgBar(title, file):
if root:
root.withdraw()
boxRoot = Toplevel(master=root)
boxRoot.withdraw()
else:
boxRoot = Tk()
boxRoot.withdraw()
boxRoot.protocol('WM_DELETE_WINDOW', denyWindowManagerClose )
boxRoot.title(title)
boxRoot.iconname('Dialog')
boxRoot.geometry(rootWindowPosition)
boxRoot.minsize(400, 100)
pgBar = ttk.Progressbar(boxRoot, orient=HORIZONTAL, length=300, mode='indeterminate')
pgBar.grid(row=1, column=0)
pgBar.pack()
pgBar.start()
def checkfile():
if os.path.exists(file):
pgBar.stop()
pgBar.destroy()
boxRoot.deiconify()
boxRoot.mainloop()
boxRoot.destroy()
if root: root.deiconify()
else:
boxRoot.after(100, checkfile)
checkfile()
I want to call this function from others scripts, so I'm not sure about using a class
EDIT: I edited the code. I no longer get an APPCRASH, but nothing happens when I run the program.
Python evaluates the arguments before passing them to a function. So when it encounters
boxRoot.after(100, checkfile(file))
it evaluates checkfile(file) -- calling checkfile -- and replaces checkfile(file) with the value returned by the function before calling boxRoot.after.
Since checkfile(file) has no return statement, None is returned by default. Thus
boxRoot.after(100, None)
gets called. This raises an error since the second argument to boxRoot.after should be a callable.
Instead, pass the function object checkfile itself:
def checkfile():
if os.path.exists(file):
pgBar.stop()
pgBar.destroy()
boxRoot.destroy()
if root: root.deiconify()
else:
# You need to update the progress bar
boxRoot.after(100, checkfile)
This allows the boxRoot.after function to call the function from within boxRoot.after instead of before after is called.
You might do something like this:
import os
import Tkinter as tk
import ttk
class App(object):
def __init__(self, master, *args, **kwargs):
self.master = master
self.button = tk.Button(master, text='Stop', command=self.stop)
self.button.pack()
self.progress = ttk.Progressbar(master, orient="horizontal",
length=200, mode="determinate")
self.progress.pack()
self.progress["value"] = 0
self.progress["maximum"] = 100
self.filename = '/tmp/out'
if os.path.exists(self.filename):
os.unlink(self.filename)
self.checkfile()
def checkfile(self):
self.progress["value"] += 1
if (not os.path.exists(self.filename)
and self.progress["value"] < self.progress["maximum"]):
self.master.after(100, self.checkfile)
def stop(self):
with open(self.filename, 'w') as f: pass
root = tk.Tk()
app = App(root)
root.mainloop()
I'm trying this:
import os, sys
from Gui import *
import Image as PIL
import ImageTk
class ImageBrowser(Gui):
def __init__(self):
Gui.__init__(self)
self.button = self.bu(command=self.quit, relief=FLAT)
def image_loop(self, dirname='.'):
files = os.listdir(dirname)
for file in files:
try:
self.show_image(file)
print (file)
self.mainloop()
except IOError:
continue
except:
break
def show_image(self, filename):
image = PIL.open(filename)
self.tkpi = ImageTk.PhotoImage(image)
self.button.config(image=self.tkpi)
def main(script, dirname='.'):
g = ImageBrowser()
g.image_loop(dirname)
if __name__ == '__main__':
main(*sys.argv)
I'm getting an error that says:
from Gui import *
ImportError: No module named Gui
I'm assuming "from Gui import *" doesn't work in python 3, does anyone know how to do this in python 3? Thank you so much (:
If you are talking about the Gui module that comes with Swampy, then
in order to use Gui with Python3, you'll need to install the Python3 version of Swampy.