반응형

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
:
반응형

JSON (JavaScript Object Notation)은 가벼운 data 교환 포멧이다. C++이 공식으로 지원하는 형식은 아니지만 분석에 사용 가능한 여러가지 라이브러리가 있다. 그 중 JsonCpp의 사용 방법이다.


홈페이지에서 소스를 다운 받고 압축을 풀면 아래와 같은 파일들이 나온다.


amalgamate.py를 실행한다.


dist라는 폴더에 소스파일과 헤더 파일이 생성된다.


makefiles - mscv2010 - jsoncpp.sln을 실행 한다.


Retarget Projects가 실행된다.


3개의 프로젝트가 나타난다.


각 프로젝트의 Property Pages - Configuration Properties - C/C++ - Code Generation - Runtime Library를 /MDd로 바꿔 준다.


Build 해 준다.


makefiles - msvc2010 - Debug 폴더에 lib_json.lib가 생성된다.


JsonCpp를 사용할 프로젝트를 만들고 Include Directory(jsoncpp-master\include)와 Library Directory(jsoncpp-master\makefiles\msvc2010\Debug)를 추가해 준다.




쓰기 예제

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
#pragma comment (lib, "lib_json.lib")
 
#include <iostream>
#include <fstream>
#include "json/json.h"
 
using namespace std;
using namespace Json;
 
int main()
{
    ofstream json_file;
    json_file.open("JSON_DATA.json");
 
    Value Computer;
    Computer["CPU"= "I7";
    Computer["RAM"= "16G";
 
    Value Language;
    Language["C++"= "Visual Studio";
    Language["Python"= "IDLE";
    
    Computer["Program"= Language;
    Computer["HDD"= "2TB";
 
    Value Cable;
    Cable.append("Power");
    Cable.append("Printer");
    Cable.append("Mouse");
 
    Computer["Computer"]["Cable"= Cable;
 
    Value number;
    number["Int"= 123;
    number["Double"= 456.012;
    number["Bool"= true;
 
    Computer["Computer"]["Number"= number;
 
    StreamWriterBuilder builder;
    builder["commentStyle"= "None";
    builder["indentation"= "    ";  // Tab
    unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
 
    // 알파벳 순으로 write 된다.
    writer->write(Computer, &cout);
    writer->write(Computer, &json_file);
    cout << endl;  // add lf and flush
 
    json_file.close();
 
    return 0;
}
cs


아래와 같은 결과가 출력 된다.


같은 결과의 JSON_DATA.json 파일이 생성 된다.

읽기 예제

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
#pragma comment (lib, "lib_json.lib")
 
#include <iostream>
#include <fstream>
#include "json/json.h"
 
using namespace std;
using namespace Json;
 
int main()
{
    ifstream json_dir("JSON_DATA.json");
    CharReaderBuilder builder;
    builder["collectComments"= false;
    Value value;
 
    JSONCPP_STRING errs;
    bool ok = parseFromStream(builder, json_dir, &value, &errs);
 
    if (ok == true)
    {
        cout << "CPU: " << value["CPU"<< endl;
        cout << "Program Python: " << value["Program"]["Python"<< endl;
        cout << "Computer Cable: " << value["Computer"]["Cable"<< endl;
        cout << "Computer Cable[0]: " << value["Computer"]["Cable"][0<< endl;
        cout << endl;
 
        cout << "Computer Number Int(as int): " << value["Computer"]["Number"].get("Int"-1).asInt() << endl;
        // "Int" 값이 없으면 -1 반환.
        cout << "Computer Number Int(as int): " << value["Computer"]["Number"]["Int"].asInt() << endl;
        // "Int" 값이 없으면 0 반환.
        cout << "Computer Number Double(as double): " << value["Computer"]["Number"].get("Double"-1).asDouble() << endl;
        // "Double" 값이 없으면 -1 반환.
        cout << "Computer Number Double(as string): " << value["Computer"]["Number"].get("Double""Empty").asString() << endl;
        // "Double" 값이 없으면 Empty 반환.
        cout << "Computer Number Bool(as bool): " << value["Computer"]["Number"].get("Bool"false).asBool() << endl;
        // "Bool" 값이 없으면 false 반환.
        cout << endl;
 
        cout << "Root size: " << value.size() << endl;
        cout << "Program size: " << value["Program"].size() << endl;
        cout << "Computer Cable size: " << value["Computer"]["Cable"].size() << endl;
        cout << endl;
 
        int size = value["Computer"]["Cable"].size();
        // size() 값을 for 문에서 그대로 비교하면 warning C4018가 발생 한다.
        for (int i = 0; i < size; i++)
            cout << "Computer Cable: " << value["Computer"]["Cable"][i] << endl;
        cout << endl;
 
        for (auto i : value["Computer"]["Cable"])
            cout << "Computer Cable: " << i << endl;
    }
    else
    {
        cout << "Parse failed." << endl;
    }
 
    return 0;
}
cs


아래와 같은 결과가 출력 된다.



반응형

'C, C++' 카테고리의 다른 글

Qt 스프라이트 애니매이션  (0) 2019.02.21
Qt 설치 및 간단한 사용 예  (4) 2019.01.16
Console 어플리케이션에 이미지 디스플레이 하기  (0) 2018.11.22
Python C API  (0) 2018.11.21
MySQL C API  (0) 2018.11.20
Posted by J-sean
:
반응형

Console에 이미지를 디스플레이 하는 간단한 코드.

윈도우 어플리케이션처럼 이미지가 지워졌을때 다시 그려주는 코드가 없기 때문에 커서 이동, 마우스 클릭등으로 이미지가 지워져도 다시 그려주지는 않는다.


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
#include<stdio.h>
#include<Windows.h>
 
int main(void)
{
    printf("Image loading...\n");
    Sleep(100); // 콘솔이 나타날때까지 잠시 멈추지 않으면 이미지가 표시되지 않는 경우가 생긴다.
 
    HWND hWnd = GetConsoleWindow();
    // Retrieves the window handle used by the console associated with the calling process.
 
    HBITMAP hImage, hOldBitmap;
 
    HDC hDC = GetDC(hWnd);
    HDC hMemDC = CreateCompatibleDC(hDC);
 
    hImage = (HBITMAP)LoadImage(NULL, TEXT("cat.bmp"), IMAGE_BITMAP, 00, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
    // Loads an icon, cursor, animated cursor, or bitmap.
 
    hOldBitmap = (HBITMAP)SelectObject(hMemDC, hImage);
    BitBlt(hDC, 505050 + 61250 + 409, hMemDC, 00, SRCCOPY); // Image(612, 409) at (50, 50)
    // The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels
    // from the specified source device context into a destination device context.
 
    SelectObject(hMemDC, hOldBitmap);
    DeleteObject(hImage);
    DeleteDC(hMemDC);
    ReleaseDC(hWnd, hDC);
 
    return 0;
}
cs


결과:






반응형

'C, C++' 카테고리의 다른 글

Qt 스프라이트 애니매이션  (0) 2019.02.21
Qt 설치 및 간단한 사용 예  (4) 2019.01.16
How to install and use JsonCpp - JsonCpp 설치 및 사용  (2) 2019.01.08
Python C API  (0) 2018.11.21
MySQL C API  (0) 2018.11.20
Posted by J-sean
:

Python C API

C, C++ 2018. 11. 21. 15:52 |
반응형

가장 간단하게 Python을 C에 embed 시키는 방법은 Very High Level interface를 사용 하는 것이다. VHL interface는 어플리케이션과 직접적인 상관 없이 Python script를 실행하기 위한 것이다.


관련 문서

Python/C API Reference Manual


우선 Python C API 관련 Include, Library 디렉토리를 프로젝트에 추가한다.


파이썬 공식 홈페이지에서 다운 받은 파이썬 인스톨러 패키지를 설치 했다면 Solution Configurations를 Release로 설정 한다. Debug 모드로 build 할 경우 pythonXX_d.lib를 찾을 수 없다는 에러가 발생한다. pythonXX_d.lib 파일을 생성하려면 파이썬 소스를 받아서 직접 컴파일해야 한다.


예제:

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
#pragma comment(lib, "python36.lib")
#include <Python.h>
 
int main(int argc, char *argv[])
{
    wchar_t *program = Py_DecodeLocale(argv[0], NULL);
    // Decode a byte string from the locale encoding with the surrogateescape error handler:
    // undecodable bytes are decoded as characters in range U+DC80..U+DCFF. If a byte sequence
    // can be decoded as a surrogate character, escape the bytes using the surrogateescape error
    // handler instead of decoding them.
    // Return a pointer to a newly allocated wide character string, use PyMem_RawFree() to free
    // the memory. If size is not NULL, write the number of wide characters excluding the null
    // character into *size
    if (program == NULL) {
        fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
        exit(1);
    }
    Py_SetProgramName(program);  /* optional but recommended */
    // This function should be called before Py_Initialize() is called for the first time, if it
    // is called at all.It tells the interpreter the value of the argv[0] argument to the main()
    // function of the program(converted to wide characters).This is used by Py_GetPath() and some
    // other functions below to find the Python run - time libraries relative to the interpreter
    // executable.
 
    Py_Initialize();
    // Initialize the Python interpreter. In an application embedding Python, this should be called
    // before using any other Python/C API functions
    if (Py_IsInitialized())
    // Return true (nonzero) when the Python interpreter has been initialized, false (zero) if not.
    // After Py_FinalizeEx() is called, this returns false until Py_Initialize() is called again.
    {
        PyRun_SimpleString("print('Hello Python')");
        // This is a simplified interface to PyRun_SimpleStringFlags(), leaving the PyCompilerFlags*
        // argument set to NULL.
        PyRun_SimpleString("from time import time, ctime\n"
            "print('Today is', ctime(time()))\n");
        //PyRun_SimpleString("from time import time, ctime\nprint('Today is', ctime(time()))\n");
 
        if (Py_FinalizeEx() < 0)
        // Undo all initializations made by Py_Initialize() and subsequent use of Python/C API
        // functions, and destroy all sub-interpreters that were created and not yet destroyed
        // since the last call to Py_Initialize().
        {
            exit(120);
        }
        PyMem_RawFree(program);
        // Frees the memory block pointed to by p, which must have been returned by a previous call
        // to PyMem_RawMalloc(), PyMem_RawRealloc() or PyMem_RawCalloc().
        // Otherwise, or if PyMem_RawFree(p) has been called before, undefined behavior occurs.
        // If p is NULL, no operation is performed.
    }
 
    return 0;
}
cs


반응형
Posted by J-sean
:

MySQL C API

C, C++ 2018. 11. 20. 11:31 |
반응형

MySQL C API 는 C 프로그램이 MySQL 데이터 베이스 내용에 접근 할 수 있도록 MySQL 서버/클라이언트 프로토콜의 저수준 접근을 제공 한다.

 

5.7 버전 참고 문서: MySQL C API

 

설정:

  • 버전 설정: X64

  • Project - XXX Properties... - Configuration Properties - C/C++ - General - Additional Include Directories - C:\Program Files\MySQL\MySQL Server 5.7\include 추가
  • Project - XXX Properties... - Configuration Properties - Linker - General - Additional Library Directories - C:\Program Files\MySQL\MySQL Server 5.7\lib 추가

 

 

  • Project - XXX Properties... - Configuration Properties - Linker - Input - Additional Dependencies - libmysql.lib 추가 하거나 소스에 아래 코드 추가
    #pragma comment (lib, "libmySQL.lib")
  • 실행파일 폴더에 libmysql.dll 복사

 

예제:

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
#include <my_global.h>
#include <mysql.h>
 
#pragma comment (lib, "libmySQL.lib")
 
int main()
{
    MYSQL mysql;            // MySQL 정보를 담을 구조체
    MYSQL* mysqlPtr = NULL;    // MySQL connection 핸들러
    MYSQL_RES* Result = NULL;        // 쿼리 성공시 결과를 담는 구조체 포인터
    MYSQL_ROW Row;            // 쿼리 성공시 결과로 나온 행의 정보를 담는 구조체
    int stat;                // 쿼리 요청 후 결과
 
    printf("MySQL Client Version: %s\n\n", mysql_get_client_info());
    // Returns client version information as a string
 
    mysql_init(&mysql); // Gets or initializes a MYSQL structure 
 
    mysqlPtr = mysql_real_connect(&mysql, "127.0.0.1""root""1234""shopdb"3306, (char*)NULL0);
    // Connects to a MySQL server
 
    if (mysqlPtr == NULL)
    {
        printf("MySQL connection error: %s\n", mysql_error(&mysql));
        // Returns the error message for the most recently invoked MySQL function
        return 1;
    }
 
    // MySQL에서 사용하는 문자세트를 Visual Studio가 사용하는 euc-kr로 바꾸기
    mysql_query(mysqlPtr, "set session character_set_connection=euckr");
    mysql_query(mysqlPtr, "set session character_set_results=euckr");
    mysql_query(mysqlPtr, "set session character_set_client=euckr");
 
    const char* Query = "SELECT * FROM memberTBL";
    stat = mysql_query(mysqlPtr, Query);    // Executes an SQLquery specified as a null-terminated string
    if (stat != 0)
    {
        printf("MySQL connection error: %s\n", mysql_error(&mysql));
        return 1;
    }
 
    Result = mysql_store_result(mysqlPtr);    // Retrieves a complete result set to the client
    while ((Row = mysql_fetch_row(Result)) != NULL)    // Fetches the next row from the result set 
    {
        printf("%s %s %s\n", Row[0], Row[1], Row[2]);
    }
 
    mysql_free_result(Result);    // Frees memory used by a result set
    mysql_close(mysqlPtr);    // Closes a server connection
 
    return 0;
}
cs

5.7 버전의 MySQL은 빌드하면 C2011('struct' type redefinition) 에러가 발생하는 경우가 있다.

C2011 에러가 발생 하면 my_global.h 파일에 #define HAVE_STRUCT_TIMESPEC 코드를 추가해 준다.

 

 

반응형
Posted by J-sean
: