Programm für Console und X11

Alles rund um die Programmierung mit Qt
Antworten
fthieme
Beiträge: 10
Registriert: 19. Mai 2007 22:47

Programm für Console und X11

Beitrag von fthieme »

Hallo!

Ich hab ein kleines Programm geschrieben, welches entweder im Batch Mode oder aber mit graphischem Interface bedienbar ist. Basis ist QCoreApplication und in einem Zweig gibt es dann ein Widget, im anderen nicht.

Wenn ich das Programm nun auf der Console im Batch Mode starten will, will es sich trotzdem zum X Server verbinden. Ich vermute wegen linken gegen -lQtGui.

Wie kann ich es dazu bringen einfach zu laufen, wenn es kein X braucht?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Wie unterscheidest du zwischen console und x11? Wie sieht deine main.cpp aus?
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
fthieme
Beiträge: 10
Registriert: 19. Mai 2007 22:47

Beitrag von fthieme »

Ich gebe einen Kommandozeilenschalter mit, den ich "-ni" getauft habe. Ausschnitsweise sieht die so aus:

Code: Alles auswählen

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QStringList arguments = QCoreApplication::arguments();

    programName = arguments.at(0);

    if (arguments.contains("-ni")) {
        // non interactive
        interactive = false;
        arguments.removeAll("-ni");
    } else {
        interactive = true;
    }

    if (interactive) {
        BumbleBeeMain bbmain(world);

        bbmain.show();
        returnValue = app.exec();
    } else {
        std::cout << "Running non-interactive mode on '" << problemFileName.toStdString() << "', "
                  << iterations << " iterations." << std::endl;
        world->doGenerations(iterations);
    }

    delete world;

    return returnValue;
}
BumbleBeeMain ist dabei von QMainWindow abgeleitet.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

QApplication braucht nun aber eine X11-Verbindung. Im Konsolen-Modus sollte man deshalb wohl eine QCoreApplication verwenden.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
fthieme
Beiträge: 10
Registriert: 19. Mai 2007 22:47

Beitrag von fthieme »

Argh - ich hab die zweite Zeile gelesen und gesehen QCoreApplicaton - alles klar...

Wie mache ich das nun also mit den Argumenten? Oder anders gefragt, wie komme ich von der QCoreApplication zu der QApplication?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Du musst die Argumente eben 'von Hand' auswerten und je nachdem QApplication oder QCoreApplication erzeugen.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
fthieme
Beiträge: 10
Registriert: 19. Mai 2007 22:47

Beitrag von fthieme »

mmh, doof, aber wenns nicht anders geht...

Danke :)

Edith: Geht doch anders. Ich erstelle jetzt ein QCoreApplication Objekt und ersetze das bei Bedarf durch ein QApplication Objekt.

Code: Alles auswählen

int main(int argc, char *argv[])
{
    QCoreApplication *app;
    app = new QCoreApplication(argc, argv);
    QStringList arguments = QCoreApplication::arguments();

    programName = arguments.at(0);

    if (arguments.contains("-i")) {
        // non interactive
        interactive = true;
        delete app;
        app = new QApplication(argc, argv);         // XXX Achtung unsauber, siehe Kommentar von franzf
        arguments = QCoreApplication::arguments();
        arguments.removeAll("-i");
    } else {
        interactive = false;
    }

    if (interactive) {
        BumbleBeeMain bbmain(world);

        bbmain.show();
        returnValue = app->exec();
    } else {
        std::cout << "Running non-interactive mode on '" << problemFileName.toStdString() << "', "
                  << iterations << " iterations." << std::endl;
        world->doGenerations(iterations);
    }

    delete world;
    delete app;

    return returnValue;
}
Falls es mal jemand braucht ;)
Zuletzt geändert von fthieme am 7. Februar 2010 16:18, insgesamt 1-mal geändert.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Bitte Q(Core)Application nicht mit new erstellen bzw delete löschen.
Probiere bitte einfach mal

Code: Alles auswählen

nt main(int argc, char *argv[])
{
    QCoreApplication app_core(argc, argv);
    QStringList arguments = QCoreApplication::arguments();

    programName = arguments.at(0);

    if (arguments.contains("-i")) {
        QApplication app(argc, argv);
aus.
ich weiß nämlich nicht ob Qt das gut findet wenn du das QCoreApplication-Singleton erstens mit new erzugst und dann auch noch wieder löschst.

Aber gut zu wissen dass man nach einer QCoreApplication auch QApplication einfach instanziieren kann wenn man X braucht.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Aber ne schöne Lösung ist es nicht...
Doku zu QCoreApplication::arguments():
Calling this function is slow - you should store the result in a variable when parsing the command line.
Du parst 2x arguments!

Ansonsten: was spricht dagegen, den Nutzer zu zwingen als ersten Parameter ein "-i" zu übergeben?
Dann wird aus deinem ganzen Hokuspokus ein:

Code: Alles auswählen

bool interactive = strcmp(argv[1], "-i") ? false : true;
fthieme
Beiträge: 10
Registriert: 19. Mai 2007 22:47

Beitrag von fthieme »

Christian81 hat geschrieben:Bitte Q(Core)Application nicht mit new erstellen bzw delete löschen.
Probiere bitte einfach mal

Code: Alles auswählen

nt main(int argc, char *argv[])
{
    QCoreApplication app_core(argc, argv);
    QStringList arguments = QCoreApplication::arguments();

    programName = arguments.at(0);

    if (arguments.contains("-i")) {
        QApplication app(argc, argv);
Wo steht, dass man diese Objekte nicht auch mit new und delete behandeln darf? Verzeih meine Unkenntnis was tiefere Programmabläufe anbelangt, aber bisher dachte ich, dass ein

Code: Alles auswählen

someObjectPrt = new SomeClass();
dasselbe tut wie ein

Code: Alles auswählen

someObject = SomeClass();
. Nur dass das eine beim Beginn der Funktion passiert und das andere erst bei new.
ich weiß nämlich nicht ob Qt das gut findet wenn du das QCoreApplication-Singleton erstens mit new erzugst und dann auch noch wieder löschst.
Ob sie es gut finden weiß ich nicht, aber es geht ;)

Zumindest hier und bei mir...
franzf hat geschrieben:Ansonsten: was spricht dagegen, den Nutzer zu zwingen als ersten Parameter ein "-i" zu übergeben?
Enfach, dass ich das nicht leiden kann. Ich meine nichts gegen Reihenfolgen von Parametern, aber "-" oder "--" Parameter sollten IMHO überall erlaubt sein...[/code]
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

fthieme hat geschrieben:
Ich weiß nämlich nicht ob Qt das gut findet wenn du das QCoreApplication-Singleton erstens mit new erzugst und dann auch noch wieder löschst.
Ob sie es gut finden weiß ich nicht, aber es geht ;)
Allein der nicht virtuelle Destruktor von QCoreApplication sollte Argument genug sein, ein QApplication-Objekt nicht über einen QCoreApplication-Basiszeiger zu verwalten! Das kann am Ende richtig Aua geben...

Wenn du beide Anforderungen
1) CmdLineArg-Parsing
2) aus 1) abgeleitet mit oder ohne Gui
unter einen Hut bringen willst, musst du app Erstellen und CmdLineArg-Parsing trennen.
Nimm Boost.Program_options, ist deutlich umfangreicher als QCoreApplication::arguments() und für deinen Anwebdungsfall fehlerunanfälliger.
Außerdem gibt es gleich ein umfangreich dokumentierendes "myapp --help" mit.
fthieme
Beiträge: 10
Registriert: 19. Mai 2007 22:47

Beitrag von fthieme »

Danke für den Hinweis. Ich schaus mir mal an. Hab bisher noch nicht mit boost gearbeitet...
Antworten