I've been at it from quite some days, searched the docs online but have not been able to find any example :/.
I want to stream video on a page using opencv.Im using QtCreator and on a QtQuick application, that is with qml files.
MediaPlayer {
id: mediaplayer
source: "videoplayback.mp4"
}
VideoOutput {
anchors.fill: parent
source: mediaplayer
}
MouseArea {
id: playArea
anchors.fill: parent
onPressed: mediaplayer.play();
}
Which shows this:
Now i can play the video.
But i rather want the source to be coming from my backend main.py file so i can work upon it.
The main.py file as of now is:
'''
class MainWindow(QObject):
def __init__(self):
QObject.__init__(self)
#QTimer
self.timer = QTimer()
self.timer.timeout.connect(lambda: self.setTime())
self.timer.start(1000)
def setTime(self):
now = datetime.datetime.now()
formatDate = now.strftime("Time: %H:%M:%S %p of %Y/%m/%d")
#print(formatDate)
self.printTime.emit(formatDate)
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
#Get Context
main = MainWindow()
engine.rootContext().setContextProperty("backend", main)
engine.load(os.fspath(Path(__file__).resolve().parent / "qml/main.qml"))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
In the above code, basically this line:
engine.rootContext().setContextProperty("backend", main)
Is the one for connection with the qml files using
Connections{
target: backend
function onPrintTime(time){
labelDate.text = time
}
}
So in context i want to ouput video on my page using source as being from opencv. Basically it's a surviellance system app, so i want to show multiple feeds, but if someone could help me with just one from webcam, as in how to stream it to the mediaplayer i'll be really really grateful.
Note: Im working with qml files inside the QT Creator application. There are a number of ways to do this with UI files but that doens't help me :/
Related
I am trying to create a pop-up dialog in my browser-based Qt/QML application in order to select a file on my workstation to upload to the unit running the web server. I am unsure what "context" the FileDialog is operating in when invoked via button click in the browser. Is it local to the unit that's running the server and hosting the page or is it local to the workstation running the browser?
I've got the following code in QML, taken from an example in the FileDialog documentation:
FileDialog {
id: fileDialog
title: "Please choose a file"
folder: shortcuts.home
onAccepted: {
console.log("You chose: " + fileDialog.fileUrls)
//Do the data_client stuff and get the file moving
client.getUploadFile(fileUrls)
}
onRejected: {
console.log("Canceled")
}
}
This dialog is displayed with the following:
Button {
id: uploadButton
x: 224
y: 14
text: qsTr("Upload")
onClicked: {
fileDialog.open()
}
}
The problem I'm seeing currently is that, when opened, the dialog gives me some filesystem "space" that I have no idea about. Regardless of whether I'm running on a Windows or Linux machine, I get the following dialog, in the "/home/web_user" directory:
To my layman's brain, this would seem to indicate that the dialog is local to the unit hosting the server(linux-based, where my workstation is USUALLY Windows-based), but I can't find that directory structure anywhere on that unit. Is it some special context that exists in the web server (lighttpd)? Is this some userspace in the context of the browser? Is there something I need to do to "point" the FileDialog at the local filesystem on the workstation I want to upload the file from?
I'm not well-versed in web development lingo/tools, hence my attempt to use Qt/WebAssembly to create a web-based GUI, so please forgive my using terms that may not be technically correct...
I'm incredibly angry with myself for not having read the documentation closely enough.
I had to change from the QGuiApplication to a QApplication in order to use widgets, add "widgets" to my project "QT +=" line, change the QML to call the backend instead of trying to invoke the FileDialog directly there in the QML, and call the appropriate function, as specified in the QFileDialog documentation...
The QML is now:
Button {
id: uploadButton
x: 224
y: 14
text: qsTr("Upload")
onClicked: {
client.getUploadFile();
}
}
In the backend C++:
auto fileContentReady = [](const QString &fileName, const QByteArray &fileContent) {
if (fileName.isEmpty()) {
// No file was selected
} else {
qDebug() << "File name: " + fileName;
}
};
void Data_Client::getUploadFile()
{
QFileDialog::getOpenFileContent("Images (*.png *.xpm *.jpg)", fileContentReady);
//...
}
It's all pretty clearly defined in the documentation for getOpenFileContent(), but I had to understand so much about emscripten, browser sand-boxes, and web stuff, just to realize what I wasn't seeing... Hope this helps people having a similar problem...
I've come across an odd behaviour when querying the names of audio capture devices in a JavaFX thread vs a 'plain' Java thread.
Normally I probably would not have noticed, except that I have some non-JavaFX applications which share a common configuration pool with a JavaFX application, and this caused some issues when programmatically setting a capture audio device to use.
In a nutshell, the same query main in a plain Java thread returns capture device names truncated to 31 characters, whereas in a JavaFX thread the capture device names are 'full'.
For example, truncated results...
Primary Sound Capture Driver
Microphone (HD Pro Webcam C910)
Microphone (Realtek(R) Audio)
Headset (Bose QuietComfort 35 H
Headset Microphone (Oculus Virt
...vs 'full' results:
Primary Sound Capture Driver
Microphone (HD Pro Webcam C910)
Microphone (Realtek(R) Audio)
Headset (Bose QuietComfort 35 Hands-Free)
Headset Microphone (Oculus Virtual Audio Device)
The minimal JavaFX application code below demonstrates the issue, and in my testing it happens in both 32 bit and 64 bit versions of the Java8 JDK on Windows 10. I have not tested non-Windows platforms, so I am not sure if the behaviour occurs outside this environment.
The showCaptureDeviceNames() method does the query and printout of the device names. If called from the main method, truncated devices names are shown. If commented out of main and triggered by the button press in the JavaFX thread, 'full' device names are shown.
Interestingly, if called in main first, and later in the JavaFX thread, truncated names are shown, indicating that there is some sort of caching going on (which luckily provides a workaround for my problem). Simply calling AudioSystem.getMixerInfo(); all by itself is sufficient to induce the 'caching' effect
Also, this only happens for capture devices; if the TargetDataLine.class is switched to SourceDataLine.class to filter for playback devices, the device name is always 'full'.
Can anyone offer any hints as to why this might be happening?
My current workaround is to ensure that the JavaFX application queries all audio devices before the JavaFX thread kicks off by calling AudioSystem.getMixerInfo(); in main(...). This works, but... as a "fix" it looks more like a mistake sitting there on its own for no apparent reason (although adequate commenting will help future developers who come across it).
I'd love for someone to tell me I'm doing something wrong and there's a better way.
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Line;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.Mixer.Info;
import javax.sound.sampled.TargetDataLine;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class CaptureDeviceListTest extends Application
{
#Override
public void start( Stage primaryStage )
throws Exception
{
primaryStage.setTitle( "Test Capture Device Queries" );
Button btn = new Button( "Get capture device names" );
btn.setOnAction( event -> showCaptureDeviceNames() );
StackPane root = new StackPane();
root.getChildren().add( btn );
primaryStage.setScene( new Scene( root, 200, 200 ) );
primaryStage.show();
}
private static void showCaptureDeviceNames()
{
// filter for capture devices - change to `SourceTargetData.class` for playback devices
Line.Info captureLine = new Line.Info( TargetDataLine.class );
for( Info mixerInfo : AudioSystem.getMixerInfo() )
{
Mixer mixer = AudioSystem.getMixer( mixerInfo );
if( mixer.isLineSupported( captureLine ) )
System.out.println( mixerInfo.getName() );
}
}
public static void main( String[] args )
{
// COMMENT / UNCOMMENT THE NEXT LINE
// showCaptureDeviceNames();
launch( args );
}
}
I`m trying to develop nice-looking app in pyqt using WebView and have a little problem.
I want to create new Window by pressing button in WebView.
I have main window(short view):
class LoginWindow(QWidget):
def __init__(self):
# creating window and different properties...
# Its not important,i think.
self.foo = LoginConnector(self)
view.page().mainFrame().addToJavaScriptWindowObject("foo", self.foo)
... connector to JS
class LoginConnector(QObject):
#pyqtSlot(result=str)
def get_user_list(self):
return ','.join(core.available_users())
#pyqtSlot()
def new_window(self):
print 'Hello!'
#What can i do here?
#pyqtSlot()
def quit(self):
QApplication.quit()
When i`m pressing button in window,its call new_window() from LoginConnector,but how create Dialog inside LoginConnector?
Full code
SOLVED! I`m idiot,listen that clever guy below
Just look at the api docs. http://pyqt.sourceforge.net/Docs/PyQt4/classes.html
If you don't like this PySide is basically the same thing with a few differences in syntax. http://pyside.github.io/docs/pyside/
class LoginWindow(QWebView):
def __init__(self, *args, **kwargs):
super(QWebView, self).__init__(*args, **kwargs):
...
self.foo = LoginConnector(self)
self.loadPage("httpdocs/login.hmtl")
# end Constructor
def loadPage(self, web_page):
"""Loads a web page in the browser.
Args:
webPage (str): The URL of the desired web page with JavaScript Python Communication.
"""
# Inspector - right click inspect to debug javascript and have access to the console.
inspector = QtWebKit.QWebInspector()
inspector.setPage(self.page())
# Force relative path otherwise you get a does not except file:// error
if os.path.isabs(web_page):
web_page = os.path.relpath(web_page)
url = QtCore.QUrl(web_page)
self.load(url)
self.frame = self.page().mainFrame()
self.frame.addToJavaScriptWindowObject("foo", self.foo)
# end loadPage
# end class LoginWindow
class LoginConnector(QObject):
#pyqtSlot()
def new_window(self):
self.dialog = QDialog()
self.dialog.show() # or exec
# end new_window
# end class LoginConnector
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = LoginWindow()
window.show()
sys.exit(app.exec_())
This is the main application structure for PySide. PyQt should be similar.
I open a web page with QWebView.load(QUrl(myurl)) , the webpage gets some input and returns a new php generated page.
If executed in Firefox the browser automatically opens a new tab/window to show the returned page.
How to tell QWebView to open a new instance of QWebview with the returned data loaded?
I was looking at at the QwebView documentation at
www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qwebview.html ... but no joy.
Example of such a page :
http://www.iqfront.com/index.php?option=com_content&view=article&id=5&Itemid=4
Thanks for any ideas.
from my understanding this is developer's job to create and open new tabs for urls clicked.You would need to define a custom slot for QWebView::linkClicked signal. This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy property is set to delegate the link handling for the specified url. There you can create a new instance of QWebView add it a tab and open new url there. Below is an example:
import sys
from PyQt4 import QtGui, QtCore, QtWebKit
class MainForm(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainForm, self).__init__(parent)
self.tabWidget = QtGui.QTabWidget(self)
self.setCentralWidget(self.tabWidget)
self.loadUrl(QtCore.QUrl('http://qt.nokia.com/'))
def loadUrl(self, url):
view = QtWebKit.QWebView()
view.connect(view, QtCore.SIGNAL('loadFinished(bool)'), self.loadFinished)
view.connect(view, QtCore.SIGNAL('linkClicked(const QUrl&)'), self.linkClicked)
view.page().setLinkDelegationPolicy(QtWebKit.QWebPage.DelegateAllLinks)
self.tabWidget.setCurrentIndex(self.tabWidget.addTab(view, 'loading...'))
view.load(url)
def loadFinished(self, ok):
index = self.tabWidget.indexOf(self.sender())
self.tabWidget.setTabText(index, self.sender().url().host())
def linkClicked(self, url):
self.loadUrl(url)
def main():
app = QtGui.QApplication(sys.argv)
form = MainForm()
form.show()
app.exec_()
if __name__ == '__main__':
main()
hope this helps, regards
Basically, irrespective of what changes I make to my source, compiling alway yields either a transcoding error, or a missing definition.
I'm new to flash so it's difficult for me to understand how to go about fixing the problem.
Anyway here is the source.
The stack overflow link I always put in all my source, to look at for encouragement every time I feel like banging my head against the keyboard.
// Main.as
package
{
// General imports
// http://stackoverflow.com/questions/564756/should-i-just-give-up-on-programming
import com.bit101.components.Label;
import flash.display.*;
import flash.events.*;
import AssetManager;
// Begin external facing class
public class Main extends Sprite
{
public function Main()
{
var globalFont:String = AssetManager.FONT_PFRONDA;
//var myLabel:com.bit101.components.Label = new Label(Main = null, xpos = 25, ypos = 30, text = "Test Successfull");
//addChild(myLabel);
}
}
---
// AssetManager.as
package
{
public class AssetManager
{
[Embed(source = 'C:\\Documents and Settings\\Geko\\Desktop\\Flash\\testclient\\lib\\MinimalComps_0_9_5_\\src\\assets\\pf_ronda_seven.ttf', fontName = 'PF Ronda Seven', fontWeight = 'normal', advancedAntiAliasing = 'true', mimeType = 'application/x-font-truetype')] public static const FONT_PFRONDA:String;
}
}
Currently when I try to compile I get the following error...
C:\Documents and Settings\Geko\Desktop\Flash\testclient\src\Main.as(6): col: 31
Error: Definition com.bit101.components:Label could not be found.
and if I remove the comment from "var myLabel" or "addChild lines" in Main.as, then I get..
C:\Documents and Settings\Geko\Desktop\Flash\testclient\lib\MinimalComps_0_9_5_\src\com\bit101\components\Component.as(51): col: 4: Error: transcoding parameter 'embedAsCFF' is not supported by 'flex2.compiler.media.FontTranscoder'
C:\Documents and Settings\Geko\Desktop\Flash\testclient\lib\MinimalComps_0_9_5_\src\com\bit101\components\Component.as(51): col: 4: Error: Unable to transcode /assets/pf_ronda_seven.ttf.
My classpaths are "src", "lib\MinimalComps_0_9_5_\src\assets", and "lib\MinimalComps_0_9_5_\src\com\bit101\components"
I'm using Flex SDK 3.5.0.12683 on Windows XP with FlashDevelop 3.2.1 RTM
Any ideas as to why I'm constantly receiving errors each time I try to build the project?
C:\Documents and Settings\Geko\Desktop\Flash\testclient\src\Main.as(6): col: 31 Error: Definition com.bit101.components:Label could not be found.
this would suggest that the application can't find the Label class, possible reasons could be a problem with your classes library path, not importing the Label class, problem with the Label class package name etc...
The other two errors have to do with the way your font is embed. "embedAsCFF" requires Flex SDK 4.
In the error message you get a mention to the flex2 compiler.
'flex2.compiler.media.FontTranscoder'
Are you sure to be using the Flex SDK 3.5? I don't use FlashDevelop myself , so I wouldn't know where to look in order to edit the current Flex SDK.