我想制作一个屏幕caster应用程序,直接将窗口或屏幕捕获到QQuickImage。为了做到这一点,我制作了这个标题,它有一个线程对象,当收到信号时经常更新屏幕截图(对不起,文件是用糟糕的语言写的(
class OtherThread : public QThread
{
Q_OBJECT
QString oldWritingFile = "filename.png";
bool loaded = true;
public:
int winId = 0;
OtherThread(QObject *parent = nullptr):QThread(parent){};
~OtherThread(){
if(isRunning()){
requestInterruption();
wait();
}
};
void setParams(int id){
winId = id;
}
void knowLoaded(){
loaded =true;
}
signals:
void fileCacheChanged(QString);
protected:
void run() override{
while (!isInterruptionRequested()) {
if(winId != 0 && loaded){
bool success;
loaded = false;
if(oldWritingFile == QString::number(winId)+".png"){
if(qApp->primaryScreen()->grabWindow(winId).save(QString::number(winId)+"file.png")){
oldWritingFile = QString::number(winId)+"file.png";
success = true;
}else{success=false;}
}else{
if(qApp->primaryScreen()->grabWindow(winId).save(QString::number(winId)+".png")){
oldWritingFile = QString::number(winId)+".png";
success = true;
}else{success = false;}
}
emit fileCacheChanged(oldWritingFile);
}
}
};
};
class Controller : public QObject
{
Q_OBJECT
QString oldWritingFile;
public:
Controller(QObject *parent = nullptr):QObject(parent) {}
virtual ~Controller() {}
void changeFile(QString message){
oldWritingFile = message;
emit newFile(message);
};
public slots:
void startThread(){
OtherThread *thread =new OtherThread;
connect(thread, &OtherThread::fileCacheChanged, this, &Controller::changeFile);
connect(this, &Controller::stop, thread, &OtherThread::requestInterruption);
connect(this, &Controller::changePrint, thread, &OtherThread::setParams);
connect(this, &Controller::loaded, thread, &OtherThread::knowLoaded);
thread->start();
}
QString getLoadedFile(){
if(oldWritingFile != NULL){
return "file:./"+oldWritingFile;
}else{
return "file:./index.png";
}
}
signals:
void stop();
void changePrint(int id);
void newFile(QString);
void loaded();
};
用我的qml图像我做了这个
Image {
id: image
anchors.fill: parent
source: "images/kalaripayattu.svg"
fillMode: Image.PreserveAspectFit
cache:false
Component.onCompleted: {
justThread.newFile.connect(updateFunction)
}
function updateFunction(filename){
source = "file:./"+filename;
justThread.loaded()
}
}
JustThread{
signal stopThread
id:justThread
onStopThread: {
stop()
}
Component.onCompleted: {
startThread()
changePrint(id)
}
}
Component.onCompleted:{
applicationWindow.closing.connect(justThread.stopThread)
}
但它的fps真的很糟糕。可以做些什么来提高fps吗?有什么简单的方法可以做到这一点吗?
Image
并不是为显示频繁变化的图像而设计的。你想要的是VideoOutput
。
我会这么做:
您需要创建一个QObject派生类实例,并将其设置为VideoOutput的源:http://doc.qt.io/qt-5/qml-qtmultimedia-videooutput.html#source-支柱你的班级需要一个Q_PROPERTY(QAbstractVideoSurface* videoSurface READ videoSurface WRITE setVideoSurface NOTIFY videoSurfaceChanged)
在你的setVideoSurface
方法中,你需要用正确的格式调用QAbstractVideoSurface的开始方法(你的大小和像素格式,我想桌面的像素格式应该是QVideoFrame::format_ARGB32(。
然后,当您想要更新VideoOutput(例如,通过QTimer(时,您可以使用从QScreen::grabWindow中获得的QPixmap构建的QVideoFrame来调用当前的QAbstractVideoSurface方法。
为此,您可以使用toImage
将QPixmap转换为QImage,然后使用QVideoFrame::QVideoFrame(const QImage &image)
构造函数将其转换为QVideoFrame。