Qt platform plugin error fix

C, C++ 2021. 9. 26. 15:14 |
반응형

Qt로 작성된 프로그램을 Qt Creator에서 실행하면 잘 되지만 실행 파일을 직접 실행하면 아래와 같은 에러가 발생한다.

 

 

This application failed to start because no Qt platform plugin could be initialized. 라는 메세지에서 알 수 있는 것 처럼 platform plugin이 없기 때문이다.

 

Qt 설치 폳더에서 platforms 폴더를 복사한다.

 

실행 파일이 있는 폴더에 붙여 넣는다.

Debug, Release 모두 동일하다.

그 외, 필요한 dll 파일도 모두 복사해 넣고 실행하면 문제없이 실행된다.

 

반응형
Posted by J-sean
:
반응형

Linux가 아닌 Windows에서는 Microsoft Visual C++을 사용하는 경우가 많다. 아래 링크와 같이 Qt를 설치한다.

2021.09.25 - [C, C++] - Qt6 설치 및 간단한 사용법

 

Qt Widgets Application 프로젝트를 생성하고 프로젝트명.pro 파일을 확인한다.

 

프로젝트명.pro 파일을 위와 같이 수정한다. (opencv는 C:\opencv에 설치되어 있다)

CONFIG(debug, debug|release) {
    LIBS += -lopencv_world453d
}

CONFIG(release, debug|release) {
    LIBS += -lopencv_world453
}

opencv_world453은 C:\opencv\build\x64\vc15\bin 폴더의 opencv_worldXXX.dll, opencv_worldXXXd.dll 파일을 참고해 작성한다.

 

Projects - Build & Run - Run - Environment - Path 에 C:\opencv\build\x64\vc15\bin을 추가한다.

 

UI Design에서 Pushbutton을 하나 추가하고 우클릭 - Go to slot...을 클릭한다.

 

 

clicked()를 선택한다.

 

on_pushButton_clicked()를 위와 같이 수정한다. (상단에 opencv.hpp가 include 되어있다)

 

프로젝트를 빌드하고 XXX-Debug 폴더에 사진 파일을 복사한다.

 

실행하면 위와 같은 위도우가 나타난다. PushButton을 클릭하자.

 

 

Barbara palvin 사진이 출력된다.

 

반응형
Posted by J-sean
:
반응형

Qt6는 더 이상 오프라인 인스톨러를 제공하지 않는다. 오픈소스 온라인 인스톨러를 다운 받고 설치하자.

예전에는 Qt에 가입할 필요는 없었지만 지금은 아이디가 필요하다. 설치 전 미리 가입하자.

 

Latest releases - Qt - Qt 6.X.X - MSVC 2019 64-bit 만 선택하고 Developer and Designer Tools는 기본 상태 그대로 설치한다.

 

Qt 설치가 완료되면 Visual Studio - Extensions - Manage Extensions를 클릭한다.

 

Online - Visual Studio Marketplace에서 qt를 검색하고 Qt Visual Studio Tools를 설치한다. (Visual Studio 재시작이 필요하다)

 

Extensions - Qt VS Tools - Options를 클릭한다.

 

 

사용할 Qt를 추가해 주어야 한다. +아이콘을 클릭하고 Path를 클릭한다.

 

Qt가 설치된 디렉토리에서 qmake.exe 파일을 선택한다.

 

위 그림과 같이 설정 되었다면 OK를 클릭한다.

 

Qt Widgets Application 프로젝트를 만들자.

 

 

프로젝트 이름, 위치등을 지정하고 Create 버튼을 클릭한다.

 

Qt Widgets Application Wizard가 실행된다.

 

적당한 옵션을 선택한다.

 

적당한 옵션을 지정하고 Finish 버튼을 클릭한다.

 

 

소스파일이 표시된다.

 

Solution Explorer에서 UI 디자인 파일을 더블 클릭한다.

 

UI 디자인 화면이 표시된다.

 

Project Property Pages - Configuration Properties - C/C++ - Language를 클릭한다

 

 

Qt6는 C++ 17을 사용한다.

 

소스나 UI 수정없이 빌드하고 실행했을 때 위와 같은 위도우가 뜨면 성공이다. 

 

그런데 UI 디자인툴에서 PushButton - 우클릭을 해도 'Go to slot...'에 해당하는 명령어가 나오지 않는다.

그 뿐만 아니라 프로젝트 생성시 Qt Creator와 생성되는 파일도 다르고 코드를 작성해도 이해할 수 없는 방식으로 작동한다.

 

Qt Creator를 실행하고 Projects - New를 클릭한다.

 

 

Application (Qt) - Qt Widgets Application을 선택한다. 나머지 옵션은 적당히 선택한다.

 

Visual Studio와는 약간 다른 파일들이 생성되었다.

 

Forms - mainwindow.ui를 더블 클릭한다.

 

Label과 Pushbutton을 적당히 배치하고 Pushbutton에서 우클릭 - Go to slot...을 클릭한다.

 

 

clicked()를 선택하고 OK 버튼을 클릭한다.

 

mainwindow.cpp에 on_pushButton_clicked()가 생성되었다. (mainwindow.h 파일도 변경된다)

 

mainwindow.h 파일을 위와 같이 수정한다.

 

mainwindow.cpp 파일을 위와 같이 수정하고 빌드한다.

 

 

프로젝트를 실행하면 위와 같은 윈도우가 나타난다.

 

Pushbutton을 클릭하면 Label이 변경된다.

 

Pushbutton을 클릭할때마다 Label은 계속 변경된다.

다른 간단한 예제는 아래 링크를 참고한다.

2019.01.16 - [C, C++] - Qt 설치 및 간단한 사용 예

2019.02.21 - [C, C++] - Qt 스프라이트 애니매이션

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 OpenCV 이미지(cv::Mat)를 Qt로(QImage::QImage) 디스플레이 해 보자.

(cv::Mat ↔  QImage::QImage)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <opencv2/opencv.hpp>
 
class Picture : public QWidget
{
public:
    Picture(QWidget* parent = 0);
    ~Picture();
 
protected:
    void paintEvent(QPaintEvent* event);
    // This event handler can be reimplemented in a subclass to receive paint events passed in event.
    void drawPicture(QPainter* qp);
    QImage Mat2QImage(cv::Mat const& src);
    cv::Mat QImage2Mat(QImage const& src);
 
private:
    int height;
    int width;
    QImage qtImage;
    cv::Mat cvImage;
};
 
Picture::Picture(QWidget* parent) : QWidget(parent)
{
    //image.load("Barbara Palvin.png");
    //cvimage = QImage2Mat(image);
 
    //Read images from OpenCV. Not from Qt.
    cvImage = cv::imread("Barbara Palvin.png", cv::IMREAD_COLOR);
    if (cvImage.empty())
    {
        std::cerr << "Image load failed." << std::endl;
 
        exit(EXIT_FAILURE);
    }
 
    cv::Mat tempCvImage;
    cv::cvtColor(cvImage, tempCvImage, cv::COLOR_RGB2GRAY);
 
    qtImage = Mat2QImage(tempCvImage);
    tempCvImage = QImage2Mat(qtImage);
 
    cv::resize(tempCvImage, tempCvImage, cv::Size(), 1.51.5);
    cv::imshow("OpenCV", tempCvImage);
 
    height = qtImage.height();
    width = qtImage.width();
 
    this->resize(width, height);
}
 
Picture::~Picture()
{
 
}
 
void Picture::paintEvent(QPaintEvent* e)
{
    Q_UNUSED(e);
    // Q_UNUSED( name)
    // Indicates to the compiler that the parameter with the specified name is not used in the body
    // of a function. This can be used to suppress compiler warnings while allowing functions to be
    // defined with meaningful parameter names in their signatures.
 
    QPainter qp(this);
    drawPicture(&qp);
}
 
void Picture::drawPicture(QPainter* qp)
{
    qp->drawImage(00, qtImage);
}
 
QImage Picture::Mat2QImage(cv::Mat const& src)
{
    cv::Mat temp;
    cv::cvtColor(src, temp, cv::COLOR_BGR2RGB);
    QImage dest((const uchar*)temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
    dest.bits();
    // Enforce deep copy
    // See documentation of QImage::QImage (const uchar * data, int width, int height, Format format)
 
    return dest;
}
 
cv::Mat Picture::QImage2Mat(QImage const& src)
{
    cv::Mat temp(src.height(), src.width(), CV_8UC3, (uchar*)src.bits(), src.bytesPerLine());
    cv::Mat result; // Deep copy
    cv::cvtColor(temp, result, cv::COLOR_BGR2RGB);
 
    return result;
}
 
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
 
    Picture window;
    window.setWindowTitle("Qt");
    //window.resize(width, height);
 
    window.show();
 
    return app.exec();
}
 
 

 

소스를 입력한다. (qtcv.cpp)

 

컴파일(빌드)하고 실행하면 cv::imshow(), QPainter::drawImage() 모두 잘 표시된다. (OpenCV는 50% 확대)

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 Qt5를 이용해 이미지를 디스플레이 해 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <QApplication>
#include <QWidget>
#include <QPainter>
 
class Picture : public QWidget
{
public:
    Picture(QWidget* parent = 0);
 
protected:
    void paintEvent(QPaintEvent* event);
    // This event handler can be reimplemented in a subclass
    // to receive paint events passed in event.
    void drawPicture(QPainter* qp);
 
private:
    int height;
    int width;
    QImage image;
};
 
Picture::Picture(QWidget* parent) : QWidget(parent)
{
    image.load("Barbara Palvin.png");
    height = image.height();
    width = image.width();
 
    this->resize(width, height);
}
 
void Picture::paintEvent(QPaintEvent* e)
{
    Q_UNUSED(e);
    // Q_UNUSED( name)
    // Indicates to the compiler that the parameter with the
    // specified name is not used in the body of a function.
    // This can be used to suppress compiler warnings while
    // allowing functions to be defined with meaningful
    // parameter names in their signatures.
 
    QPainter qp(this);
    drawPicture(&qp);
}
 
void Picture::drawPicture(QPainter* qp)
{
    qp->drawImage(00, image);
}
 
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
 
    Picture window;
    window.setWindowTitle("Picture Example");
    //window.resize(width, height);
 
    window.show();
 
    return app.exec();
}
 
 

소스를 입력한다. (qt.cpp)

 

컴파일(빌드)하고 실행하면 이미지가 디스플레이된다.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 Qt5를 이용해 GUI 프로그래밍을 해 보자.

 

Qt5를 설치한다.

 

단순한 window를 만드는 소스를 입력한다. (qt.cpp)

 

-fPIC 옵션과 함께 컴파일(빌드)하고 생성된 파일을 실행하면 Simple Example 윈도우가 나타난다.

 

이번엔 같은 소스를 qmake를 이용해 컴파일(빌드)해 보자. -project 옵션과 함께 실행하면 c.pro 파일이 생성된다. (디렉토리 이름.pro)

 

 

c.pro 파일의 내용을 보면 Qt Widgets 모듈이 포함되지 않았다.

 

파일의 끝에 Qt Widgets 모듈을 포함시킨다.

 

qmake, make 명령을 차례로 실행하면 컴파일(빌드)이 완료된다.

 

컴파일(빌드)된 파일을 실행하면 윈도우가 나타난다.

 

반응형
Posted by J-sean
:
반응형

2021.09.25 - [C, C++] - Qt6 설치 및 간단한 사용법

 

Qt의 Pixmap을 이용해 간단한 스프라이트 애니매이션을 구현 할 수 있다.

 

아래와 같은 스프라이트 이미지를 준비 한다. 

horse.zip
다운로드

이 중 처음 11개의 달리는 이미지 프레임만 사용한다.

 

 

Qt Widgets Application으로 기본 설정들을 적용해서 프로젝트를 만든다. (D:\Horse)

 

 

프로젝트를 만든 후 바로 build 디렉토리가 만들어지지 않으므로 build를 한 번 진행 한다.

 

build 디렉토리에 준비한 스프라이트 이미지를 복사한다.

 

mainwindow.h 에 아래와 같이 추가 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QMainWindow>
#include <QTimer>
#include <QPainter>
#include <QDebug>
 
namespace Ui {
class MainWindow;
}
 
