Pemrograman Qt 19 – Membaca dan Menuliskan Standard Output ke QTextEdit Secara Realtime


Bismillahirrahmanirrahim.

Tulisan ini tersedia dalam PDF

qt-creator-logoSetelah tulisan pemrograman Qt 10 kemarin, saya berpikir untuk memperbaiki program ProyekRC dengan menambah fungsi penayangan standard output untuk apt-get. Standard output yang ditayangkan harus real time (bergerak terus sampai proses selesai). Di dalam suatu program repo changer, tentu fitur ini wajib ada. Jika tidak, maka pengguna harus membuka 1 program lagi (Terminal) untuk sekadar melakukan apt-get update. Setelah melakukan riset kecil-kecilan, pada tulisan ini saya berhasil melakukannya secara terpisah. Anda dapat mengunduh kode sumber pada akhir tulisan. Semoga tulisan ini bermanfaat.

Spesifikasi Sistem

  1. Ubuntu 12.04
  2. Qt Creator 2.4.1
  3. Qt 4.8

Daftar Kelas

  1. QProcess
  2. QStringList
  3. QTextCursor
  4. QTextEdit
  5. QWidget
  6. QVBoxLayout
  7. QPushButton

Daftar Method

  1. setRange() <- milik QIntValidator
  2. setValidator() <- milik QLineEdit
  3. setEchoMode() <- milik QLineEdit
  4. setFileName() <- milik QFile
  5. open() <- milik QFile
  6. operator <<() <- milik QTextStream

Arah Tulisan Ini

Program harus mampu membaca standard output dari apt-get update ketika bekerja sampai selesai. Standard ouput tersebut harus ditayangkan di QTextEdit. Diharapkan hasilnya nanti seperti Synaptic ketika bekerja. Lihat gambar berikut.

ngite-kesembilanbelas

Mengapa ini harus dibuat? Karena program RepoChanger pada tulisan ke-10 harus memiliki fitur penting ini.

Kode

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    QPushButton     *tombolOke;
    QWidget         *widgetUtama;
    QVBoxLayout     *layoutUtama;
    QTextEdit       *keluaranKonsol;

public slots:
    void redirect_output();
    void hapus_isi_teks();
    void tunjukkan_bahwa_kamu_mati();

private slots:
    void ambillah_datanya();

private:
    Ui::MainWindow *ui;
    QProcess *prosesku;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    this->setGeometry(333, 333, 355, 355);
    QPushButton     *tombolOke      =       new     QPushButton;
    QVBoxLayout     *layoutUtama    =       new     QVBoxLayout;
    QWidget         *widgetUtama    =       new     QWidget;
                     keluaranKonsol =       new     QTextEdit;
                     prosesku       =       new     QProcess;

    tombolOke->setText("NOTHING TO SAY");
//    keluaranKonsol->setTextBackgroundColor("RED");

    layoutUtama->addWidget(tombolOke);
    layoutUtama->addWidget(keluaranKonsol);

    prosesku->setProcessChannelMode(QProcess::MergedChannels);

    //menghitamkan background dari QTextEdit dengan CSS
    keluaranKonsol->setStyleSheet("QTextEdit { background-color : black; color : white; }");

    //membuat scrollbar selalu otomatis mengikuti kursor terbawah
    //dipasang pada Wednesday, March 26, 2014 05:39 PM dari dokumentasi Qt
    keluaranKonsol->ensureCursorVisible();

    widgetUtama->setLayout(layoutUtama);
    this->setCentralWidget(widgetUtama);

    connect(tombolOke, SIGNAL(clicked()), this, SLOT(redirect_output()));
    //teknik S&S baru ini didapatkan pada Tuesday, March 25, 2014 dari http://minhazulhaque.blogspot.com/2012/07/read-shell-command-output-using.html
    //juga bisa didapatkan dari http://www.qtcentre.org/threads/47538-QProcess-read-from-stdout-lively
    connect(prosesku, SIGNAL(readyRead()), this, SLOT(ambillah_datanya()));
    //teknik pembacaan kematian proses ini ditemukan pada Wednesday, March 26, 2014 05:18 PM dari perkiraan dan dokumentasi Qt
    connect(prosesku, SIGNAL(finished(int)), this, SLOT(tunjukkan_bahwa_kamu_mati()));
//    connect(prosesku, SIGNAL(readyReadStandardError()), this, SLOT(ambillah_datanya()));

}

//satu
MainWindow::~MainWindow()
{
    delete ui;
}

//dua
void MainWindow::hapus_isi_teks()
{

}

//tiga
void MainWindow::redirect_output()
{
    prosesku->start("sh", QStringList() << "-c" << "apt-get update"); } //empat void MainWindow::ambillah_datanya() {     //teknik appending ini ditemukan pada Tuesday, March 25, 2014 05:07 PM dari http://www.jcjc-dev.com/2013/03/qt-48-appending-text-to-qtextedit.html     this->keluaranKonsol->moveCursor(QTextCursor::End);
    this->keluaranKonsol->insertPlainText(prosesku->readAll());
    this->keluaranKonsol->moveCursor(QTextCursor::End);
//    this->keluaranKonsol->setPlainText(prosesku->readAllStandardError());
}

void MainWindow::tunjukkan_bahwa_kamu_mati()
{
    this->keluaranKonsol->insertPlainText("\n\n===PROSES SELESAI===\n\n");
}

Qt Creator dan Kode

ngite-kesembilanbelas1

Hasil

ngite-kesembilanbelas2

Analisis

Saya berusaha memberikan analisis dimulai dari yang paling penting.

1. Penayangan Standard Output pada QTextEdit

Inilah inti program. Ini dilakukan hanya dengan objek QTextEdit dengan beberapa method. Berikut ini kodenya.

 //empat
 void MainWindow::ambillah_datanya()
 {
 //teknik appending ini ditemukan pada Tuesday, March 25, 2014 05:07 PM dari http://www.jcjc-dev.com/2013/03/qt-48-appending-text-to-qtextedit.html
 this->keluaranKonsol->moveCursor(QTextCursor::End);
 this->keluaranKonsol->insertPlainText(prosesku->readAll());
 this->keluaranKonsol->moveCursor(QTextCursor::End);
 }
 

Pada intinya, program ini hanya melakukan 3 aksi. Pertama, dia meletakkan kursor pada akhir baris. Kedua, dia membaca standard output (dan standard error juga). Ketiga, dia meletakkan kembali kursor pada akhir baris. Inilah yang membuat program dapat membaca standard output secara realtime. Namun fungsi ambillah_datanya() ini tidak akan mampu membaca jika tidak ada SIGNAL dan SLOT berikut.

connect(prosesku, SIGNAL(readyRead()), this, SLOT(ambillah_datanya()));

SIGNAL readyRead() dari objek prosesku (QProcess) inilah yang membuat SLOT ambillah_datanya() senantiasa dijalankan untuk membaca standard output. Tanpa ini, program ini tidak realtime.

2. Eksekusi Perintah apt-get update dari Program

//tiga
void MainWindow::redirect_output()
{
    prosesku->start("sh", QStringList() << "-c" << "apt-get update");
//    prosesku->start("sh", QStringList() << "-c" << "tailf /var/log/syslog");
} 

Seperti yang kita lakukan pada pemrograman Qt 9, kita memanfaatkan QProcess untuk menjalankan perintah shell di sini. Perhatikan standar penulisan perintah pada baris yang aktif dan yang dijadikan komentar di atas.

3. Pemeriksaan Status Berakhirnya Proses apt-get update

 void MainWindow::tunjukkan_bahwa_kamu_mati()
{
this->keluaranKonsol->insertPlainText("\n\n===PROSES SELESAI===\n\n");
}

Ide dasarnya adalah perilaku Synaptic setiap proses instalasi selesai. Dia selalu bisa menayangkan pesan bahwa proses instalasi sudah selesai dan Anda bisa menutup jendelanya. Bagaimana Synaptic tahu bahwa proses bekerja apt sudah berakhir? Qt bisa melakukannya dengan SIGNAL dan SLOT, dengan SIGNAL berisi argumen finished(int) untuk QProcess yang menjalankan apt-get. Artinya, jika QProcess mengeluarkan sinyal finished, maka segera panggil SLOT tunjukkan_bahwa_kamu_mati() di atas. Baris kode di atas akan dikerjakan setelah adanya baris SIGNAL dan SLOT berikut.

connect(prosesku, SIGNAL(finished(int)), this, SLOT(tunjukkan_bahwa_kamu_mati()));

4. Membuat Standard Output dan Standard Error Dikeluarkan Bersamaan

    prosesku->setProcessChannelMode(QProcess::MergedChannels);

Seperti yang Anda ketahui, apt tidak hanya mengeluarkan pesan output biasa. Ia juga mengeluarkan pesan error jika terjadi error. Pesan error itu dikeluarkan pada kanal yang berlainan dengan output biasa. Nama kanalnya standard output. Sedangkan nantinya aplikasi ini akan dipakai oleh pengguna pemula, sehingga pesan error sangat dibutuhkan. Oleh karena itu, pesan error harus juga bisa ditayangkan sebagaimana pesan output normal. Ini dilakukan dengan menggabungkan kanal standard output dan standard error jadi satu. Method-nya adalah setProcessChannelMode() dengan argumen QProcess::MergedChannels. Ini membuat program menayangkan standard output jika memang dalam keadaan normal dan menayangkan standard error jika memang ada error.

5. Lain-Lain

5.1 Scrollbar Selalu Menggulung Ke Bawah Mengikuti Kursor

keluaranKonsol->ensureCursorVisible();

Mungkin ini remeh. Tetapi ini penting untuk memudahkan pengguna. Method ensureCursorVisible() memastikan bahwa scrollbar akan selalu menggulung ke bawah mengikuti arah kursor bergerak. Seperti halnya Synaptic ketika instalasi.

5.2 Pembuatan GUI

Jika Anda belum memahami pemrograman GUI secara hard coding di Qt, Anda bisa merujuk ke tulisan sebelumnya. Anda bisa mulai dari memahami pembuatan GUI-nya di pemrograman Qt 1 kemudian memahami penulisan header di pemrograman Qt 5.

Kesimpulan

  1. Pembacaan standard output (dan standard error) secara realtime bisa dilakukan dengan  menghubungkan SIGNAL readyRead() dan SLOT method readAll() pada objek QProcess.
  2. Untuk membuat setiap baris standard output dicetak sebagai satu baris pula di QTextEdit, harus digunakan method moveCursor() dengan argumen QTextCursor::End pada QTextEdit.
  3. Untuk membuat scrollbar bergerak terus ke bawah mengikuti kursor secara realtime, harus digunakan method ensureCursorVisible() pada QTextEdit.
  4. Untuk menggabungkan kanal standard output dan standard error, harus digunakan method setProcessChannelMode() dengan argumen QProcess::MergedChannel pada QProcess.
  5. Untuk memeriksa masih bekerja atau sudah berhentinya suatu proses, harus digunakan SIGNAL finished(int) pada QProcess dengan SLOT-nya fungsi untuk menulis pesan berakhirnya proses.

Unduh Kode Sumber

Program kali ini bernama Konsolidasi. Silakan unduh dan buka di Qt Creator Anda.

Referensi

  1. http://minhazulhaque.blogspot.com/2012/07/read-shell-command-output-using.html
  2. http://www.qtcentre.org/threads/47538-QProcess-read-from-stdout-lively
  3. http://www.jcjc-dev.com/2013/03/qt-48-appending-text-to-qtextedit.html
Iklan

8 thoughts on “Pemrograman Qt 19 – Membaca dan Menuliskan Standard Output ke QTextEdit Secara Realtime

Dilarang menggunakan emotikon

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s