Keras를 항상 급하게 수박 겉핥기식으로만 사용하다가 온라인 강좌를 들으며 실습하던 중 또 까먹을까봐 기록으로 남겨둠

 

데이터는 fasion_mnist(Keras 내장 데이터)

 

1. 검증데이터(테스트데이터) 없이 그냥 학습하기 - 생성된 모델의 evaluate 함수를 이용해서 테스트 데이터로 확인 가능하다

1-1) 데이터 읽어서 정규화(train, test)

(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

#데이터를 0~1 값으로 정규화
def get_preprocessed_data(images, labels):
    images = np.array(images/255.0, dtype=np.float32)
    labels = np.array(labels, dtype=np.float32)
    return images, labels

train_images, train_labels = get_preprocessed_data(train_images, train_labels)
test_images, test_labels = get_preprocessed_data(test_images, test_labels)

#print("train dataset shape:", train_images.shape, train_labels.shape)
#print("test dataset shape:", test_images.shape, test_labels.shape)

> 결과

train dataset shape: (60000, 28, 28) (60000,)
test dataset shape: (10000, 28, 28) (10000,)

1-2) 모델 생성

from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras.models import Sequential

model = Sequential([
    Flatten(input_shape=(28, 28)),
    Dense(100, activation='relu'),
    Dense(30, activation='relu'),
    Dense(10, activation='softmax')
])

model.summary()

>결과 : 1차원 배열 만들기

  - flatten -> dense : 784(flatten layer) x 100(dense layer) + 100(bias)

  - dense -> dense_1 : 100 x 30 + 30

  - dense_1 -> dense_2 : 30 x 10 + 10

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
flatten (Flatten)            (None, 784)               0         
_________________________________________________________________
dense (Dense)                (None, 100)               78500     
_________________________________________________________________
dense_1 (Dense)              (None, 30)                3030      
_________________________________________________________________
dense_2 (Dense)              (None, 10)                310       
=================================================================
Total params: 81,840
Trainable params: 81,840
Non-trainable params: 0

1-3) 모델 컴파일(전에 어디서 들었을 때는 생성된 노드들 조립하는 과정이라고 들었는데 맞는지는...????)

  - 분류 모델이므로 categorical_crossentropy

 

from tensorflow.keras.optimizers import Adam
from tensorflow.keras.losses import CategoricalCrossentropy
from tensorflow.keras.metrics import Accuracy

model.compile(optimizer=Adam(0.001), loss='categorical_crossentropy', metrics=['accuracy'])

1-4) 레이블을 원핫 인코딩으로 변경

from tensorflow.keras.utils import to_categorical

train_oh_labels = to_categorical(train_labels)
test_oh_labels = to_categorical(test_labels)

print(train_oh_labels.shape, test_oh_labels.shape)

>결과

(60000, 10) (10000, 10)

1-5) 학습하기

history = model.fit(x=train_images, y=train_oh_labels, batch_size=32, epochs=20, verbose=1)

> 결과

  - 데이터는 60000개, batch_size가 32개 이므로 데이터 전체를 1번 돌면 1875(60000/32)번에 나눠서 학습하게 된다

  - epoch가 20 이므로 20번을 학습

  - 그런데, loss와 accuracy는 학습데이터에서 추출하여 측정했으므로 학습데이터와 중복되어 overfitting 여부 확인 어려움

Epoch 1/20
1875/1875 [==============================] - 7s 3ms/step - loss: 0.5217 - accuracy: 0.8173
Epoch 2/20
1875/1875 [==============================] - 6s 3ms/step - loss: 0.3848 - accuracy: 0.8622
Epoch 3/20
1875/1875 [==============================] - 6s 3ms/step - loss: 0.3449 - accuracy: 0.8744
...............................................................
...............................................................
...............................................................
1875/1875 [==============================] - 5s 3ms/step - loss: 0.2013 - accuracy: 0.9238
Epoch 19/20
1875/1875 [==============================] - 5s 3ms/step - loss: 0.1993 - accuracy: 0.9246
Epoch 20/20
1875/1875 [==============================] - 5s 3ms/step - loss: 0.1924 - accuracy: 0.9275

1-6) loss와 accuracy 이력 보기

print(history.history['loss'])
print(history.history['accuracy'])

> 결과