class Sprite
{
public:
    Sprite(QSize winsize);
    void Draw(QPainter* painter);   // 현재 프레임 그리기
    void NextFrame();   // 다음 프레임 지정
 
private:
    QPixmap* SpriteImage;   // 스프라이트
    int CurrentFrame;   // 현재 프레임
    int TotalFrame; // 전체 프레임 수(11)
    int Column; // 스프라이트내 프레임 열(4)
    int Row;    // 스프라이트내 프레임 행(3) (실제 사용되지는 않음)
    int FramesizeX; // 한 프레임의 X 길이(128)
    int FramesizeY; // 한 프레임의 Y 길이(128)
    QPoint FramePosition;   // 스프라이트내 현재 프레임의 픽셀 단위 위치
    QPoint DrawPosition;    // 윈도우에서 프레임이 그려질 위치
    QSize MainWindowSize;   // 윈도우 사이즈
};
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
 
    virtual void paintEvent(QPaintEvent* event);
 
private:
    Ui::MainWindow *ui;
 
    Sprite* sprite; // 스프라이트
    QTimer* timer;  // 타이머
};
 
#endif // MAINWINDOW_H
cs

 

 

mainwindow.cpp 에 아래와 같이 추가 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include "mainwindow.h"
#include "ui_mainwindow.h"
 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 
    sprite = new Sprite(this->size());
    timer = new QTimer(this);
    timer->start(50);   // 20Hz 타이머 시작
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));    // timeout() 시그널이 발생하면 update() 실행
    // connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)
    // Creates a connection of the given type from the signal in the sender object to the method in the receiver object.
    // Returns a handle to the connection that can be used to disconnect it later. You must use the SIGNAL() and SLOT() macros
    // when specifying the signal and the method.
}
 
MainWindow::~MainWindow()
{
    delete timer;
    delete sprite;
 
    delete ui;
}
 
void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter paint(this);   // The QPainter class performs low-level painting on widgets and other paint devices.
    sprite->Draw(&paint);
    sprite->NextFrame();
}
 
// 128X128 사이즈, 4X3배열의 11개 프레임
Sprite::Sprite(QSize winsize) : CurrentFrame(0), TotalFrame(11), Column(4), Row(3), FramesizeX(128), FramesizeY(128), FramePosition(00)
{
    MainWindowSize = winsize;   // 메인 윈도우 사이즈
    qDebug() << "Main Window Size: " << MainWindowSize << endl// Application Output 창에 메인 윈도우 사이즈(400X300) 출력
    SpriteImage = new QPixmap("horse.png"); //The QPixmap class is an off-screen image representation that can be used as a paint device.
    qDebug() << "Sprite Size: " << SpriteImage->size() << endl;    // Application Output 창에 스프라이트 사이즈(512X1024) 출력
 
    // 메인 윈도우 중앙에 프레임 출력
    DrawPosition.setX(MainWindowSize.width() / 2 - FramesizeX / 2);
    DrawPosition.setY(MainWindowSize.height() / 2 - FramesizeY / 2);
}
 
void Sprite::Draw(QPainter* painter)
{
    // Draws a pixmap at (x, y) by copying a part of the given pixmap into the paint device.
    painter->drawPixmap(DrawPosition.x(), DrawPosition.y(), *SpriteImage, FramePosition.x(), FramePosition.y(), FramesizeX, FramesizeY);
 
    // 'Running horse' 문자열 출력
    const QRect rect = QRect(00, MainWindowSize.width(), MainWindowSize.height() / 2);
    painter->setPen(Qt::blue);
    painter->setFont(QFont("Arial"30));
    painter->drawText(rect, Qt::AlignCenter, "Running horse");
}
 
void Sprite::NextFrame()
{
    if (CurrentFrame >= TotalFrame) // 11번 째 프레임을 넘어가면 0으로 초기화
        CurrentFrame = 0;
 
    // 출력할 프레임의 픽셀 단위 위치 지정
    FramePosition.setX((CurrentFrame % Column) * FramesizeX);
    FramePosition.setY((CurrentFrame / Column) * FramesizeY);
 
    CurrentFrame++;
}
cs

 

프로젝트를 build하고 실행하면 아래와 같은 애니매이션이 재생된다.

 

