@echo off
:: C 드라이브의 text.txt 파일을 D 드라이브로 복사하는 경우
copy C:\text.txt D:\text.txt
:: C 드라이브의 text.txt 파일을, 현재 bat 파일이 실행되는 경로로 복사하는 경우
copy C:\text.txt %cd%\text.txt
2. 디렉토리 생성
md [생성할 디렉토리 경로]
- md 대신 mkdir을 써도 된다. (make directory의 약자)
@echo off
:: C 드라이브 안에 test라는 폴더를 생성한다
md C:\test
:: 현재 배치파일이 실행되는 경로 안에, test라는 폴더를 생성한다.
md %cd%\test
:: 디렉토리가 없는 경우 생성한다.
if not exist "%cd%\test" (
md %cd%\test
)
3. 디렉토리 삭제
rd [삭제할 디렉토리 경로]
- rd 대신 rmdir을 써도 된다. (remove directory의 약자)
- rd는 디렉토리가 비어 있는 경우만 삭제된다.
- /s 옵션 : 디렉토리가 비어 있지 않은 경우에도 삭제한다. (삭제 여부 물음)
- /q 옵션 : 삭제 여부를 묻지 않고 삭제한다.
@echo off
:: C 드라이브의 test라는 폴더 삭제 (디렉토리가 비어있는 경우만 삭제됨)
rd C:\test
:: C 드라이브의 test라는 폴더와, 그 안의 내용까지 모두 삭제 (삭제 여부 물음, y 입력 시 삭제됨)
rd /s C:\test
:: C 드라이브의 test라는 폴더와, 그 안의 내용까지 모두 삭제 (삭제 여부 묻지 않고 삭제함)
rd /s /q C:\test
4. 파일 삭제
개별 파일을 삭제하는 방법이다. (디렉토리 삭제를 원하는 경우, 위의 rd 명령어 사용)
del [삭제할 파일 경로]
- 삭제할 파일 경로에 와일드 카드를 사용하면, 여러 개의 파일 삭제 가능 (예: *.exe 는 확장자가 exe인 모든 파일 삭제)
- 삭제할 파일 경로에 디렉토리명을 지정하면, 해당 디렉토리 내의 모든 파일 삭제(디렉토리는 남아있음)
- /P 옵션 : 각 파일 삭제 전에 삭제여부를 묻게 함 (y 입력 시 삭제됨)
- /F 옵션 : 읽기전용 파일 삭제함
@echo off
:: C 드라이브 안의 test.txt라는 파일 삭제
del C:\test.txt
:: 현재 디렉토리 안의 모든 exe 파일 삭제
del %cd%\*.exe
:: C:\BAT 라는 폴더 안의 모든 파일 삭제 (BAT이라는 폴더 자체는 삭제되지 않고 남아있음)
del C:\BAT
:: C 드라이브 안의 test.txt라는 파일 삭제시, 삭제 여부 물음 (y 입력 시 삭제됨)
del /P C:\test.txt
:: C 드라이브 안의 test.txt라는 읽기 전용 파일 삭제 (그냥 del 명령만으로는 읽기전용 파일은 삭제 안됨)
del /F C:\test.txt
5. 배치파일 실행 인자 받기
배치파일 실행 시 인자를 넘겨 받으려면, %1 ~ %9의 특수한 환경변수를 사용하면 된다.
예) <strong> 태그를 써서 특정 글자를 진하게 표현하고 싶다던가, <h4> 등의 제목 태그를 쓰고 싶다던가, <br/> 태그를 써서 줄바꿈을 하고 싶다던가..
이럴 때에는 setTextFormat(Qt::RichText); 함수로, 텍스트 포맷을 RichText로 설정해 주면 된다.
QMessageBox msg(this);
msg.setIcon(QMessageBox::Information);
msg.setTextFormat(Qt::RichText);
msg.setWindowTitle(tr("Title"));
msg.setText(tr("<strong>Hello!</strong><br/>World!");
msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
if (msg.exec() == QMessageBox::Yes) {
// do something on Yes
}
else {
// do something on No
}
.NET Framework플랫폼에는 Windows Forms와 WPF의 두 가지 GUI 라이브러리가 포함되어 있다.
Windows Forms는 쉬운 난이도 덕분에 초보자가 접하기에도 용이하다. 또한C#은C++과는 비교도 되지 않는 높은 생산성을 자랑하는 언어이며, 기존 윈도용 C/C++ 프로젝트나 라이브러리와의 연동도 수월하므로 일단 핵심 코드는 그대로 둔 채 껍데기부터 차차 교체할 수도 있다.
WPF(Windows Presentation Foundation)은 무료 오픈소스 그래픽 라이브러리로, .Net Framework 3.0의 일부로 처음 출시되었다.
Qt는 컴퓨터 프로그래밍에서GUI프로그램 개발에 널리 쓰이는 오픈 소스C++개발프레임워크이다. C++와 QML이라는 자체 스크립트 언어를 기반으로 한다. 회사 내부에서는 Qt를 "cute"로 발음하고 있으며 비공식적으로는 "큐티"로 발음한다. Qt는KDE,Qtopia,OPIE에 이용되고 있다.
"Write once, compile anywhere"를 표방하는 크로스 플랫폼 프레임워크이며, 현존하는 주요 플랫폼(Windows, Linux, OSX, Android, iOS 등)을 거의 대부분 지원한다. 초기에는 크로스플랫폼GUI 라이브러리로 시작하였으나, 점점 기능이 확대되어 각종 UI 개발 도구, 번역 작업을 위한 도구와 C++ 개발에 필요한 온갖 기능(UI,XML, 네트워크,SVG, Animation, Container Class 등등)을 제공하는 종합 프레임워크가 되었다
Qt는C++를 주로 사용하지만,파이썬,루비,C,펄,파스칼과도 연동된다. 수많은 플랫폼에서 동작하며, 상당히 좋은 국제화를 지원한다.SQL데이터베이스 접근,XML처리,스레드관리, 단일 크로스 플랫폼 파일 관리API를 제공한다.
void TreeDialog::on_itemClicked(QTreeWidgetItem *item, int column)
{
displayCurrentItem(item, column);
}
displayCurrentItem 함수
void TreeDialog::displayCurrentItem(QTreeWidgetItem *item, int column)
{
if (item) {
ui->labelCurrentItem->setText(item->data(column, Qt::DisplayRole).toString());
}
}
클릭한 데이터 행을 위/아래로 옮기기
아이템 클릭 후, Up 또는 Down 버튼을 누르면, 해당 아이템을 위로 올리거나 아래로 내린다.
enum Direction {
Up = -1,
Down = 1
};
void TreeDialog::on_pushButtonUp_clicked()
{
moveItem(Direction::Up);
}
void TreeDialog::on_pushButtonDown_clicked()
{
moveItem(Direction::Down);
}
void TreeDialog::moveItem(Direction direction)
{
QTreeWidgetItem *item = ui->treeWidget->currentItem();
if (!item)
return;
int row = ui->treeWidget->currentIndex().row();
if ((direction == Direction::Up) && (row <= 0)) // 더 이상 올라갈 곳이 없음
return;
int lastRow = 0;
QTreeWidgetItem *parent = item->parent();
if (parent)
lastRow = parent->childCount() -1;
else
lastRow = ui->treeWidget->topLevelItemCount() - 1;
if ((direction == Direction::Down) && (row == lastRow)) // 더 이상 내려갈 곳이 없음
return;
int upDownIdx = static_cast<int>(direction);
int index;
if (parent) { // 하위 아이템의 경우
index = parent->indexOfChild(item);
QTreeWidgetItem *child = parent->takeChild(index); // 선택된 아이템을 부모에서 분리하고
parent->insertChild(index + upDownIdx, child); // 옮긴 위치에 다시 insert 한다
ui->treeWidget->setCurrentItem(child);
parent->setExpanded(true);
child->setExpanded(true);
}
else { // 최상위 레벨 아이템의 경우
index = ui->treeWidget->indexOfTopLevelItem(item);
QTreeWidgetItem *child = ui->treeWidget->takeTopLevelItem(index); // 선택된 아이템을 부모에서 분리하고
ui->treeWidget->insertTopLevelItem(index + upDownIdx, child); // 옮긴 위치에 다시 insert 한다
ui->treeWidget->setCurrentItem(child);
child->setExpanded(true);
}
}
전체 소스코드
treedialog.h
#ifndef TREEDIALOG_H
#define TREEDIALOG_H
#include <QDialog>
#include <QTreeWidgetItem>
enum Direction {
Up = -1,
Down = 1
};
namespace Ui {
class TreeDialog;
}
class TreeDialog : public QDialog
{
Q_OBJECT
public:
explicit TreeDialog(QWidget *parent = nullptr);
~TreeDialog();
void moveItem(Direction direction);
void displayCurrentItem(QTreeWidgetItem *item, int column);
private slots:
void on_pushButtonAddParent_clicked();
void on_pushButtonAddChild_clicked();
void on_pushButtonDel_clicked();
void on_pushButtonUp_clicked();
void on_pushButtonDown_clicked();
void on_itemClicked(QTreeWidgetItem *item, int column);
private:
Ui::TreeDialog *ui;
};
#endif // TREEDIALOG_H
treedialog.cpp
#include "treedialog.h"
#include "ui_treedialog.h"
#include <QMessageBox>
TreeDialog::TreeDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::TreeDialog)
{
ui->setupUi(this);
ui->treeWidget->setColumnCount(2); // QTreeWidget을 열을 2개로 설정
// 헤더 설정
QStringList headers;
headers << tr("Col 1") << tr("Col 2");
ui->treeWidget->setHeaderLabels(headers);
// 데이터(아이템) 추가
QTreeWidgetItem *cities = new QTreeWidgetItem(ui->treeWidget); // 첫번째 부모
cities->setText(0, tr("Cities"));
cities->setText(1, tr(" - "));
QTreeWidgetItem *osloItem = new QTreeWidgetItem(cities); // 첫번째 부모의 첫번째 자식(row 1)
osloItem->setText(0, tr("Oslo"));
osloItem->setText(1, tr("No"));
QTreeWidgetItem *seoulItem = new QTreeWidgetItem(cities); // 첫번째 부모의 두번째 자식(row 2)
seoulItem->setText(0, tr("Seoul"));
seoulItem->setText(1, tr("Yes"));
cities->setExpanded(true);
QTreeWidgetItem *colors = new QTreeWidgetItem(ui->treeWidget); // 두번째 부모
colors->setText(0, tr("Colors"));
// 아이템을 수정 가능하게 함 - ItemIsEditable 플래그를 설정해주면 아이템을 더블 클릭시 수정 가능해짐
colors->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
QTreeWidgetItem *redItem = new QTreeWidgetItem(colors); // 두번째 부모의 첫번째 자식(row 1)
redItem->setText(0, tr("Red"));
redItem->setText(1, tr("1"));
redItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
QTreeWidgetItem *yellowItem = new QTreeWidgetItem(colors); // 두번째 부모의 두번째 자식(row 1)
yellowItem->setText(0, tr("Yellow"));
yellowItem->setText(1, tr("2"));
yellowItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
yellowItem->setHidden(true); // 아이템을 숨김(화면에 표시 안함)
QTreeWidgetItem *greenItem = new QTreeWidgetItem(colors); // 두번째 부모의 첫번째 자식(row 1)
greenItem->setText(0, tr("Green"));
greenItem->setText(1, tr("1"));
greenItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
colors->setExpanded(true);
connect(ui->treeWidget, &QTreeWidget::itemClicked, this, &TreeDialog::on_itemClicked);
// ui->treeWidget->setSortingEnabled(true); // 헤더 클릭 시 오름/내림차순 정렬되게 함
displayCurrentItem(ui->treeWidget->currentItem(), 0);
}
TreeDialog::~TreeDialog()
{
delete ui;
}
void TreeDialog::on_pushButtonAddParent_clicked()
{
// 최상위 아이템을 추가함
QTreeWidgetItem *parent = new QTreeWidgetItem(ui->treeWidget);
parent->setText(0, ui->lineEditCol1->text());
parent->setText(1, ui->lineEditCol2->text());
}
void TreeDialog::on_pushButtonAddChild_clicked()
{
// 선택된 아이템 하위에 데이터를 추가함
// QTreeWidget은 SingleSelection만 허용하도록 설정해놓았음
QList<QTreeWidgetItem*> parent = ui->treeWidget->selectedItems();
if (parent.size() > 0) {
QTreeWidgetItem *child = new QTreeWidgetItem(parent[0]);
child->setText(0, ui->lineEditCol1->text());
child->setText(1, ui->lineEditCol2->text());
child->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
parent[0]->setExpanded(true);
}
else {
QMessageBox::information(this, tr("Info"), tr("Please select the parent item"), QMessageBox::Ok);
}
}
void TreeDialog::on_pushButtonDel_clicked()
{
QTreeWidgetItem *item = ui->treeWidget->currentItem();
int index;
if (item) {
QTreeWidgetItem *parent = item->parent();
if (parent) { // 하위 아이템 삭제
index = parent->indexOfChild(item);
delete parent->takeChild(index);
}
else { // 최상위 레벨 아이템 삭제
index = ui->treeWidget->indexOfTopLevelItem(item);
delete ui->treeWidget->takeTopLevelItem(index);
}
}
else {
QMessageBox::information(this, tr("Info"), tr("Please select the item"), QMessageBox::Ok);
}
}
void TreeDialog::on_pushButtonUp_clicked()
{
moveItem(Direction::Up);
}
void TreeDialog::on_pushButtonDown_clicked()
{
moveItem(Direction::Down);
}
void TreeDialog::on_itemClicked(QTreeWidgetItem *item, int column)
{
displayCurrentItem(item, column);
}
void TreeDialog::moveItem(Direction direction)
{
QTreeWidgetItem *item = ui->treeWidget->currentItem();
if (!item)
return;
int row = ui->treeWidget->currentIndex().row();
if ((direction == Direction::Up) && (row <= 0)) // 더 이상 올라갈 곳이 없음
return;
int lastRow = 0;
QTreeWidgetItem *parent = item->parent();
if (parent)
lastRow = parent->childCount() -1;
else
lastRow = ui->treeWidget->topLevelItemCount() - 1;
if ((direction == Direction::Down) && (row == lastRow)) // 더 이상 내려갈 곳이 없음
return;
int upDownIdx = static_cast<int>(direction);
int index;
if (parent) { // 하위 아이템의 경우
index = parent->indexOfChild(item);
QTreeWidgetItem *child = parent->takeChild(index); // 선택된 아이템을 부모에서 분리하고
parent->insertChild(index + upDownIdx, child); // 옮긴 위치에 다시 insert 한다
ui->treeWidget->setCurrentItem(child);
parent->setExpanded(true);
child->setExpanded(true);
}
else { // 최상위 레벨 아이템의 경우
index = ui->treeWidget->indexOfTopLevelItem(item);
QTreeWidgetItem *child = ui->treeWidget->takeTopLevelItem(index); // 선택된 아이템을 부모에서 분리하고
ui->treeWidget->insertTopLevelItem(index + upDownIdx, child); // 옮긴 위치에 다시 insert 한다
ui->treeWidget->setCurrentItem(child);
child->setExpanded(true);
}
}
void TreeDialog::displayCurrentItem(QTreeWidgetItem *item, int column)
{
if (item) {
ui->labelCurrentItem->setText(item->data(column, Qt::DisplayRole).toString());
}
}