Russian Qt Forum
Апрель 23, 2024, 16:46 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QProcess и командная строка  (Прочитано 8148 раз)
Nelkor
Гость
« : Сентябрь 20, 2014, 16:36 »

Всем привет! Учусь работать с классом QProcess.

Архитектура программы:
На форме имеются TextBrowser, LineEdit и PushButton;
С помощью класса QProcess запускается командная строка (cmd - объект класса QProcess);
В TextBrowser отображается то, что командная строка пишет нам, а с помощью LineEdit и PushButton можно писать и отправлять команды;

Код простой и незатейливый:

Код:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    cmd.setParent(this);
    cmd.start("cmd");

    read();
}

Widget::~Widget(){ delete ui; }

void Widget::on_pushButton_clicked()
{
    cmd.write(ui->lineEdit->text().toUtf8());
    cmd.waitForBytesWritten();
    
    ui->lineEdit->clear();

    read();
}

void Widget::read()
{
    QString output;
    bool canRead = true;

    while (canRead){
        cmd.waitForReadyRead(1000);
        QString temp = cmd.readAll();

        if (temp.isEmpty()){
            canRead = false;
        }else{
            output.append(temp);
        }
    }
    ui->textBrowser->setText(output);
}

Частично программа работает, выводит на экран следующее:


Во-первых, кракозябры. Не понимаю, что можно с этим сделать, ведь в Qt 5 был сильно урезан класс QTextCodec;
Во-вторых, никакие команды на ввод не работают, после любой команды экран просто очищается (то есть cmd ничего не отвечает);
В-третьих, я не думаю, что моя функция read() является самой оптимальной для чтения из процесса... Может быть, можно как-то сделать, чтобы текст из командной строки читался тогда, когда командная что-то написала?
И кстати, командная строка запускается в "невидимом" режиме. Хотя в диспетчере задач она есть. Это так и надо или признак бага?

И любые другие комментарии по поводу этой программы.
Буду рад любой помощи!
« Последнее редактирование: Сентябрь 20, 2014, 16:40 от Nelkor » Записан
torwig
Самовар
**
Offline Offline

Сообщений: 134



Просмотр профиля
« Ответ #1 : Сентябрь 20, 2014, 16:46 »

Подключайте слоты к сигналам
Код:
void	readyReadStandardError()
void readyReadStandardOutput()
они испускаются когда командная стока что-то написала соответственно в стандартные потоки ошибок и вывода.
Записан
torwig
Самовар
**
Offline Offline

Сообщений: 134



Просмотр профиля
« Ответ #2 : Сентябрь 20, 2014, 16:54 »

В Книге Шлее есть пример в главе о процессах.
Нечто подобное как у вас.
Но он при нажатии на кнопку не делает process.write(blablabla), а process.start(commandText) (предварительно в Виндовсдобавляя "cmd /C ", то есть например "cmd /C dir"). Страница 610.
Записан
torwig
Самовар
**
Offline Offline

Сообщений: 134



Просмотр профиля
« Ответ #3 : Сентябрь 20, 2014, 16:56 »

Да простит меня господин Шлее Улыбающийся Пример из книги:
Код:
#ifndef _Shell_h_
#define _Shell_h_

#include <QtGui>

// ======================================================================
class Shell : public QWidget {
Q_OBJECT
private:
    QProcess*  m_process;
    QLineEdit* m_ptxtCommand;
    QTextEdit* m_ptxtDisplay;

public:
    // ------------------------------------------------------------------
    Shell(QWidget* pwgt = 0) : QWidget(pwgt)
    {
        m_process     = new QProcess(this);
        m_ptxtDisplay = new QTextEdit;

        QLabel* plbl = new QLabel("&Command:");

        m_ptxtCommand = new QLineEdit("dir");
        plbl->setBuddy(m_ptxtCommand);

        QPushButton* pcmd = new QPushButton("&Enter");

        connect(m_process,
                SIGNAL(readyReadStandardOutput()),
                SLOT(slotDataOnStdout())
               );
        connect(m_ptxtCommand,
                SIGNAL(returnPressed()),
                SLOT(slotReturnPressed())
               );
        connect(pcmd, SIGNAL(clicked()), SLOT(slotReturnPressed()));

        //Layout setup
        QHBoxLayout* phbxLayout = new QHBoxLayout;   
        phbxLayout->addWidget(plbl);
        phbxLayout->addWidget(m_ptxtCommand);
        phbxLayout->addWidget(pcmd);

        QVBoxLayout* pvbxLayout = new QVBoxLayout;   
        pvbxLayout->addWidget(m_ptxtDisplay);
        pvbxLayout->addLayout(phbxLayout);
        setLayout(pvbxLayout);
    }

public slots:
    // ------------------------------------------------------------------
    void slotDataOnStdout()
    {
        m_ptxtDisplay->append(m_process->readAllStandardOutput());
    }

    // ------------------------------------------------------------------
    void slotReturnPressed()
    {
        QString strCommand = "";
#ifdef Q_WS_WIN
        strCommand = "cmd /C ";
#endif
        strCommand += m_ptxtCommand->text();
        m_process->start(strCommand);
    }
}; 
#endif  //_Shell_h_
Записан
Nelkor
Гость
« Ответ #4 : Сентябрь 20, 2014, 17:06 »

Спасибо, буду разбираться!) А с крокозябрами что?)
Записан
Nelkor
Гость
« Ответ #5 : Сентябрь 21, 2014, 16:10 »

Тааак, уже кое-что получается) слоты к сигналам подключил, и понял, почему у меня на ввод ничего не работало. Вот "работающий" код:

Код:
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    cmd = new QProcess(this);

    connect(cmd, SIGNAL(readyRead()), SLOT(read()));
    connect(ui->lineEdit, SIGNAL(returnPressed()), SLOT(write()));

    cmd->start("cmd");
    cmd->waitForStarted(100);

    if(cmd->state() == QProcess::NotRunning) ui->textBrowser->append("Error 404: CMD not found");
}

Widget::~Widget()
{
    delete ui;
}

void Widget::read()
{
    ui->textBrowser->append(cmd->readAll());
}

void Widget::write()
{
    cmd->write(ui->lineEdit->text().toUtf8() + '\n');

    ui->lineEdit->clear();
}

Не решена проблема только с крокозябрами. Всё, что командная строка отвечает мне на русском - у меня либо вообще не выводится, либо выводится ромбиками и иероглифами.
Записан
_Vitaliy_
Гость
« Ответ #6 : Сентябрь 21, 2014, 16:23 »

посмотрите на эту http://www.prog.org.ru/topic_26545_0.html ветку, может и натолкнет на мысль
Записан
Nelkor
Гость
« Ответ #7 : Сентябрь 23, 2014, 19:40 »

Натолкнула вот на какую мысль:

Код:
void Widget::read()
{
    QString add;
    QTextStream stream(&add);
    stream.setCodec("csIBM866");

    stream << cmd->readAll();

    ui->textBrowser->append(add);
}

К удивлению, кодировка даже не думала меняться. Крокозябры какие были, такие же и остались.
Записан
OKTA
Гость
« Ответ #8 : Сентябрь 24, 2014, 09:30 »

А если поменять имя кодека на CP866?
Записан
Nelkor
Гость
« Ответ #9 : Сентябрь 27, 2014, 19:24 »

неа
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.049 секунд. Запросов: 23.