Qt 5 C++ – Menu và toolbar

5/5 - (1 vote)

Trong bài này chúng ta sẽ học về cách làm menu và toolbar trong một ứng dụng Qt 5.

Ví dụ

Đoạn code dưới đây sẽ hiển thị một menu đơn giản.

#pragma once

#include <QMainWindow>
#include <QApplication>

class SimpleMenu : public QMainWindow {

  public:
    SimpleMenu(QWidget *parent = 0);
};
#include "simplemenu.h"
#include <QMenu>
#include <QMenuBar>

SimpleMenu::SimpleMenu(QWidget *parent)
    : QMainWindow(parent) {
    
  QAction *quit = new QAction("&Quit", this);

  QMenu *file;
  file = menuBar()->addMenu("&File");
  file->addAction(quit);

  connect(quit, &QAction::triggered, qApp, QApplication::quit);
}

Đoạn code trên sẽ tạo ra menu File. Một lớp muốn có menu thì lớp này phải kế thừa từ QMainWindow.

QAction *quit = new QAction("&Quit", this);

Dòng code trên tạo một đối tượng QAction. Một action là một lớp chuyên để thực hiện một lệnh nào đó. Lý do tại sao nên dùng action thì bạn để ý trong một ứng dụng GUI thông thường có rất nhiều cách để thi hành một công việc nào đó, chẳng hạn muốn thoát Qt Creator thì bạn có thể bấm vào dấu “X” trên góc phải của Qt Creator, hoặc vào menu File→Quit, hoặc bấm Ctrl+Q, tất cả ba cách trên đều làm chung một việc, nên tốt nhất là ta connect cả ba cách đó vào một action. Một QMenu có thể có một hoặc nhiều action.

QMenu *file;
file = menuBar()->addMenu("&File");

Tạo một đối tượng QMenu.

file->addAction(quit);

Dùng phương thức addAction() để thêm action.

connect(quit, &QAction::triggered, qApp, QApplication::quit);

Sau đó connect action này với phương thức quit() của qApp. Nếu chưa biết qApp là gì thì bạn có thể tìm phần trước của bài này để đọc.

#include "simplemenu.h"

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

  QApplication app(argc, argv);  
    
  SimpleMenu window;

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

  return app.exec();
}

Untitled

Icon, shortcut, separator

Trong phần này chúng ta sẽ tùy biến menu bằng cách thêm icon, phím tắt (shortcut) và các dòng phân cách – separator.

#pragma once

#include <QMainWindow>
#include <QApplication>

class AnotherMenu : public QMainWindow {
    
  public:
    AnotherMenu(QWidget *parent = 0);
};
#include "anothermenu.h"
#include <QMenu>
#include <QMenuBar>

AnotherMenu::AnotherMenu(QWidget *parent)
    : QMainWindow(parent) {
          
  QPixmap newpix("new.png");
  QPixmap openpix("open.png");
  QPixmap quitpix("quit.png");

  QAction *newa = new QAction(newpix, "&New", this);
  QAction *open = new QAction(openpix, "&Open", this);
  QAction *quit = new QAction(quitpix, "&Quit", this);
  quit->setShortcut(tr("CTRL+Q"));

  QMenu *file;
  file = menuBar()->addMenu("&File");
  file->addAction(newa);
  file->addAction(open);
  file->addSeparator();
  file->addAction(quit);
  
  qApp->setAttribute(Qt::AA_DontShowIconsInMenus, false);

  connect(quit, &QAction::triggered, qApp, &QApplication::quit);
}

Trong ví dụ này chúng ta tạo ra một menu với ba action, nhưng chỉ dùng tới action quit thôi. Ngoài ra ta sẽ thêm một dòng phân cách và phím tắt Ctrl+Q. 

QPixmap newpix("new.png");
QPixmap openpix("open.png");
QPixmap quitpix("quit.png");

Đây là hình icon cho menu. Lưu ý có một số môi trường không cho phép hiển thị icon trên menu.

QAction *newa = new QAction(newpix, "&New", this);
QAction *open = new QAction(openpix, "&Open", this);
QAction *quit = new QAction(quitpix, "&Quit", this);

Đoạn code trên tạo QAction với tham số đầu tiên là icon mà nó sẽ dùng.

quit->setShortcut(tr("CTRL+Q"));

Tạo phím tắt, cứ mỗi lần bấm tổ hợp đúng tổ hợp phím thì chương trình sẽ thoát.

file->addSeparator();

Thêm dòng phân cách. Dòng phân cách chẳng qua chỉ là một đường kẻ ngang để gộp nhóm một số action có chung đặc điểm lại với nhau.

qApp->setAttribute(Qt::AA_DontShowIconsInMenus, false);

Như đã nói ở trên, trong một số môi trường icon sẽ không được hiển thị, nhưng chúng ta có thể bắt nó hiển thị bằng cách đưa thuộc tính Qt::AA_DontShowIconsInMenus thành false.

#include "anothermenu.h"

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

  QApplication app(argc, argv);  
    
  AnotherMenu window;

  window.resize(350, 200);
  window.setWindowTitle("Simple menu");
  window.show();

  return app.exec();
}

File main.

Untitled

Check menu

Ví dụ dưới đây sẽ tạo ra menu có thể check được. Chúng ta sẽ tạo ra một thanh trạng thái (statusbar), cứ mỗi lần check hoặc bỏ check menu này thì statusbar sẽ hiện hoặc ẩn.

#pragma once

#include <QMainWindow>
#include <QApplication>

class Checkable : public QMainWindow {
    
  Q_OBJECT  

  public:
    Checkable(QWidget *parent = 0);
 
  private slots:
    void toggleStatusbar();

  private:
    QAction *viewst;
};
#include "checkable.h"
#include <QMenu>
#include <QMenuBar>
#include <QStatusBar>

Checkable::Checkable(QWidget *parent)
    : QMainWindow(parent) {

  viewst = new QAction("&View statusbar", this);
  viewst->setCheckable(true);
  viewst->setChecked(true);

  QMenu *file;
  file = menuBar()->addMenu("&File");
  file->addAction(viewst);

  statusBar();

  connect(viewst, &QAction::triggered, this, &Checkable::toggleStatusbar);
}

void Checkable::toggleStatusbar() {
    
  if (viewst->isChecked()) {
      
      statusBar()->show();
  } else {
      
      statusBar()->hide();
  }
}

Check menu sẽ làm ẩn hoặc hiện statusbar.

viewst = new QAction("&View statusbar", this);
viewst->setCheckable(true);
viewst->setChecked(true);

Phương thức setCheckable() để chuyển menu thành dạng có thể check được. Rồi dùng phương thức setChecked() để làm cho menu đó đã check rồi nếu thích.

if (viewst->isChecked())     
    statusBar()->show();
else     
    statusBar()->hide();

Phương thức toggleStatusbar() sẽ làm cho thanh statusbar ẩn hoặc hiện.

#include "checkable.h"

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

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

  return app.exec();
}

Untitled

QToolBar

Lớp QToolBar sẽ hiển thị một thanh ngang chứa các nút lệnh cho ứng dụng, ngoài ra bạn có thể dùng chuột kéo thanh này sang trái, phải hoặc nằm dưới.

#pragma once

#include <QMainWindow>
#include <QApplication>

class Toolbar : public QMainWindow {
    
  Q_OBJECT  

  public:
    Toolbar(QWidget *parent = 0);
};
#include "toolbar.h"
#include <QToolBar>
#include <QIcon>
#include <QAction>

Toolbar::Toolbar(QWidget *parent)
    : QMainWindow(parent) {
    
  QPixmap newpix("new.png");
  QPixmap openpix("open.png");
  QPixmap quitpix("quit.png");
  
  QToolBar *toolbar = addToolBar("main toolbar");
  toolbar->addAction(QIcon(newpix), "New File");
  toolbar->addAction(QIcon(openpix), "Open File");
  toolbar->addSeparator();
  QAction *quit = toolbar->addAction(QIcon(quitpix), 
      "Quit Application");
  
  connect(quit, &QAction::triggered, qApp, &QApplication::quit);
}

Lưu ý là luôn phải kế thừa từ lớp QMainWindow nếu muốn tạo menu hoặc toolbar.

QToolBar *toolbar = addToolBar("main toolbar");

Phương thức addToolBar() sẽ tạo một toolbar.

toolbar->addAction(QIcon(newpix), "New File");
toolbar->addAction(QIcon(openpix), "Open File");
toolbar->addSeparator();

Tạo hai action và một separator.

#include "toolbar.h"

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

  window.resize(300, 200);
  window.setWindowTitle("QToolBar");
  window.show();

  return app.exec();
}

Capture

Khung chương trình mẫu

Để kết thúc bài này, chúng ta sẽ tạo ra một khung chương trình mẫu.

#pragma once

#include <QMainWindow>
#include <QApplication>

class Skeleton : public QMainWindow {
    
  Q_OBJECT  

  public:
    Skeleton(QWidget *parent = 0);
};
#include <QMenu>
#include <QMenuBar>
#include <QStatusBar>
#include <QTextEdit>
#include <QToolBar>
Skeleton::Skeleton(QWidget *parent)
    : QMainWindow(parent) {
        
  QPixmap newpix("new.png");
  QPixmap openpix("open.png");
  QPixmap quitpix("quit.png");

  QAction *quit = new QAction("&Quit", this);

  QMenu *file;
  file = menuBar()->addMenu("&File");
  file->addAction(quit);

  connect(quit, &QAction::triggered, qApp, &QApplication::quit);
  
  QToolBar *toolbar = addToolBar("main toolbar");
  toolbar->addAction(QIcon(newpix), "New File");
  toolbar->addAction(QIcon(openpix), "Open File");
  toolbar->addSeparator();
  
  QAction *quit2 = toolbar->addAction(QIcon(quitpix), 
      "Quit Application");
  connect(quit2, &QAction::triggered, qApp, &QApplication::quit);

  QTextEdit *edit = new QTextEdit(this);  

  setCentralWidget(edit);

  statusBar()->showMessage("Ready");
}

Trong ví dụ này  chúng ta tạo cả toolbar và statusbar.

QTextEdit *edit = new QTextEdit(this);  

setCentralWidget(edit);

Tạo một đối tượng QTextEdit và đặt nó ngay giữa QMainWindow.

#include "skeleton.h"

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

  window.resize(350, 250);
  window.setWindowTitle("Application skeleton");
  window.show();

  return app.exec();
}

Capture

0 0 votes
Article Rating
Subscribe
Thông báo cho tôi qua email khi
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

4 Comments
Inline Feedbacks
View all comments
Quy
Quy
3 năm trước

Hi ad !

Ad cho mình hỏi ngoài lề bài này 1 chút với nhé
Chương trình dưới đây của mình chỉ nhận được sự kiện chuột khi thao tác trên form, còn ngoài form thì mình chưa biết viết thế nào, mong ad gợi ý giúp mình

void MainWindow::mousePressEvent(QMouseEvent *e)
{
if(e->button() == Qt::RightButton)
{
ui->textEdit->setText(“chuột phải”);
}
if(e->button() == Qt::LeftButton)
{
ui->textEdit->setText(“chuột trái”);
}
}

Thanks !

Quy
Quy
3 năm trước
Reply to  Phở Code

Nghĩa là mình cần bắt sự kiện kích chuột mà nằm ở ngoài giao diện mình đang viết đó, ví dụ kích chuột ở ngoài desktop chẳng hạn

Thanks !