Application Output 창에는 Main Window와 Sprite 사이즈가 표시 된다.

 

iCCP 관련 warning은 무시하거나 이 링크를 참고해서 제거한다.

 

 

반응형
Posted by J-sean
:
반응형

2021.09.25 - [C, C++] - Qt6 설치 및 간단한 사용법

2021/02/13 - [C, C++] - Linux(Ubuntu) Qt5 Image Display - 리눅스(우분투) Qt5 이미지 디스플레이

2021/02/12 - [C, C++] - Linux(Ubuntu) Qt5 GUI Programming - 리눅스(우분투) Qt5 GUI 프로그래밍

 

Qt는 GUI 프로그램 개발에 널리 쓰이는 크로스 플랫폼 프레임워크이다. 홈페이지에서 Open Source 버전을 다운 받아 실행 한다.

 

기본설정에서 MSVC 2017 64-bit만 추가한다.

 

Qt 설치가 완료되면 Visual Studio에서도 사용 할 수 있도록 Extension을 설치 한다.

 

Online에서 qt를 검색해 Qt Visual Studio Tools를 설치한다.

 

설치가 완료되면 Qt Options를 선택 한다.

 

 

Qt가 설치된 위치의 msvc2017_64 폴더를 Add 한다.

 

설치가 완료 되었으면 Qt Creator를 실행하고 Qt Widgets Application 프로젝트를 만들어 준다.

 

프로젝트 폴더 선택 외에는 기본값으로 진행 한다.

 

설정이 완료되면 아래와 같은 화면이 나온다.

 

 

Forms - Mainwindow.ui 디자인 화면에서 PushButton과 Label을 적당한 위치에 배치한다. Label은 기본 크기보다 약간 크게 늘려 준다.

Label의 Property에서 alignment - Horizontal을 AlignHCenter로 바꿔준다.

 

PushButton에서 오른쪽 클릭 - Go to slot... 을 선택한다.

 

QAbstractButton - clicked() 를 선택한다.

 

mainWindow.cpp 에 on_pushButton_clicked() 가 생성된다.

 

 

mainwindow.h 에 QMessageBox 헤더 파일을 include 하고 IsClicked, OriginalStatus, MsgBox 멤버 변수를 추가한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QMainWindow>
#include <QMessageBox>
 
namespace Ui {
class MainWindow;
}
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
 
private slots:
    void on_pushButton_clicked();
 
private:
    Ui::MainWindow *ui;
 
    bool IsClicked;
    QString OriginalStatus;
    QMessageBox MsgBox;
};
 
#endif // MAINWINDOW_H
cs

 

mainwindow.cpp 에서 constructor와 on_pushButton_clicked() 를 아래와 같이 수정해 준다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include "mainwindow.h"
#include "ui_mainwindow.h"
 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 
    IsClicked = false;
    OriginalStatus = ui->pushButton->styleSheet();
    ui->label->setText("Unchanged");
    MsgBox.setWindowTitle("Sean");
    MsgBox.setText("Button Color Change");
    MsgBox.setInformativeText("Do you want to change button color?");
    MsgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
    MsgBox.setDefaultButton(QMessageBox::Yes);
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
 
void MainWindow::on_pushButton_clicked()
{
    if (IsClicked == false)
    {
        int ret = MsgBox.exec();
 
        switch(ret)
        {
            case QMessageBox::Yes:
                ui->pushButton->setStyleSheet("color: blue;"
                                              "background-color: red;");
                ui->label->setText("Changed");
                IsClicked = !IsClicked;
                break;
 
            case QMessageBox::No:
                ui->label->setText("No");
                break;
 
            default:
                ui->label->setText("Cancel");
                break;
        }
    } else {
        IsClicked = !IsClicked;
        ui->pushButton->setStyleSheet(OriginalStatus);
        ui->label->setText("Unchanged");
    }
}
cs

 

 

빌드(Ctrl + B) 후 실행 (Ctrl + R) 한다.

 

PushButton을 클릭하면 MessageBox가 나온다.

 

Yes를 클릭하면 PushButton의 색과 Label 의 text가 변한다.

 

 

반응형
Posted by J-sean
: