เรียกใช้คำสั่งระบบจากแอป QML


16

ฉันต้องการเรียกใช้คำสั่งระบบจากภายในแอปพลิเคชันของฉัน มันควรจะเรียกใช้คำสั่งบนเซิร์ฟเวอร์ระยะไกลโดยใช้ SSH แต่นั่นไม่ใช่ประเด็นจริงๆ ประเด็นก็คือฉันไม่รู้วิธีเรียกใช้คำสั่งใด ๆ จากแอป ฉันถามในรายการอีเมลและพวกเขาแนะนำให้ฉันสร้างส่วนขยาย QML โดยใช้ C ++ แต่ฉันไม่รู้ C ++ และดูเหมือนว่าฉันต้องเรียนรู้มากมายเพียงเพื่อใช้คำสั่งง่ายๆ

ใน Python (เหมือนใน PHP) มันง่ายที่จะรันคำสั่งระบบ มีวิธีอื่นในการทำในแอป Touch ของฉันหรือมีคนที่สามารถช่วยฉันได้มากกว่านี้อีกไหม? หรืออาจมีวิธีแก้ไขปัญหาของฉันได้ดีกว่า


1
คุณสามารถลบเนื้อหาทั้งหมดที่ไม่เกี่ยวข้องกับเนื้อหาหลักของคำถามของคุณเช่น "เซิร์ฟเวอร์ Minecraft" ได้อย่างไรคุณเรียนรู้สิ่งนี้ "เพื่อความสนุก" ฯลฯ ได้หรือไม่ เหตุผลที่ฉันถามก็คือเนื่องจากรายละเอียดเหล่านี้อยู่ข้างๆปัญหาและเบี่ยงเบนความสนใจได้ค่อนข้างดี
Akiva

คำตอบ:


13

นี่ไม่ใช่สิ่งที่ QML สนับสนุนคำตอบทั่วไปคือการเขียนปลั๊กอิน C ++ เพื่อจัดการกับสิ่งนั้น

อย่างไรก็ตามทีม SDK กำลังวางแผนส่วนขยายที่หลากหลายเพื่อมอบให้กับนักพัฒนาแอป QML และนี่อาจเป็นสิ่งที่พวกเขานำไปใช้ในปลั๊กอินทั่วไปที่คุณสามารถใช้ได้


2
นั่นจะได้รับการชื่นชมมาก! ฉันเริ่มค้นหาวิธีเรียกสคริปต์ Python แทน แต่ฉันสามารถค้นหาสคริปต์ Python ที่เรียกใช้ QML ได้เท่านั้นไม่ใช่วิธีอื่น ๆ
Daniel Holm

ในที่สุดสิ่งที่ฉันทำก็คือฉันได้ทำการเปลี่ยนแปลง webui ของฉันสำหรับฟังก์ชั่นเดียวกับแอพใหม่และดึงข้อมูลที่ฉันต้องการจากการใช้ XML สวยเนี๊ยบ
Daniel Holm

1
ฉันลองใช้ QProcess Launcher ใน 14.04 และใช้งานได้ดี: askubuntu.com/a/446736/20275
int_ua

@ mhall119 โปรดแก้ไขฉันหากฉันผิด แต่คุณไม่สามารถทำสิ่งนี้ด้วย QML ทางโทรศัพท์เพราะ AppArmor มันจะป้องกันไม่ให้คุณทำเช่นนี้
Akiva

10

อัปเดต: สำหรับ 14.04 ดูคำตอบที่ง่ายมากโดย int_ua

ข้อความต้นฉบับ:

ที่http://talk.maemo.org/showthread.php?t=87580มีภาพรวมพื้นฐานของวิธีเพิ่มส่วนขยายใน QML ฉันตัดสินใจถ่ายโดยใช้ ubuntu-sdk แทนซึ่งแตกต่างกันเล็กน้อย ฉันจะเอกสารด้านล่าง

สำหรับโครงการนี้ฉันเลือกUbuntu Touch / Simple UI พร้อม C ++ Backendใน QtCreator สิ่งนี้สร้างโครงการที่มีสองส่วนแยกจากกันส่วนแบ็คเอนด์และส่วนหน้า touchui ที่เขียนใน QML ในแบ็กเอนด์เราจะเพิ่มไฟล์สองไฟล์สำหรับคลาส Launcher

launcher.h:

#ifndef LAUNCHER_H
#define LAUNCHER_H

#include <QObject>
#include <QProcess>

class Launcher : public QObject
{
    Q_OBJECT
public:
    explicit Launcher(QObject *parent = 0);
    Q_INVOKABLE QString launch(const QString &program);

private:
    QProcess *m_process;
};

#endif // LAUNCHER_H

launcher.cpp:

#include "launcher.h"

Launcher::Launcher(QObject *parent) :
    QObject(parent),
    m_process(new QProcess(this))
{
}

QString Launcher::launch(const QString &program)
{
    m_process->start(program);
    m_process->waitForFinished(-1);
    QByteArray bytes = m_process->readAllStandardOutput();
    QString output = QString::fromLocal8Bit(bytes);
    return output;
}

คลาสนี้ใช้ QProcess เพื่อรันโปรแกรมรอให้เสร็จสิ้นอ่าน stdout และส่งคืนเป็นสตริง

ต่อไปเราต้องแก้ไขแบ็กเอนด์ / แบ็กเอนด์. cpp เพื่อรวมคลาส ต้องใช้สองบรรทัด ผนวกรวมถึง:

#include "launcher.h"

และในBackendPlugin :: registerTypesเพิ่มบรรทัด:

qmlRegisterType<Launcher>(uri, 1, 0, "Launcher");

ควรมีบรรทัดสำหรับ MyType อยู่แล้วซึ่งเป็นตัวอย่างที่รวมไว้ หลังจากนี้เราควรจะสามารถสร้างแบ็กเอนด์ สิ่งเดียวที่เหลืออยู่ก็คือใช้ในไฟล์ main.qml สำหรับสิ่งนี้ฉันเพิ่มบรรทัด:

Launcher { id: myLauncher }

และไปที่ตัวจัดการ onClick ของปุ่มให้ตั้งค่า:

myType.helloWorld = myLauncher.launch("date");

ณ จุดนี้สิ่งที่เหลืออยู่ก็คือการเริ่มต้นและทดสอบ นี่คือที่ฉันพบปัญหาเนื่องจาก QtCreator ดูเหมือนจะไม่ตั้งค่าทุกอย่างอย่างถูกต้องตามค่าเริ่มต้น ในขณะที่ฉันกำลังแก้ไขปัญหาในเทอร์มินัลนำทางไปยังไดเรกทอรีโครงการ QtCreator ของคุณและ:

mkdir -p Ubuntu/Example

จากนั้นคัดลอกไฟล์ libUbuntuExample.so จาก ProjectBuildDir / backend ไปยัง Ubuntu / ตัวอย่างและไฟล์ qmldir จาก ProjectName / backend / qmldir จากนั้นคุณสามารถเรียกใช้:

qmlscene -I . ProjectName/touchui/main.qml

ฉันแน่ใจว่าอาจเป็นวิธีที่ง่ายในการจัดการทั้งหมดนี้เพื่อให้ Build / Run ใช้งานได้


ตอนนี้ใช้งานได้ใน 14.04: askubuntu.com/a/446736/20275
int_ua

6

Ubuntu 14.04

แนวคิดของชนิดตัวเรียกใช้ QProcess ตอนนี้ทำงานได้โดยไม่มีปัญหาใน Trusty กับubuntu-sdk-teamPPA เพียงแค่สร้างQML Extension Library + Tabbed UIโครงการ ( อย่าใช้เครื่องหมายขีดคั่นในชื่อโครงการ ) แทนที่เนื้อหาของ

mytype.h

#ifndef LAUNCHER_H
#define LAUNCHER_H

#include <QObject>
#include <QProcess>

class Launcher : public QObject
{
    Q_OBJECT

public:
    explicit Launcher(QObject *parent = 0);
    ~Launcher();
    Q_INVOKABLE QString launch(const QString &program);

protected:
    QProcess *m_process;
};

#endif // LAUNCHER_H

mytype.cpp

#include "mytype.h"

Launcher::Launcher(QObject *parent) :
    QObject(parent),
    m_process(new QProcess(this))
{

}

QString Launcher::launch(const QString &program)
{
    m_process->start(program);
    m_process->waitForFinished(-1);
    QByteArray bytes = m_process->readAllStandardOutput();
    QString output = QString::fromLocal8Bit(bytes);
    return output;
}

Launcher::~Launcher() {

}

และการเปลี่ยนแปลงqmlRegisterTypeในbackend.cppการ

qmlRegisterType<Launcher>(uri, 1, 0, "Launcher");

ถัดไปเพียงแค่ล้างข้อมูลทั้งหมดที่MyTypeเหลือจากไฟล์ QML และเพิ่ม

        Rectangle {

          Launcher {
             id: qprocess
          }

          Text {
            anchors.centerIn: parent
            text: qprocess.launch("which bash")
          }
        }

ทุกที่ที่คุณชอบและ

import projectname 1.0

ในตอนเริ่มต้น.

ไม่จำเป็น

ฉันยังใช้กระดาษห่อนี้:

function exec(command) {
    return qprocess.launch("sh -c \"" + command + " < /dev/null \"")
}

pkexecหากคุณต้องการเข้าถึงรากเพิ่ม


1
ฉันแค่ต้องการยืนยันว่าวิธีนี้ใช้ได้ดีสำหรับฉัน อะไรก็ตามที่คุณป้อนคำสั่งเอาท์พุทมันจะปรากฏขึ้นในสี่เหลี่ยมผืนผ้า
Akiva

2

คุณไม่จำเป็นต้องรู้อะไรมากมายเกี่ยวกับ c ++ เพื่อเข้าถึงคำสั่งเทอร์มินัล เพียงแค่ใส่สิ่งต่อไปนี้ในไฟล์ใด ๆ ที่ลงท้ายด้วย. cpp ตัวอย่างเช่น runPython.cpp

#include <stdlib.h>

int main ()
{
    system("cd /home/user/path/to/script");
    system("python3 myScript.py");
    return 0;
}

สิ่งที่คุณต้องทราบในตอนนี้คือวิธีการรับรหัส c ++ ที่ทำงานใน QML แต่ฉันแน่ใจว่าเป็นเอกสารที่ดีมาก

โปรดทราบว่าคุณสามารถเพิ่มคำสั่ง linux คุณต้องการใด ๆ system("linux command");โดยทำตามไวยากรณ์เดียวกัน

หวังว่านี่จะช่วยได้!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.