Qt 2 – Permasalahan 1: Destroy Semua Child Window Ketika Parent Ditutup

Bismillahirrahmanirrahim.

  • Tanggal: Thursday, August 20, 2015 07:37 PM
  • Status: gagal.
  • Workaround: http://www.qtforum.org/article/21347/solved-qdialog-not-closed-when-qmainwindow-closed.html
  • Implementasi: this->setAttribute(Qt::WA_DeleteOnClose);
  • Keterangan: change attribute terhadap QMainWindow parent. Logikanya, jika parent mati maka semua child mati juga. Nyatanya, ada error.
  • Hasil diharapkan: semua jendela child mati setelah parent mati tanpa error.
  • Hasil nyata: semua jendela child mati tetapi ada error invalid pointer: 0xbf93e3e8 ***

[C++] Membuat Aplikasi Pengenalan Karakter dengan Qt Creator di Linux

Bismillahirrahmanirrahim.

qtcreatorSaya membuat sebuah program GUI sederhana untuk mengenali karakter (character recognition). Bentuk GUI yang saya buat adalah sebuah jendela dengan 16 x 16 (256) buah QPushButton yang dijadikan toggle button dengan mengaktifkan checked pada propertinya. Cara kerja aplikasi ini adalah dengan menerima input berupa bentuk huruf dari tombol-tombol (toggle) yang ditekan, menjadikan input itu array 16 x 16, memroses input itu dengan suatu algoritma, lalu mencocokkan hasil-hasilnya dengan variabel pengukur. Jika dinyatakan mirip A, maka huruf itu dikatakan huruf A. Jika mirip B, maka B. Jika mirip C, maka C. Jika mirip H, maka H. Saya membuat program ini dengan mengacu kepada referensi utama makalah karya Wim Permana yang berjudul Pengenalan Pola Huruf A, B, dan H dengan Perceptron. Referensi lain saya tuliskan di akhir tulisan ini. Proses pembuatan aplikasi ini adalah dengan drag and drop awalnya pada GUI Builder lalu dilanjutkan dengan menulis kodenya. Semoga tulisan ini bermanfaat.

Sistem

  • Sistem operasi: Ubuntu 12.04
  • Kompiler: g++
  • Build system: Qmake
  • IDE: Qt Creator

Baca lebih lanjut

Membuat Formulir GUI dengan Qt Creator

Bismillahirrahmanirrahim.

Inilah pertama kalinya saya membuat sebuah GUI berbentuk formulir input. Saya membuatnya dari dasar formulir PDF. Yang ingin saya katakan adalah jika Anda ingin belajar membuat GUI atau software pada umumnya, maka coba terjemahkan tampilan formulir asli menjadi formulir dalam GUI. Apa yang saya buat adalah karya pertama. Penuh dengan kekurangan. Semoga nanti saya bisa memperbaikinya. Anda yang belajar Human Computer Interaction dan sedang menggunakan Linux, patut mempertimbangkan Qt Creator. Semoga ini bermanfaat.

GUI


qt-creator-gui-formulir

Formulir Asli


qt-creator-gui-formulir1

Proses Pembuatan


Saya memang kembali menggunakan teknik drag and drop kali ini. Sebenarnya saya sudah tidak suka lagi drag and drop karena saya sangat menyukai hard coding di pemrograman Qt. Namun demi kecepatan, sementara saya mengalah. Hasilnya sudah mirip software pada umumnya. Senang hati ini.

qt-creator-gui-formulir2

Akhirnya, Realtime Data Plotting di Linux dengan Qt + QCustomPlot!

Bismillahirrahmanirrahim.

Ini adalah posting bleeding edge untuk posting Pemrograman Qt di blog utama nanti. Saya senang sekali. Dua tahun lalu saya merasa bingung dengan pengganti di Linux untuk TeeChart di Windows. Saat ini, alhamdulillah saya peroleh ganti yang free software sekaligus gratis dan di Linux pula. Nama pustaka plotting ini adalah QCustomPlot. Pustaka ini sangatlah sederhana, hanya butuh 2 berkas (satu .cpp dan satu .h) ditambahkan ke dalam proyek Qt Creator dan plotting sudah bisa dilakukan. Pustaka ini juga menyediakan contoh-contoh yang banyak untuk berbagai macam grafik (baik realtime ataupun tidak). Lihatlah hasil plot berikut.

resized_output

Asal Muasal

Saya sengaja mencari pustaka pengganti TeeChart, yakni pustaka plotting yang mampu membuat grafik dinamis realtime. Pustaka itu harus bisa digunakan di Linux. Pustaka itu harus cross platform, dalam arti tidak hanya bisa dipakai di Microsoft Visual Studio saja. Pustaka itu harus memiliki binding C++ (bukan Python). Dan pustaka itu haruslah memiliki sintaks plotting yang pendek dan sederhana. Awalnya, saya menemukan Qwt dan telah saya tuliskan artikelnya di sini. Namun, saya merasa Qwt itu kompleks dan sangat panjang. Akhirnya kemarin saya mencoba QCustomPlot dan memodifikasi kode sumber contohnya. Alhamdulillah, yang saya inginkan selama ini akhirnya saya temukan.

Komentar

Karena ini asalnya adalah karya orang lain, maka wajar jika banyak komentar berbahasa Inggris masih tersisa di sini. Saya juga tidak menghapus bagian lisensinya. Saya harap saya bisa mengolahnya jadi posting saya sendiri nanti. Gambar GIF di atas saya produksi dari screencast (MP4) yang saya konversikan ke GIF dengan ffmpeg.

Kode

mainwindow.h

/***************************************************************************
**                                                                        **
**  QCustomPlot, an easy to use, modern plotting widget for Qt            **
**  Copyright (C) 2011, 2012, 2013, 2014 Emanuel Eichhammer               **
**                                                                        **
**  This program is free software: you can redistribute it and/or modify  **
**  it under the terms of the GNU General Public License as published by  **
**  the Free Software Foundation, either version 3 of the License, or     **
**  (at your option) any later version.                                   **
**                                                                        **
**  This program is distributed in the hope that it will be useful,       **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of        **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         **
**  GNU General Public License for more details.                          **
**                                                                        **
**  You should have received a copy of the GNU General Public License     **
**  along with this program.  If not, see http://www.gnu.org/licenses/.   **
**                                                                        **
****************************************************************************
**           Author: Emanuel Eichhammer                                   **
**  Website/Contact: http://www.qcustomplot.com/                          **
**             Date: 07.04.14                                             **
**          Version: 1.2.1                                                **
****************************************************************************/

/************************************************************************************************************
**                                                                                                         **
**  This is the example code for QCustomPlot.                                                              **
**                                                                                                         **
**  It demonstrates basic and some advanced capabilities of the widget. The interesting code is inside     **
**  the "setup(...)Demo" functions of MainWindow.                                                          **
**                                                                                                         **
**  In order to see a demo in action, call the respective "setup(...)Demo" function inside the             **
**  MainWindow constructor. Alternatively you may call setupDemo(i) where i is the index of the demo       **
**  you want (for those, see MainWindow constructor comments). All other functions here are merely a       **
**  way to easily create screenshots of all demos for the website. I.e. a timer is set to successively     **
**  setup all the demos and make a screenshot of the window area and save it in the ./screenshots          **
**  directory.                                                                                             **
**                                                                                                         **
*************************************************************************************************************/

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTimer>
#include "qcustomplot.h" // the header file of QCustomPlot. Don't forget to add it to your project, if you use an IDE, so it gets compiled.
#include <QtGui>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
  Q_OBJECT

public:
  explicit MainWindow(QWidget *parent = 0);
  ~MainWindow();

  void setupDemo(int demoIndex);
  void setupQuadraticDemo(QCustomPlot *customPlot);
  void setupSimpleDemo(QCustomPlot *customPlot);
  void setupSincScatterDemo(QCustomPlot *customPlot);
  void setupScatterStyleDemo(QCustomPlot *customPlot);
  void setupLineStyleDemo(QCustomPlot *customPlot);
  void setupScatterPixmapDemo(QCustomPlot *customPlot);
  void setupDateDemo(QCustomPlot *customPlot);
  void setupTextureBrushDemo(QCustomPlot *customPlot);
  void setupMultiAxisDemo(QCustomPlot *customPlot);
  void setupLogarithmicDemo(QCustomPlot *customPlot);
  void setupRealtimeDataDemo(QCustomPlot *customPlot);
  void setupParametricCurveDemo(QCustomPlot *customPlot);
  void setupBarChartDemo(QCustomPlot *customPlot);
  void setupStatisticalDemo(QCustomPlot *customPlot);
  void setupSimpleItemDemo(QCustomPlot *customPlot);
  void setupItemDemo(QCustomPlot *customPlot);
  void setupStyledDemo(QCustomPlot *customPlot);
  void setupAdvancedAxesDemo(QCustomPlot *customPlot);
  void setupColorMapDemo(QCustomPlot *customPlot);

  void setupPlayground(QCustomPlot *customPlot);

private slots:
  void realtimeDataSlot();
  void bracketDataSlot();
  void screenShot();
  void allScreenShots();
  void jajalenIki();

private:
  Ui::MainWindow *ui;
  QCustomPlot *customPlot;      // iki pancen kudu ditulis
  QVBoxLayout *verticalLayout;
  QWidget     *widgetUtama;
  QStatusBar  *statusBar;

  QString demoName;
  QTimer dataTimer;
  QCPItemTracer *itemDemoPhaseTracer;
  int currentDemoIndex;
};

#endif // MAINWINDOW_H

mainwindow.cpp

/***************************************************************************
**                                                                        **
**  QCustomPlot, an easy to use, modern plotting widget for Qt            **
**  Copyright (C) 2011, 2012, 2013, 2014 Emanuel Eichhammer               **
**                                                                        **
**  This program is free software: you can redistribute it and/or modify  **
**  it under the terms of the GNU General Public License as published by  **
**  the Free Software Foundation, either version 3 of the License, or     **
**  (at your option) any later version.                                   **
**                                                                        **
**  This program is distributed in the hope that it will be useful,       **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of        **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         **
**  GNU General Public License for more details.                          **
**                                                                        **
**  You should have received a copy of the GNU General Public License     **
**  along with this program.  If not, see http://www.gnu.org/licenses/.   **
**                                                                        **
****************************************************************************
**           Author: Emanuel Eichhammer                                   **
**  Website/Contact: http://www.qcustomplot.com/                          **
**             Date: 07.04.14                                             **
**          Version: 1.2.1                                                **
****************************************************************************/

/************************************************************************************************************
**                                                                                                         **
**  This is the example code for QCustomPlot.                                                              **
**                                                                                                         **
**  It demonstrates basic and some advanced capabilities of the widget. The interesting code is inside     **
**  the "setup(...)Demo" functions of MainWindow.                                                          **
**                                                                                                         **
**  In order to see a demo in action, call the respective "setup(...)Demo" function inside the             **
**  MainWindow constructor. Alternatively you may call setupDemo(i) where i is the index of the demo       **
**  you want (for those, see MainWindow constructor comments). All other functions here are merely a       **
**  way to easily create screenshots of all demos for the website. I.e. a timer is set to successively     **
**  setup all the demos and make a screenshot of the window area and save it in the ./screenshots          **
**  directory.                                                                                             **
**                                                                                                         **
*************************************************************************************************************/

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QDesktopWidget>
#include <QScreen>
#include <QMessageBox>
#include <QMetaEnum>

MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
  customPlot         =   new     QCustomPlot();
  statusBar          =   new     QStatusBar(this);

  // sebaris kode ini adalah pemasangan status bar kepada QMainWindow
  // ini lebih baik daripada bersusah payah membuat layout lalu memasang sendiri status bar secara manual
  // namun hasilnya status bar tampak terlalu luas dan tidak bisa dikecilkan
  // justru sebaris kode sederhana ini melakukan pemasangan dengan sempurna
  // ditulis pada Thursday, July 03, 2014 11:47 PM
  this->setStatusBar(statusBar);

  // ternyata memang saya harus membuat satu fungsi terpisah dari konstruktor MainWindow
  // biarlah customPlot dideklarasikan ulang di dalam MainWindow, sedangkan objek lain dideklarasikan di dalam fungsi jajalenIki
  // ditulis pada Thursday, July 03, 2014 11:48 PM
  jajalenIki();
}

void MainWindow::jajalenIki()
{
    QGridLayout   *verticalLayout     =   new     QGridLayout;
    QWidget       *widgetUtama        =   new     QWidget;

    customPlot->setGeometry(1,1,300,100);
//    statusBar->setGeometry(0,0,300,10);

    verticalLayout->addWidget(customPlot, 1,1,4,3);
//    verticalLayout->addWidget(statusBar, 5,1,1,1);

    widgetUtama->setLayout(verticalLayout);
    this->setCentralWidget(widgetUtama);
    setGeometry(400, 250, 542, 390);

    setupDemo(10);
}

void MainWindow::setupDemo(int demoIndex)
{
  switch (demoIndex)
  {
    case 10: setupRealtimeDataDemo(this->customPlot); break;
  }

  setWindowTitle("QCustomPlot: "+demoName);
//  statusBar->clearMessage();
  currentDemoIndex = demoIndex;
  this->customPlot->replot();
}

// 10

void MainWindow::setupRealtimeDataDemo(QCustomPlot *customPlot)
{
#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
  QMessageBox::critical(this, "", "You're using Qt < 4.7, the realtime data demo needs functions that are available with Qt 4.7 to work properly");
#endif
  demoName = "Real Time Data Demo";

  // include this section to fully disable antialiasing for higher performance:
  /*
  customPlot->setNotAntialiasedElements(QCP::aeAll);
  QFont font;
  font.setStyleStrategy(QFont::NoAntialias);
  customPlot->xAxis->setTickLabelFont(font);
  customPlot->yAxis->setTickLabelFont(font);
  customPlot->legend->setFont(font);
  */
  customPlot->addGraph(); // blue line
  customPlot->graph(0)->setPen(QPen(Qt::magenta));
  customPlot->graph(0)->setBrush(QBrush(QColor(240, 255, 200)));
  customPlot->graph(0)->setAntialiasedFill(false);
  customPlot->addGraph(); // red line
  customPlot->graph(1)->setPen(QPen(Qt::gray));
  customPlot->graph(0)->setChannelFillGraph(customPlot->graph(1));

  customPlot->addGraph(); // blue dot
  customPlot->graph(2)->setPen(QPen(Qt::cyan));
  customPlot->graph(2)->setLineStyle(QCPGraph::lsNone);
  customPlot->graph(2)->setScatterStyle(QCPScatterStyle::ssDisc);
  customPlot->addGraph(); // red dot
  customPlot->graph(3)->setPen(QPen(Qt::yellow));
  customPlot->graph(3)->setLineStyle(QCPGraph::lsNone);
  customPlot->graph(3)->setScatterStyle(QCPScatterStyle::ssDisc);

  customPlot->xAxis->setTickLabelType(QCPAxis::ltDateTime);
  customPlot->xAxis->setDateTimeFormat("hh:mm:ss");
  customPlot->xAxis->setAutoTickStep(true);
  customPlot->xAxis->setTickStep(2);
  customPlot->axisRect()->setupFullAxesBox();

  // make left and bottom axes transfer their ranges to right and top axes:
  connect(customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->xAxis2, SLOT(setRange(QCPRange)));
  connect(customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->yAxis2, SLOT(setRange(QCPRange)));

  // setup a timer that repeatedly calls MainWindow::realtimeDataSlot:
  connect(&dataTimer, SIGNAL(timeout()), this, SLOT(realtimeDataSlot()));
  dataTimer.start(0); // Interval 0 means to refresh as fast as possible
}

// fungsi khusus realtimeDataSlot
// inilah sumber data sinus dan cosinus untuk plotter

void MainWindow::realtimeDataSlot()
{
  // calculate two new data points:
#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
  double key = 0;
#else
  double key = QDateTime::currentDateTime().toMSecsSinceEpoch()/1000.0;
#endif
  static double lastPointKey = 0;
  if (key-lastPointKey > 0.01) // at most add point every 10 ms
  {
    double value0 = qSin(key); //sin(key*1.6+cos(key*1.7)*2)*10 + sin(key*1.2+0.56)*20 + 26;
    double value1 = qCos(key); //sin(key*1.3+cos(key*1.2)*1.2)*7 + sin(key*0.9+0.26)*24 + 26;
    // add data to lines:
    this->customPlot->graph(0)->addData(key, value0);
    this->customPlot->graph(1)->addData(key, value1);
    // set data of dots:
    this->customPlot->graph(2)->clearData();
    this->customPlot->graph(2)->addData(key, value0);
    this->customPlot->graph(3)->clearData();
    this->customPlot->graph(3)->addData(key, value1);
    // remove data of lines that's outside visible range:
    this->customPlot->graph(0)->removeDataBefore(key-8);
    this->customPlot->graph(1)->removeDataBefore(key-8);
    // rescale value (vertical) axis to fit the current data:
    this->customPlot->graph(0)->rescaleValueAxis();
    this->customPlot->graph(1)->rescaleValueAxis(true);
    lastPointKey = key;
  }
  // make key axis range scroll with the data (at a constant range size of 8):
  this->customPlot->xAxis->setRange(key+0.25, 8, Qt::AlignRight);
  this->customPlot->replot();

  // calculate frames per second:
  static double lastFpsKey;
  static int frameCount;
  ++frameCount;
  if (key-lastFpsKey > 2) // average fps over 2 seconds
  {
    this->statusBar->showMessage(
          QString("%1 FPS, Total Data points: %2")
          .arg(frameCount/(key-lastFpsKey), 0, 'f', 0)
          .arg(this->customPlot->graph(0)->data()->count()+this->customPlot->graph(1)->data()->count())
          , 0);
    lastFpsKey = key;
    frameCount = 0;
  }
}


// fungsi khusus bracketDataSlot

void MainWindow::bracketDataSlot()
{
#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
  double secs = 0;
#else
  double secs = QDateTime::currentDateTime().toMSecsSinceEpoch()/1000.0;
#endif

  // update data to make phase move:
  int n = 500;
  double phase = secs*5;
  double k = 3;
  QVector<double> x(n), y(n);
  for (int i=0; i<n; ++i)
  {
    x[i] = i/(double)(n-1)*34 - 17;
    y[i] = qExp(-x[i]*x[i]/20.0)*qSin(k*x[i]+phase);
  }
  this->customPlot->graph()->setData(x, y);

  itemDemoPhaseTracer->setGraphKey((8*M_PI+fmod(M_PI*1.5-phase, 6*M_PI))/k);

  this->customPlot->replot();

  // calculate frames per second:
  double key = secs;
  static double lastFpsKey;
  static int frameCount;
  ++frameCount;
  if (key-lastFpsKey > 2) // average fps over 2 seconds
  {
    this->statusBar->showMessage(
          QString("%1 FPS, Total Data points: %2")
          .arg(frameCount/(key-lastFpsKey), 0, 'f', 0)
          .arg(this->customPlot->graph(0)->data()->count())
          , 0);
    lastFpsKey = key;
    frameCount = 0;
  }
}

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

// fungsi khusus screenShot

void MainWindow::screenShot()
{
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
  QPixmap pm = QPixmap::grabWindow(qApp->desktop()->winId(), this->x()+2, this->y()+2, this->frameGeometry().width()-4, this->frameGeometry().height()-4);
#else
  QPixmap pm = qApp->primaryScreen()->grabWindow(qApp->desktop()->winId(), this->x()+2, this->y()+2, this->frameGeometry().width()-4, this->frameGeometry().height()-4);
#endif
  QString fileName = demoName.toLower()+".png";
  fileName.replace(" ", "");
  pm.save("./screenshots/"+fileName);
  qApp->quit();
}

// fungsi khusus allScreenShots

void MainWindow::allScreenShots()
{
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
  QPixmap pm = QPixmap::grabWindow(qApp->desktop()->winId(), this->x()+2, this->y()+2, this->frameGeometry().width()-4, this->frameGeometry().height()-4);
#else
  QPixmap pm = qApp->primaryScreen()->grabWindow(qApp->desktop()->winId(), this->x()+2, this->y()+2, this->frameGeometry().width()-4, this->frameGeometry().height()-4);
#endif
  QString fileName = demoName.toLower()+".png";
  fileName.replace(" ", "");
  pm.save("./screenshots/"+fileName);

  if (currentDemoIndex < 18)
  {
    if (dataTimer.isActive())
      dataTimer.stop();
    dataTimer.disconnect();
    delete this->customPlot;
    this->customPlot = new QCustomPlot(ui->centralWidget);
    this->verticalLayout->addWidget(this->customPlot);
    setupDemo(currentDemoIndex+1);
    // setup delay for demos that need time to develop proper look:
    int delay = 250;
    if (currentDemoIndex == 10) // Next is Realtime data demo
      delay = 12000;
    else if (currentDemoIndex == 15) // Next is Item demo
      delay = 5000;
    QTimer::singleShot(delay, this, SLOT(allScreenShots()));
  } else
  {
    qApp->quit();
  }
}

Qt Creator dan Kode

opencv-32

KDevelop, IDE Canggih di Linux

Bismillahirrahmanirrahim.

Saya mengenal KDevelop sejak saya mengenal KDE. Saya telah suka kepadanya walau saat itu saya belum mengenal pemrograman. Saat ini, KDevelop menarik perhatian saya kembali dengan fitur autocomplete-nya. KDevelop mampu membaca dan mem-parse header yang digunakan dalam 1 kode untuk memberikan saran autocomplete. Ini sangat membantu saya. Jadi, fitur autocomplete KDevelop beda dengan Kate (yang hanya melakukan autocomplete berdasar string yang sudah tertulis di dalam 1 kode). Fitur autocomplete canggih ini dimiliki oleh Qt Creator, tetapi karena saya ingin yang selain Qt Creator, akhirnya saya cari fitur ini untuk Kate. Karena saya menemukannya tetapi saya gagal memasangnya, maka saya kembali ke teman lama saya. Ya, KDevelop. Ini skrinsot-skrinsotnya.

opencv-23

opencv-24

opencv-26 opencv-25