[0.5217015743255615, 0.3847706913948059, 0.3449043929576874, 0.32317453622817993, 0.30555015802383423, 0.2914452850818634, 0.2787344753742218, 0.2689889371395111, 0.2602957487106323, 0.24981915950775146, 0.2438966929912567, 0.23561082780361176, 0.22739382088184357, 0.22206111252307892, 0.2169351726770401, 0.2127165049314499, 0.20825491845607758, 0.20133952796459198, 0.1992630511522293, 0.1923792064189911]
[0.8172666430473328, 0.8622000217437744, 0.8743500113487244, 0.8816999793052673, 0.8874333500862122, 0.8915833234786987, 0.8980833292007446, 0.8997166752815247, 0.9035999774932861, 0.9058499932289124, 0.9086833596229553, 0.9110833406448364, 0.9141833186149597, 0.9162166714668274, 0.9170833230018616, 0.9195833206176758, 0.9207833409309387, 0.9238499999046326, 0.9246166944503784, 0.9274666905403137]

1-7) 생성된 모델로 예측하기(2개이상의 이미지 & 1개의 이미지 예측)

#2개 이상의 이미지 입력시
pred_proba_multi = model.predict(test_images)
#특정 index의 예측값을 원핫인코딩->숫자값으로 변경
pred_multi = np.argmax(pred_proba_multi[0])

#1개의 이미지만 입력시에는 차원을 늘려서 입력해야 한다
pred_proba_single = model.predict(np.expand_dims(test_images[0], axis=0))
#다시 차원을 줄인다
pred_single = np.argmax(np.squeeze(pred_proba_single))
#pred_single = np.argmax(pred_proba_single[0])으로 해도 되지 않을까

class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat','Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
print('target class value:', test_labels[0], 'predicted class value:', pred_single)

> 결과

target class value: 9.0 predicted class value: 9

1-8) 테스트 데이터 셋으로 모델 검증하기

model.evaluate(test_images, test_oh_labels, batch_size=64)

>결과

157/157 [==============================] - 0s 2ms/step - loss: 0.3832 - accuracy: 0.8859
[0.38321688771247864, 0.8859000205993652]

 

 

2. 학습시 테스트 데이터의 accuracy와 loss 함께 확인하기

  - 기본적으로 학습이 시작되면(model.fit) 중간에 하이퍼파라미터를 변경할 수 없지만, callback을 통하여 변경가능함

2-1) 데이터를 불러와서 train 데이터를 나눔(train data -> train data & val data)

  - 데이터를 나눌 때 sklearn 이용함

  - 아래 코드에서는 15%의 데이터를 validation 데이터로 분리함

import numpy as np 
import pandas as pd
from tensorflow.keras.datasets import fashion_mnist

(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

def get_preprocessed_data(images, labels):
    images = np.array(images/255.0, dtype=np.float32)
    labels = np.array(labels, dtype=np.float32)
    
    return images, labels
    
train_images, train_labels = get_preprocessed_data(train_images, train_labels)
test_images, test_labels = get_preprocessed_data(test_images, test_labels)


from sklearn.model_selection import train_test_split
from tensorflow.keras.utils import to_categorical

# 기존 학습 데이터를 다시 학습과 검증 데이터 세트로 분리
tr_images, val_images, tr_labels, val_labels = train_test_split(train_images, train_labels, test_size=0.15, random_state=2021)
print('train과 validation shape:', tr_images.shape, tr_labels.shape, val_images.shape, val_labels.shape)

# OHE 적용
tr_oh_labels = to_categorical(tr_labels)
val_oh_labels = to_categorical(val_labels)

print('after OHE:', tr_oh_labels.shape, val_oh_labels.shape)

> 결과 (51000개의 train, 9000개의  val 데이터로 분리)

print('after OHE:', tr_oh_labels.shape, val_oh_labels.shape)
train과 validation shape: (51000, 28, 28) (51000,) (9000, 28, 28) (9000,)
after OHE: (51000, 10) (9000, 10)

2-2) 모델 생성은 같으나 학습시 validation 데이터를 레이블과 함께 tuple로 입력

from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras.models import Sequential
from tensorflow.keras.optimizers import Adam

INPUT_SIZE = 28
model = Sequential([
    Flatten(input_shape=(INPUT_SIZE, INPUT_SIZE)),
    Dense(100, activation='relu'),
    Dense(30, activation='relu'),
    Dense(10, activation='softmax')
])

model.compile(optimizer=Adam(0.001), loss='categorical_crossentropy', metrics=['accuracy'])


#validation data는 tuple 로 넣어준다
history = model.fit(x=tr_images, y=tr_oh_labels, batch_size=128, validation_data=(val_images, val_oh_labels), 
                    epochs=20, verbose=1)

> 결과 : val_loss, val_accuracy를 추가로 확인 가능하다

Epoch 1/20
399/399 [==============================] - 3s 4ms/step - loss: 0.6180 - accuracy: 0.7885 - val_loss: 0.4737 - val_accuracy: 0.8350
Epoch 2/20
399/399 [==============================] - 1s 3ms/step - loss: 0.4172 - accuracy: 0.8536 - val_loss: 0.4027 - val_accuracy: 0.8574
Epoch 3/20
399/399 [==============================] - 1s 3ms/step - loss: 0.3766 - accuracy: 0.8664 - val_loss: 0.3831 - val_accuracy: 0.8631
...................................................................
...................................................................
Epoch 18/20
399/399 [==============================] - 1s 3ms/step - loss: 0.2224 - accuracy: 0.9169 - val_loss: 0.3041 - val_accuracy: 0.8912
Epoch 19/20
399/399 [==============================] - 1s 3ms/step - loss: 0.2119 - accuracy: 0.9205 - val_loss: 0.3205 - val_accuracy: 0.8850
Epoch 20/20
399/399 [==============================] - 1s 3ms/step - loss: 0.2094 - accuracy: 0.9217 - val_loss: 0.3190 - val_accuracy: 0.8901

3. 그래프로도 확인 가능하다

import matplotlib.pyplot as plt
%matplotlib inline

plt.plot(history.history['accuracy'], label='accuracy')
plt.plot(history.history['val_accuracy'], label='val_accuracy')
plt.plot(history.history['loss'], label='loss')
plt.plot(history.history['val_loss'], label='val_loss')
plt.legend()

> 결과

<matplotlib.legend.Legend at 0x7f00188b7e10>

 

워낙 기초가 안되어 있다보니,

 

numpy 변수의 차원을 늘리는 것조차 급하면 생각이 안나서 기록해둠

 

print('test_images[0].shape : ', test_images[0].shape)

expand_dims_val0 = np.expand_dims(test_images[0], axis=0)
print('expand_dims_val0.shape : ', expand_dims_val0.shape)

expand_dims_val1 = np.expand_dims(test_images[0], axis=1)
print('expand_dims_val1.shape : ', expand_dims_val1.shape)

expand_dims_val2 = np.expand_dims(test_images[0], axis=2)
print('expand_dims_val1.shape : ', expand_dims_val2.shape)

print('squeeze_val0.shape : ', np.squeeze(expand_dims_val0).shape)
print('squeeze_val1.shape : ', np.squeeze(expand_dims_val1).shape)
print('squeeze_val2.shape : ', np.squeeze(expand_dims_val2).shape)

 

[결과]

test_images[0].shape :  (28, 28)
expand_dims_val0.shape :  (1, 28, 28)
expand_dims_val1.shape :  (28, 1, 28)
expand_dims_val1.shape :  (28, 28, 1)
squeeze_val0.shape :  (28, 28)
squeeze_val1.shape :  (28, 28)
squeeze_val2.shape :  (28, 28)

'파이썬' 카테고리의 다른 글

그래프의 개형을 그려보자  (0) 2021.04.17
pymodbus test  (0) 2021.03.25
Pandas 관련 이것저것  (0) 2021.03.06
[파이썬] 간단한 그래프 그리기  (0) 2021.02.22
KERAS Convolution 필터 데이터 저장하기  (0) 2020.12.09

브라우저를 통해 소켓 통신을 하게 되면 다음과 같은 동작들이 일어나게 되는데, 

 

다음의 각 부분을 상세히 기록해보려고 한다.

 

아래 이미지도 나중에 바뀔 예정임

 

일단 허접하게라도 적어놔야 시작할 것 같아서....

 

 

 

윈도우 이벤트 구현을 WaitForSingleObject 나 WaitForMultipleObjects를 이용해서 구현하다가

 

리눅스에서 구현하기 위해서 이래저래 알아보다 구현 방법정리함.

 

 

1. 변수 선언

std::condition_variable trigger_event;
std::mutex              trigger_mutex;
int                     trigger_type = 0;
int                     trigger_state = 0;

 

2. 트리거 기다리는 부분

while(1){
    std::unique_lock<std::mutex> lk(trigger_mutex);
    if (trigger_event.wait_for(lk, 500ms, [] {
        return trigger_state == 1; })
    )
{
    trigger_state = 0;
    switch(trigger_type){
        case 0:
            break;
        case 1:
            break;
    }
}

 

3. 트리거 발생 부분

trigger_state = 1;
trigger_event.notify_one();

 

 

 

 

미국 출장을 가야 하는 건 알고 있었지만, 날짜가 확정되지 않아 마음을 놓고 있던 터에

 

 갑자기 출장을 오라는 통보를 받아서

 

다른 건 준비하면 되는데, 출국 72시간 안에 코로나 검사를 받아서

 

영문 음성 증명서를 받아야 출국이 가능하다는데,

 

화요일  18시 40분 비행기라서, 가능한 시간이 토요일 18시 40분 부터였다.

 

그런데, 부산인데다가 토요일 그시간에는 검사를 해주는 곳이 없고,

 

일요일도 검사는 간간이 하는데, 영문 음성 증명서를 발급해 주는 곳은 없었다.

 

그래서 이래저래 알아보다가 찾은 후보들을 기록해놓고자 이 글을 남긴다.

 

1. 해운대 백병원

 

" rel="noopener" data-mce-href="http://">http://

 - 집에서 가깝고 1일만에 나와서 처음에는 여기서 검사를 하려고 했으나, 

 

  월요일에 검사하고, 화요일 오전에 영문 결과지를 받아서 가야 하는데,

 

  김해공항 가는길이 지체되면 큰일 나기 때문에

 

  최악의 경우 오후에 검사 결과가 나올수도 있다는 말에 다른 대안을 찾음

 

  검사를 하고 나서 영문 증명서 발급도 번호표 뽑고 기다리고 이런 절차가 오전에 시간을 지체할 수 있어

 

  지금 보니 이렇게 하지 않아서 다행이었다고 생각하는데 잘 모르겠음

 

 

 

2. 보훈 병원

" rel="noopener" data-mce-href="http://">http://

 

웹으로 검사 받은 사람들의 평을 검색해보니, 결과도 빨리 나온다고 하고, 김해공항 가는 길이라 여기를 후보지로 결정했었음. 단점은 주차가 힘들다고 하는데, 나는 택시타고 갈 예정이어서 별 문제는 안되겠다 싶었음 

 

 

2. 부산 의료원

" rel="noopener" data-mce-href="http://">http://

 

최종적으로 여기서 했는데, 

이유는 일요일에도 검사가 가능하고, 월요일에 증명서를 받으러 가면 되서 

출발 당일 안 서둘러도 된다는 이유에서이다.

하지만, 월요일 증명서 받으러 가니 사람이 바글바글 함. -_-;

증명서 받는데 생각보다 오래 걸렸음

 

'기타' 카테고리의 다른 글

소켓통신 원리(1)  (0) 2021.10.22
Linux C++ 이벤트  (0) 2021.10.06
키보드 후킹을 이용한 바코드 읽기  (0) 2021.05.07
자동차 번호판 학습하기  (1) 2021.04.19
jetson board Performance  (0) 2021.03.25

 

 

 

1. MainActivity

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="vertical">

        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tabRoot"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <com.google.android.material.tabs.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="탭1" />

            <com.google.android.material.tabs.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="탭2" />

            <com.google.android.material.tabs.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="탭3" />

            <com.google.android.material.tabs.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="탭4" />
        </com.google.android.material.tabs.TabLayout>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <FrameLayout
            android:id="@+id/tab_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        </FrameLayout>
    </LinearLayout>
</LinearLayout>

 

package org.hdongle.layouttest;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import com.google.android.material.tabs.TabLayout;

public class MainActivity extends AppCompatActivity {
    TabLayout tabRoot;
    Fragment1 fragment1;
    Fragment2 fragment2;
    Fragment3 fragment3;
    Fragment4 fragment4;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        fragment1 = new Fragment1();
        fragment2 = new Fragment2();
        fragment3 = new Fragment3();
        fragment4 = new Fragment4();

        tabRoot = findViewById(R.id.tabRoot);
        tabRoot.removeAllTabs();
        tabRoot.addTab(tabRoot.newTab().setText("1번탭"));
        tabRoot.addTab(tabRoot.newTab().setText("2번탭"));
        tabRoot.addTab(tabRoot.newTab().setText("3번탭"));
        tabRoot.addTab(tabRoot.newTab().setText("4번탭"));

        getSupportFragmentManager().beginTransaction().replace(R.id.tab_container, fragment1).commit();

        tabRoot.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                switch(tab.getPosition())
                {
                    case 0:
                        getSupportFragmentManager().beginTransaction().replace(R.id.tab_container, fragment1).commit();
                        break;
                    case 1:
                        getSupportFragmentManager().beginTransaction().replace(R.id.tab_container, fragment2).commit();
                        break;
                    case 2:
                        getSupportFragmentManager().beginTransaction().replace(R.id.tab_container, fragment3).commit();
                        break;
                    case 3:
                        getSupportFragmentManager().beginTransaction().replace(R.id.tab_container, fragment4).commit();
                        break;
                }
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });

    }
}

 

2. Tab1 & Fragment1

 - getChildFragmentManager()를 활용한 중첩 Fragment

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:orientation="vertical">

        <EditText
            android:id="@+id/editTextTextPersonName2"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:ems="10"
            android:inputType="textPersonName"
            android:text="Name" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal">

            <Button
                android:id="@+id/btn1_1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="4dp"
                android:layout_marginRight="2dp"
                android:layout_weight="1"
                android:text="탭1-1" />

            <Button
                android:id="@+id/btn1_2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="2dp"
                android:layout_marginRight="2dp"
                android:layout_weight="1"
                android:text="탭1-2" />

            <Button
                android:id="@+id/btn1_3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="2dp"
                android:layout_marginRight="4dp"
                android:layout_weight="1"
                android:text="탭1-3" />

        </LinearLayout>
    </LinearLayout>

    <FrameLayout
        android:id="@+id/tab1_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>
public class Fragment1 extends Fragment {
    Fragment1_1 fragment1_1;
    Fragment1_2 fragment1_2;
    Fragment1_3 fragment1_3;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //return super.onCreateView(inflater, container, savedInstanceState);
        ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment1, container, false);

        fragment1_1 = new Fragment1_1();
        fragment1_2 = new Fragment1_2();
        fragment1_3 = new Fragment1_3();

        getChildFragmentManager().beginTransaction().replace(R.id.tab1_container, fragment1_1).commit();

        Button btn = rootView.findViewById(R.id.btn1_1);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getChildFragmentManager().beginTransaction().replace(R.id.tab1_container, fragment1_1).commit();
            }
        });

        btn = rootView.findViewById(R.id.btn1_2);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getChildFragmentManager().beginTransaction().replace(R.id.tab1_container, fragment1_2).commit();
            }
        });

        btn = rootView.findViewById(R.id.btn1_3);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getChildFragmentManager().beginTransaction().replace(R.id.tab1_container, fragment1_3).commit();
            }
        });

        return rootView;
    }
}

3. 1-1 화면들(1-2, 1-3 화면은 생략)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="4dp"
            android:text="Tab1_1 - Top"
            android:textSize="30sp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.498"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="bottom"
            android:text="Tab1_1 - Bottom"
            android:textSize="30sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>

</LinearLayout>
package org.hdongle.layouttest;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class Fragment1_1 extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //return super.onCreateView(inflater, container, savedInstanceState);
        ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment1_1, container, false);
        return rootView;
    }
}

 

4. Fragment2(Fragment3, 4는 생략)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="4dp"
            android:text="Tab2 - Top"
            android:textSize="30sp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.498"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="bottom"
            android:text="Tab2 - Bottom"
            android:textSize="30sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>

</LinearLayout>
package org.hdongle.layouttest;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class Fragment2 extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //return super.onCreateView(inflater, container, savedInstanceState);
        ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment2, container, false);
        return rootView;
    }
}

 

 

 

 

 

 

 

 

1. Empty Activity 프로젝트 생성

 

2. 프로젝트에서 마우스 우클릭 > New > Layout Resource File > fragment_top.xml 입력

3. 2번에서 생성한 Layout 변경

  1) Layout : Linear Layout(orientation : vertical)

  2) 상단에 Plain Text

  3) 하단에 Linear Layout (orientation : horizontal) - 버튼 5개

4. java class 추가 : TopFragment.java

5. fragment_bottom_all.xml Layout 생성

  * TextView 추가

    - Text : "전체화면"

    - TextSize : 30sp

 

6. 같은 방법으로 layout들을 추가한다

  1) fragment_bottom_1.xml

  2) fragment_bottom_2.xml

  3) fragment_bottom_3.xml

  4) fragment_bottom_4.xml

7. 생성한 layout들과 연결될 java class를 생성함

1) TopFragment.java

public class TopFragment extends Fragment {

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //return super.onCreateView(inflater, container, savedInstanceState);

        //Layout xml과 연결
        ViewGroup rootView = (ViewGroup)inflater.inflate(R.layout.fragment_top, container, false);

        Button btnAll = rootView.findViewById(R.id.btnAll);
        btnAll.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MainActivity mainActivity = (MainActivity)getActivity();
                if(mainActivity != null)
                    mainActivity.FragmentChange(0);
            }
        });
        Button btn1 = rootView.findViewById(R.id.btn1);
        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MainActivity mainActivity = (MainActivity)getActivity();
                if(mainActivity != null)
                    mainActivity.FragmentChange(1);
            }
        });
        Button btn2 = rootView.findViewById(R.id.btn2);
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MainActivity mainActivity = (MainActivity)getActivity();
                if(mainActivity != null)
                    mainActivity.FragmentChange(2);
            }
        });
        Button btn3 = rootView.findViewById(R.id.btn3);
        btn3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MainActivity mainActivity = (MainActivity)getActivity();
                if(mainActivity != null)
                    mainActivity.FragmentChange(3);
            }
        });
        Button btn4 = rootView.findViewById(R.id.btn4);
        btn4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MainActivity mainActivity = (MainActivity)getActivity();
                if(mainActivity != null)
                    mainActivity.FragmentChange(4);
            }
        });
        return rootView;
    }
}

2) BottomAllFragment.java

public class BottomAllFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //return super.onCreateView(inflater, container, savedInstanceState);
        ViewGroup rootView = (ViewGroup)inflater.inflate(R.layout.fragment_bottom_all, container, false);

        return rootView;
    }
}

3) Bottom1Fragment.java

public class Bottom1Fragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //return super.onCreateView(inflater, container, savedInstanceState);
        ViewGroup rootView = (ViewGroup)inflater.inflate(R.layout.fragment_bottom_1, container, false);

        return rootView;
    }
}

4) Bottom2Fragment.java

public class Bottom2Fragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //return super.onCreateView(inflater, container, savedInstanceState);
        ViewGroup rootView = (ViewGroup)inflater.inflate(R.layout.fragment_bottom_2, container, false);

        return rootView;
    }
}

5) Bottom3Fragment.java

public class Bottom3Fragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //return super.onCreateView(inflater, container, savedInstanceState);
        ViewGroup rootView = (ViewGroup)inflater.inflate(R.layout.fragment_bottom_3, container, false);

        return rootView;
    }
}

6) Bottom4Fragment.java

public class Bottom4Fragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //return super.onCreateView(inflater, container, savedInstanceState);
        ViewGroup rootView = (ViewGroup)inflater.inflate(R.layout.fragment_bottom_4, container, false);

        return rootView;
    }
}

 

8. MainActivity를 다음과 같이 코딩한다

 

1) MainActivity.java

public class MainActivity extends AppCompatActivity {

    private FragmentManager fragmentManager;
    private Fragment[] fragments;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        fragmentManager = (FragmentManager)getSupportFragmentManager();
        fragments = new Fragment[5];
        fragments[0] = new BottomAllFragment();
        fragments[1] = new Bottom1Fragment();
        fragments[2] = new Bottom2Fragment();
        fragments[3] = new Bottom3Fragment();
        fragments[4] = new Bottom4Fragment();

        FragmentChange(0);

    }

    public void FragmentChange(int idx)
    {
        if(idx >=0 && idx < 5)
        {
            fragmentManager.beginTransaction().replace(R.id.bottom_container, fragments[idx]).commit();
        }
    }
}

2) activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">


    <FrameLayout
        android:id="@+id/top_container"
        android:layout_width="match_parent"
        android:layout_height="100dp">
        <fragment
            android:id="@+id/topFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:name="org.hdongle.tab2test.TopFragment">
        </fragment>
    </FrameLayout>

    <FrameLayout
        android:id="@+id/bottom_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </FrameLayout>
</LinearLayout>

 

 

 

급조해서 구글링 한 뒤 짠거라 코드가 허접하다..-_-;

정리도 안되어 있다. 그래도 돌아간다.

나중에 정리해야히 하면서 정리 안할듯...

 

    public class KeyboardHook
    {
        public struct BarCodes
        {
            public int VirtKey;     //Virtual Code  
            public int ScanCode;    //Scan Code  
            public string KeyName;  //Key Name  
            public uint AscII;      //AscII  
            public char Chr;        //character  

            public string BarCode;  //Bar code information  
            public bool IsValid;    //Is the bar code valid  
            public DateTime Time;   //Scan time  
        }

        private struct EventMsg
        {
            public int message;
            public int paramL;
            public int paramH;
            public int Time;
            public int hwnd;
        }

        static BarCodes barCode = new BarCodes();

        public delegate void ProcessCode(string code);
        public static ProcessCode ProcCode;

        [DllImport("user32.dll")]
        static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc callback, IntPtr hInstance, uint threadId);

        [DllImport("user32.dll")]
        static extern bool UnhookWindowsHookEx(IntPtr hInstance);

        [DllImport("user32.dll")]
        static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, int wParam, IntPtr lParam);

        [DllImport("kernel32.dll")]
        static extern IntPtr LoadLibrary(string lpFileName);

        [DllImport("user32.dll")]
        static extern uint MapVirtualKey(uint uCode, uint uMapType);

        [DllImport("user32", EntryPoint = "GetKeyNameText")]
        private static extern int GetKeyNameText(int lParam, StringBuilder lpBuffer, int nSize);

        [DllImport("user32", EntryPoint = "GetKeyboardState")]
        private static extern int GetKeyboardState(byte[] pbKeyState);

        [DllImport("user32", EntryPoint = "ToAscii")]
        private static extern bool ToAscii(int VirtualKey, int ScanCode, byte[] lpKeyState, ref uint lpChar, int uFlags);


        private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
        
        
        const int WH_KEYBOARD_LL = 13;
        const int WM_KEYDOWN     = 0x100;

        private static LowLevelKeyboardProc _proc = hookProc;
        private static IntPtr hhook = IntPtr.Zero;
        static string strBarCode = "";

        public static IntPtr hookProc(int code, IntPtr wParam, IntPtr lParam)
        {
            if(code == 0)
            {
                EventMsg msg = (EventMsg)Marshal.PtrToStructure(lParam, typeof(EventMsg));

                if(wParam == (IntPtr)WM_KEYDOWN)
                {
                    barCode.VirtKey  = msg.message & 0xff;  //Virtual Code
                    barCode.ScanCode = msg.paramL & 0xff;   //Scan Code


                    
                    uint nonVirtualKey = MapVirtualKey((byte)barCode.VirtKey, 2);
                    if (nonVirtualKey != 0)
                    {
                        barCode.Chr = Convert.ToChar(nonVirtualKey);
                        if (DateTime.Now.Subtract(barCode.Time).TotalMilliseconds > 50)
                        {
                            strBarCode = barCode.Chr.ToString();
                        }
                        else
                        {
                            if ((msg.message & 0xff) == 13 && strBarCode.Length > 3)  //Enter  
                            {
                                barCode.BarCode = strBarCode;
                                barCode.IsValid = true;

                                ProcCode?.Invoke(strBarCode);
                            }
                            strBarCode += barCode.Chr.ToString();
                        }

                        barCode.Time = DateTime.Now;
                        barCode.IsValid = false;
                    }
                    
                }
            }
            //
            return CallNextHookEx(hhook, code, (int)wParam, lParam);
        }
        
        public static void SetHook()
        {
            IntPtr hInstance = LoadLibrary("User32");
            hhook = SetWindowsHookEx(WH_KEYBOARD_LL, _proc, hInstance, 0);
        }

        public static void UnHook()
        {
            UnhookWindowsHookEx(hhook);
        }
    }

 

실제로 갖다 쓸때는 다음과 같이 하면 된다

//1. Form_Load같은 초기화 코드
KeyboardHook.SetHook();
KeyboardHook.ProcCode += ProcessCode;

//2. Form_Closing시
KeyboardHook.UnHook();

//3. 바코드가 읽어지면 호출되는 함수
private void ProcessCode(string code)
{
	this.Invoke(new MethodInvoker(delegate ()
	{
		MessageBox.Show(code);
	}));

}

 

'기타' 카테고리의 다른 글

Linux C++ 이벤트  (0) 2021.10.06
(부산)해외 출국을 위한 영문 코로나 음성 검사 증명서  (0) 2021.07.30
자동차 번호판 학습하기  (1) 2021.04.19
jetson board Performance  (0) 2021.03.25
Jetson Xavier boot from SSD  (0) 2021.03.24

1. Fragment 생성(MainFragment, MenuFragment)

2. 다음의 창이 나타나면 이름 입력(TestFrament => MainFragment)

3. MainFragment는 MainActivity의 xml에 바로 등록한다. MainActivity는 FrameLayout으로 변경

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >
    <fragment
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="org.hdongle.fragment.MainFragment"
        android:id="@+id/mainFragment">

    </fragment>
</FrameLayout>

4. 각각의 fragment들을 다음과 같이 바꾼다

 

* fragment_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFEB3B"
    android:orientation="vertical"
    tools:context=".MainFragment">

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center|center_vertical"
        android:text="메인 프레그먼트"
        android:textSize="50sp" />

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#FFC107"
        android:text="화면전환" />
</LinearLayout>

* fragment_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#0000FF"
    android:orientation="vertical"
    tools:context=".MainFragment">

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center|center_vertical"
        android:text="메뉴 프레그먼트"
        android:textSize="50sp" />

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#FFC107"
        android:text="돌아가기" />
</LinearLayout>

 

5. Fragment들의 java에 다음과 같이 코딩한다

 

*MainFragment.java

package org.hdongle.fragment;

import android.os.Bundle;

import androidx.fragment.app.Fragment;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

public class MainFragment extends Fragment {

    //xml layout을 메모리에 올리는 역할을 한다.
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        //return inflater.inflate(R.layout.fragment_main, container, false);
        ViewGroup vg = (ViewGroup)inflater.inflate(R.layout.fragment_main, container, false);
        Button button = vg.findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MainActivity mainActivity = (MainActivity)getActivity();
                mainActivity.OnFragmentChanged(1);
            }
        });

        return vg;
    }
}

 

* MenuFragment.java

package org.hdongle.fragment;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import androidx.fragment.app.Fragment;

public class MenuFragment extends Fragment {

    //xml layout을 메모리에 올리는 역할을 한다.
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        ViewGroup rootView = (ViewGroup)inflater.inflate(R.layout.fragment_menu, container, false);

        Button button = rootView.findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MainActivity activity = (MainActivity)getActivity();
                activity.OnFragmentChanged(0);
            }
        });

        return rootView;
        //return inflater.inflate(R.layout.fragment_menu, container, false);
    }
}

 

6. MainActivity에 다음과 같이 코드를 넣어준다

* 핵심 코드 : container(FrameLayout)에 Fragment를 교체해준다

public class MainActivity extends AppCompatActivity {

    MainFragment mainFragment;
    MenuFragment menuFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mainFragment = (MainFragment)getSupportFragmentManager().findFragmentById(R.id.mainFragment);
        menuFragment = new MenuFragment();
    }

    public void OnFragmentChanged(int idx)
    {
        if(idx == 0)
        {
            getSupportFragmentManager().beginTransaction().replace(R.id.container, mainFragment).commit();
        }
        else if(idx == 1){
            getSupportFragmentManager().beginTransaction().replace(R.id.container, menuFragment).commit();
        }
    }
}

 

1. Main Activity의 Layout을 LinearLayout으로 변경, orientation은 Vertical로 변경

2. 다음과 같은 구조로 컨트롤 추가

 * LinearLayout(vertical)

     > LinearLayout(horizontal)

         > Button(id:btnView1, layout_width:0dp, layout_marginLeft:10dp, layout_marginRight:5dp, layout_weight:1, text:1번화면)

         > Button(id:btnView2, layout_width:0dp, layout_marginLeft: 5dp, layout_marginRight:5dp, layout_weight:1, text:2번화면)

         > Button(id:btnView1, layout_width:0dp, layout_marginLeft: 5dp, layout_marginRight:10dp, layout_weight:1, text:3번화면)

     > LinearLayout(id : container)

3. 좌측 프로젝트 창에서 app/res/layout 메뉴에서 마우스 우클릭한 뒤 나타나는 메뉴에서 New > Activity > Empty Activity 선택 후 activity를 3개 생성한다. (sub1.xml, sub2.xml, sub3.xml)

 

4. 각 Activity의 Layout을 LinearLayout(vertical)로 변경 후 각 화면에 TextView 하나씩 추가 한 뒤 화면 번호 입력

5. 다음과 같이 하면 View가 계속 바뀔줄 알았는데, 한번만 바뀌고 마네..-_-

public class MainActivity extends AppCompatActivity {

    LinearLayout container;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btn = findViewById(R.id.btnView1);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ChangeView(0);
            }
        });

        btn = findViewById(R.id.btnView2);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ChangeView(1);
            }
        });

        btn = findViewById(R.id.btnView3);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ChangeView(2);
            }
        });

        container = findViewById(R.id.container);
    }

    public void ChangeView(int index)
    {
        LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        container.removeAllViews();
        
        switch(index)
        {
            case 0:
                inflater.inflate(R.layout.sub1, container, true);
                //inflater.inflate(null, container, true);
                break;
            case 1:
                inflater.inflate(R.layout.sub2, container, true);
                //inflater.inflate(null, container, true);
                break;
            case 2:
                inflater.inflate(R.layout.sub3, container, true);
                //inflater.inflate(null, container, true);
                break;
        }


    }
}

 

'앱개발' 카테고리의 다른 글

Fragment를 이용한 sub화면 전환  (0) 2021.05.09
Fragment  (0) 2021.05.05
[안드로이드] 화면 회전 2  (0) 2021.04.30
[안드로이드] 버튼 상태 drawable  (0) 2021.04.26
[안드로이드] 텍스트  (0) 2021.04.24

+ Recent posts