Daily Archives: 11/01/2016

Qt 5 C++ – GUI

Những bài trước chủ yếu ta làm việc qua console. Từ bài này chúng ta sẽ bắt đầu làm việc với GUI, widgets.

Ở đây chúng ta sẽ cho hiển thị icon, tooltip. Hiển thị cửa sổ window ở giữa màn hình. Sau đó tìm hiểu qua về cơ chế Signal và Slot.

Ví dụ

#include <QApplication>
#include <QWidget>

int main(int argc, char *argv[]) {

    QApplication app(argc, argv);

    QWidget window;

    window.resize(250, 150);
    window.setWindowTitle("Simple example");
    window.show();

    return app.exec();
}

Ví dụ trên sẽ hiển thị một cửa sổ lên màn hình.

QApplication app(argc, argv);

Đây là đối tượng QApplication. Bất cứ project nào trong Qt 5 đều phải có dòng này. Trừ project console thì dùng QCoreApplication.

QWidget window;

Bạn có thể hiểu lớp QWidget là một lớp window, chuyên để tạo window :).

window.resize(250, 150);
window.setWindowTitle("Simple example");
window.show();

Thay đổi kích thước của widget, thêm tiêu đề cho widget rồi hiển thị lên màn hình.

return app.exec();

Cuối cùng app.exec() sẽ chạy chương trình.

Capture

Tooltip

Tooltip chính là các câu gợi ý khi bạn di chuyển chuột vào vị trí nào đó. Xem ví dụ.

#include <QApplication>
#include <QWidget>

int main(int argc, char *argv[]) {

  QApplication app(argc, argv);  

  QWidget window;

  window.resize(250, 150);
  window.move(300, 300);
  window.setWindowTitle("Simple Example");
  window.setToolTip("This is a tooltip");
  window.show();

  return app.exec();
}

Ví dụ này sẽ show tooltip khi bạn di chuyển chuột trên widget.

window.setWindowTitle("ToolTip");

Phương thức setToolTip() sẽ làm việc này.

Untitled

Icon

Chắc bạn cũng chẳng còn lạ lẫm gì với Icon. Xem ví dụ.

#include <QApplication>
#include <QWidget>
#include <QIcon>

int main(int argc, char *argv[]) {

  QApplication app(argc, argv);  
    
  QWidget window;

  window.resize(250, 150);
  window.setWindowTitle("Icon");
  window.setWindowIcon(QIcon("web.png"));
  window.show();

  return app.exec();
}

Icon sẽ hiện lên trên góc trái của widget.

window.setWindowIcon(QIcon("web.png"));

Để hiện icon thì bạn dùng phương thức setWindowIcon() và đưa vào đường dẫn đến một file ảnh bất kỳ.

Capture

Con trỏ chuột

#include <QApplication>
#include <QWidget>
#include <QFrame>
#include <QGridLayout>

class Cursors : public QWidget {

 public:
     Cursors(QWidget *parent = 0);
};

Cursors::Cursors(QWidget *parent)
    : QWidget(parent) {
    
  QFrame *frame1 = new QFrame(this);
  frame1->setFrameStyle(QFrame::Box);
  frame1->setCursor(Qt::SizeAllCursor);

  QFrame *frame2 = new QFrame(this);
  frame2->setFrameStyle(QFrame::Box);
  frame2->setCursor(Qt::WaitCursor);

  QFrame *frame3 = new QFrame(this);
  frame3->setFrameStyle(QFrame::Box);
  frame3->setCursor(Qt::PointingHandCursor);

  QGridLayout *grid = new QGridLayout(this);
  grid->addWidget(frame1, 0, 0);
  grid->addWidget(frame2, 0, 1);
  grid->addWidget(frame3, 0, 2);

  setLayout(grid);
}

int main(int argc, char *argv[]) {

  QApplication app(argc, argv);  
    
  Cursors window;

  window.resize(350, 150);
  window.setWindowTitle("Cursors");
  window.show();

  return app.exec();
}

Code ví dụ trên sẽ hiển thị 3 hình vuông trên 1 cửa sổ, mỗi lần bạn di chuột vào hình vuông khác thì con trỏ chuột sẽ hiển thị kiểu khác.

QFrame *frame1 = new QFrame(this);

Tạo một đối tượng QFrame, mình sẽ nói về QFrame ở bài viết khác.

frame1->setFrameStyle(QFrame::Box);

Phương thức setFrameStyle() để set style cho nó là Box, như thế sẽ thấy được đường viền của nó.

frame1->setCursor(Qt::SizeAllCursor);

Phương thức setCursor() để set kiểu con trỏ chuột, dùng các kiểu có sẵn trong Qt.

QGridLayout *grid = new QGridLayout(this);
grid->addWidget(frame1, 0, 0);
grid->addWidget(frame2, 0, 1);
grid->addWidget(frame3, 0, 2);
setLayout(grid);

QGridLayout sẽ tự động điều chỉnh vị trí các frame theo kiểu bảng. Chúng ta sẽ học về các layout này trong các bài viết sau.

QPushButton

QPushButton là lớp widget dùng để hiển thị nút bấm. Ví dụ dưới đây sẽ hiển thị một button, khi click vào nút thì thoát chương trình.

#include <QApplication>
#include <QWidget>
#include <QPushButton>

class MyButton : public QWidget {
    
 public:
     MyButton(QWidget *parent = 0);
};

MyButton::MyButton(QWidget *parent)
    : QWidget(parent) {
           
  QPushButton *quitBtn = new QPushButton("Quit", this);
  quitBtn->setGeometry(50, 40, 75, 30);

  connect(quitBtn, &QPushButton::clicked, qApp, &QApplication::quit);
}

int main(int argc, char *argv[]) {
    
  QApplication app(argc, argv);  
    
  MyButton window;

  window.resize(250, 150);  
  window.setWindowTitle("QPushButton");
  window.show();

  return app.exec();
}

Ví dụ trên có sử dụng cơ chế Signal Slot.

QPushButton *quitBtn = new QPushButton("Quit", this);
quitBtn->setGeometry(50, 40, 75, 30);

Tạo đối tượng QPushButton. Điều chỉnh kích thước và đưa nó lên cửa sổ bằng phương thức setGeometry().

connect(quitBtn, &QPushButton::clicked, qApp, &QApplication::quit);

Khi click vào nút bấm, một signal sẽ được phát ra. Slot là một phương thức của một đối tượng nào đó được dùng để nhận signal và xử lý signal đó. Trong trường hợp này là đối tượng qApp, đây là một biến toàn cục tham chiếu đến chương trình của chúng ta, bạn muốn tìm hiểu về nó có thể tìm đọc thêm về QAplication.

Capture

Signal và Slot

Chúng ta sẽ tìm hiểu thêm về Signal và slot bằng cách viết một chương trình tăng-giảm số đếm, signal và slot là cách mà các đối tượng giao tiếp với nhau trong Qt.

#pragma once

#include <QWidget>
#include <QApplication>
#include <QPushButton>
#include <QLabel>

class PlusMinus : public QWidget {
    
  Q_OBJECT

  public:
    PlusMinus(QWidget *parent = 0);

  private slots:
    void OnPlus();
    void OnMinus();

  private:
    QLabel *lbl;

};
class PlusMinus : public QWidget {
    
  Q_OBJECT
...  

Bạn phải thêm Q_OBJECT vào đầu định nghĩa lớp nếu muốn sử dụng signal và slot.

#include "plusminus.h"
#include <QGridLayout>

PlusMinus::PlusMinus(QWidget *parent)
    : QWidget(parent) {
        
  QPushButton *plsBtn = new QPushButton("+", this);
  QPushButton *minBtn = new QPushButton("-", this);
  lbl = new QLabel("0", this);
  
  QGridLayout *grid = new QGridLayout(this);
  grid->addWidget(plsBtn, 0, 0);
  grid->addWidget(minBtn, 0, 1);
  grid->addWidget(lbl, 1, 1);

  setLayout(grid);  

  connect(plsBtn, &QPushButton::clicked, this, &PlusMinus::OnPlus);
  connect(minBtn, &QPushButton::clicked, this, &PlusMinus::OnMinus);
}

void PlusMinus::OnPlus() {
    
  int val = lbl->text().toInt();
  val++;
  lbl->setText(QString::number(val));
}

void PlusMinus::OnMinus() {
    
  int val = lbl->text().toInt();
  val--;
  lbl->setText(QString::number(val));
}

Chúng ta có hai button và một label. Hai button này sẽ tăng hoặc giảm biến đếm và hiển thị biến đếm lên label.

connect(plsBtn, &QPushButton::clicked, this, &PlusMinus::OnPlus);
connect(minBtn, &QPushButton::clicked, this, &PlusMinus::OnMinus);

Ở đây chúng ta định nghĩa từng slot cho signal clicked.

void PlusMinus::OnPlus() {
    
  int val = lbl->text().toInt();
  val++;
  lbl->setText(QString::number(val));
}

Trong phương thức OnPlus() chúng ta lấy biến đếm từ label. Label này chỉ trả về 1 string nên chúng ta phải chuyển sang kiểu số. Sau đó chúng ta tăng con số đó lên rồi chuyển ngược lại string để hiển thị lên label.

#include "plusminus.h"

int main(int argc, char *argv[]) {
    
  QApplication app(argc, argv);  
    
  PlusMinus window;

  window.resize(300, 190);
  window.setWindowTitle("Plus minus");
  window.show();

  return app.exec();
}

File main.cpp.
Capture